From 66f10855577d39e476420840a9cfbc9f8e2fd183 Mon Sep 17 00:00:00 2001 From: Cybwan Date: Mon, 16 Sep 2024 14:30:57 +0800 Subject: [PATCH] optimized sidecar's config.json (#341) * add isolation policy. * optimized sidecar's config.json. * optimized sidecar's config.json. * optimized sidecar's config.json. * optimized sidecar's config.json. * fix dns proxy issue. * fix dns proxy issue. * optimized sidecar's config.json. --- charts/fsm/README.md | 2 +- charts/fsm/templates/fsm-rbac.yaml | 2 +- charts/fsm/values.schema.json | 63 ++++-- charts/fsm/values.yaml | 5 +- .../crds/config.flomesh.io_meshconfigs.yaml | 46 ++++- .../crds/policy.flomesh.io_isolations.yaml | 71 +++++++ pkg/announcements/types.go | 9 + pkg/apis/config/v1alpha3/mesh_config.go | 21 +- .../config/v1alpha3/zz_generated.deepcopy.go | 28 ++- pkg/apis/connector/v1alpha1/consul.go | 1 - pkg/apis/connector/v1alpha1/eureka.go | 1 - pkg/apis/connector/v1alpha1/nacos.go | 1 - pkg/apis/policy/v1alpha1/isolation.go | 55 +++++ .../policy/v1alpha1/zz_generated.deepcopy.go | 98 +++++++++ .../policy/v1alpha1/zz_generated.register.go | 2 + pkg/catalog/endpoint.go | 74 ++++++- pkg/catalog/endpoint_test.go | 4 + pkg/catalog/inbound_traffic_policies_test.go | 1 + pkg/catalog/ingress_test.go | 1 + pkg/catalog/isolation.go | 27 +++ pkg/catalog/outbound_traffic_policies_test.go | 2 + pkg/configurator/methods.go | 5 + pkg/configurator/mock_client_generated.go | 14 ++ pkg/configurator/types.go | 3 + .../policy/v1alpha1/fake/fake_isolation.go | 138 +++++++++++++ .../v1alpha1/fake/fake_policy_client.go | 4 + .../policy/v1alpha1/generated_expansion.go | 2 + .../typed/policy/v1alpha1/isolation.go | 192 ++++++++++++++++++ .../typed/policy/v1alpha1/policy_client.go | 5 + .../informers/externalversions/generic.go | 2 + .../policy/v1alpha1/interface.go | 7 + .../policy/v1alpha1/isolation.go | 87 ++++++++ .../policy/v1alpha1/expansion_generated.go | 8 + .../listers/policy/v1alpha1/isolation.go | 96 +++++++++ pkg/k8s/informers/informers.go | 1 + pkg/k8s/informers/types.go | 2 + pkg/manager/listeners/client.go | 5 + pkg/messaging/broker.go | 2 + pkg/policy/client.go | 18 ++ pkg/policy/mock_client_generated.go | 14 ++ pkg/policy/types.go | 3 + .../providers/pipy/repo/codebase/dns-main.js | 6 +- .../codebase/modules/outbound-http-routing.js | 3 +- pkg/sidecar/providers/pipy/repo/jobs.go | 112 ++++++---- pkg/sidecar/providers/pipy/repo/policy.go | 21 +- pkg/sidecar/providers/pipy/repo/types.go | 17 +- pkg/sidecar/providers/pipy/repo/util.go | 32 +-- pkg/utils/cidr/cidr.go | 5 + pkg/utils/{ip2int.go => ipconv.go} | 14 ++ pkg/utils/util.go | 35 ---- 50 files changed, 1205 insertions(+), 162 deletions(-) create mode 100644 cmd/fsm-bootstrap/crds/policy.flomesh.io_isolations.yaml create mode 100644 pkg/apis/policy/v1alpha1/isolation.go create mode 100644 pkg/catalog/isolation.go create mode 100644 pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/fake/fake_isolation.go create mode 100644 pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/isolation.go create mode 100644 pkg/gen/client/policy/informers/externalversions/policy/v1alpha1/isolation.go create mode 100644 pkg/gen/client/policy/listers/policy/v1alpha1/isolation.go rename pkg/utils/{ip2int.go => ipconv.go} (57%) diff --git a/charts/fsm/README.md b/charts/fsm/README.md index 767c78ef7..0cfaf2be5 100644 --- a/charts/fsm/README.md +++ b/charts/fsm/README.md @@ -349,7 +349,7 @@ The following table lists the configurable parameters of the fsm chart and their | fsm.injector.resource | object | `{"limits":{"cpu":"1","memory":"512M"},"requests":{"cpu":"0.5","memory":"128M"}}` | Sidecar injector's container resource parameters | | fsm.injector.tolerations | list | `[]` | Node tolerations applied to control plane pods. The specified tolerations allow pods to schedule onto nodes with matching taints. | | fsm.injector.webhookTimeoutSeconds | int | `20` | Mutating webhook timeout | -| fsm.localDNSProxy | object | `{"enable":false,"searchesWithNamespace":true,"searchesWithTrustDomain":true,"wildcard":{"enable":false,"ipv4":["127.0.0.2"]}}` | Local DNS Proxy improves the performance of your computer by caching the responses coming from your DNS servers | +| fsm.localDNSProxy | object | `{"enable":false,"generateIPv6BasedOnIPv4":false,"searchesWithNamespace":true,"searchesWithTrustDomain":true,"wildcard":{"enable":false,"ips":[{"ipv4":"127.0.0.2"}]}}` | Local DNS Proxy improves the performance of your computer by caching the responses coming from your DNS servers | | fsm.localProxyMode | string | `"Localhost"` | Proxy mode for the proxy sidecar. Acceptable values are ['Localhost', 'PodIP'] | | fsm.maxDataPlaneConnections | int | `0` | Sets the max data plane connections allowed for an instance of fsm-controller, set to 0 to not enforce limits | | fsm.meshName | string | `"fsm"` | Identifier for the instance of a service mesh within a cluster | diff --git a/charts/fsm/templates/fsm-rbac.yaml b/charts/fsm/templates/fsm-rbac.yaml index bc413ac20..f39fc9eb9 100644 --- a/charts/fsm/templates/fsm-rbac.yaml +++ b/charts/fsm/templates/fsm-rbac.yaml @@ -89,7 +89,7 @@ rules: # FSM's custom policy API - apiGroups: ["policy.flomesh.io"] - resources: ["egresses", "egressgateways", "ingressbackends", "accesscontrols", "accesscerts", "retries", "upstreamtrafficsettings"] + resources: ["egresses", "egressgateways", "ingressbackends", "accesscontrols", "accesscerts", "isolations", "retries", "upstreamtrafficsettings"] verbs: ["list", "get", "watch"] - apiGroups: ["policy.flomesh.io"] resources: ["ingressbackends/status", "accesscontrols/status", "accesscerts/status", "upstreamtrafficsettings/status"] diff --git a/charts/fsm/values.schema.json b/charts/fsm/values.schema.json index aab8962b8..11e7a4927 100644 --- a/charts/fsm/values.schema.json +++ b/charts/fsm/values.schema.json @@ -1238,6 +1238,12 @@ "title": "Secondary upstream DNS server for local DNS Proxy", "description": "Secondary upstream DNS server for local DNS Proxy" }, + "generateIPv6BasedOnIPv4": { + "$id": "#/properties/fsm/properties/localDNSProxy/properties/generateIPv6BasedOnIPv4", + "type": "boolean", + "title": "Auto generate IPv6 based on IPv4", + "description": "Auto generate IPv6 based on IPv4" + }, "wildcard": { "$id": "#/properties/fsm/properties/localDNSProxy/properties/wildcard", "type": "object", @@ -1245,7 +1251,7 @@ "description": "The wildcard schema for local DNS Proxy", "required": [ "enable", - "ipv4" + "ips" ], "properties": { "enable": { @@ -1254,14 +1260,28 @@ "title": "The enable schema for wildcard", "description": "Indicates whether wildcard is enabled or not" }, - "ipv4": { - "$id": "#/properties/fsm/properties/localDNSProxy/properties/wildcard/properties/ipv4", + "ips": { + "$id": "#/properties/fsm/properties/localDNSProxy/properties/wildcard/properties/ips", "type": "array", - "title": "The ipv4 schema for wildcard", - "pattern": "((?:\\d{1,3}\\.){3}\\d{1,3})$", + "title": "The ips schema for wildcard", "items": { - "type": "string", - "pattern": "((?:\\d{1,3}\\.){3}\\d{1,3})$" + "type": "object", + "required": [ + "ipv4" + ], + "properties": { + "ipv4": { + "$id": "#/properties/fsm/properties/localDNSProxy/properties/wildcard/properties/ips/properties/ipv4", + "type": "string", + "title": "ipv4", + "pattern": "((?:\\d{1,3}\\.){3}\\d{1,3})$" + }, + "ipv6": { + "$id": "#/properties/fsm/properties/localDNSProxy/properties/wildcard/properties/ips/properties/ipv6", + "type": "string", + "title": "ipv6" + } + } } } } @@ -1275,22 +1295,37 @@ "type": "object", "required": [ "dn", - "ipv4" + "ips" ], "properties": { "dn": { - "$id": "#/properties/fsm/properties/localDNSProxy/properties/wildcard/properties/db/properties/dn", + "$id": "#/properties/fsm/properties/localDNSProxy/properties/db/properties/db/properties/dn", "type": "string", "title": "The dn schema for wildcard", "description": "FQDN" }, - "ipv4": { - "$id": "#/properties/fsm/properties/localDNSProxy/properties/wildcard/properties/db/properties/ipv4", + "ips": { + "$id": "#/properties/fsm/properties/localDNSProxy/properties/db/properties/ips", "type": "array", - "title": "ipv4", + "title": "The ips schema for wildcard", "items": { - "type": "string", - "pattern": "((?:\\d{1,3}\\.){3}\\d{1,3})$" + "type": "object", + "required": [ + "ipv4" + ], + "properties": { + "ipv4": { + "$id": "#/properties/fsm/properties/localDNSProxy/properties/db/properties/ips/properties/ipv4", + "type": "string", + "title": "ipv4", + "pattern": "((?:\\d{1,3}\\.){3}\\d{1,3})$" + }, + "ipv6": { + "$id": "#/properties/fsm/properties/localDNSProxy/properties/db/properties/ips/properties/ipv6", + "type": "string", + "title": "ipv6" + } + } } } } diff --git a/charts/fsm/values.yaml b/charts/fsm/values.yaml index 7d2aaa05c..b0215a776 100644 --- a/charts/fsm/values.yaml +++ b/charts/fsm/values.yaml @@ -507,10 +507,11 @@ fsm: enable: false searchesWithNamespace: true searchesWithTrustDomain: true + generateIPv6BasedOnIPv4: false wildcard: enable: false - ipv4: - - 127.0.0.2 + ips: + - ipv4: 127.0.0.2 # -- Sets the max data plane connections allowed for an instance of fsm-controller, set to 0 to not enforce limits maxDataPlaneConnections: 0 diff --git a/cmd/fsm-bootstrap/crds/config.flomesh.io_meshconfigs.yaml b/cmd/fsm-bootstrap/crds/config.flomesh.io_meshconfigs.yaml index fc9aa3ef0..ab1e5cce0 100644 --- a/cmd/fsm-bootstrap/crds/config.flomesh.io_meshconfigs.yaml +++ b/cmd/fsm-bootstrap/crds/config.flomesh.io_meshconfigs.yaml @@ -2161,21 +2161,36 @@ spec: dn: description: DN defines resolve DN. type: string - ipv4: - description: IPv4 defines a ipv4 address for resolve - DN. + ips: + description: IPs defines ip addresses for resolve DN. items: - type: string + description: ResolveAddr is the type to represent + FSM's Resolve Addr configuration. + properties: + ipv4: + description: IPv4 defines a ipv4 address for resolve + DN. + type: string + ipv6: + description: IPv6 defines a ipv6 address for resolve + DN. + type: string + required: + - ipv4 + type: object type: array required: - dn - - ipv4 + - ips type: object type: array enable: description: Enable defines a boolean indicating if the sidecars are enabled for local DNS Proxy. type: boolean + generateIPv6BasedOnIPv4: + default: false + type: boolean primaryUpstreamDNSServerIPAddr: description: PrimaryUpstreamDNSServerIPAddr defines a primary upstream DNS server for local DNS Proxy. @@ -2191,14 +2206,27 @@ spec: description: Enable defines a boolean indicating if wildcard are enabled for local DNS Proxy. type: boolean - ipv4: - description: IPv4 defines a ipv4 address for wildcard - DN. + ips: + description: IPs defines ip addresses for resolve DN. items: - type: string + description: ResolveAddr is the type to represent FSM's + Resolve Addr configuration. + properties: + ipv4: + description: IPv4 defines a ipv4 address for resolve + DN. + type: string + ipv6: + description: IPv6 defines a ipv6 address for resolve + DN. + type: string + required: + - ipv4 + type: object type: array required: - enable + - ips type: object required: - enable diff --git a/cmd/fsm-bootstrap/crds/policy.flomesh.io_isolations.yaml b/cmd/fsm-bootstrap/crds/policy.flomesh.io_isolations.yaml new file mode 100644 index 000000000..0c33f8f7f --- /dev/null +++ b/cmd/fsm-bootstrap/crds/policy.flomesh.io_isolations.yaml @@ -0,0 +1,71 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + app.kubernetes.io/name: flomesh.io + name: isolations.policy.flomesh.io +spec: + group: policy.flomesh.io + names: + kind: Isolation + listKind: IsolationList + plural: isolations + shortNames: + - iso + singular: isolation + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Isolation is the type used to represent an isolation policy. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec is the Isolation specification + properties: + cidrs: + description: |- + cidr is a string representing the IP Isolation + Valid examples are "192.168.1.0/24" + items: + type: string + minItems: 1 + type: array + required: + - cidrs + type: object + status: + description: Status is the status of the Isolation configuration. + properties: + currentStatus: + description: CurrentStatus defines the current status of an Isolation + resource. + type: string + reason: + description: Reason defines the reason for the current status of an + Isolation resource. + type: string + type: object + type: object + served: true + storage: true diff --git a/pkg/announcements/types.go b/pkg/announcements/types.go index c039ac446..f5459bd1d 100644 --- a/pkg/announcements/types.go +++ b/pkg/announcements/types.go @@ -303,6 +303,15 @@ const ( // GlobalTrafficPolicyUpdated is the type of announcement emitted when we observe an update to serviceimports.flomesh.io GlobalTrafficPolicyUpdated Kind = "globaltrafficpolicy-updated" + // IsolationPolicyAdded is the type of announcement emitted when we observe an addition of isolations.policy.flomesh.io + IsolationPolicyAdded Kind = "isolation-added" + + // IsolationPolicyDeleted the type of announcement emitted when we observe a deletion of isolations.policy.flomesh.io + IsolationPolicyDeleted Kind = "isolation-deleted" + + // IsolationPolicyUpdated is the type of announcement emitted when we observe an update to isolations.policy.flomesh.io + IsolationPolicyUpdated Kind = "isolation-updated" + // RetryPolicyAdded is the type of announcement emitted when we observe an addition of retries.policy.flomesh.io RetryPolicyAdded Kind = "retry-added" diff --git a/pkg/apis/config/v1alpha3/mesh_config.go b/pkg/apis/config/v1alpha3/mesh_config.go index 3247ead9c..4e37487aa 100644 --- a/pkg/apis/config/v1alpha3/mesh_config.go +++ b/pkg/apis/config/v1alpha3/mesh_config.go @@ -87,13 +87,22 @@ const ( LocalProxyModePodIP LocalProxyMode = "PodIP" ) +// ResolveAddr is the type to represent FSM's Resolve Addr configuration. +type ResolveAddr struct { + // IPv4 defines a ipv4 address for resolve DN. + IPv4 string `json:"ipv4"` + + // IPv6 defines a ipv6 address for resolve DN. + IPv6 string `json:"ipv6,omitempty"` +} + // WildcardDN is the type to represent FSM's Wildcard DN configuration. type WildcardDN struct { // Enable defines a boolean indicating if wildcard are enabled for local DNS Proxy. Enable bool `json:"enable"` - // IPv4 defines a ipv4 address for wildcard DN. - IPv4 []string `json:"ipv4,omitempty"` + // IPs defines ip addresses for resolve DN. + IPs []ResolveAddr `json:"ips"` } // ResolveDN is the type to represent FSM's Resolve DN configuration. @@ -101,8 +110,8 @@ type ResolveDN struct { // DN defines resolve DN. DN string `json:"dn"` - // IPv4 defines a ipv4 address for resolve DN. - IPv4 []string `json:"ipv4"` + // IPs defines ip addresses for resolve DN. + IPs []ResolveAddr `json:"ips"` } // LocalDNSProxy is the type to represent FSM's local DNS proxy configuration. @@ -118,6 +127,10 @@ type LocalDNSProxy struct { // +optional SecondaryUpstreamDNSServerIPAddr string `json:"secondaryUpstreamDNSServerIPAddr,omitempty"` + // +kubebuilder:default=false + // +optional + GenerateIPv6BasedOnIPv4 bool `json:"generateIPv6BasedOnIPv4,omitempty"` + // Wildcard defines Wildcard DN. Wildcard WildcardDN `json:"wildcard"` diff --git a/pkg/apis/config/v1alpha3/zz_generated.deepcopy.go b/pkg/apis/config/v1alpha3/zz_generated.deepcopy.go index a998e3389..129629b0b 100644 --- a/pkg/apis/config/v1alpha3/zz_generated.deepcopy.go +++ b/pkg/apis/config/v1alpha3/zz_generated.deepcopy.go @@ -725,12 +725,28 @@ func (in *RepoServerSpec) DeepCopy() *RepoServerSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResolveAddr) DeepCopyInto(out *ResolveAddr) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResolveAddr. +func (in *ResolveAddr) DeepCopy() *ResolveAddr { + if in == nil { + return nil + } + out := new(ResolveAddr) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResolveDN) DeepCopyInto(out *ResolveDN) { *out = *in - if in.IPv4 != nil { - in, out := &in.IPv4, &out.IPv4 - *out = make([]string, len(*in)) + if in.IPs != nil { + in, out := &in.IPs, &out.IPs + *out = make([]ResolveAddr, len(*in)) copy(*out, *in) } return @@ -1005,9 +1021,9 @@ func (in *VaultTokenSpec) DeepCopy() *VaultTokenSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WildcardDN) DeepCopyInto(out *WildcardDN) { *out = *in - if in.IPv4 != nil { - in, out := &in.IPv4, &out.IPv4 - *out = make([]string, len(*in)) + if in.IPs != nil { + in, out := &in.IPs, &out.IPs + *out = make([]ResolveAddr, len(*in)) copy(*out, *in) } return diff --git a/pkg/apis/connector/v1alpha1/consul.go b/pkg/apis/connector/v1alpha1/consul.go index 427cbe25d..aa416144e 100644 --- a/pkg/apis/connector/v1alpha1/consul.go +++ b/pkg/apis/connector/v1alpha1/consul.go @@ -64,7 +64,6 @@ type ConsulSyncToK8SSpec struct { // +optional PassingOnly bool `json:"passingOnly,omitempty"` - // +optional // +optional FilterIPRanges []string `json:"filterIpRanges,omitempty"` diff --git a/pkg/apis/connector/v1alpha1/eureka.go b/pkg/apis/connector/v1alpha1/eureka.go index a9212f16a..b3e1fc0fc 100644 --- a/pkg/apis/connector/v1alpha1/eureka.go +++ b/pkg/apis/connector/v1alpha1/eureka.go @@ -60,7 +60,6 @@ type EurekaSyncToK8SSpec struct { // +optional ClusterId string `json:"clusterId,omitempty"` - // +optional // +optional FilterIPRanges []string `json:"filterIpRanges,omitempty"` diff --git a/pkg/apis/connector/v1alpha1/nacos.go b/pkg/apis/connector/v1alpha1/nacos.go index d1befa1d8..d456fc16c 100644 --- a/pkg/apis/connector/v1alpha1/nacos.go +++ b/pkg/apis/connector/v1alpha1/nacos.go @@ -64,7 +64,6 @@ type NacosSyncToK8SSpec struct { // +optional PassingOnly bool `json:"passingOnly,omitempty"` - // +optional // +optional FilterIPRanges []string `json:"filterIpRanges,omitempty"` diff --git a/pkg/apis/policy/v1alpha1/isolation.go b/pkg/apis/policy/v1alpha1/isolation.go new file mode 100644 index 000000000..836a0c834 --- /dev/null +++ b/pkg/apis/policy/v1alpha1/isolation.go @@ -0,0 +1,55 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// Isolation is the type used to represent an isolation policy. +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:metadata:labels=app.kubernetes.io/name=flomesh.io +// +kubebuilder:resource:shortName=iso,scope=Cluster +type Isolation struct { + // Object's type metadata + metav1.TypeMeta `json:",inline"` + + // Object's metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec is the Isolation specification + // +optional + Spec IsolationSpec `json:"spec,omitempty"` + + // Status is the status of the Isolation configuration. + // +optional + Status IsolationStatus `json:"status,omitempty"` +} + +// IsolationSpec is the type used to represent the IsolationSpec policy specification. +type IsolationSpec struct { + // cidr is a string representing the IP Isolation + // Valid examples are "192.168.1.0/24" + // +kubebuilder:validation:MinItems=1 + CIDR []string `json:"cidrs"` +} + +// IsolationList defines the list of Isolation objects. +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type IsolationList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []Isolation `json:"items"` +} + +// IsolationStatus is the type used to represent the status of an Isolation resource. +type IsolationStatus struct { + // CurrentStatus defines the current status of an Isolation resource. + // +optional + CurrentStatus string `json:"currentStatus,omitempty"` + + // Reason defines the reason for the current status of an Isolation resource. + // +optional + Reason string `json:"reason,omitempty"` +} diff --git a/pkg/apis/policy/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/policy/v1alpha1/zz_generated.deepcopy.go index 8dab38fb2..a0e6804c6 100644 --- a/pkg/apis/policy/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/policy/v1alpha1/zz_generated.deepcopy.go @@ -947,6 +947,104 @@ func (in *IngressSourceSpec) DeepCopy() *IngressSourceSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Isolation) DeepCopyInto(out *Isolation) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Isolation. +func (in *Isolation) DeepCopy() *Isolation { + if in == nil { + return nil + } + out := new(Isolation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Isolation) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IsolationList) DeepCopyInto(out *IsolationList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Isolation, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IsolationList. +func (in *IsolationList) DeepCopy() *IsolationList { + if in == nil { + return nil + } + out := new(IsolationList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IsolationList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IsolationSpec) DeepCopyInto(out *IsolationSpec) { + *out = *in + if in.CIDR != nil { + in, out := &in.CIDR, &out.CIDR + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IsolationSpec. +func (in *IsolationSpec) DeepCopy() *IsolationSpec { + if in == nil { + return nil + } + out := new(IsolationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IsolationStatus) DeepCopyInto(out *IsolationStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IsolationStatus. +func (in *IsolationStatus) DeepCopy() *IsolationStatus { + if in == nil { + return nil + } + out := new(IsolationStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LocalRateLimitSpec) DeepCopyInto(out *LocalRateLimitSpec) { *out = *in diff --git a/pkg/apis/policy/v1alpha1/zz_generated.register.go b/pkg/apis/policy/v1alpha1/zz_generated.register.go index a59c8db9e..a9f1ebb08 100644 --- a/pkg/apis/policy/v1alpha1/zz_generated.register.go +++ b/pkg/apis/policy/v1alpha1/zz_generated.register.go @@ -68,6 +68,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &EgressList{}, &IngressBackend{}, &IngressBackendList{}, + &Isolation{}, + &IsolationList{}, &Retry{}, &RetryList{}, &UpstreamTrafficSetting{}, diff --git a/pkg/catalog/endpoint.go b/pkg/catalog/endpoint.go index 1732c79b4..d59208d6f 100644 --- a/pkg/catalog/endpoint.go +++ b/pkg/catalog/endpoint.go @@ -9,13 +9,29 @@ import ( // ListEndpointsForService returns the list of provider endpoints corresponding to a service func (mc *MeshCatalog) listEndpointsForService(svc service.MeshService) []endpoint.Endpoint { var endpoints []endpoint.Endpoint + isolationCidrs := mc.GetIsolationCidrs() for _, provider := range mc.endpointsProviders { - ep := provider.ListEndpointsForService(svc) - if len(ep) == 0 { + eps := provider.ListEndpointsForService(svc) + if len(eps) == 0 { log.Trace().Msgf("No endpoints found for service %s by endpoints provider %s", provider.GetID(), svc) continue } - endpoints = append(endpoints, ep...) + if len(isolationCidrs) > 0 { + for _, ep := range eps { + isolation := false + for _, isolationCidr := range isolationCidrs { + if isolationCidr.Has(ep.IP) { + isolation = true + break + } + } + if !isolation { + endpoints = append(endpoints, ep) + } + } + } else { + endpoints = append(endpoints, eps...) + } } return endpoints } @@ -23,9 +39,28 @@ func (mc *MeshCatalog) listEndpointsForService(svc service.MeshService) []endpoi // getDNSResolvableServiceEndpoints returns the resolvable set of endpoint over which a service is accessible using its FQDN func (mc *MeshCatalog) getDNSResolvableServiceEndpoints(svc service.MeshService) []endpoint.Endpoint { var endpoints []endpoint.Endpoint + isolationCidrs := mc.GetIsolationCidrs() for _, provider := range mc.endpointsProviders { - ep := provider.GetResolvableEndpointsForService(svc) - endpoints = append(endpoints, ep...) + eps := provider.GetResolvableEndpointsForService(svc) + if len(eps) == 0 { + continue + } + if len(isolationCidrs) > 0 { + for _, ep := range eps { + isolation := false + for _, isolationCidr := range isolationCidrs { + if isolationCidr.Has(ep.IP) { + isolation = true + break + } + } + if !isolation { + endpoints = append(endpoints, ep) + } + } + } else { + endpoints = append(endpoints, eps...) + } } return endpoints } @@ -34,14 +69,15 @@ func (mc *MeshCatalog) getDNSResolvableServiceEndpoints(svc service.MeshService) // is allowed access the upstream service func (mc *MeshCatalog) ListAllowedUpstreamEndpointsForService(downstreamIdentity identity.ServiceIdentity, upstreamSvc service.MeshService) []endpoint.Endpoint { outboundEndpoints := mc.listEndpointsForService(upstreamSvc) - if len(outboundEndpoints) == 0 { - return nil - } if mc.configurator.IsPermissiveTrafficPolicyMode() { return outboundEndpoints } + if len(outboundEndpoints) == 0 { + return nil + } + // In SMI mode, the endpoints for an upstream service must be filtered based on the service account // associated with the endpoint. Only endpoints associated with authorized service accounts as referenced // in SMI TrafficTarget resources should be returned. @@ -73,13 +109,29 @@ func (mc *MeshCatalog) ListAllowedUpstreamEndpointsForService(downstreamIdentity // Note: ServiceIdentity must be in the format "name.namespace" [https://github.com/flomesh-io/fsm/issues/3188] func (mc *MeshCatalog) listEndpointsForServiceIdentity(serviceIdentity identity.ServiceIdentity) []endpoint.Endpoint { var endpoints []endpoint.Endpoint + isolationCidrs := mc.GetIsolationCidrs() for _, provider := range mc.endpointsProviders { - ep := provider.ListEndpointsForIdentity(serviceIdentity) - if len(ep) == 0 { + eps := provider.ListEndpointsForIdentity(serviceIdentity) + if len(eps) == 0 { log.Trace().Msgf("[%s] No endpoints found for service account=%s", provider.GetID(), serviceIdentity) continue } - endpoints = append(endpoints, ep...) + if len(isolationCidrs) > 0 { + for _, ep := range eps { + isolation := false + for _, isolationCidr := range isolationCidrs { + if isolationCidr.Has(ep.IP) { + isolation = true + break + } + } + if !isolation { + endpoints = append(endpoints, ep) + } + } + } else { + endpoints = append(endpoints, eps...) + } } return endpoints } diff --git a/pkg/catalog/endpoint_test.go b/pkg/catalog/endpoint_test.go index 9a2780ed3..3813f60bd 100644 --- a/pkg/catalog/endpoint_test.go +++ b/pkg/catalog/endpoint_test.go @@ -18,6 +18,7 @@ import ( "github.com/flomesh-io/fsm/pkg/endpoint" "github.com/flomesh-io/fsm/pkg/identity" "github.com/flomesh-io/fsm/pkg/k8s" + "github.com/flomesh-io/fsm/pkg/policy" "github.com/flomesh-io/fsm/pkg/service" "github.com/flomesh-io/fsm/pkg/smi" "github.com/flomesh-io/fsm/pkg/tests" @@ -141,6 +142,7 @@ func TestListAllowedUpstreamEndpointsForService(t *testing.T) { mockKubeController := k8s.NewMockController(mockCtrl) mockEndpointProvider := endpoint.NewMockProvider(mockCtrl) mockServiceProvider := service.NewMockProvider(mockCtrl) + mockPolicyController := policy.NewMockController(mockCtrl) mockMeshSpec := smi.NewMockMeshSpec(mockCtrl) mc := MeshCatalog{ @@ -148,10 +150,12 @@ func TestListAllowedUpstreamEndpointsForService(t *testing.T) { meshSpec: mockMeshSpec, endpointsProviders: []endpoint.Provider{mockEndpointProvider}, serviceProviders: []service.Provider{mockServiceProvider}, + policyController: mockPolicyController, configurator: mockConfigurator, } mockConfigurator.EXPECT().IsPermissiveTrafficPolicyMode().Return(tc.permissiveMode).AnyTimes() + mockPolicyController.EXPECT().ListIsolationPolicies().Return(nil).AnyTimes() for svc, endpoints := range tc.outboundServiceEndpoints { mockEndpointProvider.EXPECT().ListEndpointsForService(svc).Return(endpoints).AnyTimes() diff --git a/pkg/catalog/inbound_traffic_policies_test.go b/pkg/catalog/inbound_traffic_policies_test.go index 3dfdebd70..f75296034 100644 --- a/pkg/catalog/inbound_traffic_policies_test.go +++ b/pkg/catalog/inbound_traffic_policies_test.go @@ -2033,6 +2033,7 @@ func TestGetInboundMeshTrafficPolicy(t *testing.T) { } mockEndpointProvider.EXPECT().GetResolvableEndpointsForService(gomock.Any()).Return(nil).AnyTimes() + mockPolicyController.EXPECT().ListIsolationPolicies().Return(nil).AnyTimes() mockPolicyController.EXPECT().GetUpstreamTrafficSetting(gomock.Any()).Return(tc.upstreamTrafficSetting).AnyTimes() mockCfg.EXPECT().IsPermissiveTrafficPolicyMode().Return(tc.permissiveMode) mockCfg.EXPECT().GetServiceAccessMode().Return(configv1alpha3.ServiceAccessModeDomain).AnyTimes() diff --git a/pkg/catalog/ingress_test.go b/pkg/catalog/ingress_test.go index bc40b8965..a2ab9987f 100644 --- a/pkg/catalog/ingress_test.go +++ b/pkg/catalog/ingress_test.go @@ -416,6 +416,7 @@ func TestGetIngressTrafficPolicy(t *testing.T) { // depending on the test case. mockPolicyController.EXPECT().GetIngressBackendPolicy(tc.meshSvc).Return(tc.ingressBackend).AnyTimes() mockPolicyController.EXPECT().GetUpstreamTrafficSetting(policy.UpstreamTrafficSettingGetOpt{MeshService: &tc.meshSvc}).Return(nil).AnyTimes() + mockPolicyController.EXPECT().ListIsolationPolicies().Return(nil).AnyTimes() mockServiceProvider.EXPECT().GetID().Return("mock").AnyTimes() mockEndpointsProvider.EXPECT().ListEndpointsForService(ingressSourceSvc).Return(ingressBackendSvcEndpoints).AnyTimes() mockEndpointsProvider.EXPECT().ListEndpointsForService(sourceSvcWithoutEndpoints).Return(nil).AnyTimes() diff --git a/pkg/catalog/isolation.go b/pkg/catalog/isolation.go new file mode 100644 index 000000000..bcf9a7063 --- /dev/null +++ b/pkg/catalog/isolation.go @@ -0,0 +1,27 @@ +package catalog + +import ( + "github.com/flomesh-io/fsm/pkg/utils/cidr" +) + +// GetIsolationCidrs returns the isolation cidrs +func (mc *MeshCatalog) GetIsolationCidrs() []*cidr.CIDR { + // List the isolation policies + isolationPolicies := mc.policyController.ListIsolationPolicies() + if isolationPolicies == nil { + return nil + } + + var isolationCidrs []*cidr.CIDR + for _, p := range isolationPolicies { + if len(p.Spec.CIDR) > 0 { + for _, isolationCidr := range p.Spec.CIDR { + if parsedCidr, err := cidr.ParseCIDR(isolationCidr); err == nil { + isolationCidrs = append(isolationCidrs, parsedCidr) + } + } + } + } + + return isolationCidrs +} diff --git a/pkg/catalog/outbound_traffic_policies_test.go b/pkg/catalog/outbound_traffic_policies_test.go index 2b57a7f01..00271dc6c 100644 --- a/pkg/catalog/outbound_traffic_policies_test.go +++ b/pkg/catalog/outbound_traffic_policies_test.go @@ -645,6 +645,8 @@ func TestGetOutboundMeshTrafficPolicy(t *testing.T) { return svcToEndpointsMap[svc.String()], nil }).AnyTimes() + mockPolicyController.EXPECT().ListIsolationPolicies().Return(nil).AnyTimes() + // Mock calls to UpstreamTrafficSetting lookups mockPolicyController.EXPECT().GetUpstreamTrafficSetting(gomock.Any()).DoAndReturn( func(opt policy.UpstreamTrafficSettingGetOpt) *policyv1alpha1.UpstreamTrafficSetting { diff --git a/pkg/configurator/methods.go b/pkg/configurator/methods.go index 5bbf2289c..855de98a6 100644 --- a/pkg/configurator/methods.go +++ b/pkg/configurator/methods.go @@ -123,6 +123,11 @@ func (c *Client) GetLocalDNSProxySecondaryUpstream() string { return c.getMeshConfig().Spec.Sidecar.LocalDNSProxy.SecondaryUpstreamDNSServerIPAddr } +// GenerateIPv6BasedOnIPv4 returns whether auto generate IPv6 based on IPv4 +func (c *Client) GenerateIPv6BasedOnIPv4() bool { + return c.getMeshConfig().Spec.Sidecar.LocalDNSProxy.GenerateIPv6BasedOnIPv4 +} + // GetTracingHost is the host to which we send tracing spans func (c *Client) GetTracingHost() string { tracingAddress := c.getMeshConfig().Spec.Observability.Tracing.Address diff --git a/pkg/configurator/mock_client_generated.go b/pkg/configurator/mock_client_generated.go index 489808f77..2cb917486 100644 --- a/pkg/configurator/mock_client_generated.go +++ b/pkg/configurator/mock_client_generated.go @@ -38,6 +38,20 @@ func (m *MockConfigurator) EXPECT() *MockConfiguratorMockRecorder { return m.recorder } +// GenerateIPv6BasedOnIPv4 mocks base method. +func (m *MockConfigurator) GenerateIPv6BasedOnIPv4() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GenerateIPv6BasedOnIPv4") + ret0, _ := ret[0].(bool) + return ret0 +} + +// GenerateIPv6BasedOnIPv4 indicates an expected call of GenerateIPv6BasedOnIPv4. +func (mr *MockConfiguratorMockRecorder) GenerateIPv6BasedOnIPv4() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GenerateIPv6BasedOnIPv4", reflect.TypeOf((*MockConfigurator)(nil).GenerateIPv6BasedOnIPv4)) +} + // GetCertKeyBitSize mocks base method. func (m *MockConfigurator) GetCertKeyBitSize() int { m.ctrl.T.Helper() diff --git a/pkg/configurator/types.go b/pkg/configurator/types.go index af668121a..43e6924bc 100644 --- a/pkg/configurator/types.go +++ b/pkg/configurator/types.go @@ -69,6 +69,9 @@ type Configurator interface { // GetLocalDNSProxySecondaryUpstream returns the secondary upstream DNS server for local DNS Proxy GetLocalDNSProxySecondaryUpstream() string + // GenerateIPv6BasedOnIPv4 returns whether auto generate IPv6 based on IPv4 + GenerateIPv6BasedOnIPv4() bool + // GetTracingHost is the host to which we send tracing spans GetTracingHost() string diff --git a/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/fake/fake_isolation.go b/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/fake/fake_isolation.go new file mode 100644 index 000000000..b67d3ea99 --- /dev/null +++ b/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/fake/fake_isolation.go @@ -0,0 +1,138 @@ +/* +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "github.com/flomesh-io/fsm/pkg/apis/policy/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeIsolations implements IsolationInterface +type FakeIsolations struct { + Fake *FakePolicyV1alpha1 + ns string +} + +var isolationsResource = v1alpha1.SchemeGroupVersion.WithResource("isolations") + +var isolationsKind = v1alpha1.SchemeGroupVersion.WithKind("Isolation") + +// Get takes name of the isolation, and returns the corresponding isolation object, and an error if there is any. +func (c *FakeIsolations) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.Isolation, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(isolationsResource, c.ns, name), &v1alpha1.Isolation{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Isolation), err +} + +// List takes label and field selectors, and returns the list of Isolations that match those selectors. +func (c *FakeIsolations) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.IsolationList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(isolationsResource, isolationsKind, c.ns, opts), &v1alpha1.IsolationList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.IsolationList{ListMeta: obj.(*v1alpha1.IsolationList).ListMeta} + for _, item := range obj.(*v1alpha1.IsolationList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested isolations. +func (c *FakeIsolations) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(isolationsResource, c.ns, opts)) + +} + +// Create takes the representation of a isolation and creates it. Returns the server's representation of the isolation, and an error, if there is any. +func (c *FakeIsolations) Create(ctx context.Context, isolation *v1alpha1.Isolation, opts v1.CreateOptions) (result *v1alpha1.Isolation, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(isolationsResource, c.ns, isolation), &v1alpha1.Isolation{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Isolation), err +} + +// Update takes the representation of a isolation and updates it. Returns the server's representation of the isolation, and an error, if there is any. +func (c *FakeIsolations) Update(ctx context.Context, isolation *v1alpha1.Isolation, opts v1.UpdateOptions) (result *v1alpha1.Isolation, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(isolationsResource, c.ns, isolation), &v1alpha1.Isolation{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Isolation), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeIsolations) UpdateStatus(ctx context.Context, isolation *v1alpha1.Isolation, opts v1.UpdateOptions) (*v1alpha1.Isolation, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(isolationsResource, "status", c.ns, isolation), &v1alpha1.Isolation{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Isolation), err +} + +// Delete takes name of the isolation and deletes it. Returns an error if one occurs. +func (c *FakeIsolations) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(isolationsResource, c.ns, name, opts), &v1alpha1.Isolation{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeIsolations) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(isolationsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.IsolationList{}) + return err +} + +// Patch applies the patch and returns the patched isolation. +func (c *FakeIsolations) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.Isolation, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(isolationsResource, c.ns, name, pt, data, subresources...), &v1alpha1.Isolation{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Isolation), err +} diff --git a/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/fake/fake_policy_client.go b/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/fake/fake_policy_client.go index 627130f9d..78d2e3f2a 100644 --- a/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/fake/fake_policy_client.go +++ b/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/fake/fake_policy_client.go @@ -45,6 +45,10 @@ func (c *FakePolicyV1alpha1) IngressBackends(namespace string) v1alpha1.IngressB return &FakeIngressBackends{c, namespace} } +func (c *FakePolicyV1alpha1) Isolations(namespace string) v1alpha1.IsolationInterface { + return &FakeIsolations{c, namespace} +} + func (c *FakePolicyV1alpha1) Retries(namespace string) v1alpha1.RetryInterface { return &FakeRetries{c, namespace} } diff --git a/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/generated_expansion.go b/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/generated_expansion.go index b4bcb1a64..18877650b 100644 --- a/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/generated_expansion.go +++ b/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/generated_expansion.go @@ -25,6 +25,8 @@ type EgressGatewayExpansion interface{} type IngressBackendExpansion interface{} +type IsolationExpansion interface{} + type RetryExpansion interface{} type UpstreamTrafficSettingExpansion interface{} diff --git a/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/isolation.go b/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/isolation.go new file mode 100644 index 000000000..ba0cf0133 --- /dev/null +++ b/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/isolation.go @@ -0,0 +1,192 @@ +/* +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "github.com/flomesh-io/fsm/pkg/apis/policy/v1alpha1" + scheme "github.com/flomesh-io/fsm/pkg/gen/client/policy/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// IsolationsGetter has a method to return a IsolationInterface. +// A group's client should implement this interface. +type IsolationsGetter interface { + Isolations(namespace string) IsolationInterface +} + +// IsolationInterface has methods to work with Isolation resources. +type IsolationInterface interface { + Create(ctx context.Context, isolation *v1alpha1.Isolation, opts v1.CreateOptions) (*v1alpha1.Isolation, error) + Update(ctx context.Context, isolation *v1alpha1.Isolation, opts v1.UpdateOptions) (*v1alpha1.Isolation, error) + UpdateStatus(ctx context.Context, isolation *v1alpha1.Isolation, opts v1.UpdateOptions) (*v1alpha1.Isolation, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.Isolation, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.IsolationList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.Isolation, err error) + IsolationExpansion +} + +// isolations implements IsolationInterface +type isolations struct { + client rest.Interface + ns string +} + +// newIsolations returns a Isolations +func newIsolations(c *PolicyV1alpha1Client, namespace string) *isolations { + return &isolations{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the isolation, and returns the corresponding isolation object, and an error if there is any. +func (c *isolations) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.Isolation, err error) { + result = &v1alpha1.Isolation{} + err = c.client.Get(). + Namespace(c.ns). + Resource("isolations"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Isolations that match those selectors. +func (c *isolations) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.IsolationList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.IsolationList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("isolations"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested isolations. +func (c *isolations) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("isolations"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a isolation and creates it. Returns the server's representation of the isolation, and an error, if there is any. +func (c *isolations) Create(ctx context.Context, isolation *v1alpha1.Isolation, opts v1.CreateOptions) (result *v1alpha1.Isolation, err error) { + result = &v1alpha1.Isolation{} + err = c.client.Post(). + Namespace(c.ns). + Resource("isolations"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(isolation). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a isolation and updates it. Returns the server's representation of the isolation, and an error, if there is any. +func (c *isolations) Update(ctx context.Context, isolation *v1alpha1.Isolation, opts v1.UpdateOptions) (result *v1alpha1.Isolation, err error) { + result = &v1alpha1.Isolation{} + err = c.client.Put(). + Namespace(c.ns). + Resource("isolations"). + Name(isolation.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(isolation). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *isolations) UpdateStatus(ctx context.Context, isolation *v1alpha1.Isolation, opts v1.UpdateOptions) (result *v1alpha1.Isolation, err error) { + result = &v1alpha1.Isolation{} + err = c.client.Put(). + Namespace(c.ns). + Resource("isolations"). + Name(isolation.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(isolation). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the isolation and deletes it. Returns an error if one occurs. +func (c *isolations) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("isolations"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *isolations) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("isolations"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched isolation. +func (c *isolations) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.Isolation, err error) { + result = &v1alpha1.Isolation{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("isolations"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/policy_client.go b/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/policy_client.go index 640fe62c4..b5de4d0f0 100644 --- a/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/policy_client.go +++ b/pkg/gen/client/policy/clientset/versioned/typed/policy/v1alpha1/policy_client.go @@ -30,6 +30,7 @@ type PolicyV1alpha1Interface interface { EgressesGetter EgressGatewaysGetter IngressBackendsGetter + IsolationsGetter RetriesGetter UpstreamTrafficSettingsGetter } @@ -59,6 +60,10 @@ func (c *PolicyV1alpha1Client) IngressBackends(namespace string) IngressBackendI return newIngressBackends(c, namespace) } +func (c *PolicyV1alpha1Client) Isolations(namespace string) IsolationInterface { + return newIsolations(c, namespace) +} + func (c *PolicyV1alpha1Client) Retries(namespace string) RetryInterface { return newRetries(c, namespace) } diff --git a/pkg/gen/client/policy/informers/externalversions/generic.go b/pkg/gen/client/policy/informers/externalversions/generic.go index ed7a53f42..cd1c40564 100644 --- a/pkg/gen/client/policy/informers/externalversions/generic.go +++ b/pkg/gen/client/policy/informers/externalversions/generic.go @@ -60,6 +60,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Policy().V1alpha1().EgressGateways().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("ingressbackends"): return &genericInformer{resource: resource.GroupResource(), informer: f.Policy().V1alpha1().IngressBackends().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("isolations"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Policy().V1alpha1().Isolations().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("retries"): return &genericInformer{resource: resource.GroupResource(), informer: f.Policy().V1alpha1().Retries().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("upstreamtrafficsettings"): diff --git a/pkg/gen/client/policy/informers/externalversions/policy/v1alpha1/interface.go b/pkg/gen/client/policy/informers/externalversions/policy/v1alpha1/interface.go index 74013a9ce..d2855c4a9 100644 --- a/pkg/gen/client/policy/informers/externalversions/policy/v1alpha1/interface.go +++ b/pkg/gen/client/policy/informers/externalversions/policy/v1alpha1/interface.go @@ -31,6 +31,8 @@ type Interface interface { EgressGateways() EgressGatewayInformer // IngressBackends returns a IngressBackendInformer. IngressBackends() IngressBackendInformer + // Isolations returns a IsolationInformer. + Isolations() IsolationInformer // Retries returns a RetryInformer. Retries() RetryInformer // UpstreamTrafficSettings returns a UpstreamTrafficSettingInformer. @@ -73,6 +75,11 @@ func (v *version) IngressBackends() IngressBackendInformer { return &ingressBackendInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } +// Isolations returns a IsolationInformer. +func (v *version) Isolations() IsolationInformer { + return &isolationInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // Retries returns a RetryInformer. func (v *version) Retries() RetryInformer { return &retryInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/gen/client/policy/informers/externalversions/policy/v1alpha1/isolation.go b/pkg/gen/client/policy/informers/externalversions/policy/v1alpha1/isolation.go new file mode 100644 index 000000000..370c3544e --- /dev/null +++ b/pkg/gen/client/policy/informers/externalversions/policy/v1alpha1/isolation.go @@ -0,0 +1,87 @@ +/* +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + policyv1alpha1 "github.com/flomesh-io/fsm/pkg/apis/policy/v1alpha1" + versioned "github.com/flomesh-io/fsm/pkg/gen/client/policy/clientset/versioned" + internalinterfaces "github.com/flomesh-io/fsm/pkg/gen/client/policy/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/flomesh-io/fsm/pkg/gen/client/policy/listers/policy/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// IsolationInformer provides access to a shared informer and lister for +// Isolations. +type IsolationInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.IsolationLister +} + +type isolationInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewIsolationInformer constructs a new informer for Isolation type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewIsolationInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredIsolationInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredIsolationInformer constructs a new informer for Isolation type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredIsolationInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.PolicyV1alpha1().Isolations(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.PolicyV1alpha1().Isolations(namespace).Watch(context.TODO(), options) + }, + }, + &policyv1alpha1.Isolation{}, + resyncPeriod, + indexers, + ) +} + +func (f *isolationInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredIsolationInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *isolationInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&policyv1alpha1.Isolation{}, f.defaultInformer) +} + +func (f *isolationInformer) Lister() v1alpha1.IsolationLister { + return v1alpha1.NewIsolationLister(f.Informer().GetIndexer()) +} diff --git a/pkg/gen/client/policy/listers/policy/v1alpha1/expansion_generated.go b/pkg/gen/client/policy/listers/policy/v1alpha1/expansion_generated.go index b72e67bea..cbd9ccf1a 100644 --- a/pkg/gen/client/policy/listers/policy/v1alpha1/expansion_generated.go +++ b/pkg/gen/client/policy/listers/policy/v1alpha1/expansion_generated.go @@ -55,6 +55,14 @@ type IngressBackendListerExpansion interface{} // IngressBackendNamespaceLister. type IngressBackendNamespaceListerExpansion interface{} +// IsolationListerExpansion allows custom methods to be added to +// IsolationLister. +type IsolationListerExpansion interface{} + +// IsolationNamespaceListerExpansion allows custom methods to be added to +// IsolationNamespaceLister. +type IsolationNamespaceListerExpansion interface{} + // RetryListerExpansion allows custom methods to be added to // RetryLister. type RetryListerExpansion interface{} diff --git a/pkg/gen/client/policy/listers/policy/v1alpha1/isolation.go b/pkg/gen/client/policy/listers/policy/v1alpha1/isolation.go new file mode 100644 index 000000000..de57fb799 --- /dev/null +++ b/pkg/gen/client/policy/listers/policy/v1alpha1/isolation.go @@ -0,0 +1,96 @@ +/* +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/flomesh-io/fsm/pkg/apis/policy/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// IsolationLister helps list Isolations. +// All objects returned here must be treated as read-only. +type IsolationLister interface { + // List lists all Isolations in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.Isolation, err error) + // Isolations returns an object that can list and get Isolations. + Isolations(namespace string) IsolationNamespaceLister + IsolationListerExpansion +} + +// isolationLister implements the IsolationLister interface. +type isolationLister struct { + indexer cache.Indexer +} + +// NewIsolationLister returns a new IsolationLister. +func NewIsolationLister(indexer cache.Indexer) IsolationLister { + return &isolationLister{indexer: indexer} +} + +// List lists all Isolations in the indexer. +func (s *isolationLister) List(selector labels.Selector) (ret []*v1alpha1.Isolation, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.Isolation)) + }) + return ret, err +} + +// Isolations returns an object that can list and get Isolations. +func (s *isolationLister) Isolations(namespace string) IsolationNamespaceLister { + return isolationNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// IsolationNamespaceLister helps list and get Isolations. +// All objects returned here must be treated as read-only. +type IsolationNamespaceLister interface { + // List lists all Isolations in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.Isolation, err error) + // Get retrieves the Isolation from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.Isolation, error) + IsolationNamespaceListerExpansion +} + +// isolationNamespaceLister implements the IsolationNamespaceLister +// interface. +type isolationNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Isolations in the indexer for a given namespace. +func (s isolationNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.Isolation, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.Isolation)) + }) + return ret, err +} + +// Get retrieves the Isolation from the indexer for a given namespace and name. +func (s isolationNamespaceLister) Get(name string) (*v1alpha1.Isolation, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("isolation"), name) + } + return obj.(*v1alpha1.Isolation), nil +} diff --git a/pkg/k8s/informers/informers.go b/pkg/k8s/informers/informers.go index ad1bef046..b7d3afdea 100644 --- a/pkg/k8s/informers/informers.go +++ b/pkg/k8s/informers/informers.go @@ -162,6 +162,7 @@ func WithPolicyClient(policyClient policyClientset.Interface) InformerCollection ic.informers[InformerKeyEgressGateway] = informerFactory.Policy().V1alpha1().EgressGateways().Informer() ic.informers[InformerKeyIngressBackend] = informerFactory.Policy().V1alpha1().IngressBackends().Informer() ic.informers[InformerKeyUpstreamTrafficSetting] = informerFactory.Policy().V1alpha1().UpstreamTrafficSettings().Informer() + ic.informers[InformerKeyIsolation] = informerFactory.Policy().V1alpha1().Isolations().Informer() ic.informers[InformerKeyRetry] = informerFactory.Policy().V1alpha1().Retries().Informer() ic.informers[InformerKeyAccessControl] = informerFactory.Policy().V1alpha1().AccessControls().Informer() ic.informers[InformerKeyAccessCert] = informerFactory.Policy().V1alpha1().AccessCerts().Informer() diff --git a/pkg/k8s/informers/types.go b/pkg/k8s/informers/types.go index 892281ffb..a906752ad 100644 --- a/pkg/k8s/informers/types.go +++ b/pkg/k8s/informers/types.go @@ -44,6 +44,8 @@ const ( // InformerKeyMeshRootCertificate is the InformerKey for a MeshRootCertificate informer InformerKeyMeshRootCertificate InformerKey = "MeshRootCertificate" + // InformerKeyIsolation is the InformerKey for a Isolation informer + InformerKeyIsolation InformerKey = "Isolation" // InformerKeyEgress is the InformerKey for an Egress informer InformerKeyEgress InformerKey = "Egress" // InformerKeyEgressGateway is the InformerKey for an EgressGateway informer diff --git a/pkg/manager/listeners/client.go b/pkg/manager/listeners/client.go index d6c78a85c..c0312e4f5 100644 --- a/pkg/manager/listeners/client.go +++ b/pkg/manager/listeners/client.go @@ -153,6 +153,11 @@ func (c *client) GetLocalDNSProxySecondaryUpstream() string { panic("implement me") } +func (c *client) GenerateIPv6BasedOnIPv4() bool { + //TODO implement me + panic("implement me") +} + func (c *client) GetTracingHost() string { //TODO implement me panic("implement me") diff --git a/pkg/messaging/broker.go b/pkg/messaging/broker.go index 43133ac4c..fc9c0615d 100644 --- a/pkg/messaging/broker.go +++ b/pkg/messaging/broker.go @@ -937,6 +937,8 @@ func getProxyUpdateEvent(msg events.PubSubMessage) *proxyUpdateEvent { announcements.IngressBackendAdded, announcements.IngressBackendDeleted, announcements.IngressBackendUpdated, // AccessControl event announcements.AccessControlAdded, announcements.AccessControlDeleted, announcements.AccessControlUpdated, + // Isolation event + announcements.IsolationPolicyAdded, announcements.IsolationPolicyDeleted, announcements.IsolationPolicyUpdated, // Retry event announcements.RetryPolicyAdded, announcements.RetryPolicyDeleted, announcements.RetryPolicyUpdated, // UpstreamTrafficSetting event diff --git a/pkg/policy/client.go b/pkg/policy/client.go index b5169b578..a1f434b01 100644 --- a/pkg/policy/client.go +++ b/pkg/policy/client.go @@ -73,6 +73,13 @@ func NewPolicyController(informerCollection *informers.InformerCollection, kubeC } client.informers.AddEventHandler(informers.InformerKeyAccessCert, k8s.GetEventHandlerFuncs(shouldObserve, acertEventTypes, msgBroker)) + isolationEventTypes := k8s.EventTypes{ + Add: announcements.IsolationPolicyAdded, + Update: announcements.IsolationPolicyUpdated, + Delete: announcements.IsolationPolicyDeleted, + } + client.informers.AddEventHandler(informers.InformerKeyIsolation, k8s.GetEventHandlerFuncs(nil, isolationEventTypes, msgBroker)) + retryEventTypes := k8s.EventTypes{ Add: announcements.RetryPolicyAdded, Update: announcements.RetryPolicyUpdated, @@ -90,6 +97,17 @@ func NewPolicyController(informerCollection *informers.InformerCollection, kubeC return client } +// ListIsolationPolicies returns the Isolation policies +func (c *Client) ListIsolationPolicies() []*policyV1alpha1.Isolation { + var isolations []*policyV1alpha1.Isolation + for _, isolationIface := range c.informers.List(informers.InformerKeyIsolation) { + isolation := isolationIface.(*policyV1alpha1.Isolation) + isolations = append(isolations, isolation) + } + + return isolations +} + // ListEgressGateways lists egress gateways func (c *Client) ListEgressGateways() []*policyV1alpha1.EgressGateway { var egressGateways []*policyV1alpha1.EgressGateway diff --git a/pkg/policy/mock_client_generated.go b/pkg/policy/mock_client_generated.go index a2ef37025..705c9b78f 100644 --- a/pkg/policy/mock_client_generated.go +++ b/pkg/policy/mock_client_generated.go @@ -122,6 +122,20 @@ func (mr *MockControllerMockRecorder) ListEgressPoliciesForSourceIdentity(arg0 i return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListEgressPoliciesForSourceIdentity", reflect.TypeOf((*MockController)(nil).ListEgressPoliciesForSourceIdentity), arg0) } +// ListIsolationPolicies mocks base method. +func (m *MockController) ListIsolationPolicies() []*v1alpha1.Isolation { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListIsolationPolicies") + ret0, _ := ret[0].([]*v1alpha1.Isolation) + return ret0 +} + +// ListIsolationPolicies indicates an expected call of ListIsolationPolicies. +func (mr *MockControllerMockRecorder) ListIsolationPolicies() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListIsolationPolicies", reflect.TypeOf((*MockController)(nil).ListIsolationPolicies)) +} + // ListRetryPolicies mocks base method. func (m *MockController) ListRetryPolicies(arg0 identity.K8sServiceAccount) []*v1alpha1.Retry { m.ctrl.T.Helper() diff --git a/pkg/policy/types.go b/pkg/policy/types.go index 2eff1c8be..06769eab5 100644 --- a/pkg/policy/types.go +++ b/pkg/policy/types.go @@ -28,6 +28,9 @@ type Client struct { // Controller is the interface for the functionality provided by the resources part of the policy.flomesh.io API group type Controller interface { + // ListIsolationPolicies returns the Isolation policies + ListIsolationPolicies() []*policyv1alpha1.Isolation + // ListEgressGateways lists Egress gateways ListEgressGateways() []*policyv1alpha1.EgressGateway diff --git a/pkg/sidecar/providers/pipy/repo/codebase/dns-main.js b/pkg/sidecar/providers/pipy/repo/codebase/dns-main.js index 284739a5a..788334e55 100644 --- a/pkg/sidecar/providers/pipy/repo/codebase/dns-main.js +++ b/pkg/sidecar/providers/pipy/repo/codebase/dns-main.js @@ -14,17 +14,17 @@ rrv6 = [], v.map( ip => ( - rr.push({ + new IP(ip).version === 4 ? rr.push({ 'name': k, 'type': 'A', 'ttl': 600, // TTL : 10 minutes 'rdata': ip - }), + }) : rrv6.push({ 'name': k, 'type': 'AAAA', 'ttl': 600, // TTL : 10 minutes - 'rdata': '00000000000000000000ffff' + ip.split('.').reduce((result, item) => (result += (n => '0123456789abcdef'.charAt(n / 16) + '0123456789abcdef'.charAt(n % 16))(Number.parseInt(item) % 256)), '') + 'rdata': ip }) ) ), diff --git a/pkg/sidecar/providers/pipy/repo/codebase/modules/outbound-http-routing.js b/pkg/sidecar/providers/pipy/repo/codebase/modules/outbound-http-routing.js index 83f2c86f8..fd591231c 100644 --- a/pkg/sidecar/providers/pipy/repo/codebase/modules/outbound-http-routing.js +++ b/pkg/sidecar/providers/pipy/repo/codebase/modules/outbound-http-routing.js @@ -1,5 +1,6 @@ (( config = pipy.solve('config.js'), + specServiceIdentity = config?.Spec?.ServiceIdentity, { shuffle, failover, @@ -72,7 +73,7 @@ (method, path, headers) => void ( tree[method]?.find?.(rule => rule(path, headers)), __service && ( - headers['serviceidentity'] = __service.ServiceIdentity + headers['serviceidentity'] = specServiceIdentity ) ) ) diff --git a/pkg/sidecar/providers/pipy/repo/jobs.go b/pkg/sidecar/providers/pipy/repo/jobs.go index a6b0fb04f..19e2bc532 100644 --- a/pkg/sidecar/providers/pipy/repo/jobs.go +++ b/pkg/sidecar/providers/pipy/repo/jobs.go @@ -18,12 +18,12 @@ import ( "github.com/flomesh-io/fsm/pkg/connector" "github.com/flomesh-io/fsm/pkg/connector/ctok" "github.com/flomesh-io/fsm/pkg/errcode" - "github.com/flomesh-io/fsm/pkg/identity" "github.com/flomesh-io/fsm/pkg/injector" "github.com/flomesh-io/fsm/pkg/k8s" "github.com/flomesh-io/fsm/pkg/service" "github.com/flomesh-io/fsm/pkg/sidecar/providers/pipy" "github.com/flomesh-io/fsm/pkg/sidecar/providers/pipy/client" + "github.com/flomesh-io/fsm/pkg/utils" ) // PipyConfGeneratorJob is the job to generate pipy policy json @@ -95,10 +95,10 @@ func (job *PipyConfGeneratorJob) Run() { features(s, proxy, pipyConf) certs(s, proxy, pipyConf, proxyServices) plugin(cataloger, s, pipyConf, proxy) - inbound(cataloger, proxy.Identity, s, pipyConf, proxyServices, proxy) - outbound(cataloger, proxy.Identity, s, pipyConf, proxy, s.cfg, desiredSuffix) - egress(cataloger, proxy.Identity, s, pipyConf, proxy, desiredSuffix) - forward(cataloger, proxy.Identity, s, pipyConf, proxy) + inbound(cataloger, s, pipyConf, proxyServices, proxy) + outbound(cataloger, s, pipyConf, proxy, s.cfg, desiredSuffix) + egress(cataloger, s, pipyConf, proxy, desiredSuffix) + forward(cataloger, s, pipyConf, proxy) cloudConnector(cataloger, pipyConf, s.cfg, proxy) balance(pipyConf) reorder(pipyConf) @@ -148,8 +148,8 @@ func reorder(pipyConf *PipyConf) { } } -func egress(cataloger catalog.MeshCataloger, serviceIdentity identity.ServiceIdentity, s *Server, pipyConf *PipyConf, proxy *pipy.Proxy, desiredSuffix string) bool { - egressTrafficPolicy, egressErr := cataloger.GetEgressTrafficPolicy(serviceIdentity) +func egress(cataloger catalog.MeshCataloger, s *Server, pipyConf *PipyConf, proxy *pipy.Proxy, desiredSuffix string) bool { + egressTrafficPolicy, egressErr := cataloger.GetEgressTrafficPolicy(proxy.Identity) if egressErr != nil { if s.retryProxiesJob != nil { s.retryProxiesJob() @@ -158,11 +158,9 @@ func egress(cataloger catalog.MeshCataloger, serviceIdentity identity.ServiceIde } if egressTrafficPolicy != nil { - egressDependClusters := generatePipyEgressTrafficRoutePolicy(cataloger, serviceIdentity, pipyConf, - egressTrafficPolicy, desiredSuffix) + egressDependClusters := generatePipyEgressTrafficRoutePolicy(cataloger, pipyConf, egressTrafficPolicy, desiredSuffix) if len(egressDependClusters) > 0 { - if ready := generatePipyEgressTrafficBalancePolicy(cataloger, proxy, serviceIdentity, pipyConf, - egressTrafficPolicy, egressDependClusters); !ready { + if ready := generatePipyEgressTrafficBalancePolicy(cataloger, proxy, pipyConf, egressTrafficPolicy, egressDependClusters); !ready { if s.retryProxiesJob != nil { s.retryProxiesJob() } @@ -173,7 +171,7 @@ func egress(cataloger catalog.MeshCataloger, serviceIdentity identity.ServiceIde return true } -func forward(cataloger catalog.MeshCataloger, serviceIdentity identity.ServiceIdentity, s *Server, pipyConf *PipyConf, _ *pipy.Proxy) bool { +func forward(cataloger catalog.MeshCataloger, s *Server, pipyConf *PipyConf, _ *pipy.Proxy) bool { egressGatewayPolicy, egressErr := cataloger.GetEgressGatewayPolicy() if egressErr != nil { if s.retryProxiesJob != nil { @@ -182,8 +180,7 @@ func forward(cataloger catalog.MeshCataloger, serviceIdentity identity.ServiceId return false } if egressGatewayPolicy != nil { - if ready := generatePipyEgressTrafficForwardPolicy(cataloger, serviceIdentity, pipyConf, - egressGatewayPolicy); !ready { + if ready := generatePipyEgressTrafficForwardPolicy(cataloger, pipyConf, egressGatewayPolicy); !ready { if s.retryProxiesJob != nil { s.retryProxiesJob() } @@ -193,22 +190,28 @@ func forward(cataloger catalog.MeshCataloger, serviceIdentity identity.ServiceId return true } -func outbound(cataloger catalog.MeshCataloger, serviceIdentity identity.ServiceIdentity, s *Server, pipyConf *PipyConf, proxy *pipy.Proxy, cfg configurator.Configurator, desiredSuffix string) bool { - outboundTrafficPolicy := cataloger.GetOutboundMeshTrafficPolicy(serviceIdentity) +func outbound(cataloger catalog.MeshCataloger, s *Server, pipyConf *PipyConf, proxy *pipy.Proxy, cfg configurator.Configurator, desiredSuffix string) bool { + outboundTrafficPolicy := cataloger.GetOutboundMeshTrafficPolicy(proxy.Identity) if cfg.IsLocalDNSProxyEnabled() && !cfg.IsWildcardDNSProxyEnabled() { if len(outboundTrafficPolicy.ServicesResolvableSet) > 0 { if pipyConf.DNSResolveDB == nil { - pipyConf.DNSResolveDB = make(map[string][]interface{}) + pipyConf.DNSResolveDB = make(map[string][]string) } - for k, v := range outboundTrafficPolicy.ServicesResolvableSet { - pipyConf.DNSResolveDB[k] = v + for dn, ipv4s := range outboundTrafficPolicy.ServicesResolvableSet { + ipAddrs := make([]string, 0) + for _, ipv4 := range ipv4s { + ipAddrs = append(ipAddrs, ipv4.(string)) + if cfg.GenerateIPv6BasedOnIPv4() { + ipAddrs = append(ipAddrs, utils.IPv4Tov6(ipv4.(string))) + } + } + pipyConf.DNSResolveDB[dn] = ipAddrs } } } - outboundDependClusters := generatePipyOutboundTrafficRoutePolicy(cataloger, serviceIdentity, pipyConf, - cfg, outboundTrafficPolicy, desiredSuffix) + outboundDependClusters := generatePipyOutboundTrafficRoutePolicy(cataloger, pipyConf, cfg, outboundTrafficPolicy, desiredSuffix) if len(outboundDependClusters) > 0 { - if ready := generatePipyOutboundTrafficBalancePolicy(cataloger, cfg, proxy, serviceIdentity, pipyConf, + if ready := generatePipyOutboundTrafficBalancePolicy(cataloger, cfg, proxy, pipyConf, outboundTrafficPolicy, outboundDependClusters); !ready { if s.retryProxiesJob != nil { s.retryProxiesJob() @@ -219,28 +222,34 @@ func outbound(cataloger catalog.MeshCataloger, serviceIdentity identity.ServiceI return true } -func inbound(cataloger catalog.MeshCataloger, serviceIdentity identity.ServiceIdentity, s *Server, pipyConf *PipyConf, proxyServices []service.MeshService, proxy *pipy.Proxy) { +func inbound(cataloger catalog.MeshCataloger, s *Server, pipyConf *PipyConf, proxyServices []service.MeshService, proxy *pipy.Proxy) { // Build inbound mesh route configurations. These route configurations allow // the services associated with this proxy to accept traffic from downstream // clients on allowed routes. - inboundTrafficPolicy := cataloger.GetInboundMeshTrafficPolicy(serviceIdentity, proxyServices) - generatePipyInboundTrafficPolicy(cataloger, serviceIdentity, pipyConf, inboundTrafficPolicy, s.certManager.GetTrustDomain(), proxy) + inboundTrafficPolicy := cataloger.GetInboundMeshTrafficPolicy(proxy.Identity, proxyServices) + generatePipyInboundTrafficPolicy(cataloger, pipyConf, inboundTrafficPolicy, s.certManager.GetTrustDomain(), proxy) if len(proxyServices) > 0 { for _, svc := range proxyServices { if ingressTrafficPolicy, ingressErr := cataloger.GetIngressTrafficPolicy(svc); ingressErr == nil { if ingressTrafficPolicy != nil { - generatePipyIngressTrafficRoutePolicy(cataloger, serviceIdentity, pipyConf, ingressTrafficPolicy) + generatePipyIngressTrafficRoutePolicy(cataloger, pipyConf, ingressTrafficPolicy) } + } else { + log.Error().Err(ingressErr).Msg(ingressErr.Error()) } if aclTrafficPolicy, aclErr := cataloger.GetAccessControlTrafficPolicy(svc); aclErr == nil { if aclTrafficPolicy != nil { - generatePipyAccessControlTrafficRoutePolicy(cataloger, serviceIdentity, pipyConf, aclTrafficPolicy) + generatePipyAccessControlTrafficRoutePolicy(cataloger, pipyConf, aclTrafficPolicy) } + } else { + log.Error().Err(aclErr).Msg(aclErr.Error()) } if expTrafficPolicy, expErr := cataloger.GetExportTrafficPolicy(svc); expErr == nil { if expTrafficPolicy != nil { - generatePipyServiceExportTrafficRoutePolicy(cataloger, serviceIdentity, pipyConf, expTrafficPolicy) + generatePipyServiceExportTrafficRoutePolicy(cataloger, pipyConf, expTrafficPolicy) } + } else { + log.Error().Err(expErr).Msg(expErr.Error()) } } } @@ -356,6 +365,7 @@ func features(s *Server, proxy *pipy.Proxy, pipyConf *PipyConf) { if mc, ok := s.catalog.(*catalog.MeshCatalog); ok { meshConf := mc.GetConfigurator() proxy.MeshConf = meshConf + pipyConf.setServiceIdentity(proxy.Identity) pipyConf.setSidecarLogLevel((*meshConf).GetMeshConfig().Spec.Sidecar.LogLevel) pipyConf.setSidecarTimeout((*meshConf).GetMeshConfig().Spec.Sidecar.SidecarTimeout) pipyConf.setEnableSidecarActiveHealthChecks((*meshConf).GetFeatureFlags().EnableSidecarActiveHealthChecks) @@ -416,7 +426,7 @@ func cloudConnector(cataloger catalog.MeshCataloger, pipyConf *PipyConf, cfg con } if len(svc.Annotations) > 0 { if pipyConf.DNSResolveDB == nil { - pipyConf.DNSResolveDB = make(map[string][]interface{}) + pipyConf.DNSResolveDB = make(map[string][]string) } resolvableIPSet := mapset.NewSet() if v, exists := svc.Annotations[connector.AnnotationMeshEndpointAddr]; exists { @@ -433,13 +443,21 @@ func cloudConnector(cataloger catalog.MeshCataloger, pipyConf *PipyConf, cfg con } } } - addrItems := resolvableIPSet.ToSlice() - sort.SliceStable(addrItems, func(i, j int) bool { - addr1 := addrItems[i].(string) - addr2 := addrItems[j].(string) + ipv4s := resolvableIPSet.ToSlice() + sort.SliceStable(ipv4s, func(i, j int) bool { + addr1 := ipv4s[i].(string) + addr2 := ipv4s[j].(string) return addr1 < addr2 }) - pipyConf.DNSResolveDB[fmt.Sprintf("%s.%s.svc.%s", svc.Name, proxy.Metadata.Namespace, service.GetTrustDomain())] = addrItems + ipAddrs := make([]string, 0) + for _, ipv4 := range ipv4s { + ipAddrs = append(ipAddrs, ipv4.(string)) + if cfg.GenerateIPv6BasedOnIPv4() { + ipAddrs = append(ipAddrs, utils.IPv4Tov6(ipv4.(string))) + } + } + dn := fmt.Sprintf("%s.%s.svc.%s", svc.Name, proxy.Metadata.Namespace, service.GetTrustDomain()) + pipyConf.DNSResolveDB[dn] = ipAddrs delete(pipyConf.DNSResolveDB, svc.Name) } } @@ -451,24 +469,30 @@ func dnsResolveDB(pipyConf *PipyConf, cfg configurator.Configurator) { return } if pipyConf.DNSResolveDB == nil { - pipyConf.DNSResolveDB = make(map[string][]interface{}) + pipyConf.DNSResolveDB = make(map[string][]string) } dnsProxy := cfg.GetMeshConfig().Spec.Sidecar.LocalDNSProxy if cfg.IsWildcardDNSProxyEnabled() { - ipv4s := make([]interface{}, 0) - for _, ipv4 := range dnsProxy.Wildcard.IPv4 { - ipv4s = append(ipv4s, ipv4) + ipAddrs := make([]string, 0) + for _, ipAddr := range dnsProxy.Wildcard.IPs { + ipAddrs = append(ipAddrs, ipAddr.IPv4) + if len(ipAddr.IPv6) == 0 && cfg.GenerateIPv6BasedOnIPv4() { + ipAddrs = append(ipAddrs, utils.IPv4Tov6(ipAddr.IPv4)) + } } - pipyConf.DNSResolveDB["*"] = ipv4s + pipyConf.DNSResolveDB["*"] = ipAddrs } else { if len(dnsProxy.DB) > 0 { for _, db := range dnsProxy.DB { - if len(db.IPv4) > 0 { - ipv4s := make([]interface{}, 0) - for _, ipv4 := range db.IPv4 { - ipv4s = append(ipv4s, ipv4) + if len(db.IPs) > 0 { + ipAddrs := make([]string, 0) + for _, ipAddr := range db.IPs { + ipAddrs = append(ipAddrs, ipAddr.IPv4) + if len(ipAddr.IPv6) == 0 && cfg.GenerateIPv6BasedOnIPv4() { + ipAddrs = append(ipAddrs, utils.IPv4Tov6(ipAddr.IPv4)) + } } - pipyConf.DNSResolveDB[db.DN] = ipv4s + pipyConf.DNSResolveDB[db.DN] = ipAddrs } } } diff --git a/pkg/sidecar/providers/pipy/repo/policy.go b/pkg/sidecar/providers/pipy/repo/policy.go index dd8688f12..229018cdd 100644 --- a/pkg/sidecar/providers/pipy/repo/policy.go +++ b/pkg/sidecar/providers/pipy/repo/policy.go @@ -29,6 +29,13 @@ func (plugin *Pluggable) setPlugins(plugins map[string]*runtime.RawExtension) { plugin.Plugins = plugins } +func (p *PipyConf) setServiceIdentity(serviceIdentity identity.ServiceIdentity) (update bool) { + if update = p.Spec.ServiceIdentity != serviceIdentity; update { + p.Spec.ServiceIdentity = serviceIdentity + } + return +} + func (p *PipyConf) setSidecarLogLevel(sidecarLogLevel string) (update bool) { if update = !strings.EqualFold(p.Spec.SidecarLogLevel, sidecarLogLevel); update { p.Spec.SidecarLogLevel = sidecarLogLevel @@ -295,7 +302,15 @@ func (p *PipyConf) copyAllowedEndpoints(kubeController k8s.Controller, proxyRegi } func (p *PipyConf) hashName(hash uint64) HTTPRouteRuleName { - return HTTPRouteRuleName(fmt.Sprintf("%X", hash)) + if p.hashNameSet == nil { + p.hashNameSet = make(map[uint64]int) + } + flowcode, exists := p.hashNameSet[hash] + if !exists { + flowcode = len(p.hashNameSet) + 1 + p.hashNameSet[hash] = flowcode + } + return HTTPRouteRuleName(fmt.Sprintf("%05X", flowcode)) } func (p *PipyConf) Pack() { @@ -719,10 +734,6 @@ func (hrrs *InboundHTTPRouteRules) newHTTPServiceRouteRule(matchRule *HTTPMatchR return routeRule, false } -func (hrrs *OutboundHTTPRouteRules) setServiceIdentity(serviceIdentity identity.ServiceIdentity) { - hrrs.ServiceIdentity = serviceIdentity -} - func (hrrs *OutboundHTTPRouteRules) newHTTPServiceRouteRule(matchRule *HTTPMatchRule) (route *OutboundHTTPRouteRule, duplicate bool) { for _, routeRule := range hrrs.RouteRules { if reflect.DeepEqual(*matchRule, routeRule.HTTPMatchRule) { diff --git a/pkg/sidecar/providers/pipy/repo/types.go b/pkg/sidecar/providers/pipy/repo/types.go index cf682e744..37f8da614 100644 --- a/pkg/sidecar/providers/pipy/repo/types.go +++ b/pkg/sidecar/providers/pipy/repo/types.go @@ -253,6 +253,7 @@ type ObservabilitySpec struct { // MeshConfigSpec represents the spec of mesh config type MeshConfigSpec struct { + ServiceIdentity identity.ServiceIdentity SidecarLogLevel string SidecarTimeout int Traffic TrafficSpec @@ -364,8 +365,7 @@ type OutboundHTTPRouteRuleSlice []*OutboundHTTPRouteRule // OutboundHTTPRouteRules is a wrapper type type OutboundHTTPRouteRules struct { RouteRules OutboundHTTPRouteRuleSlice `json:"RouteRules"` - ServiceIdentity identity.ServiceIdentity - EgressForwardGateway *string `json:"EgressForwardGateway,omitempty"` + EgressForwardGateway *string `json:"EgressForwardGateway,omitempty"` Pluggable } @@ -551,13 +551,14 @@ type PipyConf struct { Metrics bool Spec MeshConfigSpec Certificate *Certificate - Inbound *InboundTrafficPolicy `json:"Inbound"` - Outbound *OutboundTrafficPolicy `json:"Outbound"` - Forward *ForwardTrafficPolicy `json:"Forward,omitempty"` - AllowedEndpoints map[string]string `json:"AllowedEndpoints"` - Chains map[string][]string `json:"Chains,omitempty"` - DNSResolveDB map[string][]interface{} `json:"DNSResolveDB,omitempty"` + Inbound *InboundTrafficPolicy `json:"Inbound"` + Outbound *OutboundTrafficPolicy `json:"Outbound"` + Forward *ForwardTrafficPolicy `json:"Forward,omitempty"` + AllowedEndpoints map[string]string `json:"AllowedEndpoints"` + Chains map[string][]string `json:"Chains,omitempty"` + DNSResolveDB map[string][]string `json:"DNSResolveDB,omitempty"` PluginSetV string `json:"-"` pluginPolicies map[string]map[string]*map[string]*runtime.RawExtension + hashNameSet map[uint64]int } diff --git a/pkg/sidecar/providers/pipy/repo/util.go b/pkg/sidecar/providers/pipy/repo/util.go index c2448f876..352e6584b 100644 --- a/pkg/sidecar/providers/pipy/repo/util.go +++ b/pkg/sidecar/providers/pipy/repo/util.go @@ -23,7 +23,7 @@ import ( "github.com/flomesh-io/fsm/pkg/utils" ) -func generatePipyInboundTrafficPolicy(meshCatalog catalog.MeshCataloger, _ identity.ServiceIdentity, pipyConf *PipyConf, inboundPolicy *trafficpolicy.InboundMeshTrafficPolicy, trustDomain string, proxy *pipy.Proxy) { +func generatePipyInboundTrafficPolicy(meshCatalog catalog.MeshCataloger, pipyConf *PipyConf, inboundPolicy *trafficpolicy.InboundMeshTrafficPolicy, trustDomain string, proxy *pipy.Proxy) { itp := pipyConf.newInboundTrafficPolicy() for _, trafficMatch := range inboundPolicy.TrafficMatches { @@ -131,7 +131,9 @@ func generatePipyInboundTrafficPolicy(meshCatalog catalog.MeshCataloger, _ ident } } -func generatePipyOutboundTrafficRoutePolicy(_ catalog.MeshCataloger, proxyIdentity identity.ServiceIdentity, pipyConf *PipyConf, cfg configurator.Configurator, outboundPolicy *trafficpolicy.OutboundMeshTrafficPolicy, desiredSuffix string) map[service.ClusterName]*WeightedCluster { +func generatePipyOutboundTrafficRoutePolicy(_ catalog.MeshCataloger, pipyConf *PipyConf, cfg configurator.Configurator, + outboundPolicy *trafficpolicy.OutboundMeshTrafficPolicy, + desiredSuffix string) map[service.ClusterName]*WeightedCluster { if len(outboundPolicy.TrafficMatches) == 0 { return nil } @@ -169,7 +171,6 @@ func generatePipyOutboundTrafficRoutePolicy(_ catalog.MeshCataloger, proxyIdenti for _, httpRouteConfig := range httpRouteConfigs { ruleRef := &HTTPRouteRuleRef{RuleName: HTTPRouteRuleName(httpRouteConfig.Name)} hsrrs := tm.newHTTPServiceRouteRules(ruleRef) - hsrrs.setServiceIdentity(proxyIdentity) hsrrs.setPlugins(pipyConf.getTrafficMatchPluginConfigs(trafficMatch.Name)) for _, hostname := range httpRouteConfig.Hostnames { tm.addHTTPHostPort2Service(HTTPHostPort(hostname), ruleRef, desiredSuffix) @@ -273,15 +274,17 @@ func generatePipyWildcardIPRanges(cfg configurator.Configurator) []string { if cfg.IsLocalDNSProxyEnabled() { dnsProxy := cfg.GetMeshConfig().Spec.Sidecar.LocalDNSProxy if cfg.IsWildcardDNSProxyEnabled() { - for _, ipv4 := range dnsProxy.Wildcard.IPv4 { - wildcardIPv4 = append(wildcardIPv4, fmt.Sprintf("%s/32", ipv4)) + for _, ipAddr := range dnsProxy.Wildcard.IPs { + if len(ipAddr.IPv4) > 0 { + wildcardIPv4 = append(wildcardIPv4, fmt.Sprintf("%s/32", ipAddr.IPv4)) + } } } } return wildcardIPv4 } -func generatePipyEgressTrafficRoutePolicy(meshCatalog catalog.MeshCataloger, _ identity.ServiceIdentity, pipyConf *PipyConf, egressPolicy *trafficpolicy.EgressTrafficPolicy, desiredSuffix string) map[service.ClusterName]*WeightedCluster { +func generatePipyEgressTrafficRoutePolicy(meshCatalog catalog.MeshCataloger, pipyConf *PipyConf, egressPolicy *trafficpolicy.EgressTrafficPolicy, desiredSuffix string) map[service.ClusterName]*WeightedCluster { if len(egressPolicy.TrafficMatches) == 0 { return nil } @@ -414,8 +417,7 @@ func getEgressClusterDestinationSpec(meshCatalog catalog.MeshCataloger, egressPo } func generatePipyOutboundTrafficBalancePolicy(meshCatalog catalog.MeshCataloger, cfg configurator.Configurator, - proxy *pipy.Proxy, proxyIdentity identity.ServiceIdentity, - pipyConf *PipyConf, outboundPolicy *trafficpolicy.OutboundMeshTrafficPolicy, + proxy *pipy.Proxy, pipyConf *PipyConf, outboundPolicy *trafficpolicy.OutboundMeshTrafficPolicy, dependClusters map[service.ClusterName]*WeightedCluster) bool { ready := true viaGateway := cfg.GetMeshConfig().Spec.Connector.ViaGateway @@ -440,7 +442,7 @@ func generatePipyOutboundTrafficBalancePolicy(meshCatalog catalog.MeshCataloger, } for _, clusterConfig := range meshClusterConfigs { clusterConfigs := otp.newClusterConfigs(ClusterName(cluster.ClusterName.String())) - upstreamEndpoints := getUpstreamEndpoints(meshCatalog, proxyIdentity, service.ClusterName(clusterConfig.Service.ClusterName())) + upstreamEndpoints := getUpstreamEndpoints(meshCatalog, proxy.Identity, service.ClusterName(clusterConfig.Service.ClusterName())) if len(upstreamEndpoints) == 0 { ready = false continue @@ -517,7 +519,7 @@ func generatePipyViaGateway(appProtocol, clusterID string, proxy *pipy.Proxy, vi return viaGw } -func generatePipyIngressTrafficRoutePolicy(_ catalog.MeshCataloger, _ identity.ServiceIdentity, pipyConf *PipyConf, ingressPolicy *trafficpolicy.IngressTrafficPolicy) { +func generatePipyIngressTrafficRoutePolicy(_ catalog.MeshCataloger, pipyConf *PipyConf, ingressPolicy *trafficpolicy.IngressTrafficPolicy) { if len(ingressPolicy.TrafficMatches) == 0 { return } @@ -619,7 +621,7 @@ func generatePipyIngressTrafficRoutePolicy(_ catalog.MeshCataloger, _ identity.S } } -func generatePipyEgressTrafficForwardPolicy(_ catalog.MeshCataloger, _ identity.ServiceIdentity, pipyConf *PipyConf, egressGatewayPolicy *trafficpolicy.EgressGatewayPolicy) bool { +func generatePipyEgressTrafficForwardPolicy(_ catalog.MeshCataloger, pipyConf *PipyConf, egressGatewayPolicy *trafficpolicy.EgressGatewayPolicy) bool { if egressGatewayPolicy == nil || (egressGatewayPolicy.Global == nil && (egressGatewayPolicy.Rules == nil || len(egressGatewayPolicy.Rules) == 0)) { return true } @@ -675,7 +677,7 @@ func generatePipyEgressTrafficForwardPolicy(_ catalog.MeshCataloger, _ identity. return success } -func generatePipyAccessControlTrafficRoutePolicy(_ catalog.MeshCataloger, _ identity.ServiceIdentity, pipyConf *PipyConf, aclPolicy *trafficpolicy.AccessControlTrafficPolicy) { +func generatePipyAccessControlTrafficRoutePolicy(_ catalog.MeshCataloger, pipyConf *PipyConf, aclPolicy *trafficpolicy.AccessControlTrafficPolicy) { if len(aclPolicy.TrafficMatches) == 0 { return } @@ -777,7 +779,7 @@ func generatePipyAccessControlTrafficRoutePolicy(_ catalog.MeshCataloger, _ iden } } -func generatePipyServiceExportTrafficRoutePolicy(_ catalog.MeshCataloger, _ identity.ServiceIdentity, pipyConf *PipyConf, expPolicy *trafficpolicy.ServiceExportTrafficPolicy) { +func generatePipyServiceExportTrafficRoutePolicy(_ catalog.MeshCataloger, pipyConf *PipyConf, expPolicy *trafficpolicy.ServiceExportTrafficPolicy) { if len(expPolicy.TrafficMatches) == 0 { return } @@ -876,7 +878,7 @@ func generatePipyServiceExportTrafficRoutePolicy(_ catalog.MeshCataloger, _ iden } } -func generatePipyEgressTrafficBalancePolicy(meshCatalog catalog.MeshCataloger, _ *pipy.Proxy, serviceIdentity identity.ServiceIdentity, pipyConf *PipyConf, egressPolicy *trafficpolicy.EgressTrafficPolicy, dependClusters map[service.ClusterName]*WeightedCluster) bool { +func generatePipyEgressTrafficBalancePolicy(meshCatalog catalog.MeshCataloger, proxy *pipy.Proxy, pipyConf *PipyConf, egressPolicy *trafficpolicy.EgressTrafficPolicy, dependClusters map[service.ClusterName]*WeightedCluster) bool { ready := true otp := pipyConf.newOutboundTrafficPolicy() for _, cluster := range dependClusters { @@ -922,7 +924,7 @@ func generatePipyEgressTrafficBalancePolicy(meshCatalog catalog.MeshCataloger, _ if cluster.RetryPolicy != nil { clusterConfigs.setRetryPolicy(cluster.RetryPolicy) } else if upstreamSvc, err := hostToMeshSvc(cluster.ClusterName.String()); err == nil { - if retryPolicy := meshCatalog.GetRetryPolicy(serviceIdentity, upstreamSvc); retryPolicy != nil { + if retryPolicy := meshCatalog.GetRetryPolicy(proxy.Identity, upstreamSvc); retryPolicy != nil { clusterConfigs.setRetryPolicy(retryPolicy) } } diff --git a/pkg/utils/cidr/cidr.go b/pkg/utils/cidr/cidr.go index 4a2289a76..af3949e77 100644 --- a/pkg/utils/cidr/cidr.go +++ b/pkg/utils/cidr/cidr.go @@ -56,6 +56,11 @@ func (c CIDR) Contains(ip string) bool { return c.ipnet.Contains(net.ParseIP(ip)) } +// Has reports whether the CIDR includes ip +func (c CIDR) Has(ip net.IP) bool { + return c.ipnet.Contains(ip) +} + // CIDR returns the CIDR string. If the IP prefix of the input CIDR string is inaccurate, it returns the string which be corrected by the mask length. For example, "192.0.2.10/24" return "192.0.2.0/24" func (c CIDR) CIDR() string { return c.ipnet.String() diff --git a/pkg/utils/ip2int.go b/pkg/utils/ipconv.go similarity index 57% rename from pkg/utils/ip2int.go rename to pkg/utils/ipconv.go index f3534afd2..a1e4f98b8 100644 --- a/pkg/utils/ip2int.go +++ b/pkg/utils/ipconv.go @@ -4,6 +4,8 @@ import ( "encoding/binary" "math/big" "net" + "net/netip" + "strings" ) // IP2Int converts ip addr to int. @@ -26,3 +28,15 @@ func Int2IP16(nn uint64) net.IP { binary.BigEndian.PutUint64(ip, nn) return ip } + +func IPv4Tov6(ipv41 string) string { + var ipv6 [net.IPv6len]byte + ipv4 := net.ParseIP(ipv41) + + copy(ipv6[:], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}) + copy(ipv6[12:], ipv4.To4()) + + str := netip.AddrFrom16(ipv6).StringExpanded() + + return strings.Replace(str, "0000:0000:0000:0000:0000:ffff", "::ffff", 1) +} diff --git a/pkg/utils/util.go b/pkg/utils/util.go index 0744bc76e..9ea3279fc 100644 --- a/pkg/utils/util.go +++ b/pkg/utils/util.go @@ -1,13 +1,8 @@ package utils import ( - "bytes" - "crypto/rand" - "encoding/gob" "fmt" "hash/adler32" - "hash/fnv" - "io" "github.com/mitchellh/hashstructure/v2" corev1 "k8s.io/api/core/v1" @@ -26,36 +21,6 @@ func SimpleHash(obj interface{}) string { return fmt.Sprintf("%x", hash) } -//func Hash(data []byte) string { -// return fmt.Sprintf("%x", sha256.Sum256(data)) -//} - -// GetBytes returns the bytes of the given object. -func GetBytes(key interface{}) ([]byte, error) { - var buf bytes.Buffer - enc := gob.NewEncoder(&buf) - err := enc.Encode(key) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// HashFNV returns a hash string of the given string. -func HashFNV(s string) string { - hasher := fnv.New32a() - // Hash.Write never returns an error - _, _ = hasher.Write([]byte(s)) - return fmt.Sprintf("%x", hasher.Sum(nil)) -} - -// GenerateRandom generates random string. -func GenerateRandom(n int) string { - b := make([]byte, 8) - _, _ = io.ReadFull(rand.Reader, b) - return fmt.Sprintf("%x", b)[:n] -} - // GetSecretDataHash returns a hash of the given secret data. func GetSecretDataHash(secret *corev1.Secret) uint32 { secretDataHasher := adler32.New()