From 941941f164e09bf5a439496fc22ff89807b1cdb8 Mon Sep 17 00:00:00 2001 From: Wenqi Qiu Date: Tue, 27 Jun 2023 16:50:55 +0800 Subject: [PATCH] Promote Egress API to v1beta1 Signed-off-by: Wenqi Qiu --- build/charts/antrea/crds/egress.yaml | 116 +++++++++ build/yamls/antrea-aks.yml | 116 +++++++++ build/yamls/antrea-crds.yml | 116 +++++++++ build/yamls/antrea-eks.yml | 116 +++++++++ build/yamls/antrea-gke.yml | 116 +++++++++ build/yamls/antrea-ipsec.yml | 116 +++++++++ build/yamls/antrea.yml | 116 +++++++++ cmd/antrea-agent/agent.go | 2 +- cmd/antrea-controller/controller.go | 2 +- docs/api.md | 29 ++- docs/egress.md | 10 +- .../controller/egress/egress_controller.go | 28 +- .../egress/egress_controller_test.go | 206 +++++++-------- pkg/agent/controller/egress/ip_scheduler.go | 18 +- .../controller/egress/ip_scheduler_test.go | 44 ++-- pkg/agent/memberlist/cluster_test.go | 33 +-- pkg/apis/crd/v1beta1/register.go | 2 + pkg/apis/crd/v1beta1/types.go | 77 ++++++ pkg/apis/crd/v1beta1/zz_generated.deepcopy.go | 136 ++++++++++ pkg/apiserver/openapi/zz_generated.openapi.go | 243 ++++++++++++++++++ .../versioned/typed/crd/v1beta1/crd_client.go | 7 +- .../versioned/typed/crd/v1beta1/egress.go | 182 +++++++++++++ .../typed/crd/v1beta1/fake/fake_crd_client.go | 6 +- .../typed/crd/v1beta1/fake/fake_egress.go | 131 ++++++++++ .../typed/crd/v1beta1/generated_expansion.go | 4 +- .../externalversions/crd/v1alpha2/egress.go | 4 +- .../externalversions/crd/v1beta1/egress.go | 87 +++++++ .../externalversions/crd/v1beta1/interface.go | 9 +- .../informers/externalversions/generic.go | 4 +- pkg/client/listers/crd/v1beta1/egress.go | 66 +++++ .../crd/v1beta1/expansion_generated.go | 6 +- pkg/controller/egress/controller.go | 26 +- pkg/controller/egress/controller_test.go | 121 ++++----- test/e2e/egress_test.go | 51 ++-- 34 files changed, 2055 insertions(+), 291 deletions(-) create mode 100644 pkg/client/clientset/versioned/typed/crd/v1beta1/egress.go create mode 100644 pkg/client/clientset/versioned/typed/crd/v1beta1/fake/fake_egress.go create mode 100644 pkg/client/informers/externalversions/crd/v1beta1/egress.go create mode 100644 pkg/client/listers/crd/v1beta1/egress.go diff --git a/build/charts/antrea/crds/egress.yaml b/build/charts/antrea/crds/egress.yaml index e47ac0fc47c..621edbde5ba 100644 --- a/build/charts/antrea/crds/egress.yaml +++ b/build/charts/antrea/crds/egress.yaml @@ -8,6 +8,122 @@ spec: group: crd.antrea.io versions: - name: v1alpha2 + served: true + storage: false + schema: + openAPIV3Schema: + type: object + required: + - spec + properties: + spec: + type: object + required: + - appliedTo + oneOf: + - anyOf: + - required: + - egressIP + - required: + - externalIPPool + - anyOf: + - required: + - egressIPs + - required: + - externalIPPools + properties: + appliedTo: + type: object + properties: + podSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + type: array + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + matchLabels: + x-kubernetes-preserve-unknown-fields: true + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + type: array + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + matchLabels: + x-kubernetes-preserve-unknown-fields: true + egressIP: + type: string + oneOf: + - format: ipv4 + - format: ipv6 + egressIPs: + type: array + items: + type: string + oneOf: + - maxLength: 0 + - format: ipv4 + - format: ipv6 + externalIPPool: + type: string + externalIPPools: + type: array + items: + type: string + status: + type: object + properties: + egressNode: + type: string + egressIP: + type: string + additionalPrinterColumns: + - description: The effective SNAT IP address for the selected workloads. + jsonPath: .status.egressIP + name: EgressIP + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - description: The Owner Node of egress IP + jsonPath: .status.egressNode + name: Node + type: string + subresources: + status: {} + - name: v1beta1 served: true storage: true schema: diff --git a/build/yamls/antrea-aks.yml b/build/yamls/antrea-aks.yml index ec792ec21e6..2aa2b5adcfd 100644 --- a/build/yamls/antrea-aks.yml +++ b/build/yamls/antrea-aks.yml @@ -1086,6 +1086,122 @@ spec: group: crd.antrea.io versions: - name: v1alpha2 + served: true + storage: false + schema: + openAPIV3Schema: + type: object + required: + - spec + properties: + spec: + type: object + required: + - appliedTo + oneOf: + - anyOf: + - required: + - egressIP + - required: + - externalIPPool + - anyOf: + - required: + - egressIPs + - required: + - externalIPPools + properties: + appliedTo: + type: object + properties: + podSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + type: array + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + matchLabels: + x-kubernetes-preserve-unknown-fields: true + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + type: array + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + matchLabels: + x-kubernetes-preserve-unknown-fields: true + egressIP: + type: string + oneOf: + - format: ipv4 + - format: ipv6 + egressIPs: + type: array + items: + type: string + oneOf: + - maxLength: 0 + - format: ipv4 + - format: ipv6 + externalIPPool: + type: string + externalIPPools: + type: array + items: + type: string + status: + type: object + properties: + egressNode: + type: string + egressIP: + type: string + additionalPrinterColumns: + - description: The effective SNAT IP address for the selected workloads. + jsonPath: .status.egressIP + name: EgressIP + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - description: The Owner Node of egress IP + jsonPath: .status.egressNode + name: Node + type: string + subresources: + status: {} + - name: v1beta1 served: true storage: true schema: diff --git a/build/yamls/antrea-crds.yml b/build/yamls/antrea-crds.yml index f1ac54f55ea..f1cfdd6ded3 100644 --- a/build/yamls/antrea-crds.yml +++ b/build/yamls/antrea-crds.yml @@ -1077,6 +1077,122 @@ spec: group: crd.antrea.io versions: - name: v1alpha2 + served: true + storage: false + schema: + openAPIV3Schema: + type: object + required: + - spec + properties: + spec: + type: object + required: + - appliedTo + oneOf: + - anyOf: + - required: + - egressIP + - required: + - externalIPPool + - anyOf: + - required: + - egressIPs + - required: + - externalIPPools + properties: + appliedTo: + type: object + properties: + podSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + type: array + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + matchLabels: + x-kubernetes-preserve-unknown-fields: true + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + type: array + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + matchLabels: + x-kubernetes-preserve-unknown-fields: true + egressIP: + type: string + oneOf: + - format: ipv4 + - format: ipv6 + egressIPs: + type: array + items: + type: string + oneOf: + - maxLength: 0 + - format: ipv4 + - format: ipv6 + externalIPPool: + type: string + externalIPPools: + type: array + items: + type: string + status: + type: object + properties: + egressNode: + type: string + egressIP: + type: string + additionalPrinterColumns: + - description: The effective SNAT IP address for the selected workloads. + jsonPath: .status.egressIP + name: EgressIP + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - description: The Owner Node of egress IP + jsonPath: .status.egressNode + name: Node + type: string + subresources: + status: {} + - name: v1beta1 served: true storage: true schema: diff --git a/build/yamls/antrea-eks.yml b/build/yamls/antrea-eks.yml index c8175867cfd..89aa535937c 100644 --- a/build/yamls/antrea-eks.yml +++ b/build/yamls/antrea-eks.yml @@ -1086,6 +1086,122 @@ spec: group: crd.antrea.io versions: - name: v1alpha2 + served: true + storage: false + schema: + openAPIV3Schema: + type: object + required: + - spec + properties: + spec: + type: object + required: + - appliedTo + oneOf: + - anyOf: + - required: + - egressIP + - required: + - externalIPPool + - anyOf: + - required: + - egressIPs + - required: + - externalIPPools + properties: + appliedTo: + type: object + properties: + podSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + type: array + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + matchLabels: + x-kubernetes-preserve-unknown-fields: true + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + type: array + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + matchLabels: + x-kubernetes-preserve-unknown-fields: true + egressIP: + type: string + oneOf: + - format: ipv4 + - format: ipv6 + egressIPs: + type: array + items: + type: string + oneOf: + - maxLength: 0 + - format: ipv4 + - format: ipv6 + externalIPPool: + type: string + externalIPPools: + type: array + items: + type: string + status: + type: object + properties: + egressNode: + type: string + egressIP: + type: string + additionalPrinterColumns: + - description: The effective SNAT IP address for the selected workloads. + jsonPath: .status.egressIP + name: EgressIP + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - description: The Owner Node of egress IP + jsonPath: .status.egressNode + name: Node + type: string + subresources: + status: {} + - name: v1beta1 served: true storage: true schema: diff --git a/build/yamls/antrea-gke.yml b/build/yamls/antrea-gke.yml index 7812ff71dc6..9b438c7cba9 100644 --- a/build/yamls/antrea-gke.yml +++ b/build/yamls/antrea-gke.yml @@ -1086,6 +1086,122 @@ spec: group: crd.antrea.io versions: - name: v1alpha2 + served: true + storage: false + schema: + openAPIV3Schema: + type: object + required: + - spec + properties: + spec: + type: object + required: + - appliedTo + oneOf: + - anyOf: + - required: + - egressIP + - required: + - externalIPPool + - anyOf: + - required: + - egressIPs + - required: + - externalIPPools + properties: + appliedTo: + type: object + properties: + podSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + type: array + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + matchLabels: + x-kubernetes-preserve-unknown-fields: true + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + type: array + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + matchLabels: + x-kubernetes-preserve-unknown-fields: true + egressIP: + type: string + oneOf: + - format: ipv4 + - format: ipv6 + egressIPs: + type: array + items: + type: string + oneOf: + - maxLength: 0 + - format: ipv4 + - format: ipv6 + externalIPPool: + type: string + externalIPPools: + type: array + items: + type: string + status: + type: object + properties: + egressNode: + type: string + egressIP: + type: string + additionalPrinterColumns: + - description: The effective SNAT IP address for the selected workloads. + jsonPath: .status.egressIP + name: EgressIP + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - description: The Owner Node of egress IP + jsonPath: .status.egressNode + name: Node + type: string + subresources: + status: {} + - name: v1beta1 served: true storage: true schema: diff --git a/build/yamls/antrea-ipsec.yml b/build/yamls/antrea-ipsec.yml index f8f6d4f8538..67223d735a9 100644 --- a/build/yamls/antrea-ipsec.yml +++ b/build/yamls/antrea-ipsec.yml @@ -1086,6 +1086,122 @@ spec: group: crd.antrea.io versions: - name: v1alpha2 + served: true + storage: false + schema: + openAPIV3Schema: + type: object + required: + - spec + properties: + spec: + type: object + required: + - appliedTo + oneOf: + - anyOf: + - required: + - egressIP + - required: + - externalIPPool + - anyOf: + - required: + - egressIPs + - required: + - externalIPPools + properties: + appliedTo: + type: object + properties: + podSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + type: array + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + matchLabels: + x-kubernetes-preserve-unknown-fields: true + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + type: array + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + matchLabels: + x-kubernetes-preserve-unknown-fields: true + egressIP: + type: string + oneOf: + - format: ipv4 + - format: ipv6 + egressIPs: + type: array + items: + type: string + oneOf: + - maxLength: 0 + - format: ipv4 + - format: ipv6 + externalIPPool: + type: string + externalIPPools: + type: array + items: + type: string + status: + type: object + properties: + egressNode: + type: string + egressIP: + type: string + additionalPrinterColumns: + - description: The effective SNAT IP address for the selected workloads. + jsonPath: .status.egressIP + name: EgressIP + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - description: The Owner Node of egress IP + jsonPath: .status.egressNode + name: Node + type: string + subresources: + status: {} + - name: v1beta1 served: true storage: true schema: diff --git a/build/yamls/antrea.yml b/build/yamls/antrea.yml index 8f9e23e8511..fceac745cff 100644 --- a/build/yamls/antrea.yml +++ b/build/yamls/antrea.yml @@ -1086,6 +1086,122 @@ spec: group: crd.antrea.io versions: - name: v1alpha2 + served: true + storage: false + schema: + openAPIV3Schema: + type: object + required: + - spec + properties: + spec: + type: object + required: + - appliedTo + oneOf: + - anyOf: + - required: + - egressIP + - required: + - externalIPPool + - anyOf: + - required: + - egressIPs + - required: + - externalIPPools + properties: + appliedTo: + type: object + properties: + podSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + type: array + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + matchLabels: + x-kubernetes-preserve-unknown-fields: true + namespaceSelector: + type: object + properties: + matchExpressions: + type: array + items: + type: object + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + type: array + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + matchLabels: + x-kubernetes-preserve-unknown-fields: true + egressIP: + type: string + oneOf: + - format: ipv4 + - format: ipv6 + egressIPs: + type: array + items: + type: string + oneOf: + - maxLength: 0 + - format: ipv4 + - format: ipv6 + externalIPPool: + type: string + externalIPPools: + type: array + items: + type: string + status: + type: object + properties: + egressNode: + type: string + egressIP: + type: string + additionalPrinterColumns: + - description: The effective SNAT IP address for the selected workloads. + jsonPath: .status.egressIP + name: EgressIP + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - description: The Owner Node of egress IP + jsonPath: .status.egressNode + name: Node + type: string + subresources: + status: {} + - name: v1beta1 served: true storage: true schema: diff --git a/cmd/antrea-agent/agent.go b/cmd/antrea-agent/agent.go index 94deecedadf..b88d4caf0b2 100644 --- a/cmd/antrea-agent/agent.go +++ b/cmd/antrea-agent/agent.go @@ -107,7 +107,7 @@ func run(o *Options) error { informerFactory := informers.NewSharedInformerFactory(k8sClient, informerDefaultResync) crdInformerFactory := crdinformers.NewSharedInformerFactory(crdClient, informerDefaultResync) traceflowInformer := crdInformerFactory.Crd().V1alpha1().Traceflows() - egressInformer := crdInformerFactory.Crd().V1alpha2().Egresses() + egressInformer := crdInformerFactory.Crd().V1beta1().Egresses() externalIPPoolInformer := crdInformerFactory.Crd().V1alpha2().ExternalIPPools() trafficControlInformer := crdInformerFactory.Crd().V1alpha2().TrafficControls() nodeInformer := informerFactory.Core().V1().Nodes() diff --git a/cmd/antrea-controller/controller.go b/cmd/antrea-controller/controller.go index f2655b15289..9a5c6c31f0d 100644 --- a/cmd/antrea-controller/controller.go +++ b/cmd/antrea-controller/controller.go @@ -141,7 +141,7 @@ func run(o *Options) error { tfInformer := crdInformerFactory.Crd().V1alpha1().Traceflows() cgInformer := crdInformerFactory.Crd().V1alpha3().ClusterGroups() grpInformer := crdInformerFactory.Crd().V1alpha3().Groups() - egressInformer := crdInformerFactory.Crd().V1alpha2().Egresses() + egressInformer := crdInformerFactory.Crd().V1beta1().Egresses() externalIPPoolInformer := crdInformerFactory.Crd().V1alpha2().ExternalIPPools() externalNodeInformer := crdInformerFactory.Crd().V1alpha1().ExternalNodes() diff --git a/docs/api.md b/docs/api.md index 926930618d8..6069f27b55f 100644 --- a/docs/api.md +++ b/docs/api.md @@ -25,18 +25,18 @@ For information about the Antrea API versioning policy, please refer to this These are the CRDs currently available in `crd.antrea.io`. | CRD | CRD version | Introduced in | Deprecated in / Planned Deprecation | Planned Removal | -|---|---|---|---|---| -| `AntreaAgentInfo` | v1beta1 | v1.0.0 | N/A | N/A | -| `AntreaControllerInfo` | v1beta1 | v1.0.0 | N/A | N/A | -| `ClusterGroup` | v1alpha3 | v1.1.0 | N/A | N/A | -| `ClusterNetworkPolicy` | v1alpha1 | v1.0.0 | N/A | N/A | -| `Egress` | v1alpha2 | v1.0.0 | N/A | N/A | -| `ExternalEntity` | v1alpha2 | v1.0.0 | N/A | N/A | -| `ExternalIPPool` | v1alpha2 | v1.2.0 | N/A | N/A | -| `Group` | v1alpha3 | v1.8.0 | N/A | N/A | -| `NetworkPolicy` | v1alpha1 | v1.0.0 | N/A | N/A | -| `Tier` | v1alpha1 | v1.0.0 | N/A | N/A | -| `Traceflow` | v1alpha1 | v1.0.0 | N/A | N/A | +|---|---|---------------|---|---| +| `AntreaAgentInfo` | v1beta1 | v1.0.0 | N/A | N/A | +| `AntreaControllerInfo` | v1beta1 | v1.0.0 | N/A | N/A | +| `ClusterGroup` | v1alpha3 | v1.1.0 | N/A | N/A | +| `ClusterNetworkPolicy` | v1alpha1 | v1.0.0 | N/A | N/A | +| `Egress` | v1beta1 | v1.13.0 | N/A | N/A | +| `ExternalEntity` | v1alpha2 | v1.0.0 | N/A | N/A | +| `ExternalIPPool` | v1alpha2 | v1.2.0 | N/A | N/A | +| `Group` | v1alpha3 | v1.8.0 | N/A | N/A | +| `NetworkPolicy` | v1alpha1 | v1.0.0 | N/A | N/A | +| `Tier` | v1alpha1 | v1.0.0 | N/A | N/A | +| `Traceflow` | v1alpha1 | v1.0.0 | N/A | N/A | ### Other API groups @@ -67,9 +67,10 @@ These are the API group versions which are curently available when using Antrea. ### Previously-supported CRDs -| CRD | CRD version | Introduced in | Deprecated in | Removed in | -|---|---|---|---|---| +| CRD | CRD version | Introduced in | Deprecated in | Removed in | +|----------------|---|---|---|---| | `ClusterGroup` | v1alpha2 | v1.0.0 | v1.1.0 | v1.12.0 [^1] | +| `Egress` | v1alpha2 | v1.0.0 | v1.13.0 | v2.0.0 | [^1]: The v1alpha2 version of the `ClusterGroup` CRD is no longer served by the apiserver in v1.12 and is completely removed in v1.13. diff --git a/docs/egress.md b/docs/egress.md index dd44af45f4b..9dcb3bb433f 100644 --- a/docs/egress.md +++ b/docs/egress.md @@ -65,7 +65,7 @@ data: A typical Egress resource example: ```yaml -apiVersion: crd.antrea.io/v1alpha2 +apiVersion: crd.antrea.io/v1beta1 kind: Egress metadata: name: egress-prod-web @@ -188,7 +188,7 @@ Then create two `Egress` resources, each of which applies to web apps in one Namespace. ```yaml -apiVersion: crd.antrea.io/v1alpha2 +apiVersion: crd.antrea.io/v1beta1 kind: Egress metadata: name: egress-prod-web @@ -202,7 +202,7 @@ spec: app: web externalIPPool: external-ip-pool --- -apiVersion: crd.antrea.io/v1alpha2 +apiVersion: crd.antrea.io/v1beta1 kind: Egress metadata: name: egress-staging-web @@ -248,7 +248,7 @@ Since the Egress IPs have been configured to the Nodes, we can create `Egress` resources with specific IPs directly. ```yaml -apiVersion: crd.antrea.io/v1alpha2 +apiVersion: crd.antrea.io/v1beta1 kind: Egress metadata: name: egress-prod @@ -259,7 +259,7 @@ spec: kubernetes.io/metadata.name: prod egressIP: 10.10.0.104 # node-4's IP --- -apiVersion: crd.antrea.io/v1alpha2 +apiVersion: crd.antrea.io/v1beta1 kind: Egress metadata: name: egress-staging diff --git a/pkg/agent/controller/egress/egress_controller.go b/pkg/agent/controller/egress/egress_controller.go index d77dbd47062..d310c757cf3 100644 --- a/pkg/agent/controller/egress/egress_controller.go +++ b/pkg/agent/controller/egress/egress_controller.go @@ -44,10 +44,10 @@ import ( "antrea.io/antrea/pkg/agent/route" "antrea.io/antrea/pkg/agent/types" cpv1b2 "antrea.io/antrea/pkg/apis/controlplane/v1beta2" - crdv1a2 "antrea.io/antrea/pkg/apis/crd/v1alpha2" + crdv1b1 "antrea.io/antrea/pkg/apis/crd/v1beta1" clientsetversioned "antrea.io/antrea/pkg/client/clientset/versioned" - crdinformers "antrea.io/antrea/pkg/client/informers/externalversions/crd/v1alpha2" - crdlisters "antrea.io/antrea/pkg/client/listers/crd/v1alpha2" + crdinformers "antrea.io/antrea/pkg/client/informers/externalversions/crd/v1beta1" + crdlisters "antrea.io/antrea/pkg/client/listers/crd/v1beta1" "antrea.io/antrea/pkg/controller/metrics" "antrea.io/antrea/pkg/util/channel" "antrea.io/antrea/pkg/util/k8s" @@ -194,7 +194,7 @@ func NewEgressController( cache.Indexers{ // egressIPIndex will be used to get all Egresses sharing the same Egress IP. egressIPIndex: func(obj interface{}) ([]string, error) { - egress, ok := obj.(*crdv1a2.Egress) + egress, ok := obj.(*crdv1b1.Egress) if !ok { return nil, fmt.Errorf("obj is not Egress: %+v", obj) } @@ -247,7 +247,7 @@ func (c *EgressController) processPodUpdate(e interface{}) { // addEgress processes Egress ADD events. func (c *EgressController) addEgress(obj interface{}) { - egress := obj.(*crdv1a2.Egress) + egress := obj.(*crdv1b1.Egress) if egress.Spec.EgressIP == "" { return } @@ -257,8 +257,8 @@ func (c *EgressController) addEgress(obj interface{}) { // updateEgress processes Egress UPDATE events. func (c *EgressController) updateEgress(old, cur interface{}) { - oldEgress := old.(*crdv1a2.Egress) - curEgress := cur.(*crdv1a2.Egress) + oldEgress := old.(*crdv1b1.Egress) + curEgress := cur.(*crdv1b1.Egress) // Ignore handling the Egress Status change if Egress IP already has been assigned on current node. if curEgress.Status.EgressNode == c.nodeName && oldEgress.GetGeneration() == curEgress.GetGeneration() { return @@ -269,14 +269,14 @@ func (c *EgressController) updateEgress(old, cur interface{}) { // deleteEgress processes Egress DELETE events. func (c *EgressController) deleteEgress(obj interface{}) { - egress, ok := obj.(*crdv1a2.Egress) + egress, ok := obj.(*crdv1b1.Egress) if !ok { deletedState, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { klog.Errorf("Received unexpected object: %v", obj) return } - egress, ok = deletedState.Obj.(*crdv1a2.Egress) + egress, ok = deletedState.Obj.(*crdv1b1.Egress) if !ok { klog.Errorf("DeletedFinalStateUnknown contains non-Egress object: %v", deletedState.Obj) return @@ -297,7 +297,7 @@ func (c *EgressController) onLocalIPUpdate(ip string, added bool) { klog.Infof("Detected Egress IP address %s deleted from this Node", ip) } for _, obj := range egresses { - egress := obj.(*crdv1a2.Egress) + egress := obj.(*crdv1b1.Egress) c.queue.Add(egress.Name) } } @@ -561,7 +561,7 @@ func (c *EgressController) unbindPodEgress(pod, egress string) (string, bool) { return "", false } -func (c *EgressController) updateEgressStatus(egress *crdv1a2.Egress, egressIP string) error { +func (c *EgressController) updateEgressStatus(egress *crdv1b1.Egress, egressIP string) error { isLocal := false if egressIP != "" { isLocal = c.localIPDetector.IsLocalIP(egressIP) @@ -585,9 +585,9 @@ func (c *EgressController) updateEgressStatus(egress *crdv1a2.Egress, egressIP s toUpdate.Status.EgressIP = "" } klog.V(2).InfoS("Updating Egress status", "Egress", egress.Name, "oldNode", egress.Status.EgressNode, "newNode", toUpdate.Status.EgressNode) - _, updateErr = c.crdClient.CrdV1alpha2().Egresses().UpdateStatus(context.TODO(), toUpdate, metav1.UpdateOptions{}) + _, updateErr = c.crdClient.CrdV1beta1().Egresses().UpdateStatus(context.TODO(), toUpdate, metav1.UpdateOptions{}) if updateErr != nil && errors.IsConflict(updateErr) { - if toUpdate, getErr = c.crdClient.CrdV1alpha2().Egresses().Get(context.TODO(), egress.Name, metav1.GetOptions{}); getErr != nil { + if toUpdate, getErr = c.crdClient.CrdV1beta1().Egresses().Get(context.TODO(), egress.Name, metav1.GetOptions{}); getErr != nil { return getErr } } @@ -971,6 +971,6 @@ func (c *EgressController) GetEgress(ns, podName string) (string, string, error) } // An Egress is schedulable if its Egress IP is allocated from ExternalIPPool. -func isEgressSchedulable(egress *crdv1a2.Egress) bool { +func isEgressSchedulable(egress *crdv1b1.Egress) bool { return egress.Spec.EgressIP != "" && egress.Spec.ExternalIPPool != "" } diff --git a/pkg/agent/controller/egress/egress_controller_test.go b/pkg/agent/controller/egress/egress_controller_test.go index 088ec46f03c..f956f280070 100644 --- a/pkg/agent/controller/egress/egress_controller_test.go +++ b/pkg/agent/controller/egress/egress_controller_test.go @@ -44,7 +44,7 @@ import ( "antrea.io/antrea/pkg/agent/types" "antrea.io/antrea/pkg/agent/util" cpv1b2 "antrea.io/antrea/pkg/apis/controlplane/v1beta2" - crdv1a2 "antrea.io/antrea/pkg/apis/crd/v1alpha2" + crdv1b1 "antrea.io/antrea/pkg/apis/crd/v1beta1" "antrea.io/antrea/pkg/client/clientset/versioned" fakeversioned "antrea.io/antrea/pkg/client/clientset/versioned/fake" crdinformers "antrea.io/antrea/pkg/client/informers/externalversions" @@ -150,7 +150,7 @@ func newFakeController(t *testing.T, initObjects []runtime.Object) *fakeControll clientset := &fakeversioned.Clientset{} crdClient := fakeversioned.NewSimpleClientset(initObjects...) crdInformerFactory := crdinformers.NewSharedInformerFactory(crdClient, 0) - egressInformer := crdInformerFactory.Crd().V1alpha2().Egresses() + egressInformer := crdInformerFactory.Crd().V1beta1().Egresses() k8sClient := fake.NewSimpleClientset() informerFactory := informers.NewSharedInformerFactory(k8sClient, 0) nodeInformer := informerFactory.Core().V1().Nodes() @@ -195,23 +195,23 @@ func TestSyncEgress(t *testing.T) { tests := []struct { name string maxEgressIPsPerNode int - existingEgress *crdv1a2.Egress - newEgress *crdv1a2.Egress + existingEgress *crdv1b1.Egress + newEgress *crdv1b1.Egress existingEgressGroup *cpv1b2.EgressGroup newEgressGroup *cpv1b2.EgressGroup newLocalIPs sets.Set[string] - expectedEgresses []*crdv1a2.Egress + expectedEgresses []*crdv1b1.Egress expectedCalls func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) }{ { name: "Local IP becomes non local", - existingEgress: &crdv1a2.Egress{ + existingEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, }, - newEgress: &crdv1a2.Egress{ + newEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, }, existingEgressGroup: &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, @@ -228,10 +228,10 @@ func TestSyncEgress(t *testing.T) { }, }, newLocalIPs: sets.New[string](), - expectedEgresses: []*crdv1a2.Egress{ + expectedEgresses: []*crdv1b1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, }, }, expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) { @@ -254,13 +254,13 @@ func TestSyncEgress(t *testing.T) { }, { name: "Non local IP becomes local", - existingEgress: &crdv1a2.Egress{ + existingEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeRemoteEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeRemoteEgressIP1}, }, - newEgress: &crdv1a2.Egress{ + newEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeRemoteEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeRemoteEgressIP1}, }, existingEgressGroup: &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, @@ -277,11 +277,11 @@ func TestSyncEgress(t *testing.T) { }, }, newLocalIPs: sets.New[string](fakeRemoteEgressIP1), - expectedEgresses: []*crdv1a2.Egress{ + expectedEgresses: []*crdv1b1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeRemoteEgressIP1}, - Status: crdv1a2.EgressStatus{EgressIP: fakeRemoteEgressIP1, EgressNode: fakeNode}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeRemoteEgressIP1}, + Status: crdv1b1.EgressStatus{EgressIP: fakeRemoteEgressIP1, EgressNode: fakeNode}, }, }, expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) { @@ -302,13 +302,13 @@ func TestSyncEgress(t *testing.T) { }, { name: "Change from local Egress IP to another local one", - existingEgress: &crdv1a2.Egress{ + existingEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, }, - newEgress: &crdv1a2.Egress{ + newEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP2}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP2}, }, existingEgressGroup: &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, @@ -324,11 +324,11 @@ func TestSyncEgress(t *testing.T) { {Pod: &cpv1b2.PodReference{Name: "pod3", Namespace: "ns3"}}, }, }, - expectedEgresses: []*crdv1a2.Egress{ + expectedEgresses: []*crdv1b1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP2}, - Status: crdv1a2.EgressStatus{EgressIP: fakeLocalEgressIP2, EgressNode: fakeNode}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP2}, + Status: crdv1b1.EgressStatus{EgressIP: fakeLocalEgressIP2, EgressNode: fakeNode}, }, }, expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) { @@ -354,13 +354,13 @@ func TestSyncEgress(t *testing.T) { }, { name: "Change from local Egress IP to a remote one", - existingEgress: &crdv1a2.Egress{ + existingEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, }, - newEgress: &crdv1a2.Egress{ + newEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeRemoteEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeRemoteEgressIP1}, }, existingEgressGroup: &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, @@ -376,10 +376,10 @@ func TestSyncEgress(t *testing.T) { {Pod: &cpv1b2.PodReference{Name: "pod3", Namespace: "ns3"}}, }, }, - expectedEgresses: []*crdv1a2.Egress{ + expectedEgresses: []*crdv1b1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeRemoteEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeRemoteEgressIP1}, }, }, expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) { @@ -403,13 +403,13 @@ func TestSyncEgress(t *testing.T) { }, { name: "Change from remote Egress IP to a local one", - existingEgress: &crdv1a2.Egress{ + existingEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeRemoteEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeRemoteEgressIP1}, }, - newEgress: &crdv1a2.Egress{ + newEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, }, existingEgressGroup: &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, @@ -425,11 +425,11 @@ func TestSyncEgress(t *testing.T) { {Pod: &cpv1b2.PodReference{Name: "pod3", Namespace: "ns3"}}, }, }, - expectedEgresses: []*crdv1a2.Egress{ + expectedEgresses: []*crdv1b1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, - Status: crdv1a2.EgressStatus{EgressIP: fakeLocalEgressIP1, EgressNode: fakeNode}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Status: crdv1b1.EgressStatus{EgressIP: fakeLocalEgressIP1, EgressNode: fakeNode}, }, }, expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) { @@ -451,13 +451,13 @@ func TestSyncEgress(t *testing.T) { }, { name: "Add an Egress having overlapping Pods", - existingEgress: &crdv1a2.Egress{ + existingEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, }, - newEgress: &crdv1a2.Egress{ + newEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP2}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP2}, }, existingEgressGroup: &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, @@ -473,16 +473,16 @@ func TestSyncEgress(t *testing.T) { {Pod: &cpv1b2.PodReference{Name: "pod3", Namespace: "ns3"}}, }, }, - expectedEgresses: []*crdv1a2.Egress{ + expectedEgresses: []*crdv1b1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, - Status: crdv1a2.EgressStatus{EgressIP: fakeLocalEgressIP1, EgressNode: fakeNode}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Status: crdv1b1.EgressStatus{EgressIP: fakeLocalEgressIP1, EgressNode: fakeNode}, }, { ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP2}, - Status: crdv1a2.EgressStatus{EgressIP: fakeLocalEgressIP2, EgressNode: fakeNode}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP2}, + Status: crdv1b1.EgressStatus{EgressIP: fakeLocalEgressIP2, EgressNode: fakeNode}, }, }, expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) { @@ -502,13 +502,13 @@ func TestSyncEgress(t *testing.T) { }, { name: "Add an Egress sharing the same Egress IP and having overlapping Pods", - existingEgress: &crdv1a2.Egress{ + existingEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, }, - newEgress: &crdv1a2.Egress{ + newEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, }, existingEgressGroup: &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, @@ -524,16 +524,16 @@ func TestSyncEgress(t *testing.T) { {Pod: &cpv1b2.PodReference{Name: "pod3", Namespace: "ns3"}}, }, }, - expectedEgresses: []*crdv1a2.Egress{ + expectedEgresses: []*crdv1b1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, - Status: crdv1a2.EgressStatus{EgressIP: fakeLocalEgressIP1, EgressNode: fakeNode}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Status: crdv1b1.EgressStatus{EgressIP: fakeLocalEgressIP1, EgressNode: fakeNode}, }, { ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, - Status: crdv1a2.EgressStatus{EgressIP: fakeLocalEgressIP1, EgressNode: fakeNode}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Status: crdv1b1.EgressStatus{EgressIP: fakeLocalEgressIP1, EgressNode: fakeNode}, }, }, expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) { @@ -549,13 +549,13 @@ func TestSyncEgress(t *testing.T) { name: "Not exceed maxEgressIPsPerNode", maxEgressIPsPerNode: 1, // It's on this Node but doesn't occupy the quota as it's not allocated from an ExternalIPPool. - existingEgress: &crdv1a2.Egress{ + existingEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, }, - newEgress: &crdv1a2.Egress{ + newEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP2, ExternalIPPool: "external-ip-pool"}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP2, ExternalIPPool: "external-ip-pool"}, }, existingEgressGroup: &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, @@ -570,16 +570,16 @@ func TestSyncEgress(t *testing.T) { {Pod: &cpv1b2.PodReference{Name: "pod3", Namespace: "ns3"}}, }, }, - expectedEgresses: []*crdv1a2.Egress{ + expectedEgresses: []*crdv1b1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, - Status: crdv1a2.EgressStatus{EgressIP: fakeLocalEgressIP1, EgressNode: fakeNode}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Status: crdv1b1.EgressStatus{EgressIP: fakeLocalEgressIP1, EgressNode: fakeNode}, }, { ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP2, ExternalIPPool: "external-ip-pool"}, - Status: crdv1a2.EgressStatus{EgressIP: fakeLocalEgressIP2, EgressNode: fakeNode}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP2, ExternalIPPool: "external-ip-pool"}, + Status: crdv1b1.EgressStatus{EgressIP: fakeLocalEgressIP2, EgressNode: fakeNode}, }, }, expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) { @@ -599,13 +599,13 @@ func TestSyncEgress(t *testing.T) { { name: "Exceed maxEgressIPsPerNode", maxEgressIPsPerNode: 1, - existingEgress: &crdv1a2.Egress{ + existingEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1, ExternalIPPool: "external-ip-pool"}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1, ExternalIPPool: "external-ip-pool"}, }, - newEgress: &crdv1a2.Egress{ + newEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeRemoteEgressIP1, ExternalIPPool: "external-ip-pool"}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeRemoteEgressIP1, ExternalIPPool: "external-ip-pool"}, }, existingEgressGroup: &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, @@ -620,16 +620,16 @@ func TestSyncEgress(t *testing.T) { {Pod: &cpv1b2.PodReference{Name: "pod3", Namespace: "ns3"}}, }, }, - expectedEgresses: []*crdv1a2.Egress{ + expectedEgresses: []*crdv1b1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1, ExternalIPPool: "external-ip-pool"}, - Status: crdv1a2.EgressStatus{EgressIP: fakeLocalEgressIP1, EgressNode: fakeNode}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1, ExternalIPPool: "external-ip-pool"}, + Status: crdv1b1.EgressStatus{EgressIP: fakeLocalEgressIP1, EgressNode: fakeNode}, }, { ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeRemoteEgressIP1, ExternalIPPool: "external-ip-pool"}, - Status: crdv1a2.EgressStatus{}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeRemoteEgressIP1, ExternalIPPool: "external-ip-pool"}, + Status: crdv1b1.EgressStatus{}, }, }, expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) { @@ -645,14 +645,14 @@ func TestSyncEgress(t *testing.T) { { name: "Remove Egress IP", maxEgressIPsPerNode: 1, - existingEgress: &crdv1a2.Egress{ + existingEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1, ExternalIPPool: "external-ip-pool"}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1, ExternalIPPool: "external-ip-pool"}, }, - newEgress: &crdv1a2.Egress{ + newEgress: &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{ExternalIPPool: "external-ip-pool"}, - Status: crdv1a2.EgressStatus{EgressIP: fakeLocalEgressIP1, EgressNode: fakeNode}, + Spec: crdv1b1.EgressSpec{ExternalIPPool: "external-ip-pool"}, + Status: crdv1b1.EgressStatus{EgressIP: fakeLocalEgressIP1, EgressNode: fakeNode}, }, existingEgressGroup: &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, @@ -667,11 +667,11 @@ func TestSyncEgress(t *testing.T) { {Pod: &cpv1b2.PodReference{Name: "pod3", Namespace: "ns3"}}, }, }, - expectedEgresses: []*crdv1a2.Egress{ + expectedEgresses: []*crdv1b1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{ExternalIPPool: "external-ip-pool"}, - Status: crdv1a2.EgressStatus{}, + Spec: crdv1b1.EgressSpec{ExternalIPPool: "external-ip-pool"}, + Status: crdv1b1.EgressStatus{}, }, }, expectedCalls: func(mockOFClient *openflowtest.MockClient, mockRouteClient *routetest.MockInterface, mockIPAssigner *ipassignertest.MockIPAssigner) { @@ -710,9 +710,9 @@ func TestSyncEgress(t *testing.T) { assert.NoError(t, err) if tt.newEgress.Name == tt.existingEgress.Name { - c.crdClient.CrdV1alpha2().Egresses().Update(context.TODO(), tt.newEgress, metav1.UpdateOptions{}) + c.crdClient.CrdV1beta1().Egresses().Update(context.TODO(), tt.newEgress, metav1.UpdateOptions{}) } else { - c.crdClient.CrdV1alpha2().Egresses().Create(context.TODO(), tt.newEgress, metav1.CreateOptions{}) + c.crdClient.CrdV1beta1().Egresses().Create(context.TODO(), tt.newEgress, metav1.CreateOptions{}) } c.addEgressGroup(tt.newEgressGroup) @@ -730,7 +730,7 @@ func TestSyncEgress(t *testing.T) { err = c.syncEgress(tt.newEgress.Name) assert.NoError(t, err) for _, expectedEgress := range tt.expectedEgresses { - gotEgress, err := c.crdClient.CrdV1alpha2().Egresses().Get(context.TODO(), expectedEgress.Name, metav1.GetOptions{}) + gotEgress, err := c.crdClient.CrdV1beta1().Egresses().Get(context.TODO(), expectedEgress.Name, metav1.GetOptions{}) require.NoError(t, err) assert.Equal(t, expectedEgress, gotEgress) } @@ -739,9 +739,9 @@ func TestSyncEgress(t *testing.T) { } func TestPodUpdateShouldSyncEgress(t *testing.T) { - egress := &crdv1a2.Egress{ + egress := &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, } egressGroup := &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, @@ -789,9 +789,9 @@ func TestPodUpdateShouldSyncEgress(t *testing.T) { } func TestSyncOverlappingEgress(t *testing.T) { - egress1 := &crdv1a2.Egress{ + egress1 := &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, } egressGroup1 := &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, @@ -801,9 +801,9 @@ func TestSyncOverlappingEgress(t *testing.T) { }, } // egress2 shares a Pod with egress1. - egress2 := &crdv1a2.Egress{ + egress2 := &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeRemoteEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeRemoteEgressIP1}, } egressGroup2 := &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB"}, @@ -813,9 +813,9 @@ func TestSyncOverlappingEgress(t *testing.T) { }, } // egress3 shares a Pod with egress1 and has the same EgressIP. - egress3 := &crdv1a2.Egress{ + egress3 := &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressC", UID: "uidC"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, } egressGroup3 := &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressC", UID: "uidC"}, @@ -861,7 +861,7 @@ func TestSyncOverlappingEgress(t *testing.T) { // egress2 and egress3 are expected to be triggered for resync. c.mockOFClient.EXPECT().UninstallPodSNATFlows(uint32(1)) c.mockOFClient.EXPECT().UninstallPodSNATFlows(uint32(2)) - c.crdClient.CrdV1alpha2().Egresses().Delete(context.TODO(), egress1.Name, metav1.DeleteOptions{}) + c.crdClient.CrdV1beta1().Egresses().Delete(context.TODO(), egress1.Name, metav1.DeleteOptions{}) assert.NoError(t, wait.Poll(time.Millisecond*100, time.Second, func() (bool, error) { _, err := c.egressLister.Get(egress1.Name) return err != nil, nil @@ -887,7 +887,7 @@ func TestSyncOverlappingEgress(t *testing.T) { // After deleting egress2, pod1 and pod3 no longer enforces any Egress. c.mockOFClient.EXPECT().UninstallPodSNATFlows(uint32(1)) c.mockOFClient.EXPECT().UninstallPodSNATFlows(uint32(3)) - c.crdClient.CrdV1alpha2().Egresses().Delete(context.TODO(), egress2.Name, metav1.DeleteOptions{}) + c.crdClient.CrdV1beta1().Egresses().Delete(context.TODO(), egress2.Name, metav1.DeleteOptions{}) c.mockIPAssigner.EXPECT().UnassignIP(fakeRemoteEgressIP1) assert.NoError(t, wait.Poll(time.Millisecond*100, time.Second, func() (bool, error) { _, err := c.egressLister.Get(egress2.Name) @@ -903,7 +903,7 @@ func TestSyncOverlappingEgress(t *testing.T) { c.mockRouteClient.EXPECT().DeleteSNATRule(uint32(1)) c.mockOFClient.EXPECT().UninstallPodSNATFlows(uint32(2)) c.mockOFClient.EXPECT().UninstallPodSNATFlows(uint32(4)) - c.crdClient.CrdV1alpha2().Egresses().Delete(context.TODO(), egress3.Name, metav1.DeleteOptions{}) + c.crdClient.CrdV1beta1().Egresses().Delete(context.TODO(), egress3.Name, metav1.DeleteOptions{}) c.mockIPAssigner.EXPECT().UnassignIP(fakeLocalEgressIP1) assert.NoError(t, wait.Poll(time.Millisecond*100, time.Second, func() (bool, error) { _, err := c.egressLister.Get(egress3.Name) @@ -980,9 +980,9 @@ func TestUpdateEgressStatus(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - egress := crdv1a2.Egress{ + egress := crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA", ResourceVersion: "fake-ResourceVersion"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, } fakeClient := &fakeversioned.Clientset{} getCalled := 0 @@ -1004,7 +1004,7 @@ func TestUpdateEgressStatus(t *testing.T) { localIPDetector := &fakeLocalIPDetector{localIPs: sets.New[string](fakeLocalEgressIP1)} c := &EgressController{crdClient: fakeClient, nodeName: fakeNode, localIPDetector: localIPDetector} - _, err := c.crdClient.CrdV1alpha2().Egresses().Create(context.TODO(), &egress, metav1.CreateOptions{}) + _, err := c.crdClient.CrdV1beta1().Egresses().Create(context.TODO(), &egress, metav1.CreateOptions{}) assert.NoError(t, err) err = c.updateEgressStatus(&egress, fakeLocalEgressIP1) if err != tt.expectedError { @@ -1017,9 +1017,9 @@ func TestUpdateEgressStatus(t *testing.T) { } func TestGetEgress(t *testing.T) { - egress := &crdv1a2.Egress{ + egress := &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, } egressGroup := &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, @@ -1087,9 +1087,9 @@ func TestGetEgress(t *testing.T) { } func TestGetEgressIPByMark(t *testing.T) { - egress := &crdv1a2.Egress{ + egress := &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: crdv1a2.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, } c := newFakeController(t, []runtime.Object{egress}) diff --git a/pkg/agent/controller/egress/ip_scheduler.go b/pkg/agent/controller/egress/ip_scheduler.go index 78ba04ca961..439279460a3 100644 --- a/pkg/agent/controller/egress/ip_scheduler.go +++ b/pkg/agent/controller/egress/ip_scheduler.go @@ -30,9 +30,9 @@ import ( "antrea.io/antrea/pkg/agent/memberlist" "antrea.io/antrea/pkg/agent/types" - crdv1a2 "antrea.io/antrea/pkg/apis/crd/v1alpha2" - crdinformers "antrea.io/antrea/pkg/client/informers/externalversions/crd/v1alpha2" - crdlisters "antrea.io/antrea/pkg/client/listers/crd/v1alpha2" + crdv1b1 "antrea.io/antrea/pkg/apis/crd/v1beta1" + crdinformers "antrea.io/antrea/pkg/client/informers/externalversions/crd/v1beta1" + crdlisters "antrea.io/antrea/pkg/client/listers/crd/v1beta1" ) const ( @@ -170,7 +170,7 @@ func (s *egressIPScheduler) deleteNode(obj interface{}) { // addEgress processes Egress ADD events. func (s *egressIPScheduler) addEgress(obj interface{}) { - egress := obj.(*crdv1a2.Egress) + egress := obj.(*crdv1b1.Egress) if !isEgressSchedulable(egress) { return } @@ -180,8 +180,8 @@ func (s *egressIPScheduler) addEgress(obj interface{}) { // updateEgress processes Egress UPDATE events. func (s *egressIPScheduler) updateEgress(old, cur interface{}) { - oldEgress := old.(*crdv1a2.Egress) - curEgress := cur.(*crdv1a2.Egress) + oldEgress := old.(*crdv1b1.Egress) + curEgress := cur.(*crdv1b1.Egress) if !isEgressSchedulable(oldEgress) && !isEgressSchedulable(curEgress) { return } @@ -194,14 +194,14 @@ func (s *egressIPScheduler) updateEgress(old, cur interface{}) { // deleteEgress processes Egress DELETE events. func (s *egressIPScheduler) deleteEgress(obj interface{}) { - egress, ok := obj.(*crdv1a2.Egress) + egress, ok := obj.(*crdv1b1.Egress) if !ok { deletedState, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { klog.Errorf("Received unexpected object: %v", obj) return } - egress, ok = deletedState.Obj.(*crdv1a2.Egress) + egress, ok = deletedState.Obj.(*crdv1b1.Egress) if !ok { klog.Errorf("DeletedFinalStateUnknown contains non-Egress object: %v", deletedState.Obj) return @@ -260,7 +260,7 @@ func (s *egressIPScheduler) GetEgressIPAndNode(egress string) (string, string, b } // EgressesByCreationTimestamp sorts a list of Egresses by creation timestamp. -type EgressesByCreationTimestamp []*crdv1a2.Egress +type EgressesByCreationTimestamp []*crdv1b1.Egress func (o EgressesByCreationTimestamp) Len() int { return len(o) } func (o EgressesByCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] } diff --git a/pkg/agent/controller/egress/ip_scheduler_test.go b/pkg/agent/controller/egress/ip_scheduler_test.go index 4900c666eda..2d2847e200a 100644 --- a/pkg/agent/controller/egress/ip_scheduler_test.go +++ b/pkg/agent/controller/egress/ip_scheduler_test.go @@ -34,7 +34,7 @@ import ( "antrea.io/antrea/pkg/agent/consistenthash" "antrea.io/antrea/pkg/agent/memberlist" agenttypes "antrea.io/antrea/pkg/agent/types" - crdv1a2 "antrea.io/antrea/pkg/apis/crd/v1alpha2" + crdv1b1 "antrea.io/antrea/pkg/apis/crd/v1beta1" fakeversioned "antrea.io/antrea/pkg/client/clientset/versioned/fake" crdinformers "antrea.io/antrea/pkg/client/informers/externalversions" ) @@ -85,17 +85,17 @@ func (f *fakeMemberlistCluster) ShouldSelectIP(ip string, pool string, filters . func TestSchedule(t *testing.T) { egresses := []runtime.Object{ - &crdv1a2.Egress{ + &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA", CreationTimestamp: metav1.NewTime(time.Unix(1, 0))}, - Spec: crdv1a2.EgressSpec{EgressIP: "1.1.1.1", ExternalIPPool: "pool1"}, + Spec: crdv1b1.EgressSpec{EgressIP: "1.1.1.1", ExternalIPPool: "pool1"}, }, - &crdv1a2.Egress{ + &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB", CreationTimestamp: metav1.NewTime(time.Unix(2, 0))}, - Spec: crdv1a2.EgressSpec{EgressIP: "1.1.1.11", ExternalIPPool: "pool1"}, + Spec: crdv1b1.EgressSpec{EgressIP: "1.1.1.11", ExternalIPPool: "pool1"}, }, - &crdv1a2.Egress{ + &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressC", UID: "uidC", CreationTimestamp: metav1.NewTime(time.Unix(3, 0))}, - Spec: crdv1a2.EgressSpec{EgressIP: "1.1.1.21", ExternalIPPool: "pool1"}, + Spec: crdv1b1.EgressSpec{EgressIP: "1.1.1.21", ExternalIPPool: "pool1"}, }, } tests := []struct { @@ -186,7 +186,7 @@ func TestSchedule(t *testing.T) { fakeCluster := newFakeMemberlistCluster(tt.nodes) crdClient := fakeversioned.NewSimpleClientset(egresses...) crdInformerFactory := crdinformers.NewSharedInformerFactory(crdClient, 0) - egressInformer := crdInformerFactory.Crd().V1alpha2().Egresses() + egressInformer := crdInformerFactory.Crd().V1beta1().Egresses() clientset := fake.NewSimpleClientset() informerFactory := informers.NewSharedInformerFactory(clientset, 0) nodeInformer := informerFactory.Core().V1().Nodes() @@ -209,9 +209,9 @@ func TestSchedule(t *testing.T) { func BenchmarkSchedule(b *testing.B) { var egresses []runtime.Object for i := 0; i < 1000; i++ { - egresses = append(egresses, &crdv1a2.Egress{ + egresses = append(egresses, &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("egress-%d", i), UID: types.UID(fmt.Sprintf("uid-%d", i)), CreationTimestamp: metav1.NewTime(time.Unix(int64(i), 0))}, - Spec: crdv1a2.EgressSpec{EgressIP: fmt.Sprintf("1.1.%d.%d", rand.Intn(256), rand.Intn(256)), ExternalIPPool: "pool1"}, + Spec: crdv1b1.EgressSpec{EgressIP: fmt.Sprintf("1.1.%d.%d", rand.Intn(256), rand.Intn(256)), ExternalIPPool: "pool1"}, }) } var nodes []string @@ -221,7 +221,7 @@ func BenchmarkSchedule(b *testing.B) { fakeCluster := newFakeMemberlistCluster(nodes) crdClient := fakeversioned.NewSimpleClientset(egresses...) crdInformerFactory := crdinformers.NewSharedInformerFactory(crdClient, 0) - egressInformer := crdInformerFactory.Crd().V1alpha2().Egresses() + egressInformer := crdInformerFactory.Crd().V1beta1().Egresses() clientset := fake.NewSimpleClientset() informerFactory := informers.NewSharedInformerFactory(clientset, 0) nodeInformer := informerFactory.Core().V1().Nodes() @@ -243,17 +243,17 @@ func BenchmarkSchedule(b *testing.B) { func TestRun(t *testing.T) { ctx := context.Background() egresses := []runtime.Object{ - &crdv1a2.Egress{ + &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA", CreationTimestamp: metav1.NewTime(time.Unix(1, 0))}, - Spec: crdv1a2.EgressSpec{EgressIP: "1.1.1.1", ExternalIPPool: "pool1"}, + Spec: crdv1b1.EgressSpec{EgressIP: "1.1.1.1", ExternalIPPool: "pool1"}, }, - &crdv1a2.Egress{ + &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB", CreationTimestamp: metav1.NewTime(time.Unix(2, 0))}, - Spec: crdv1a2.EgressSpec{EgressIP: "1.1.1.11", ExternalIPPool: "pool1"}, + Spec: crdv1b1.EgressSpec{EgressIP: "1.1.1.11", ExternalIPPool: "pool1"}, }, - &crdv1a2.Egress{ + &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressC", UID: "uidC", CreationTimestamp: metav1.NewTime(time.Unix(3, 0))}, - Spec: crdv1a2.EgressSpec{EgressIP: "1.1.1.21", ExternalIPPool: "pool1"}, + Spec: crdv1b1.EgressSpec{EgressIP: "1.1.1.21", ExternalIPPool: "pool1"}, }, } node1 := &corev1.Node{ @@ -271,7 +271,7 @@ func TestRun(t *testing.T) { fakeCluster := newFakeMemberlistCluster([]string{"node1", "node2"}) crdClient := fakeversioned.NewSimpleClientset(egresses...) crdInformerFactory := crdinformers.NewSharedInformerFactory(crdClient, 0) - egressInformer := crdInformerFactory.Crd().V1alpha2().Egresses() + egressInformer := crdInformerFactory.Crd().V1beta1().Egresses() clientset := fake.NewSimpleClientset(node1, node2) informerFactory := informers.NewSharedInformerFactory(clientset, 0) nodeInformer := informerFactory.Core().V1().Nodes() @@ -303,7 +303,7 @@ func TestRun(t *testing.T) { }, } patchBytes, _ := json.Marshal(patch) - crdClient.CrdV1alpha2().Egresses().Patch(context.TODO(), "egressA", types.MergePatchType, patchBytes, metav1.PatchOptions{}) + crdClient.CrdV1beta1().Egresses().Patch(context.TODO(), "egressA", types.MergePatchType, patchBytes, metav1.PatchOptions{}) assertReceivedItems(t, egressUpdates, sets.New[string]("egressA")) assertScheduleResult(t, s, "egressA", "1.1.1.5", "node2", true) assertScheduleResult(t, s, "egressB", "1.1.1.11", "node2", true) @@ -318,16 +318,16 @@ func TestRun(t *testing.T) { assertScheduleResult(t, s, "egressC", "", "", false) // After egressA is deleted, egressC should be assigned to node1. - crdClient.CrdV1alpha2().Egresses().Delete(ctx, "egressA", metav1.DeleteOptions{}) + crdClient.CrdV1beta1().Egresses().Delete(ctx, "egressA", metav1.DeleteOptions{}) assertReceivedItems(t, egressUpdates, sets.New[string]("egressA", "egressC")) assertScheduleResult(t, s, "egressA", "", "", false) assertScheduleResult(t, s, "egressB", "1.1.1.11", "node1", true) assertScheduleResult(t, s, "egressC", "1.1.1.21", "node1", true) // After egressD is created, it should be left unassigned as the total capacity is insufficient. - crdClient.CrdV1alpha2().Egresses().Create(ctx, &crdv1a2.Egress{ + crdClient.CrdV1beta1().Egresses().Create(ctx, &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressD", UID: "uidD", CreationTimestamp: metav1.NewTime(time.Unix(4, 0))}, - Spec: crdv1a2.EgressSpec{EgressIP: "1.1.1.1", ExternalIPPool: "pool1"}, + Spec: crdv1b1.EgressSpec{EgressIP: "1.1.1.1", ExternalIPPool: "pool1"}, }, metav1.CreateOptions{}) assertReceivedItems(t, egressUpdates, sets.New[string]()) assertScheduleResult(t, s, "egressD", "", "", false) diff --git a/pkg/agent/memberlist/cluster_test.go b/pkg/agent/memberlist/cluster_test.go index ca472407a65..cd4729cdde5 100644 --- a/pkg/agent/memberlist/cluster_test.go +++ b/pkg/agent/memberlist/cluster_test.go @@ -36,6 +36,7 @@ import ( "antrea.io/antrea/pkg/agent/consistenthash" "antrea.io/antrea/pkg/apis" crdv1a2 "antrea.io/antrea/pkg/apis/crd/v1alpha2" + crdv1b1 "antrea.io/antrea/pkg/apis/crd/v1beta1" fakeversioned "antrea.io/antrea/pkg/client/clientset/versioned/fake" crdinformers "antrea.io/antrea/pkg/client/informers/externalversions" "antrea.io/antrea/pkg/util/ip" @@ -93,15 +94,15 @@ func TestCluster_Run(t *testing.T) { localNodeName := "localNodeName" testCases := []struct { name string - egress *crdv1a2.Egress + egress *crdv1b1.Egress externalIPPool *crdv1a2.ExternalIPPool localNode *v1.Node expectEgressSelectResult bool }{ { name: "Local Node matches ExternalIPPool nodeSelectors", - egress: &crdv1a2.Egress{ - Spec: crdv1a2.EgressSpec{ExternalIPPool: "", EgressIP: "1.1.1.1"}, + egress: &crdv1b1.Egress{ + Spec: crdv1b1.EgressSpec{ExternalIPPool: "", EgressIP: "1.1.1.1"}, }, externalIPPool: &crdv1a2.ExternalIPPool{ TypeMeta: metav1.TypeMeta{Kind: "CustomResourceDefinition"}, @@ -116,8 +117,8 @@ func TestCluster_Run(t *testing.T) { }, { name: "Local Node not match ExternalIPPool nodeSelectors", - egress: &crdv1a2.Egress{ - Spec: crdv1a2.EgressSpec{ExternalIPPool: "", EgressIP: "1.1.1.1"}, + egress: &crdv1b1.Egress{ + Spec: crdv1b1.EgressSpec{ExternalIPPool: "", EgressIP: "1.1.1.1"}, }, externalIPPool: &crdv1a2.ExternalIPPool{ TypeMeta: metav1.TypeMeta{Kind: "CustomResourceDefinition"}, @@ -197,9 +198,9 @@ func TestCluster_RunClusterEvents(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "fakeExternalIPPool1"}, Spec: crdv1a2.ExternalIPPoolSpec{NodeSelector: metav1.LabelSelector{MatchLabels: map[string]string{"env": "pro"}}}, } - fakeEgress1 := &crdv1a2.Egress{ + fakeEgress1 := &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "fakeEgress1", UID: "fakeUID1"}, - Spec: crdv1a2.EgressSpec{ExternalIPPool: fakeEIP1.Name, EgressIP: "1.1.1.2"}, + Spec: crdv1b1.EgressSpec{ExternalIPPool: fakeEIP1.Name, EgressIP: "1.1.1.2"}, } mockMemberlist := NewMockMemberlist(controller) fakeCluster, err := newFakeCluster(nodeConfig, stopCh, mockMemberlist) @@ -323,13 +324,13 @@ func TestCluster_RunClusterEvents(t *testing.T) { Spec: crdv1a2.ExternalIPPoolSpec{NodeSelector: metav1.LabelSelector{MatchLabels: map[string]string{"env": "test"}}}, } fakeEgressIP2 := "1.1.1.2" - fakeEgress2 := &crdv1a2.Egress{ + fakeEgress2 := &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "fakeEgress2", UID: "fakeUID2"}, - Spec: crdv1a2.EgressSpec{ExternalIPPool: fakeEIP2.Name, EgressIP: fakeEgressIP2}, + Spec: crdv1b1.EgressSpec{ExternalIPPool: fakeEIP2.Name, EgressIP: fakeEgressIP2}, } assert.NoError(t, createExternalIPPool(fakeCluster.crdClient, fakeEIP2)) - assertEgressSelectResult := func(egress *crdv1a2.Egress, expectedRes bool, hasSyncedErr bool) { + assertEgressSelectResult := func(egress *crdv1b1.Egress, expectedRes bool, hasSyncedErr bool) { assert.NoErrorf(t, wait.Poll(100*time.Millisecond, time.Second, func() (done bool, err error) { res, err := fakeCluster.cluster.ShouldSelectIP(egress.Spec.EgressIP, egress.Spec.ExternalIPPool) if hasSyncedErr { @@ -455,9 +456,9 @@ func TestCluster_ConsistentHashDistribute(t *testing.T) { fakeCluster := genLocalNodeCluster(node, fakeEIPName, testC.nodes) selectedNodes := []int{} for i := 0; i < egressNum; i++ { - fakeEgress := &crdv1a2.Egress{ + fakeEgress := &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "fakeEgress"}, - Spec: crdv1a2.EgressSpec{ExternalIPPool: fakeEIPName, EgressIP: fmt.Sprintf("10.1.1.%d", i)}, + Spec: crdv1b1.EgressSpec{ExternalIPPool: fakeEIPName, EgressIP: fmt.Sprintf("10.1.1.%d", i)}, } selected, err := fakeCluster.ShouldSelectIP(fakeEgress.Spec.EgressIP, fakeEgress.Spec.ExternalIPPool) assert.NoError(t, err) @@ -514,9 +515,9 @@ func TestCluster_ShouldSelectEgress(t *testing.T) { for _, tCase := range testCases { t.Run(tCase.name, func(t *testing.T) { fakeEIPName := "fakeExternalIPPool" - fakeEgress := &crdv1a2.Egress{ + fakeEgress := &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "fakeEgress"}, - Spec: crdv1a2.EgressSpec{ExternalIPPool: fakeEIPName, EgressIP: tCase.egressIP}, + Spec: crdv1b1.EgressSpec{ExternalIPPool: fakeEIPName, EgressIP: tCase.egressIP}, } consistentHashMap := NewNodeConsistentHashMap() consistentHashMap.Add(genNodes(tCase.nodeNum)...) @@ -624,9 +625,9 @@ func BenchmarkCluster_ShouldSelect(b *testing.B) { for _, bc := range benchmarkCases { fakeEIPName := "fakeExternalIPPool" - fakeEgress := &crdv1a2.Egress{ + fakeEgress := &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "fakeEgress"}, - Spec: crdv1a2.EgressSpec{ExternalIPPool: fakeEIPName, EgressIP: "1.1.1.1"}, + Spec: crdv1b1.EgressSpec{ExternalIPPool: fakeEIPName, EgressIP: "1.1.1.1"}, } fakeCluster := genLocalNodeCluster("fakeLocalNodeName", fakeEIPName, bc.nodes) b.Run(fmt.Sprintf("%s-nodeSelectedForEgress", bc.name), func(b *testing.B) { diff --git a/pkg/apis/crd/v1beta1/register.go b/pkg/apis/crd/v1beta1/register.go index 7ff2c5e2d64..64ddf513524 100644 --- a/pkg/apis/crd/v1beta1/register.go +++ b/pkg/apis/crd/v1beta1/register.go @@ -46,6 +46,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &AntreaControllerInfoList{}, &AntreaAgentInfo{}, &AntreaAgentInfoList{}, + &Egress{}, + &EgressList{}, ) metav1.AddToGroupVersion( diff --git a/pkg/apis/crd/v1beta1/types.go b/pkg/apis/crd/v1beta1/types.go index 80962b6c4bf..e582067ba9e 100644 --- a/pkg/apis/crd/v1beta1/types.go +++ b/pkg/apis/crd/v1beta1/types.go @@ -154,3 +154,80 @@ type ControllerCondition struct { // Human readable message indicating details Message string `json:"message,omitempty"` } + +// AppliedTo selects the entities to which a policy is applied. +type AppliedTo struct { + // Select Pods matched by this selector. If set with NamespaceSelector, + // Pods are matched from Namespaces matched by the NamespaceSelector; + // otherwise, Pods are matched from all Namespaces. + // +optional + PodSelector *metav1.LabelSelector `json:"podSelector,omitempty"` + // Select all Pods from Namespaces matched by this selector. If set with + // PodSelector, Pods are matched from Namespaces matched by the + // NamespaceSelector. + // +optional + NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty"` + // Groups is the set of ClusterGroup names. + // +optional + Groups []string `json:"groups,omitempty"` +} + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Egress defines which egress (SNAT) IP the traffic from the selected Pods to +// the external network should use. +type Egress struct { + metav1.TypeMeta `json:",inline"` + // Standard metadata of the object. + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Specification of the desired behavior of Egress. + Spec EgressSpec `json:"spec"` + + // EgressStatus represents the current status of an Egress. + Status EgressStatus `json:"status"` +} + +// EgressStatus represents the current status of an Egress. +type EgressStatus struct { + // The name of the Node that holds the Egress IP. + EgressNode string `json:"egressNode"` + // EgressIP indicates the effective Egress IP for the selected workloads. It could be empty if the Egress IP in spec + // is not assigned to any Node. It's also useful when there are more than one Egress IP specified in spec. + EgressIP string `json:"egressIP"` +} + +// EgressSpec defines the desired state for Egress. +type EgressSpec struct { + // AppliedTo selects Pods to which the Egress will be applied. + AppliedTo AppliedTo `json:"appliedTo"` + // EgressIP specifies the SNAT IP address for the selected workloads. + // If ExternalIPPool is empty, it must be specified manually. + // If ExternalIPPool is non-empty, it can be empty and will be assigned by Antrea automatically. + // If both ExternalIPPool and EgressIP are non-empty, the IP must be in the pool. + EgressIP string `json:"egressIP,omitempty"` + // EgressIPs specifies multiple SNAT IP addresses for the selected workloads. + // Cannot be set with EgressIP. + EgressIPs []string `json:"egressIPs,omitempty"` + // ExternalIPPool specifies the IP Pool that the EgressIP should be allocated from. + // If it is empty, the specified EgressIP must be assigned to a Node manually. + // If it is non-empty, the EgressIP will be assigned to a Node specified by the pool automatically and will failover + // to a different Node when the Node becomes unreachable. + ExternalIPPool string `json:"externalIPPool,omitempty"` + // ExternalIPPools specifies multiple unique IP Pools that the EgressIPs should be allocated from. Entries with the + // same index in EgressIPs and ExternalIPPools are correlated. + // Cannot be set with ExternalIPPool. + ExternalIPPools []string `json:"externalIPPools,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type EgressList struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + + Items []Egress `json:"items"` +} diff --git a/pkg/apis/crd/v1beta1/zz_generated.deepcopy.go b/pkg/apis/crd/v1beta1/zz_generated.deepcopy.go index ab06a42283f..89dcc856b36 100644 --- a/pkg/apis/crd/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/crd/v1beta1/zz_generated.deepcopy.go @@ -20,6 +20,7 @@ package v1beta1 import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -190,6 +191,37 @@ func (in *AntreaControllerInfoList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AppliedTo) DeepCopyInto(out *AppliedTo) { + *out = *in + if in.PodSelector != nil { + in, out := &in.PodSelector, &out.PodSelector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.NamespaceSelector != nil { + in, out := &in.NamespaceSelector, &out.NamespaceSelector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.Groups != nil { + in, out := &in.Groups, &out.Groups + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppliedTo. +func (in *AppliedTo) DeepCopy() *AppliedTo { + if in == nil { + return nil + } + out := new(AppliedTo) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ControllerCondition) DeepCopyInto(out *ControllerCondition) { *out = *in @@ -207,6 +239,110 @@ func (in *ControllerCondition) DeepCopy() *ControllerCondition { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Egress) DeepCopyInto(out *Egress) { + *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 Egress. +func (in *Egress) DeepCopy() *Egress { + if in == nil { + return nil + } + out := new(Egress) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Egress) 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 *EgressList) DeepCopyInto(out *EgressList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Egress, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EgressList. +func (in *EgressList) DeepCopy() *EgressList { + if in == nil { + return nil + } + out := new(EgressList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *EgressList) 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 *EgressSpec) DeepCopyInto(out *EgressSpec) { + *out = *in + in.AppliedTo.DeepCopyInto(&out.AppliedTo) + if in.EgressIPs != nil { + in, out := &in.EgressIPs, &out.EgressIPs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ExternalIPPools != nil { + in, out := &in.ExternalIPPools, &out.ExternalIPPools + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EgressSpec. +func (in *EgressSpec) DeepCopy() *EgressSpec { + if in == nil { + return nil + } + out := new(EgressSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EgressStatus) DeepCopyInto(out *EgressStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EgressStatus. +func (in *EgressStatus) DeepCopy() *EgressStatus { + if in == nil { + return nil + } + out := new(EgressStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NetworkPolicyControllerInfo) DeepCopyInto(out *NetworkPolicyControllerInfo) { *out = *in diff --git a/pkg/apiserver/openapi/zz_generated.openapi.go b/pkg/apiserver/openapi/zz_generated.openapi.go index fe220e3d179..c74c15bb6ed 100644 --- a/pkg/apiserver/openapi/zz_generated.openapi.go +++ b/pkg/apiserver/openapi/zz_generated.openapi.go @@ -77,7 +77,12 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "antrea.io/antrea/pkg/apis/crd/v1beta1.AntreaAgentInfoList": schema_pkg_apis_crd_v1beta1_AntreaAgentInfoList(ref), "antrea.io/antrea/pkg/apis/crd/v1beta1.AntreaControllerInfo": schema_pkg_apis_crd_v1beta1_AntreaControllerInfo(ref), "antrea.io/antrea/pkg/apis/crd/v1beta1.AntreaControllerInfoList": schema_pkg_apis_crd_v1beta1_AntreaControllerInfoList(ref), + "antrea.io/antrea/pkg/apis/crd/v1beta1.AppliedTo": schema_pkg_apis_crd_v1beta1_AppliedTo(ref), "antrea.io/antrea/pkg/apis/crd/v1beta1.ControllerCondition": schema_pkg_apis_crd_v1beta1_ControllerCondition(ref), + "antrea.io/antrea/pkg/apis/crd/v1beta1.Egress": schema_pkg_apis_crd_v1beta1_Egress(ref), + "antrea.io/antrea/pkg/apis/crd/v1beta1.EgressList": schema_pkg_apis_crd_v1beta1_EgressList(ref), + "antrea.io/antrea/pkg/apis/crd/v1beta1.EgressSpec": schema_pkg_apis_crd_v1beta1_EgressSpec(ref), + "antrea.io/antrea/pkg/apis/crd/v1beta1.EgressStatus": schema_pkg_apis_crd_v1beta1_EgressStatus(ref), "antrea.io/antrea/pkg/apis/crd/v1beta1.NetworkPolicyControllerInfo": schema_pkg_apis_crd_v1beta1_NetworkPolicyControllerInfo(ref), "antrea.io/antrea/pkg/apis/crd/v1beta1.OVSInfo": schema_pkg_apis_crd_v1beta1_OVSInfo(ref), "antrea.io/antrea/pkg/apis/stats/v1alpha1.AntreaClusterNetworkPolicyStats": schema_pkg_apis_stats_v1alpha1_AntreaClusterNetworkPolicyStats(ref), @@ -2769,6 +2774,48 @@ func schema_pkg_apis_crd_v1beta1_AntreaControllerInfoList(ref common.ReferenceCa } } +func schema_pkg_apis_crd_v1beta1_AppliedTo(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "AppliedTo selects the entities to which a policy is applied.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "podSelector": { + SchemaProps: spec.SchemaProps{ + Description: "Select Pods matched by this selector. If set with NamespaceSelector, Pods are matched from Namespaces matched by the NamespaceSelector; otherwise, Pods are matched from all Namespaces.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"), + }, + }, + "namespaceSelector": { + SchemaProps: spec.SchemaProps{ + Description: "Select all Pods from Namespaces matched by this selector. If set with PodSelector, Pods are matched from Namespaces matched by the NamespaceSelector.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"), + }, + }, + "groups": { + SchemaProps: spec.SchemaProps{ + Description: "Groups is the set of ClusterGroup names.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"}, + } +} + func schema_pkg_apis_crd_v1beta1_ControllerCondition(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -2821,6 +2868,202 @@ func schema_pkg_apis_crd_v1beta1_ControllerCondition(ref common.ReferenceCallbac } } +func schema_pkg_apis_crd_v1beta1_Egress(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Egress defines which egress (SNAT) IP the traffic from the selected Pods to the external network should use.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Description: "Standard metadata of the object.", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Description: "Specification of the desired behavior of Egress.", + Default: map[string]interface{}{}, + Ref: ref("antrea.io/antrea/pkg/apis/crd/v1beta1.EgressSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "EgressStatus represents the current status of an Egress.", + Default: map[string]interface{}{}, + Ref: ref("antrea.io/antrea/pkg/apis/crd/v1beta1.EgressStatus"), + }, + }, + }, + Required: []string{"spec", "status"}, + }, + }, + Dependencies: []string{ + "antrea.io/antrea/pkg/apis/crd/v1beta1.EgressSpec", "antrea.io/antrea/pkg/apis/crd/v1beta1.EgressStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_pkg_apis_crd_v1beta1_EgressList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("antrea.io/antrea/pkg/apis/crd/v1beta1.Egress"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "antrea.io/antrea/pkg/apis/crd/v1beta1.Egress", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_pkg_apis_crd_v1beta1_EgressSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "EgressSpec defines the desired state for Egress.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "appliedTo": { + SchemaProps: spec.SchemaProps{ + Description: "AppliedTo selects Pods to which the Egress will be applied.", + Default: map[string]interface{}{}, + Ref: ref("antrea.io/antrea/pkg/apis/crd/v1beta1.AppliedTo"), + }, + }, + "egressIP": { + SchemaProps: spec.SchemaProps{ + Description: "EgressIP specifies the SNAT IP address for the selected workloads. If ExternalIPPool is empty, it must be specified manually. If ExternalIPPool is non-empty, it can be empty and will be assigned by Antrea automatically. If both ExternalIPPool and EgressIP are non-empty, the IP must be in the pool.", + Type: []string{"string"}, + Format: "", + }, + }, + "egressIPs": { + SchemaProps: spec.SchemaProps{ + Description: "EgressIPs specifies multiple SNAT IP addresses for the selected workloads. Cannot be set with EgressIP.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "externalIPPool": { + SchemaProps: spec.SchemaProps{ + Description: "ExternalIPPool specifies the IP Pool that the EgressIP should be allocated from. If it is empty, the specified EgressIP must be assigned to a Node manually. If it is non-empty, the EgressIP will be assigned to a Node specified by the pool automatically and will failover to a different Node when the Node becomes unreachable.", + Type: []string{"string"}, + Format: "", + }, + }, + "externalIPPools": { + SchemaProps: spec.SchemaProps{ + Description: "ExternalIPPools specifies multiple unique IP Pools that the EgressIPs should be allocated from. Entries with the same index in EgressIPs and ExternalIPPools are correlated. Cannot be set with ExternalIPPool.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + Required: []string{"appliedTo"}, + }, + }, + Dependencies: []string{ + "antrea.io/antrea/pkg/apis/crd/v1beta1.AppliedTo"}, + } +} + +func schema_pkg_apis_crd_v1beta1_EgressStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "EgressStatus represents the current status of an Egress.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "egressNode": { + SchemaProps: spec.SchemaProps{ + Description: "The name of the Node that holds the Egress IP.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "egressIP": { + SchemaProps: spec.SchemaProps{ + Description: "EgressIP indicates the effective Egress IP for the selected workloads. It could be empty if the Egress IP in spec is not assigned to any Node. It's also useful when there are more than one Egress IP specified in spec.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"egressNode", "egressIP"}, + }, + }, + } +} + func schema_pkg_apis_crd_v1beta1_NetworkPolicyControllerInfo(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/pkg/client/clientset/versioned/typed/crd/v1beta1/crd_client.go b/pkg/client/clientset/versioned/typed/crd/v1beta1/crd_client.go index 672e970dcba..e936044c956 100644 --- a/pkg/client/clientset/versioned/typed/crd/v1beta1/crd_client.go +++ b/pkg/client/clientset/versioned/typed/crd/v1beta1/crd_client.go @@ -1,4 +1,4 @@ -// Copyright 2022 Antrea Authors +// Copyright 2023 Antrea Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -28,6 +28,7 @@ type CrdV1beta1Interface interface { RESTClient() rest.Interface AntreaAgentInfosGetter AntreaControllerInfosGetter + EgressesGetter } // CrdV1beta1Client is used to interact with features provided by the crd.antrea.io group. @@ -43,6 +44,10 @@ func (c *CrdV1beta1Client) AntreaControllerInfos() AntreaControllerInfoInterface return newAntreaControllerInfos(c) } +func (c *CrdV1beta1Client) Egresses() EgressInterface { + return newEgresses(c) +} + // NewForConfig creates a new CrdV1beta1Client for the given config. // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), // where httpClient was generated with rest.HTTPClientFor(c). diff --git a/pkg/client/clientset/versioned/typed/crd/v1beta1/egress.go b/pkg/client/clientset/versioned/typed/crd/v1beta1/egress.go new file mode 100644 index 00000000000..298ca8b6af4 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/crd/v1beta1/egress.go @@ -0,0 +1,182 @@ +// Copyright 2023 Antrea Authors +// +// 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 v1beta1 + +import ( + "context" + "time" + + v1beta1 "antrea.io/antrea/pkg/apis/crd/v1beta1" + scheme "antrea.io/antrea/pkg/client/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" +) + +// EgressesGetter has a method to return a EgressInterface. +// A group's client should implement this interface. +type EgressesGetter interface { + Egresses() EgressInterface +} + +// EgressInterface has methods to work with Egress resources. +type EgressInterface interface { + Create(ctx context.Context, egress *v1beta1.Egress, opts v1.CreateOptions) (*v1beta1.Egress, error) + Update(ctx context.Context, egress *v1beta1.Egress, opts v1.UpdateOptions) (*v1beta1.Egress, error) + UpdateStatus(ctx context.Context, egress *v1beta1.Egress, opts v1.UpdateOptions) (*v1beta1.Egress, 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) (*v1beta1.Egress, error) + List(ctx context.Context, opts v1.ListOptions) (*v1beta1.EgressList, 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 *v1beta1.Egress, err error) + EgressExpansion +} + +// egresses implements EgressInterface +type egresses struct { + client rest.Interface +} + +// newEgresses returns a Egresses +func newEgresses(c *CrdV1beta1Client) *egresses { + return &egresses{ + client: c.RESTClient(), + } +} + +// Get takes name of the egress, and returns the corresponding egress object, and an error if there is any. +func (c *egresses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.Egress, err error) { + result = &v1beta1.Egress{} + err = c.client.Get(). + Resource("egresses"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Egresses that match those selectors. +func (c *egresses) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.EgressList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1beta1.EgressList{} + err = c.client.Get(). + Resource("egresses"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested egresses. +func (c *egresses) 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(). + Resource("egresses"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a egress and creates it. Returns the server's representation of the egress, and an error, if there is any. +func (c *egresses) Create(ctx context.Context, egress *v1beta1.Egress, opts v1.CreateOptions) (result *v1beta1.Egress, err error) { + result = &v1beta1.Egress{} + err = c.client.Post(). + Resource("egresses"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(egress). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a egress and updates it. Returns the server's representation of the egress, and an error, if there is any. +func (c *egresses) Update(ctx context.Context, egress *v1beta1.Egress, opts v1.UpdateOptions) (result *v1beta1.Egress, err error) { + result = &v1beta1.Egress{} + err = c.client.Put(). + Resource("egresses"). + Name(egress.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(egress). + 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 *egresses) UpdateStatus(ctx context.Context, egress *v1beta1.Egress, opts v1.UpdateOptions) (result *v1beta1.Egress, err error) { + result = &v1beta1.Egress{} + err = c.client.Put(). + Resource("egresses"). + Name(egress.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(egress). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the egress and deletes it. Returns an error if one occurs. +func (c *egresses) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Resource("egresses"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *egresses) 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(). + Resource("egresses"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched egress. +func (c *egresses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.Egress, err error) { + result = &v1beta1.Egress{} + err = c.client.Patch(pt). + Resource("egresses"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/crd/v1beta1/fake/fake_crd_client.go b/pkg/client/clientset/versioned/typed/crd/v1beta1/fake/fake_crd_client.go index cc16e366e0b..b3d7806adc3 100644 --- a/pkg/client/clientset/versioned/typed/crd/v1beta1/fake/fake_crd_client.go +++ b/pkg/client/clientset/versioned/typed/crd/v1beta1/fake/fake_crd_client.go @@ -1,4 +1,4 @@ -// Copyright 2021 Antrea Authors +// Copyright 2023 Antrea Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -34,6 +34,10 @@ func (c *FakeCrdV1beta1) AntreaControllerInfos() v1beta1.AntreaControllerInfoInt return &FakeAntreaControllerInfos{c} } +func (c *FakeCrdV1beta1) Egresses() v1beta1.EgressInterface { + return &FakeEgresses{c} +} + // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. func (c *FakeCrdV1beta1) RESTClient() rest.Interface { diff --git a/pkg/client/clientset/versioned/typed/crd/v1beta1/fake/fake_egress.go b/pkg/client/clientset/versioned/typed/crd/v1beta1/fake/fake_egress.go new file mode 100644 index 00000000000..5a098af19da --- /dev/null +++ b/pkg/client/clientset/versioned/typed/crd/v1beta1/fake/fake_egress.go @@ -0,0 +1,131 @@ +// Copyright 2023 Antrea Authors +// +// 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" + + v1beta1 "antrea.io/antrea/pkg/apis/crd/v1beta1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeEgresses implements EgressInterface +type FakeEgresses struct { + Fake *FakeCrdV1beta1 +} + +var egressesResource = schema.GroupVersionResource{Group: "crd.antrea.io", Version: "v1beta1", Resource: "egresses"} + +var egressesKind = schema.GroupVersionKind{Group: "crd.antrea.io", Version: "v1beta1", Kind: "Egress"} + +// Get takes name of the egress, and returns the corresponding egress object, and an error if there is any. +func (c *FakeEgresses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.Egress, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(egressesResource, name), &v1beta1.Egress{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.Egress), err +} + +// List takes label and field selectors, and returns the list of Egresses that match those selectors. +func (c *FakeEgresses) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.EgressList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(egressesResource, egressesKind, opts), &v1beta1.EgressList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1beta1.EgressList{ListMeta: obj.(*v1beta1.EgressList).ListMeta} + for _, item := range obj.(*v1beta1.EgressList).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 egresses. +func (c *FakeEgresses) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(egressesResource, opts)) +} + +// Create takes the representation of a egress and creates it. Returns the server's representation of the egress, and an error, if there is any. +func (c *FakeEgresses) Create(ctx context.Context, egress *v1beta1.Egress, opts v1.CreateOptions) (result *v1beta1.Egress, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(egressesResource, egress), &v1beta1.Egress{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.Egress), err +} + +// Update takes the representation of a egress and updates it. Returns the server's representation of the egress, and an error, if there is any. +func (c *FakeEgresses) Update(ctx context.Context, egress *v1beta1.Egress, opts v1.UpdateOptions) (result *v1beta1.Egress, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(egressesResource, egress), &v1beta1.Egress{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.Egress), 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 *FakeEgresses) UpdateStatus(ctx context.Context, egress *v1beta1.Egress, opts v1.UpdateOptions) (*v1beta1.Egress, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(egressesResource, "status", egress), &v1beta1.Egress{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.Egress), err +} + +// Delete takes name of the egress and deletes it. Returns an error if one occurs. +func (c *FakeEgresses) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteActionWithOptions(egressesResource, name, opts), &v1beta1.Egress{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeEgresses) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(egressesResource, listOpts) + + _, err := c.Fake.Invokes(action, &v1beta1.EgressList{}) + return err +} + +// Patch applies the patch and returns the patched egress. +func (c *FakeEgresses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.Egress, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(egressesResource, name, pt, data, subresources...), &v1beta1.Egress{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.Egress), err +} diff --git a/pkg/client/clientset/versioned/typed/crd/v1beta1/generated_expansion.go b/pkg/client/clientset/versioned/typed/crd/v1beta1/generated_expansion.go index 9e4c79f4934..a415604b9bb 100644 --- a/pkg/client/clientset/versioned/typed/crd/v1beta1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/crd/v1beta1/generated_expansion.go @@ -1,4 +1,4 @@ -// Copyright 2021 Antrea Authors +// Copyright 2023 Antrea Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,3 +19,5 @@ package v1beta1 type AntreaAgentInfoExpansion interface{} type AntreaControllerInfoExpansion interface{} + +type EgressExpansion interface{} diff --git a/pkg/client/informers/externalversions/crd/v1alpha2/egress.go b/pkg/client/informers/externalversions/crd/v1alpha2/egress.go index 36cb1d1c4f8..3da41e584c1 100644 --- a/pkg/client/informers/externalversions/crd/v1alpha2/egress.go +++ b/pkg/client/informers/externalversions/crd/v1alpha2/egress.go @@ -59,13 +59,13 @@ func NewFilteredEgressInformer(client versioned.Interface, resyncPeriod time.Dur if tweakListOptions != nil { tweakListOptions(&options) } - return client.CrdV1alpha2().Egresses().List(context.TODO(), options) + return client.CrdV1beta1().Egresses().List(context.TODO(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.CrdV1alpha2().Egresses().Watch(context.TODO(), options) + return client.CrdV1beta1().Egresses().Watch(context.TODO(), options) }, }, &crdv1alpha2.Egress{}, diff --git a/pkg/client/informers/externalversions/crd/v1beta1/egress.go b/pkg/client/informers/externalversions/crd/v1beta1/egress.go new file mode 100644 index 00000000000..f6b00d92dbe --- /dev/null +++ b/pkg/client/informers/externalversions/crd/v1beta1/egress.go @@ -0,0 +1,87 @@ +// Copyright 2023 Antrea Authors +// +// 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 v1beta1 + +import ( + "context" + time "time" + + crdv1beta1 "antrea.io/antrea/pkg/apis/crd/v1beta1" + versioned "antrea.io/antrea/pkg/client/clientset/versioned" + internalinterfaces "antrea.io/antrea/pkg/client/informers/externalversions/internalinterfaces" + v1beta1 "antrea.io/antrea/pkg/client/listers/crd/v1beta1" + 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" +) + +// EgressInformer provides access to a shared informer and lister for +// Egresses. +type EgressInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1beta1.EgressLister +} + +type egressInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewEgressInformer constructs a new informer for Egress 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 NewEgressInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredEgressInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredEgressInformer constructs a new informer for Egress 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 NewFilteredEgressInformer(client versioned.Interface, 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.CrdV1beta1().Egresses().List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CrdV1beta1().Egresses().Watch(context.TODO(), options) + }, + }, + &crdv1beta1.Egress{}, + resyncPeriod, + indexers, + ) +} + +func (f *egressInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredEgressInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *egressInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&crdv1beta1.Egress{}, f.defaultInformer) +} + +func (f *egressInformer) Lister() v1beta1.EgressLister { + return v1beta1.NewEgressLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/crd/v1beta1/interface.go b/pkg/client/informers/externalversions/crd/v1beta1/interface.go index 79585d9e5c5..fb08f520028 100644 --- a/pkg/client/informers/externalversions/crd/v1beta1/interface.go +++ b/pkg/client/informers/externalversions/crd/v1beta1/interface.go @@ -1,4 +1,4 @@ -// Copyright 2021 Antrea Authors +// Copyright 2023 Antrea Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,6 +26,8 @@ type Interface interface { AntreaAgentInfos() AntreaAgentInfoInformer // AntreaControllerInfos returns a AntreaControllerInfoInformer. AntreaControllerInfos() AntreaControllerInfoInformer + // Egresses returns a EgressInformer. + Egresses() EgressInformer } type version struct { @@ -48,3 +50,8 @@ func (v *version) AntreaAgentInfos() AntreaAgentInfoInformer { func (v *version) AntreaControllerInfos() AntreaControllerInfoInformer { return &antreaControllerInfoInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} } + +// Egresses returns a EgressInformer. +func (v *version) Egresses() EgressInformer { + return &egressInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index c706d13834c..11825ce6d84 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -1,4 +1,4 @@ -// Copyright 2022 Antrea Authors +// Copyright 2023 Antrea Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -92,6 +92,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Crd().V1beta1().AntreaAgentInfos().Informer()}, nil case v1beta1.SchemeGroupVersion.WithResource("antreacontrollerinfos"): return &genericInformer{resource: resource.GroupResource(), informer: f.Crd().V1beta1().AntreaControllerInfos().Informer()}, nil + case v1beta1.SchemeGroupVersion.WithResource("egresses"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Crd().V1beta1().Egresses().Informer()}, nil } diff --git a/pkg/client/listers/crd/v1beta1/egress.go b/pkg/client/listers/crd/v1beta1/egress.go new file mode 100644 index 00000000000..47111652351 --- /dev/null +++ b/pkg/client/listers/crd/v1beta1/egress.go @@ -0,0 +1,66 @@ +// Copyright 2023 Antrea Authors +// +// 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 v1beta1 + +import ( + v1beta1 "antrea.io/antrea/pkg/apis/crd/v1beta1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// EgressLister helps list Egresses. +// All objects returned here must be treated as read-only. +type EgressLister interface { + // List lists all Egresses in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1beta1.Egress, err error) + // Get retrieves the Egress from the index for a given name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1beta1.Egress, error) + EgressListerExpansion +} + +// egressLister implements the EgressLister interface. +type egressLister struct { + indexer cache.Indexer +} + +// NewEgressLister returns a new EgressLister. +func NewEgressLister(indexer cache.Indexer) EgressLister { + return &egressLister{indexer: indexer} +} + +// List lists all Egresses in the indexer. +func (s *egressLister) List(selector labels.Selector) (ret []*v1beta1.Egress, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1beta1.Egress)) + }) + return ret, err +} + +// Get retrieves the Egress from the index for a given name. +func (s *egressLister) Get(name string) (*v1beta1.Egress, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1beta1.Resource("egress"), name) + } + return obj.(*v1beta1.Egress), nil +} diff --git a/pkg/client/listers/crd/v1beta1/expansion_generated.go b/pkg/client/listers/crd/v1beta1/expansion_generated.go index 2181551a0c7..b3ab30018c4 100644 --- a/pkg/client/listers/crd/v1beta1/expansion_generated.go +++ b/pkg/client/listers/crd/v1beta1/expansion_generated.go @@ -1,4 +1,4 @@ -// Copyright 2021 Antrea Authors +// Copyright 2023 Antrea Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,3 +23,7 @@ type AntreaAgentInfoListerExpansion interface{} // AntreaControllerInfoListerExpansion allows custom methods to be added to // AntreaControllerInfoLister. type AntreaControllerInfoListerExpansion interface{} + +// EgressListerExpansion allows custom methods to be added to +// EgressLister. +type EgressListerExpansion interface{} diff --git a/pkg/controller/egress/controller.go b/pkg/controller/egress/controller.go index 65ceee14324..cb93f600b7d 100644 --- a/pkg/controller/egress/controller.go +++ b/pkg/controller/egress/controller.go @@ -34,11 +34,11 @@ import ( "k8s.io/klog/v2" "antrea.io/antrea/pkg/apis/controlplane" - egressv1alpha2 "antrea.io/antrea/pkg/apis/crd/v1alpha2" + egressv1beta1 "antrea.io/antrea/pkg/apis/crd/v1beta1" "antrea.io/antrea/pkg/apiserver/storage" clientset "antrea.io/antrea/pkg/client/clientset/versioned" - egressinformers "antrea.io/antrea/pkg/client/informers/externalversions/crd/v1alpha2" - egresslisters "antrea.io/antrea/pkg/client/listers/crd/v1alpha2" + egressinformers "antrea.io/antrea/pkg/client/informers/externalversions/crd/v1beta1" + egresslisters "antrea.io/antrea/pkg/client/listers/crd/v1beta1" "antrea.io/antrea/pkg/controller/externalippool" "antrea.io/antrea/pkg/controller/grouping" antreatypes "antrea.io/antrea/pkg/controller/types" @@ -122,7 +122,7 @@ func NewEgressController(crdClient clientset.Interface, ) // externalIPPoolIndex will be used to get all Egresses associated with a given ExternalIPPool. egressInformer.Informer().AddIndexers(cache.Indexers{externalIPPoolIndex: func(obj interface{}) (strings []string, e error) { - egress, ok := obj.(*egressv1alpha2.Egress) + egress, ok := obj.(*egressv1beta1.Egress) if !ok { return nil, fmt.Errorf("obj is not Egress: %+v", obj) } @@ -163,7 +163,7 @@ func (c *EgressController) Run(stopCh <-chan struct{}) { } // restoreIPAllocations restores the existing EgressIPs of Egresses and records the successful ones in ipAllocationMap. -func (c *EgressController) restoreIPAllocations(egresses []*egressv1alpha2.Egress) { +func (c *EgressController) restoreIPAllocations(egresses []*egressv1beta1.Egress) { var previousIPAllocations []externalippool.IPAllocation for _, egress := range egresses { // Ignore Egress that is not associated to ExternalIPPool or doesn't have EgressIP assigned. @@ -239,7 +239,7 @@ func (c *EgressController) setIPAllocation(egressName string, ip net.IP, poolNam } // syncEgressIP is responsible for releasing stale EgressIP and allocating new EgressIP for an Egress if applicable. -func (c *EgressController) syncEgressIP(egress *egressv1alpha2.Egress) (net.IP, error) { +func (c *EgressController) syncEgressIP(egress *egressv1beta1.Egress) (net.IP, error) { prevIP, prevIPPool, exists := c.getIPAllocation(egress.Name) if exists { // The EgressIP and the ExternalIPPool don't change, do nothing. @@ -296,7 +296,7 @@ func (c *EgressController) syncEgressIP(egress *egressv1alpha2.Egress) (net.IP, } // updateEgressIP updates the Egress's EgressIP in Kubernetes API. -func (c *EgressController) updateEgressIP(egress *egressv1alpha2.Egress, ip string) error { +func (c *EgressController) updateEgressIP(egress *egressv1beta1.Egress, ip string) error { var egressIPPtr *string if len(ip) > 0 { egressIPPtr = &ip @@ -307,7 +307,7 @@ func (c *EgressController) updateEgressIP(egress *egressv1alpha2.Egress, ip stri }, } patchBytes, _ := json.Marshal(patch) - if _, err := c.crdClient.CrdV1alpha2().Egresses().Patch(context.TODO(), egress.Name, types.MergePatchType, patchBytes, metav1.PatchOptions{}); err != nil { + if _, err := c.crdClient.CrdV1beta1().Egresses().Patch(context.TODO(), egress.Name, types.MergePatchType, patchBytes, metav1.PatchOptions{}); err != nil { return fmt.Errorf("error when updating EgressIP for Egress %s: %v", egress.Name, err) } return nil @@ -401,7 +401,7 @@ func (c *EgressController) enqueueEgressGroup(key string) { // addEgress processes Egress ADD events and creates corresponding EgressGroup. func (c *EgressController) addEgress(obj interface{}) { - egress := obj.(*egressv1alpha2.Egress) + egress := obj.(*egressv1beta1.Egress) klog.InfoS("Processing Egress ADD event", "egress", egress.Name, "selector", egress.Spec.AppliedTo) // Create an EgressGroup object corresponding to this Egress and enqueue task to the workqueue. egressGroup := &antreatypes.EgressGroup{ @@ -417,8 +417,8 @@ func (c *EgressController) addEgress(obj interface{}) { // updateEgress processes Egress UPDATE events and updates corresponding EgressGroup. func (c *EgressController) updateEgress(old, cur interface{}) { - oldEgress := old.(*egressv1alpha2.Egress) - curEgress := cur.(*egressv1alpha2.Egress) + oldEgress := old.(*egressv1beta1.Egress) + curEgress := cur.(*egressv1beta1.Egress) klog.InfoS("Processing Egress UPDATE event", "egress", curEgress.Name, "selector", curEgress.Spec.AppliedTo) // TODO: Define custom Equal function to be more efficient. if !reflect.DeepEqual(oldEgress.Spec.AppliedTo, curEgress.Spec.AppliedTo) { @@ -433,7 +433,7 @@ func (c *EgressController) updateEgress(old, cur interface{}) { // deleteEgress processes Egress DELETE events and deletes corresponding EgressGroup. func (c *EgressController) deleteEgress(obj interface{}) { - egress := obj.(*egressv1alpha2.Egress) + egress := obj.(*egressv1beta1.Egress) klog.InfoS("Processing Egress DELETE event", "egress", egress.Name) c.egressGroupStore.Delete(egress.Name) // Unregister the group from the grouping interface. @@ -445,7 +445,7 @@ func (c *EgressController) deleteEgress(obj interface{}) { func (c *EgressController) enqueueEgresses(poolName string) { objects, _ := c.egressIndexer.ByIndex(externalIPPoolIndex, poolName) for _, object := range objects { - egress := object.(*egressv1alpha2.Egress) + egress := object.(*egressv1beta1.Egress) c.queue.Add(egress.Name) } } diff --git a/pkg/controller/egress/controller_test.go b/pkg/controller/egress/controller_test.go index a2e4d59fbe2..9d4f22ce3c8 100644 --- a/pkg/controller/egress/controller_test.go +++ b/pkg/controller/egress/controller_test.go @@ -39,6 +39,7 @@ import ( "antrea.io/antrea/pkg/apis/controlplane" "antrea.io/antrea/pkg/apis/crd/v1alpha2" + "antrea.io/antrea/pkg/apis/crd/v1beta1" "antrea.io/antrea/pkg/client/clientset/versioned" fakeversioned "antrea.io/antrea/pkg/client/clientset/versioned/fake" crdinformers "antrea.io/antrea/pkg/client/informers/externalversions" @@ -67,11 +68,11 @@ var ( eipFoo2 = newExternalIPPool("pool2", "", "2.2.2.10", "2.2.2.20") ) -func newEgress(name, egressIP, externalIPPool string, podSelector, namespaceSelector *metav1.LabelSelector) *v1alpha2.Egress { - egress := &v1alpha2.Egress{ +func newEgress(name, egressIP, externalIPPool string, podSelector, namespaceSelector *metav1.LabelSelector) *v1beta1.Egress { + egress := &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: name}, - Spec: v1alpha2.EgressSpec{ - AppliedTo: v1alpha2.AppliedTo{ + Spec: v1beta1.EgressSpec{ + AppliedTo: v1beta1.AppliedTo{ PodSelector: podSelector, NamespaceSelector: namespaceSelector, }, @@ -149,7 +150,7 @@ func newController(objects, crdObjects []runtime.Object) *egressController { generation := map[string]int64{} updateReactor := func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) { ua := action.(k8stesting.UpdateAction) - egress := ua.GetObject().(*v1alpha2.Egress) + egress := ua.GetObject().(*v1beta1.Egress) generation[egress.Name] += 1 egress.Generation = generation[egress.Name] return false, egress, nil @@ -182,7 +183,7 @@ func newController(objects, crdObjects []runtime.Object) *egressController { crdInformerFactory := crdinformers.NewSharedInformerFactory(crdClient, resyncPeriod) externalIPAllocator := externalippool.NewExternalIPPoolController(crdClient, crdInformerFactory.Crd().V1alpha2().ExternalIPPools()) egressGroupStore := store.NewEgressGroupStore() - egressInformer := crdInformerFactory.Crd().V1alpha2().Egresses() + egressInformer := crdInformerFactory.Crd().V1beta1().Egresses() groupEntityIndex := grouping.NewGroupEntityIndex() groupingController := grouping.NewGroupEntityController(groupEntityIndex, informerFactory.Core().V1().Pods(), @@ -203,16 +204,16 @@ func newController(objects, crdObjects []runtime.Object) *egressController { func TestAddEgress(t *testing.T) { tests := []struct { name string - inputEgress *v1alpha2.Egress + inputEgress *v1beta1.Egress expectedEgressIP string expectedEgressGroups map[string]*controlplane.EgressGroup }{ { name: "Egress with podSelector and namespaceSelector", - inputEgress: &v1alpha2.Egress{ + inputEgress: &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ - AppliedTo: v1alpha2.AppliedTo{ + Spec: v1beta1.EgressSpec{ + AppliedTo: v1beta1.AppliedTo{ PodSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{"app": "foo"}, }, @@ -243,10 +244,10 @@ func TestAddEgress(t *testing.T) { }, { name: "Egress with namespaceSelector", - inputEgress: &v1alpha2.Egress{ + inputEgress: &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ - AppliedTo: v1alpha2.AppliedTo{ + Spec: v1beta1.EgressSpec{ + AppliedTo: v1beta1.AppliedTo{ NamespaceSelector: &metav1.LabelSelector{ MatchLabels: nsDefault.Labels, }, @@ -275,10 +276,10 @@ func TestAddEgress(t *testing.T) { }, { name: "Egress with podSelector", - inputEgress: &v1alpha2.Egress{ + inputEgress: &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ - AppliedTo: v1alpha2.AppliedTo{ + Spec: v1beta1.EgressSpec{ + AppliedTo: v1beta1.AppliedTo{ PodSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{"app": "foo"}, }, @@ -307,10 +308,10 @@ func TestAddEgress(t *testing.T) { }, { name: "Egress with podSelector and empty EgressIP", - inputEgress: &v1alpha2.Egress{ + inputEgress: &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ - AppliedTo: v1alpha2.AppliedTo{ + Spec: v1beta1.EgressSpec{ + AppliedTo: v1beta1.AppliedTo{ PodSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{"app": "foo"}, }, @@ -359,7 +360,7 @@ func TestAddEgress(t *testing.T) { go controller.groupingController.Run(stopCh) go controller.Run(stopCh) - controller.crdClient.CrdV1alpha2().Egresses().Create(context.TODO(), tt.inputEgress, metav1.CreateOptions{}) + controller.crdClient.CrdV1beta1().Egresses().Create(context.TODO(), tt.inputEgress, metav1.CreateOptions{}) for nodeName, expectedEgressGroup := range tt.expectedEgressGroups { watcher, err := controller.egressGroupStore.Watch(context.TODO(), "", nil, fields.ParseSelectorOrDie(fmt.Sprintf("nodeName=%s", nodeName))) @@ -388,7 +389,7 @@ func TestAddEgress(t *testing.T) { } } - gotEgress, err := controller.crdClient.CrdV1alpha2().Egresses().Get(context.TODO(), tt.inputEgress.Name, metav1.GetOptions{}) + gotEgress, err := controller.crdClient.CrdV1beta1().Egresses().Get(context.TODO(), tt.inputEgress.Name, metav1.GetOptions{}) require.NoError(t, err) assert.Equal(t, tt.expectedEgressIP, gotEgress.Spec.EgressIP) if gotEgress.Spec.ExternalIPPool != "" && gotEgress.Spec.EgressIP != "" { @@ -412,10 +413,10 @@ func TestUpdateEgress(t *testing.T) { go controller.groupingController.Run(stopCh) go controller.Run(stopCh) - egress := &v1alpha2.Egress{ + egress := &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ - AppliedTo: v1alpha2.AppliedTo{ + Spec: v1beta1.EgressSpec{ + AppliedTo: v1beta1.AppliedTo{ PodSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{"app": "foo"}, }, @@ -424,7 +425,7 @@ func TestUpdateEgress(t *testing.T) { ExternalIPPool: eipFoo1.Name, }, } - controller.crdClient.CrdV1alpha2().Egresses().Create(context.TODO(), egress, metav1.CreateOptions{}) + controller.crdClient.CrdV1beta1().Egresses().Create(context.TODO(), egress, metav1.CreateOptions{}) watcher, err := controller.egressGroupStore.Watch(context.TODO(), "", nil, fields.ParseSelectorOrDie(fmt.Sprintf("nodeName=%s", node1))) assert.NoError(t, err) @@ -446,7 +447,7 @@ func TestUpdateEgress(t *testing.T) { getEgressIP := func() string { var err error - egress, err = controller.crdClient.CrdV1alpha2().Egresses().Get(context.TODO(), egress.Name, metav1.GetOptions{}) + egress, err = controller.crdClient.CrdV1beta1().Egresses().Get(context.TODO(), egress.Name, metav1.GetOptions{}) if err != nil { return "" } @@ -490,14 +491,14 @@ func TestUpdateEgress(t *testing.T) { }, getEvent()) // Updating the Egress's spec to make it match no Pods on this Node and use a new ExternalIPPool. - egress.Spec.AppliedTo = v1alpha2.AppliedTo{ + egress.Spec.AppliedTo = v1beta1.AppliedTo{ PodSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{"app": "non-existing-app"}, }, } egress.Spec.ExternalIPPool = eipFoo2.Name egress.Spec.EgressIP = "" - controller.crdClient.CrdV1alpha2().Egresses().Update(context.TODO(), egress, metav1.UpdateOptions{}) + controller.crdClient.CrdV1beta1().Egresses().Update(context.TODO(), egress, metav1.UpdateOptions{}) assert.Equal(t, &watch.Event{ Type: watch.Deleted, Object: &controlplane.EgressGroup{ @@ -531,7 +532,7 @@ func TestUpdateEgress(t *testing.T) { checkExternalIPPoolUsed(t, controller, eipFoo2.Name, 1) // Delete the Egress. The EgressIP should be released. - controller.crdClient.CrdV1alpha2().Egresses().Delete(context.TODO(), egress.Name, metav1.DeleteOptions{}) + controller.crdClient.CrdV1beta1().Egresses().Delete(context.TODO(), egress.Name, metav1.DeleteOptions{}) assert.Eventually(t, func() bool { _, _, exists := controller.getIPAllocation(egress.Name) return !exists @@ -542,26 +543,26 @@ func TestUpdateEgress(t *testing.T) { func TestSyncEgressIP(t *testing.T) { tests := []struct { name string - existingEgresses []*v1alpha2.Egress + existingEgresses []*v1beta1.Egress existingExternalIPPool *v1alpha2.ExternalIPPool - inputEgress *v1alpha2.Egress + inputEgress *v1beta1.Egress expectedEgressIP string expectedExternalIPPoolUsed int expectErr bool }{ { name: "Egress with empty EgressIP and existing ExternalIPPool", - existingEgresses: []*v1alpha2.Egress{ + existingEgresses: []*v1beta1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ EgressIP: "1.1.1.1", ExternalIPPool: "ipPoolA", }, }, { ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ EgressIP: "1.1.1.2", ExternalIPPool: "ipPoolA", }, @@ -570,9 +571,9 @@ func TestSyncEgressIP(t *testing.T) { // The first IPRange 1.1.1.0/30 should be occupied by the existing Egresses. The input Egress's IP should // be allocated from the second IPRange 1.1.2.10-1.1.2.20. existingExternalIPPool: newExternalIPPool("ipPoolA", "1.1.1.0/30", "1.1.2.10", "1.1.2.20"), - inputEgress: &v1alpha2.Egress{ + inputEgress: &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressC", UID: "uidC"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ EgressIP: "", ExternalIPPool: "ipPoolA", }, @@ -584,9 +585,9 @@ func TestSyncEgressIP(t *testing.T) { { name: "Egress with empty EgressIP and non-existing ExternalIPPool", existingExternalIPPool: newExternalIPPool("ipPoolA", "1.1.1.0/24", "", ""), - inputEgress: &v1alpha2.Egress{ + inputEgress: &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ EgressIP: "", ExternalIPPool: "ipPoolB", }, @@ -598,9 +599,9 @@ func TestSyncEgressIP(t *testing.T) { { name: "[IPv6]Egress with empty EgressIP and proper ExternalIPPool", existingExternalIPPool: newExternalIPPool("ipPoolA", "2021:2::aaa0/124", "", ""), - inputEgress: &v1alpha2.Egress{ + inputEgress: &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ ExternalIPPool: "ipPoolA", }, }, @@ -611,9 +612,9 @@ func TestSyncEgressIP(t *testing.T) { { name: "Egress with non-empty EgressIP and proper ExternalIPPool", existingExternalIPPool: newExternalIPPool("ipPoolA", "1.1.1.0/24", "", ""), - inputEgress: &v1alpha2.Egress{ + inputEgress: &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ EgressIP: "1.1.1.2", ExternalIPPool: "ipPoolA", }, @@ -625,9 +626,9 @@ func TestSyncEgressIP(t *testing.T) { { name: "Egress with non-empty EgressIP and improper ExternalIPPool", existingExternalIPPool: newExternalIPPool("ipPoolA", "1.1.1.0/24", "", ""), - inputEgress: &v1alpha2.Egress{ + inputEgress: &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ EgressIP: "1.1.2.2", ExternalIPPool: "ipPoolA", }, @@ -638,19 +639,19 @@ func TestSyncEgressIP(t *testing.T) { }, { name: "Egress with updated EgressIP", - existingEgresses: []*v1alpha2.Egress{ + existingEgresses: []*v1beta1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ EgressIP: "1.1.1.2", ExternalIPPool: "ipPoolA", }, }, }, existingExternalIPPool: newExternalIPPool("ipPoolA", "1.1.1.0/24", "", ""), - inputEgress: &v1alpha2.Egress{ + inputEgress: &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ EgressIP: "1.1.1.3", ExternalIPPool: "ipPoolA", }, @@ -661,19 +662,19 @@ func TestSyncEgressIP(t *testing.T) { }, { name: "Egress with unchanged EgressIP", - existingEgresses: []*v1alpha2.Egress{ + existingEgresses: []*v1beta1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ EgressIP: "1.1.1.2", ExternalIPPool: "ipPoolA", }, }, }, existingExternalIPPool: newExternalIPPool("ipPoolA", "1.1.1.0/24", "", ""), - inputEgress: &v1alpha2.Egress{ + inputEgress: &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ EgressIP: "1.1.1.2", ExternalIPPool: "ipPoolA", }, @@ -684,19 +685,19 @@ func TestSyncEgressIP(t *testing.T) { }, { name: "Egress with conflicting EgressIP", - existingEgresses: []*v1alpha2.Egress{ + existingEgresses: []*v1beta1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ EgressIP: "1.1.1.2", ExternalIPPool: "ipPoolA", }, }, }, existingExternalIPPool: newExternalIPPool("ipPoolA", "1.1.1.0/24", "", ""), - inputEgress: &v1alpha2.Egress{ + inputEgress: &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressB", UID: "uidB"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ EgressIP: "1.1.1.2", ExternalIPPool: "ipPoolA", }, @@ -707,19 +708,19 @@ func TestSyncEgressIP(t *testing.T) { }, { name: "Egress with empty ExternalIPPool", - existingEgresses: []*v1alpha2.Egress{ + existingEgresses: []*v1beta1.Egress{ { ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ EgressIP: "1.1.1.2", ExternalIPPool: "ipPoolA", }, }, }, existingExternalIPPool: newExternalIPPool("ipPoolA", "1.1.1.0/24", "", ""), - inputEgress: &v1alpha2.Egress{ + inputEgress: &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, - Spec: v1alpha2.EgressSpec{ + Spec: v1beta1.EgressSpec{ EgressIP: "10.10.10.10", }, }, diff --git a/test/e2e/egress_test.go b/test/e2e/egress_test.go index 99a16de0c7e..9493e1aec3b 100644 --- a/test/e2e/egress_test.go +++ b/test/e2e/egress_test.go @@ -34,6 +34,7 @@ import ( "antrea.io/antrea/pkg/agent/config" "antrea.io/antrea/pkg/apis/crd/v1alpha2" + "antrea.io/antrea/pkg/apis/crd/v1beta1" "antrea.io/antrea/pkg/features" ) @@ -215,13 +216,13 @@ ip netns exec %[1]s /agnhost netexec }, } egress := data.createEgress(t, "egress-", matchExpressions, nil, "", egressNodeIP) - defer data.crdClient.CrdV1alpha2().Egresses().Delete(context.TODO(), egress.Name, metav1.DeleteOptions{}) + defer data.crdClient.CrdV1beta1().Egresses().Delete(context.TODO(), egress.Name, metav1.DeleteOptions{}) assertClientIP(localPod, egressNodeIP) assertClientIP(remotePod, egressNodeIP) var err error err = wait.Poll(time.Millisecond*100, time.Second, func() (bool, error) { - egress, err = data.crdClient.CrdV1alpha2().Egresses().Get(context.TODO(), egress.Name, metav1.GetOptions{}) + egress, err = data.crdClient.CrdV1beta1().Egresses().Get(context.TODO(), egress.Name, metav1.GetOptions{}) if err != nil { return false, err } @@ -249,12 +250,12 @@ ip netns exec %[1]s /agnhost netexec assert.NoError(t, err, "Failed to get expected client IP %s for Pod initial-ip-checker", initialIPChecker) t.Log("Updating the Egress's AppliedTo to remotePod only") - egress.Spec.AppliedTo = v1alpha2.AppliedTo{ + egress.Spec.AppliedTo = v1beta1.AppliedTo{ PodSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{"antrea-e2e": remotePod}, }, } - egress, err = data.crdClient.CrdV1alpha2().Egresses().Update(context.TODO(), egress, metav1.UpdateOptions{}) + egress, err = data.crdClient.CrdV1beta1().Egresses().Update(context.TODO(), egress, metav1.UpdateOptions{}) if err != nil { t.Fatalf("Failed to update Egress %v: %v", egress, err) } @@ -262,12 +263,12 @@ ip netns exec %[1]s /agnhost netexec assertClientIP(remotePod, egressNodeIP) t.Log("Updating the Egress's AppliedTo to localPod only") - egress.Spec.AppliedTo = v1alpha2.AppliedTo{ + egress.Spec.AppliedTo = v1beta1.AppliedTo{ PodSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{"antrea-e2e": localPod}, }, } - egress, err = data.crdClient.CrdV1alpha2().Egresses().Update(context.TODO(), egress, metav1.UpdateOptions{}) + egress, err = data.crdClient.CrdV1beta1().Egresses().Update(context.TODO(), egress, metav1.UpdateOptions{}) if err != nil { t.Fatalf("Failed to update Egress %v: %v", egress, err) } @@ -276,7 +277,7 @@ ip netns exec %[1]s /agnhost netexec t.Logf("Updating the Egress's EgressIP to %s", tt.localIP1) egress.Spec.EgressIP = tt.localIP1 - egress, err = data.crdClient.CrdV1alpha2().Egresses().Update(context.TODO(), egress, metav1.UpdateOptions{}) + egress, err = data.crdClient.CrdV1beta1().Egresses().Update(context.TODO(), egress, metav1.UpdateOptions{}) if err != nil { t.Fatalf("Failed to update Egress %v: %v", egress, err) } @@ -284,7 +285,7 @@ ip netns exec %[1]s /agnhost netexec assertConnError(remotePod) t.Log("Deleting the Egress") - err = data.crdClient.CrdV1alpha2().Egresses().Delete(context.TODO(), egress.Name, metav1.DeleteOptions{}) + err = data.crdClient.CrdV1beta1().Egresses().Delete(context.TODO(), egress.Name, metav1.DeleteOptions{}) if err != nil { t.Fatalf("Failed to delete Egress %v: %v", egress, err) } @@ -367,11 +368,11 @@ func testEgressCRUD(t *testing.T, data *TestData) { defer data.crdClient.CrdV1alpha2().ExternalIPPools().Delete(context.TODO(), pool.Name, metav1.DeleteOptions{}) egress := data.createEgress(t, "crud-egress-", nil, map[string]string{"foo": "bar"}, pool.Name, "") - defer data.crdClient.CrdV1alpha2().Egresses().Delete(context.TODO(), egress.Name, metav1.DeleteOptions{}) + defer data.crdClient.CrdV1beta1().Egresses().Delete(context.TODO(), egress.Name, metav1.DeleteOptions{}) // Use Poll to wait the interval before the first run to detect the case that the IP is assigned to any Node // when it's not supposed to. err := wait.Poll(500*time.Millisecond, 3*time.Second, func() (done bool, err error) { - egress, err = data.crdClient.CrdV1alpha2().Egresses().Get(context.TODO(), egress.Name, metav1.GetOptions{}) + egress, err = data.crdClient.CrdV1beta1().Egresses().Get(context.TODO(), egress.Name, metav1.GetOptions{}) if err != nil { return false, err } @@ -416,7 +417,7 @@ func testEgressCRUD(t *testing.T, data *TestData) { } checkEIPStatus(1) - err = data.crdClient.CrdV1alpha2().Egresses().Delete(context.TODO(), egress.Name, metav1.DeleteOptions{}) + err = data.crdClient.CrdV1beta1().Egresses().Delete(context.TODO(), egress.Name, metav1.DeleteOptions{}) require.NoError(t, err, "Failed to delete Egress") if egress.Status.EgressNode != "" { err := wait.PollImmediate(200*time.Millisecond, timeout, func() (done bool, err error) { @@ -484,7 +485,7 @@ func testEgressUpdateEgressIP(t *testing.T, data *TestData) { defer data.crdClient.CrdV1alpha2().ExternalIPPools().Delete(context.TODO(), newPool.Name, metav1.DeleteOptions{}) egress := data.createEgress(t, "egress-", nil, map[string]string{"foo": "bar"}, originalPool.Name, "") - defer data.crdClient.CrdV1alpha2().Egresses().Delete(context.TODO(), egress.Name, metav1.DeleteOptions{}) + defer data.crdClient.CrdV1beta1().Egresses().Delete(context.TODO(), egress.Name, metav1.DeleteOptions{}) egress, err := data.checkEgressState(egress.Name, tt.originalEgressIP, tt.originalNode, "", time.Second) require.NoError(t, err) @@ -493,9 +494,9 @@ func testEgressUpdateEgressIP(t *testing.T, data *TestData) { err = retry.RetryOnConflict(retry.DefaultRetry, func() error { toUpdate.Spec.ExternalIPPool = newPool.Name toUpdate.Spec.EgressIP = tt.newEgressIP - _, err = data.crdClient.CrdV1alpha2().Egresses().Update(context.TODO(), toUpdate, metav1.UpdateOptions{}) + _, err = data.crdClient.CrdV1beta1().Egresses().Update(context.TODO(), toUpdate, metav1.UpdateOptions{}) if err != nil && errors.IsConflict(err) { - toUpdate, _ = data.crdClient.CrdV1alpha2().Egresses().Get(context.TODO(), egress.Name, metav1.GetOptions{}) + toUpdate, _ = data.crdClient.CrdV1beta1().Egresses().Get(context.TODO(), egress.Name, metav1.GetOptions{}) } return err }) @@ -632,7 +633,7 @@ func testEgressMigration(t *testing.T, data *TestData, triggerFunc, revertFunc f defer data.crdClient.CrdV1alpha2().ExternalIPPools().Delete(context.TODO(), externalIPPoolTwoNodes.Name, metav1.DeleteOptions{}) egress := data.createEgress(t, "migration-egress-", nil, map[string]string{"foo": "bar"}, externalIPPoolTwoNodes.Name, "") - defer data.crdClient.CrdV1alpha2().Egresses().Delete(context.TODO(), egress.Name, metav1.DeleteOptions{}) + defer data.crdClient.CrdV1beta1().Egresses().Delete(context.TODO(), egress.Name, metav1.DeleteOptions{}) var err error egress, err = data.waitForEgressRealized(egress) @@ -675,12 +676,12 @@ func testEgressMigration(t *testing.T, data *TestData, triggerFunc, revertFunc f checkIPNeighbor(fromNode) } -func (data *TestData) checkEgressState(egressName, expectedIP, expectedNode, otherNode string, timeout time.Duration) (*v1alpha2.Egress, error) { - var egress *v1alpha2.Egress +func (data *TestData) checkEgressState(egressName, expectedIP, expectedNode, otherNode string, timeout time.Duration) (*v1beta1.Egress, error) { + var egress *v1beta1.Egress var expectedNodeHasIP, otherNodeHasIP bool pollErr := wait.PollImmediate(200*time.Millisecond, timeout, func() (bool, error) { var err error - egress, err = data.crdClient.CrdV1alpha2().Egresses().Get(context.TODO(), egressName, metav1.GetOptions{}) + egress, err = data.crdClient.CrdV1beta1().Egresses().Get(context.TODO(), egressName, metav1.GetOptions{}) if err != nil { return false, err } @@ -801,11 +802,11 @@ func (data *TestData) createExternalIPPool(t *testing.T, generateName string, ip return pool } -func (data *TestData) createEgress(t *testing.T, generateName string, matchExpressions []metav1.LabelSelectorRequirement, matchLabels map[string]string, externalPoolName string, egressIP string) *v1alpha2.Egress { - egress := &v1alpha2.Egress{ +func (data *TestData) createEgress(t *testing.T, generateName string, matchExpressions []metav1.LabelSelectorRequirement, matchLabels map[string]string, externalPoolName string, egressIP string) *v1beta1.Egress { + egress := &v1beta1.Egress{ ObjectMeta: metav1.ObjectMeta{GenerateName: generateName}, - Spec: v1alpha2.EgressSpec{ - AppliedTo: v1alpha2.AppliedTo{ + Spec: v1beta1.EgressSpec{ + AppliedTo: v1beta1.AppliedTo{ PodSelector: &metav1.LabelSelector{ MatchExpressions: matchExpressions, MatchLabels: matchLabels, @@ -815,14 +816,14 @@ func (data *TestData) createEgress(t *testing.T, generateName string, matchExpre EgressIP: egressIP, }, } - egress, err := data.crdClient.CrdV1alpha2().Egresses().Create(context.TODO(), egress, metav1.CreateOptions{}) + egress, err := data.crdClient.CrdV1beta1().Egresses().Create(context.TODO(), egress, metav1.CreateOptions{}) require.NoError(t, err, "Failed to create Egress") return egress } -func (data *TestData) waitForEgressRealized(egress *v1alpha2.Egress) (*v1alpha2.Egress, error) { +func (data *TestData) waitForEgressRealized(egress *v1beta1.Egress) (*v1beta1.Egress, error) { err := wait.PollImmediate(200*time.Millisecond, waitEgressRealizedTimeout, func() (done bool, err error) { - egress, err = data.crdClient.CrdV1alpha2().Egresses().Get(context.TODO(), egress.Name, metav1.GetOptions{}) + egress, err = data.crdClient.CrdV1beta1().Egresses().Get(context.TODO(), egress.Name, metav1.GetOptions{}) if err != nil { return false, err }