From 169bc643158740d7c8c14cf920c36079591988f6 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 20 Oct 2023 15:19:24 +0200 Subject: [PATCH 001/121] Added dns aliases types and crd --- Makefile | 7 +- .../templates/radix-operator-rbac.yaml | 2 + .../templates/radixapplication.yaml | 44 +++- .../templates/radixdnsalias.yaml | 71 +++++++ json-schema/radixapplication.json | 48 ++++- json-schema/radixdnsalias.json | 58 ++++++ pkg/apis/radix/v1/radixapptypes.go | 34 ++- pkg/apis/radix/v1/radixdnsalias.go | 44 ++++ pkg/apis/radix/v1/zz_generated.deepcopy.go | 115 +++++++++++ pkg/apis/radixvalidators/validate_ra.go | 6 +- pkg/apis/radixvalidators/validate_rr.go | 8 +- .../typed/radix/v1/fake/fake_radix_client.go | 4 + .../typed/radix/v1/fake/fake_radixdnsalias.go | 142 +++++++++++++ .../typed/radix/v1/generated_expansion.go | 2 + .../versioned/typed/radix/v1/radix_client.go | 5 + .../versioned/typed/radix/v1/radixdnsalias.go | 195 ++++++++++++++++++ .../informers/externalversions/generic.go | 2 + .../externalversions/radix/v1/interface.go | 7 + .../radix/v1/radixdnsalias.go | 90 ++++++++ .../listers/radix/v1/expansion_generated.go | 8 + pkg/client/listers/radix/v1/radixdnsalias.go | 99 +++++++++ 21 files changed, 974 insertions(+), 17 deletions(-) create mode 100644 charts/radix-operator/templates/radixdnsalias.yaml create mode 100644 json-schema/radixdnsalias.json create mode 100644 pkg/apis/radix/v1/radixdnsalias.go create mode 100644 pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go create mode 100644 pkg/client/clientset/versioned/typed/radix/v1/radixdnsalias.go create mode 100644 pkg/client/informers/externalversions/radix/v1/radixdnsalias.go create mode 100644 pkg/client/listers/radix/v1/radixdnsalias.go diff --git a/Makefile b/Makefile index 0c3c035e9..c76ef732b 100644 --- a/Makefile +++ b/Makefile @@ -129,7 +129,7 @@ code-gen: $(GOPATH)/pkg/mod/k8s.io/code-generator@v0.25.3/generate-groups.sh all $(ROOT_PACKAGE)/pkg/client $(ROOT_PACKAGE)/pkg/apis $(CUSTOM_RESOURCE_NAME):$(CUSTOM_RESOURCE_VERSION) --go-header-file $(GOPATH)/pkg/mod/k8s.io/code-generator@v0.25.3/hack/boilerplate.go.txt .PHONY: crds -crds: temp-crds radixapplication-crd radixbatch-crd delete-temp-crds +crds: temp-crds radixapplication-crd radixbatch-crd radixdnsalias-crd delete-temp-crds .PHONY: radixapplication-crd radixapplication-crd: temp-crds @@ -140,6 +140,11 @@ radixapplication-crd: temp-crds radixbatch-crd: temp-crds cp $(CRD_TEMP_DIR)radix.equinor.com_radixbatches.yaml $(CRD_CHART_DIR)radixbatch.yaml +.PHONY: radixdnsalias-crd +radixdnsalias-crd: temp-crds + cp $(CRD_TEMP_DIR)radix.equinor.com_radixdnsalias.yaml $(CRD_CHART_DIR)radixdnsalias.yaml + yq eval '.spec.versions[0].schema.openAPIV3Schema' -ojson $(CRD_CHART_DIR)radixdnsalias.yaml > $(JSON_SCHEMA_DIR)radixdnsalias.json + .PHONY: temp-crds temp-crds: controller-gen echo "tempcrdrun" diff --git a/charts/radix-operator/templates/radix-operator-rbac.yaml b/charts/radix-operator/templates/radix-operator-rbac.yaml index c4efedb89..856b36ec8 100644 --- a/charts/radix-operator/templates/radix-operator-rbac.yaml +++ b/charts/radix-operator/templates/radix-operator-rbac.yaml @@ -29,6 +29,8 @@ rules: - radixalerts/status - radixbatches - radixbatches/status + - radixdnsalias + - radixdnsalias/status verbs: - get - list diff --git a/charts/radix-operator/templates/radixapplication.yaml b/charts/radix-operator/templates/radixapplication.yaml index 7ca2c5255..78ff2dc9f 100644 --- a/charts/radix-operator/templates/radixapplication.yaml +++ b/charts/radix-operator/templates/radixapplication.yaml @@ -882,7 +882,7 @@ spec: description: Name of the component. maxLength: 253 minLength: 1 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string node: description: 'Defines GPU requirements for the component. More @@ -1074,6 +1074,42 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map + dnsAlias: + description: 'List of DNS names and which component and environment + incoming requests shall be routed to. More info: https://www.radix.equinor.com/references/reference-radix-config/#dnsalias' + items: + description: DNSAlias defines mapping between an DNS alias and a + component and environment. + properties: + component: + description: Name of the component that shall receive the incoming + requests. + maxLength: 63 + minLength: 1 + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ + type: string + domain: + description: Domain name, e.g. my-app, which will prefix full + internal alias my-app.radix.equinor.com + maxLength: 63 + minLength: 1 + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ + type: string + environment: + description: Name of the environment for the component. + maxLength: 63 + minLength: 1 + pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + type: string + required: + - component + - domain + - environment + type: object + type: array + x-kubernetes-list-map-keys: + - domain + x-kubernetes-list-type: map dnsAppAlias: description: 'Configure a component and environment to be linked to the app alias DNS record. More info: https://www.radix.equinor.com/references/reference-radix-config/#dnsappalias' @@ -1083,7 +1119,7 @@ spec: requests. maxLength: 63 minLength: 1 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string environment: description: Name of the environment for the component. @@ -1110,7 +1146,7 @@ spec: requests. maxLength: 63 minLength: 1 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string environment: description: Name of the environment for the component. @@ -1729,7 +1765,7 @@ spec: to. maxLength: 253 minLength: 1 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string node: description: 'Defines GPU requirements for the job. More info: diff --git a/charts/radix-operator/templates/radixdnsalias.yaml b/charts/radix-operator/templates/radixdnsalias.yaml new file mode 100644 index 000000000..a40d70a90 --- /dev/null +++ b/charts/radix-operator/templates/radixdnsalias.yaml @@ -0,0 +1,71 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.10.0 + creationTimestamp: null + name: radixdnsalias.radix.equinor.com +spec: + group: radix.equinor.com + names: + kind: RadixDNSAlias + listKind: RadixDNSAliasList + plural: radixdnsalias + shortNames: + - rda + singular: radixdnsalias + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: RadixDNSAlias is a Custom Resource Definition + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: RadixDNSAliasSpec is the spec for an RadixDNSAlias + properties: + component: + description: Name of the component that shall receive the incoming + requests. + maxLength: 63 + minLength: 1 + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ + type: string + environment: + description: Name of the environment for the component. + maxLength: 63 + minLength: 1 + pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + type: string + required: + - component + - environment + type: object + status: + description: RadixDNSAliasStatus is the status for an RadixDNSAlias + properties: + reconciled: + format: date-time + type: string + required: + - reconciled + type: object + required: + - spec + - status + type: object + served: true + storage: true diff --git a/json-schema/radixapplication.json b/json-schema/radixapplication.json index 3e887af7a..1763ea299 100644 --- a/json-schema/radixapplication.json +++ b/json-schema/radixapplication.json @@ -872,7 +872,7 @@ "description": "Name of the component.", "maxLength": 253, "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" }, "node": { @@ -1083,6 +1083,46 @@ ], "x-kubernetes-list-type": "map" }, + "dnsAlias": { + "description": "List of DNS names and which component and environment incoming requests shall be routed to. More info: https://www.radix.equinor.com/references/reference-radix-config/#dnsalias", + "items": { + "description": "DNSAlias defines mapping between an DNS alias and a component and environment.", + "properties": { + "component": { + "description": "Name of the component that shall receive the incoming requests.", + "maxLength": 63, + "minLength": 1, + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", + "type": "string" + }, + "domain": { + "description": "Domain name, e.g. my-app, which will prefix full internal alias my-app.radix.equinor.com", + "maxLength": 63, + "minLength": 1, + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", + "type": "string" + }, + "environment": { + "description": "Name of the environment for the component.", + "maxLength": 63, + "minLength": 1, + "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "type": "string" + } + }, + "required": [ + "component", + "domain", + "environment" + ], + "type": "object" + }, + "type": "array", + "x-kubernetes-list-map-keys": [ + "domain" + ], + "x-kubernetes-list-type": "map" + }, "dnsAppAlias": { "description": "Configure a component and environment to be linked to the app alias DNS record. More info: https://www.radix.equinor.com/references/reference-radix-config/#dnsappalias", "properties": { @@ -1090,7 +1130,7 @@ "description": "Name of the component that shall receive the incoming requests.", "maxLength": 63, "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" }, "environment": { @@ -1119,7 +1159,7 @@ "description": "Name of the component that shall receive the incoming requests.", "maxLength": 63, "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" }, "environment": { @@ -1752,7 +1792,7 @@ "description": "Name of the environment which the settings applies to.", "maxLength": 253, "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" }, "node": { diff --git a/json-schema/radixdnsalias.json b/json-schema/radixdnsalias.json new file mode 100644 index 000000000..dd74c60ee --- /dev/null +++ b/json-schema/radixdnsalias.json @@ -0,0 +1,58 @@ +{ + "description": "RadixDNSAlias is a Custom Resource Definition", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "type": "object" + }, + "spec": { + "description": "RadixDNSAliasSpec is the spec for an RadixDNSAlias", + "properties": { + "component": { + "description": "Name of the component that shall receive the incoming requests.", + "maxLength": 63, + "minLength": 1, + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", + "type": "string" + }, + "environment": { + "description": "Name of the environment for the component.", + "maxLength": 63, + "minLength": 1, + "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "type": "string" + } + }, + "required": [ + "component", + "environment" + ], + "type": "object" + }, + "status": { + "description": "RadixDNSAliasStatus is the status for an RadixDNSAlias", + "properties": { + "reconciled": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "reconciled" + ], + "type": "object" + } + }, + "required": [ + "spec", + "status" + ], + "type": "object" +} diff --git a/pkg/apis/radix/v1/radixapptypes.go b/pkg/apis/radix/v1/radixapptypes.go index 3ccd07133..e5d71abbe 100644 --- a/pkg/apis/radix/v1/radixapptypes.go +++ b/pkg/apis/radix/v1/radixapptypes.go @@ -66,6 +66,13 @@ type RadixApplicationSpec struct { // +optional DNSExternalAlias []ExternalAlias `json:"dnsExternalAlias,omitempty"` + // List of DNS names and which component and environment incoming requests shall be routed to. + // More info: https://www.radix.equinor.com/references/reference-radix-config/#dnsalias + // +listType=map + // +listMapKey=domain + // +optional + DNSAlias []DNSAlias `json:"dnsAlias,omitempty"` + // Defines protected container registries used by components or jobs. // More info: https://www.radix.equinor.com/references/reference-radix-config/#privateimagehubs // +optional @@ -185,7 +192,7 @@ type AppAlias struct { // Name of the component that shall receive the incoming requests. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 - // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ Component string `json:"component,omitempty"` } @@ -206,7 +213,28 @@ type ExternalAlias struct { // Name of the component that shall receive the incoming requests. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ + Component string `json:"component"` +} + +// DNSAlias defines mapping between an DNS alias and a component and environment. +type DNSAlias struct { + // Domain name, e.g. my-app, which will prefix full internal alias my-app.radix.equinor.com + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:Pattern=`^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$` + Domain string `json:"domain"` + + // Name of the environment for the component. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + Environment string `json:"environment"` + + // Name of the component that shall receive the incoming requests. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ Component string `json:"component"` } @@ -246,7 +274,7 @@ type RadixComponent struct { // Name of the component. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 - // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ Name string `json:"name"` // Path to the Dockerfile that builds the component. @@ -427,7 +455,7 @@ type RadixJobComponent struct { // Name of the environment which the settings applies to. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 - // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ Name string `json:"name"` // Path to the Dockerfile that builds the job. diff --git a/pkg/apis/radix/v1/radixdnsalias.go b/pkg/apis/radix/v1/radixdnsalias.go new file mode 100644 index 000000000..64dc7a916 --- /dev/null +++ b/pkg/apis/radix/v1/radixdnsalias.go @@ -0,0 +1,44 @@ +package v1 + +import meta "k8s.io/apimachinery/pkg/apis/meta/v1" + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:path=radixdnsalias,scope=Cluster,shortName=rda + +// RadixDNSAlias is a Custom Resource Definition +type RadixDNSAlias struct { + meta.TypeMeta `json:",inline" yaml:",inline"` + meta.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"` + Spec RadixDNSAliasSpec `json:"spec" yaml:"spec"` + Status RadixDNSAliasStatus `json:"status" yaml:"status"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// RadixDNSAliasList is a list of RadixDNSAliases +type RadixDNSAliasList struct { + meta.TypeMeta `json:",inline" yaml:",inline"` + meta.ListMeta `json:"metadata" yaml:"metadata"` + Items []RadixDNSAlias `json:"items" yaml:"items"` +} + +// RadixDNSAliasSpec is the spec for an RadixDNSAlias +type RadixDNSAliasSpec struct { + // Name of the environment for the component. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + Environment string `json:"environment"` + + // Name of the component that shall receive the incoming requests. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ + Component string `json:"component"` +} + +// RadixDNSAliasStatus is the status for an RadixDNSAlias +type RadixDNSAliasStatus struct { + Reconciled meta.Time `json:"reconciled" yaml:"reconciled"` +} diff --git a/pkg/apis/radix/v1/zz_generated.deepcopy.go b/pkg/apis/radix/v1/zz_generated.deepcopy.go index 50c7db029..67834effa 100644 --- a/pkg/apis/radix/v1/zz_generated.deepcopy.go +++ b/pkg/apis/radix/v1/zz_generated.deepcopy.go @@ -175,6 +175,22 @@ func (in *ComponentPort) DeepCopy() *ComponentPort { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DNSAlias) DeepCopyInto(out *DNSAlias) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSAlias. +func (in *DNSAlias) DeepCopy() *DNSAlias { + if in == nil { + return nil + } + out := new(DNSAlias) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EgressConfig) DeepCopyInto(out *EgressConfig) { *out = *in @@ -774,6 +790,11 @@ func (in *RadixApplicationSpec) DeepCopyInto(out *RadixApplicationSpec) { *out = make([]ExternalAlias, len(*in)) copy(*out, *in) } + if in.DNSAlias != nil { + in, out := &in.DNSAlias, &out.DNSAlias + *out = make([]DNSAlias, len(*in)) + copy(*out, *in) + } if in.PrivateImageHubs != nil { in, out := &in.PrivateImageHubs, &out.PrivateImageHubs *out = make(PrivateImageHubEntries, len(*in)) @@ -1215,6 +1236,100 @@ func (in *RadixComponent) DeepCopy() *RadixComponent { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RadixDNSAlias) DeepCopyInto(out *RadixDNSAlias) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RadixDNSAlias. +func (in *RadixDNSAlias) DeepCopy() *RadixDNSAlias { + if in == nil { + return nil + } + out := new(RadixDNSAlias) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RadixDNSAlias) 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 *RadixDNSAliasList) DeepCopyInto(out *RadixDNSAliasList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]RadixDNSAlias, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RadixDNSAliasList. +func (in *RadixDNSAliasList) DeepCopy() *RadixDNSAliasList { + if in == nil { + return nil + } + out := new(RadixDNSAliasList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RadixDNSAliasList) 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 *RadixDNSAliasSpec) DeepCopyInto(out *RadixDNSAliasSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RadixDNSAliasSpec. +func (in *RadixDNSAliasSpec) DeepCopy() *RadixDNSAliasSpec { + if in == nil { + return nil + } + out := new(RadixDNSAliasSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RadixDNSAliasStatus) DeepCopyInto(out *RadixDNSAliasStatus) { + *out = *in + in.Reconciled.DeepCopyInto(&out.Reconciled) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RadixDNSAliasStatus. +func (in *RadixDNSAliasStatus) DeepCopy() *RadixDNSAliasStatus { + if in == nil { + return nil + } + out := new(RadixDNSAliasStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RadixDeployComponent) DeepCopyInto(out *RadixDeployComponent) { *out = *in diff --git a/pkg/apis/radixvalidators/validate_ra.go b/pkg/apis/radixvalidators/validate_ra.go index 6a826ed01..ec3c1e656 100644 --- a/pkg/apis/radixvalidators/validate_ra.go +++ b/pkg/apis/radixvalidators/validate_ra.go @@ -174,7 +174,7 @@ func RAContainsOldPublic(app *radixv1.RadixApplication) bool { } func validateDNSAppAlias(app *radixv1.RadixApplication) []error { - errs := []error{} + var errs []error alias := app.Spec.DNSAppAlias if alias.Component == "" && alias.Environment == "" { return errs @@ -190,7 +190,7 @@ func validateDNSAppAlias(app *radixv1.RadixApplication) []error { } func validateDNSExternalAlias(app *radixv1.RadixApplication) []error { - errs := []error{} + var errs []error distinctAlias := make(map[string]bool) @@ -1385,7 +1385,7 @@ func doesComponentHaveAPublicPort(app *radixv1.RadixApplication, name string) bo } func validateComponentName(componentName, componentType string) error { - if err := validateRequiredResourceName(fmt.Sprintf("%s name", componentType), componentName); err != nil { + if err := validateResourceNameByRegex(fmt.Sprintf("%s name", componentType), componentName, `^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$`); err != nil { return err } diff --git a/pkg/apis/radixvalidators/validate_rr.go b/pkg/apis/radixvalidators/validate_rr.go index e20be8aad..947b9f164 100644 --- a/pkg/apis/radixvalidators/validate_rr.go +++ b/pkg/apis/radixvalidators/validate_rr.go @@ -120,6 +120,10 @@ func validateConfigurationItem(value string) error { } func validateRequiredResourceName(resourceName, value string) error { + return validateResourceNameByRegex(resourceName, value, `^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$`) +} + +func validateResourceNameByRegex(resourceName string, value string, expression string) error { if len(value) > 253 { return InvalidStringValueMaxLengthError(resourceName, value, 253) } @@ -128,7 +132,7 @@ func validateRequiredResourceName(resourceName, value string) error { return ResourceNameCannotBeEmptyError(resourceName) } - re := regexp.MustCompile(`^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$`) + re := regexp.MustCompile(expression) isValid := re.MatchString(value) if !isValid { @@ -229,7 +233,7 @@ func validateConfigBranch(name string) error { // ValidateRadixConfigFullName Validates the radixconfig file name and path func ValidateRadixConfigFullName(radixConfigFullName string) error { if len(radixConfigFullName) == 0 { - return nil //for empty radixConfigFullName it is used default radixconfig.yaml file name + return nil // for empty radixConfigFullName it is used default radixconfig.yaml file name } matched, err := regexp.Match(radixConfigFullNamePattern, []byte(radixConfigFullName)) if err != nil { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radix_client.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radix_client.go index 59c61713a..e3919aecd 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radix_client.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radix_client.go @@ -40,6 +40,10 @@ func (c *FakeRadixV1) RadixBatches(namespace string) v1.RadixBatchInterface { return &FakeRadixBatches{c, namespace} } +func (c *FakeRadixV1) RadixDNSAliases(namespace string) v1.RadixDNSAliasInterface { + return &FakeRadixDNSAliases{c, namespace} +} + func (c *FakeRadixV1) RadixDeployments(namespace string) v1.RadixDeploymentInterface { return &FakeRadixDeployments{c, namespace} } diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go new file mode 100644 index 000000000..d54cc05b9 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go @@ -0,0 +1,142 @@ +/* +Copyright The Kubernetes 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" + + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + 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" +) + +// FakeRadixDNSAliases implements RadixDNSAliasInterface +type FakeRadixDNSAliases struct { + Fake *FakeRadixV1 + ns string +} + +var radixdnsaliasesResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixdnsaliases"} + +var radixdnsaliasesKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixDNSAlias"} + +// Get takes name of the radixDNSAlias, and returns the corresponding radixDNSAlias object, and an error if there is any. +func (c *FakeRadixDNSAliases) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixDNSAlias, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(radixdnsaliasesResource, c.ns, name), &radixv1.RadixDNSAlias{}) + + if obj == nil { + return nil, err + } + return obj.(*radixv1.RadixDNSAlias), err +} + +// List takes label and field selectors, and returns the list of RadixDNSAliases that match those selectors. +func (c *FakeRadixDNSAliases) List(ctx context.Context, opts v1.ListOptions) (result *radixv1.RadixDNSAliasList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(radixdnsaliasesResource, radixdnsaliasesKind, c.ns, opts), &radixv1.RadixDNSAliasList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &radixv1.RadixDNSAliasList{ListMeta: obj.(*radixv1.RadixDNSAliasList).ListMeta} + for _, item := range obj.(*radixv1.RadixDNSAliasList).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 radixDNSAliases. +func (c *FakeRadixDNSAliases) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(radixdnsaliasesResource, c.ns, opts)) + +} + +// Create takes the representation of a radixDNSAlias and creates it. Returns the server's representation of the radixDNSAlias, and an error, if there is any. +func (c *FakeRadixDNSAliases) Create(ctx context.Context, radixDNSAlias *radixv1.RadixDNSAlias, opts v1.CreateOptions) (result *radixv1.RadixDNSAlias, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(radixdnsaliasesResource, c.ns, radixDNSAlias), &radixv1.RadixDNSAlias{}) + + if obj == nil { + return nil, err + } + return obj.(*radixv1.RadixDNSAlias), err +} + +// Update takes the representation of a radixDNSAlias and updates it. Returns the server's representation of the radixDNSAlias, and an error, if there is any. +func (c *FakeRadixDNSAliases) Update(ctx context.Context, radixDNSAlias *radixv1.RadixDNSAlias, opts v1.UpdateOptions) (result *radixv1.RadixDNSAlias, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(radixdnsaliasesResource, c.ns, radixDNSAlias), &radixv1.RadixDNSAlias{}) + + if obj == nil { + return nil, err + } + return obj.(*radixv1.RadixDNSAlias), 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 *FakeRadixDNSAliases) UpdateStatus(ctx context.Context, radixDNSAlias *radixv1.RadixDNSAlias, opts v1.UpdateOptions) (*radixv1.RadixDNSAlias, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(radixdnsaliasesResource, "status", c.ns, radixDNSAlias), &radixv1.RadixDNSAlias{}) + + if obj == nil { + return nil, err + } + return obj.(*radixv1.RadixDNSAlias), err +} + +// Delete takes name of the radixDNSAlias and deletes it. Returns an error if one occurs. +func (c *FakeRadixDNSAliases) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(radixdnsaliasesResource, c.ns, name, opts), &radixv1.RadixDNSAlias{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeRadixDNSAliases) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(radixdnsaliasesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &radixv1.RadixDNSAliasList{}) + return err +} + +// Patch applies the patch and returns the patched radixDNSAlias. +func (c *FakeRadixDNSAliases) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *radixv1.RadixDNSAlias, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(radixdnsaliasesResource, c.ns, name, pt, data, subresources...), &radixv1.RadixDNSAlias{}) + + if obj == nil { + return nil, err + } + return obj.(*radixv1.RadixDNSAlias), err +} diff --git a/pkg/client/clientset/versioned/typed/radix/v1/generated_expansion.go b/pkg/client/clientset/versioned/typed/radix/v1/generated_expansion.go index d655d98a9..e975a3d08 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/generated_expansion.go @@ -24,6 +24,8 @@ type RadixApplicationExpansion interface{} type RadixBatchExpansion interface{} +type RadixDNSAliasExpansion interface{} + type RadixDeploymentExpansion interface{} type RadixEnvironmentExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/radix/v1/radix_client.go b/pkg/client/clientset/versioned/typed/radix/v1/radix_client.go index d1fa7cd7e..5bbd0af62 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/radix_client.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/radix_client.go @@ -31,6 +31,7 @@ type RadixV1Interface interface { RadixAlertsGetter RadixApplicationsGetter RadixBatchesGetter + RadixDNSAliasesGetter RadixDeploymentsGetter RadixEnvironmentsGetter RadixJobsGetter @@ -54,6 +55,10 @@ func (c *RadixV1Client) RadixBatches(namespace string) RadixBatchInterface { return newRadixBatches(c, namespace) } +func (c *RadixV1Client) RadixDNSAliases(namespace string) RadixDNSAliasInterface { + return newRadixDNSAliases(c, namespace) +} + func (c *RadixV1Client) RadixDeployments(namespace string) RadixDeploymentInterface { return newRadixDeployments(c, namespace) } diff --git a/pkg/client/clientset/versioned/typed/radix/v1/radixdnsalias.go b/pkg/client/clientset/versioned/typed/radix/v1/radixdnsalias.go new file mode 100644 index 000000000..d24ff3ebe --- /dev/null +++ b/pkg/client/clientset/versioned/typed/radix/v1/radixdnsalias.go @@ -0,0 +1,195 @@ +/* +Copyright The Kubernetes 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 v1 + +import ( + "context" + "time" + + v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + scheme "github.com/equinor/radix-operator/pkg/client/clientset/versioned/scheme" + metav1 "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" +) + +// RadixDNSAliasesGetter has a method to return a RadixDNSAliasInterface. +// A group's client should implement this interface. +type RadixDNSAliasesGetter interface { + RadixDNSAliases(namespace string) RadixDNSAliasInterface +} + +// RadixDNSAliasInterface has methods to work with RadixDNSAlias resources. +type RadixDNSAliasInterface interface { + Create(ctx context.Context, radixDNSAlias *v1.RadixDNSAlias, opts metav1.CreateOptions) (*v1.RadixDNSAlias, error) + Update(ctx context.Context, radixDNSAlias *v1.RadixDNSAlias, opts metav1.UpdateOptions) (*v1.RadixDNSAlias, error) + UpdateStatus(ctx context.Context, radixDNSAlias *v1.RadixDNSAlias, opts metav1.UpdateOptions) (*v1.RadixDNSAlias, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.RadixDNSAlias, error) + List(ctx context.Context, opts metav1.ListOptions) (*v1.RadixDNSAliasList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.RadixDNSAlias, err error) + RadixDNSAliasExpansion +} + +// radixDNSAliases implements RadixDNSAliasInterface +type radixDNSAliases struct { + client rest.Interface + ns string +} + +// newRadixDNSAliases returns a RadixDNSAliases +func newRadixDNSAliases(c *RadixV1Client, namespace string) *radixDNSAliases { + return &radixDNSAliases{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the radixDNSAlias, and returns the corresponding radixDNSAlias object, and an error if there is any. +func (c *radixDNSAliases) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.RadixDNSAlias, err error) { + result = &v1.RadixDNSAlias{} + err = c.client.Get(). + Namespace(c.ns). + Resource("radixdnsaliases"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of RadixDNSAliases that match those selectors. +func (c *radixDNSAliases) List(ctx context.Context, opts metav1.ListOptions) (result *v1.RadixDNSAliasList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.RadixDNSAliasList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("radixdnsaliases"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested radixDNSAliases. +func (c *radixDNSAliases) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("radixdnsaliases"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a radixDNSAlias and creates it. Returns the server's representation of the radixDNSAlias, and an error, if there is any. +func (c *radixDNSAliases) Create(ctx context.Context, radixDNSAlias *v1.RadixDNSAlias, opts metav1.CreateOptions) (result *v1.RadixDNSAlias, err error) { + result = &v1.RadixDNSAlias{} + err = c.client.Post(). + Namespace(c.ns). + Resource("radixdnsaliases"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(radixDNSAlias). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a radixDNSAlias and updates it. Returns the server's representation of the radixDNSAlias, and an error, if there is any. +func (c *radixDNSAliases) Update(ctx context.Context, radixDNSAlias *v1.RadixDNSAlias, opts metav1.UpdateOptions) (result *v1.RadixDNSAlias, err error) { + result = &v1.RadixDNSAlias{} + err = c.client.Put(). + Namespace(c.ns). + Resource("radixdnsaliases"). + Name(radixDNSAlias.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(radixDNSAlias). + 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 *radixDNSAliases) UpdateStatus(ctx context.Context, radixDNSAlias *v1.RadixDNSAlias, opts metav1.UpdateOptions) (result *v1.RadixDNSAlias, err error) { + result = &v1.RadixDNSAlias{} + err = c.client.Put(). + Namespace(c.ns). + Resource("radixdnsaliases"). + Name(radixDNSAlias.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(radixDNSAlias). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the radixDNSAlias and deletes it. Returns an error if one occurs. +func (c *radixDNSAliases) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("radixdnsaliases"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *radixDNSAliases) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("radixdnsaliases"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched radixDNSAlias. +func (c *radixDNSAliases) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.RadixDNSAlias, err error) { + result = &v1.RadixDNSAlias{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("radixdnsaliases"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index dc226408a..2b213c227 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -59,6 +59,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Radix().V1().RadixApplications().Informer()}, nil case v1.SchemeGroupVersion.WithResource("radixbatches"): return &genericInformer{resource: resource.GroupResource(), informer: f.Radix().V1().RadixBatches().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("radixdnsaliases"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Radix().V1().RadixDNSAliases().Informer()}, nil case v1.SchemeGroupVersion.WithResource("radixdeployments"): return &genericInformer{resource: resource.GroupResource(), informer: f.Radix().V1().RadixDeployments().Informer()}, nil case v1.SchemeGroupVersion.WithResource("radixenvironments"): diff --git a/pkg/client/informers/externalversions/radix/v1/interface.go b/pkg/client/informers/externalversions/radix/v1/interface.go index 2a6c4a831..a972aa91a 100644 --- a/pkg/client/informers/externalversions/radix/v1/interface.go +++ b/pkg/client/informers/externalversions/radix/v1/interface.go @@ -30,6 +30,8 @@ type Interface interface { RadixApplications() RadixApplicationInformer // RadixBatches returns a RadixBatchInformer. RadixBatches() RadixBatchInformer + // RadixDNSAliases returns a RadixDNSAliasInformer. + RadixDNSAliases() RadixDNSAliasInformer // RadixDeployments returns a RadixDeploymentInformer. RadixDeployments() RadixDeploymentInformer // RadixEnvironments returns a RadixEnvironmentInformer. @@ -66,6 +68,11 @@ func (v *version) RadixBatches() RadixBatchInformer { return &radixBatchInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } +// RadixDNSAliases returns a RadixDNSAliasInformer. +func (v *version) RadixDNSAliases() RadixDNSAliasInformer { + return &radixDNSAliasInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // RadixDeployments returns a RadixDeploymentInformer. func (v *version) RadixDeployments() RadixDeploymentInformer { return &radixDeploymentInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/client/informers/externalversions/radix/v1/radixdnsalias.go b/pkg/client/informers/externalversions/radix/v1/radixdnsalias.go new file mode 100644 index 000000000..99cbfb298 --- /dev/null +++ b/pkg/client/informers/externalversions/radix/v1/radixdnsalias.go @@ -0,0 +1,90 @@ +/* +Copyright The Kubernetes 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 v1 + +import ( + "context" + time "time" + + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + versioned "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + internalinterfaces "github.com/equinor/radix-operator/pkg/client/informers/externalversions/internalinterfaces" + v1 "github.com/equinor/radix-operator/pkg/client/listers/radix/v1" + metav1 "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" +) + +// RadixDNSAliasInformer provides access to a shared informer and lister for +// RadixDNSAliases. +type RadixDNSAliasInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.RadixDNSAliasLister +} + +type radixDNSAliasInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewRadixDNSAliasInformer constructs a new informer for RadixDNSAlias 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 NewRadixDNSAliasInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredRadixDNSAliasInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredRadixDNSAliasInformer constructs a new informer for RadixDNSAlias 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 NewFilteredRadixDNSAliasInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.RadixV1().RadixDNSAliases(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.RadixV1().RadixDNSAliases(namespace).Watch(context.TODO(), options) + }, + }, + &radixv1.RadixDNSAlias{}, + resyncPeriod, + indexers, + ) +} + +func (f *radixDNSAliasInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredRadixDNSAliasInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *radixDNSAliasInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&radixv1.RadixDNSAlias{}, f.defaultInformer) +} + +func (f *radixDNSAliasInformer) Lister() v1.RadixDNSAliasLister { + return v1.NewRadixDNSAliasLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/listers/radix/v1/expansion_generated.go b/pkg/client/listers/radix/v1/expansion_generated.go index ff68b04df..7d57021f6 100644 --- a/pkg/client/listers/radix/v1/expansion_generated.go +++ b/pkg/client/listers/radix/v1/expansion_generated.go @@ -42,6 +42,14 @@ type RadixBatchListerExpansion interface{} // RadixBatchNamespaceLister. type RadixBatchNamespaceListerExpansion interface{} +// RadixDNSAliasListerExpansion allows custom methods to be added to +// RadixDNSAliasLister. +type RadixDNSAliasListerExpansion interface{} + +// RadixDNSAliasNamespaceListerExpansion allows custom methods to be added to +// RadixDNSAliasNamespaceLister. +type RadixDNSAliasNamespaceListerExpansion interface{} + // RadixDeploymentListerExpansion allows custom methods to be added to // RadixDeploymentLister. type RadixDeploymentListerExpansion interface{} diff --git a/pkg/client/listers/radix/v1/radixdnsalias.go b/pkg/client/listers/radix/v1/radixdnsalias.go new file mode 100644 index 000000000..799234b4e --- /dev/null +++ b/pkg/client/listers/radix/v1/radixdnsalias.go @@ -0,0 +1,99 @@ +/* +Copyright The Kubernetes 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 v1 + +import ( + v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// RadixDNSAliasLister helps list RadixDNSAliases. +// All objects returned here must be treated as read-only. +type RadixDNSAliasLister interface { + // List lists all RadixDNSAliases in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.RadixDNSAlias, err error) + // RadixDNSAliases returns an object that can list and get RadixDNSAliases. + RadixDNSAliases(namespace string) RadixDNSAliasNamespaceLister + RadixDNSAliasListerExpansion +} + +// radixDNSAliasLister implements the RadixDNSAliasLister interface. +type radixDNSAliasLister struct { + indexer cache.Indexer +} + +// NewRadixDNSAliasLister returns a new RadixDNSAliasLister. +func NewRadixDNSAliasLister(indexer cache.Indexer) RadixDNSAliasLister { + return &radixDNSAliasLister{indexer: indexer} +} + +// List lists all RadixDNSAliases in the indexer. +func (s *radixDNSAliasLister) List(selector labels.Selector) (ret []*v1.RadixDNSAlias, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.RadixDNSAlias)) + }) + return ret, err +} + +// RadixDNSAliases returns an object that can list and get RadixDNSAliases. +func (s *radixDNSAliasLister) RadixDNSAliases(namespace string) RadixDNSAliasNamespaceLister { + return radixDNSAliasNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// RadixDNSAliasNamespaceLister helps list and get RadixDNSAliases. +// All objects returned here must be treated as read-only. +type RadixDNSAliasNamespaceLister interface { + // List lists all RadixDNSAliases in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.RadixDNSAlias, err error) + // Get retrieves the RadixDNSAlias from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1.RadixDNSAlias, error) + RadixDNSAliasNamespaceListerExpansion +} + +// radixDNSAliasNamespaceLister implements the RadixDNSAliasNamespaceLister +// interface. +type radixDNSAliasNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all RadixDNSAliases in the indexer for a given namespace. +func (s radixDNSAliasNamespaceLister) List(selector labels.Selector) (ret []*v1.RadixDNSAlias, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.RadixDNSAlias)) + }) + return ret, err +} + +// Get retrieves the RadixDNSAlias from the indexer for a given namespace and name. +func (s radixDNSAliasNamespaceLister) Get(name string) (*v1.RadixDNSAlias, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("radixdnsalias"), name) + } + return obj.(*v1.RadixDNSAlias), nil +} From b5c16df2a9b77666279b64fd18667813fa201eb7 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 20 Oct 2023 16:33:26 +0200 Subject: [PATCH 002/121] Added dns aliases controller and handler bases --- pkg/apis/radix/v1/radixdnsalias.go | 1 + .../typed/radix/v1/fake/fake_radix_client.go | 4 +- .../typed/radix/v1/fake/fake_radixdnsalias.go | 27 +-- .../versioned/typed/radix/v1/radix_client.go | 4 +- .../versioned/typed/radix/v1/radixdnsalias.go | 15 +- .../externalversions/radix/v1/interface.go | 2 +- .../radix/v1/radixdnsalias.go | 13 +- .../listers/radix/v1/expansion_generated.go | 4 - pkg/client/listers/radix/v1/radixdnsalias.go | 43 +--- radix-operator/dnsalias/controller.go | 190 ++++++++++++++++++ radix-operator/dnsalias/handler.go | 105 ++++++++++ radix-operator/main.go | 64 ++++-- 12 files changed, 370 insertions(+), 102 deletions(-) create mode 100644 radix-operator/dnsalias/controller.go create mode 100644 radix-operator/dnsalias/handler.go diff --git a/pkg/apis/radix/v1/radixdnsalias.go b/pkg/apis/radix/v1/radixdnsalias.go index 64dc7a916..f4a8eaf2a 100644 --- a/pkg/apis/radix/v1/radixdnsalias.go +++ b/pkg/apis/radix/v1/radixdnsalias.go @@ -3,6 +3,7 @@ package v1 import meta "k8s.io/apimachinery/pkg/apis/meta/v1" // +genclient +// +genclient:nonNamespaced // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +kubebuilder:resource:path=radixdnsalias,scope=Cluster,shortName=rda diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radix_client.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radix_client.go index e3919aecd..1453a27b4 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radix_client.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radix_client.go @@ -40,8 +40,8 @@ func (c *FakeRadixV1) RadixBatches(namespace string) v1.RadixBatchInterface { return &FakeRadixBatches{c, namespace} } -func (c *FakeRadixV1) RadixDNSAliases(namespace string) v1.RadixDNSAliasInterface { - return &FakeRadixDNSAliases{c, namespace} +func (c *FakeRadixV1) RadixDNSAliases() v1.RadixDNSAliasInterface { + return &FakeRadixDNSAliases{c} } func (c *FakeRadixV1) RadixDeployments(namespace string) v1.RadixDeploymentInterface { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go index d54cc05b9..863ed75b8 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go @@ -33,7 +33,6 @@ import ( // FakeRadixDNSAliases implements RadixDNSAliasInterface type FakeRadixDNSAliases struct { Fake *FakeRadixV1 - ns string } var radixdnsaliasesResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixdnsaliases"} @@ -43,8 +42,7 @@ var radixdnsaliasesKind = schema.GroupVersionKind{Group: "radix.equinor.com", Ve // Get takes name of the radixDNSAlias, and returns the corresponding radixDNSAlias object, and an error if there is any. func (c *FakeRadixDNSAliases) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixDNSAlias, err error) { obj, err := c.Fake. - Invokes(testing.NewGetAction(radixdnsaliasesResource, c.ns, name), &radixv1.RadixDNSAlias{}) - + Invokes(testing.NewRootGetAction(radixdnsaliasesResource, name), &radixv1.RadixDNSAlias{}) if obj == nil { return nil, err } @@ -54,8 +52,7 @@ func (c *FakeRadixDNSAliases) Get(ctx context.Context, name string, options v1.G // List takes label and field selectors, and returns the list of RadixDNSAliases that match those selectors. func (c *FakeRadixDNSAliases) List(ctx context.Context, opts v1.ListOptions) (result *radixv1.RadixDNSAliasList, err error) { obj, err := c.Fake. - Invokes(testing.NewListAction(radixdnsaliasesResource, radixdnsaliasesKind, c.ns, opts), &radixv1.RadixDNSAliasList{}) - + Invokes(testing.NewRootListAction(radixdnsaliasesResource, radixdnsaliasesKind, opts), &radixv1.RadixDNSAliasList{}) if obj == nil { return nil, err } @@ -76,15 +73,13 @@ func (c *FakeRadixDNSAliases) List(ctx context.Context, opts v1.ListOptions) (re // Watch returns a watch.Interface that watches the requested radixDNSAliases. func (c *FakeRadixDNSAliases) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { return c.Fake. - InvokesWatch(testing.NewWatchAction(radixdnsaliasesResource, c.ns, opts)) - + InvokesWatch(testing.NewRootWatchAction(radixdnsaliasesResource, opts)) } // Create takes the representation of a radixDNSAlias and creates it. Returns the server's representation of the radixDNSAlias, and an error, if there is any. func (c *FakeRadixDNSAliases) Create(ctx context.Context, radixDNSAlias *radixv1.RadixDNSAlias, opts v1.CreateOptions) (result *radixv1.RadixDNSAlias, err error) { obj, err := c.Fake. - Invokes(testing.NewCreateAction(radixdnsaliasesResource, c.ns, radixDNSAlias), &radixv1.RadixDNSAlias{}) - + Invokes(testing.NewRootCreateAction(radixdnsaliasesResource, radixDNSAlias), &radixv1.RadixDNSAlias{}) if obj == nil { return nil, err } @@ -94,8 +89,7 @@ func (c *FakeRadixDNSAliases) Create(ctx context.Context, radixDNSAlias *radixv1 // Update takes the representation of a radixDNSAlias and updates it. Returns the server's representation of the radixDNSAlias, and an error, if there is any. func (c *FakeRadixDNSAliases) Update(ctx context.Context, radixDNSAlias *radixv1.RadixDNSAlias, opts v1.UpdateOptions) (result *radixv1.RadixDNSAlias, err error) { obj, err := c.Fake. - Invokes(testing.NewUpdateAction(radixdnsaliasesResource, c.ns, radixDNSAlias), &radixv1.RadixDNSAlias{}) - + Invokes(testing.NewRootUpdateAction(radixdnsaliasesResource, radixDNSAlias), &radixv1.RadixDNSAlias{}) if obj == nil { return nil, err } @@ -106,8 +100,7 @@ func (c *FakeRadixDNSAliases) Update(ctx context.Context, radixDNSAlias *radixv1 // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). func (c *FakeRadixDNSAliases) UpdateStatus(ctx context.Context, radixDNSAlias *radixv1.RadixDNSAlias, opts v1.UpdateOptions) (*radixv1.RadixDNSAlias, error) { obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(radixdnsaliasesResource, "status", c.ns, radixDNSAlias), &radixv1.RadixDNSAlias{}) - + Invokes(testing.NewRootUpdateSubresourceAction(radixdnsaliasesResource, "status", radixDNSAlias), &radixv1.RadixDNSAlias{}) if obj == nil { return nil, err } @@ -117,14 +110,13 @@ func (c *FakeRadixDNSAliases) UpdateStatus(ctx context.Context, radixDNSAlias *r // Delete takes name of the radixDNSAlias and deletes it. Returns an error if one occurs. func (c *FakeRadixDNSAliases) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { _, err := c.Fake. - Invokes(testing.NewDeleteActionWithOptions(radixdnsaliasesResource, c.ns, name, opts), &radixv1.RadixDNSAlias{}) - + Invokes(testing.NewRootDeleteActionWithOptions(radixdnsaliasesResource, name, opts), &radixv1.RadixDNSAlias{}) return err } // DeleteCollection deletes a collection of objects. func (c *FakeRadixDNSAliases) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(radixdnsaliasesResource, c.ns, listOpts) + action := testing.NewRootDeleteCollectionAction(radixdnsaliasesResource, listOpts) _, err := c.Fake.Invokes(action, &radixv1.RadixDNSAliasList{}) return err @@ -133,8 +125,7 @@ func (c *FakeRadixDNSAliases) DeleteCollection(ctx context.Context, opts v1.Dele // Patch applies the patch and returns the patched radixDNSAlias. func (c *FakeRadixDNSAliases) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *radixv1.RadixDNSAlias, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(radixdnsaliasesResource, c.ns, name, pt, data, subresources...), &radixv1.RadixDNSAlias{}) - + Invokes(testing.NewRootPatchSubresourceAction(radixdnsaliasesResource, name, pt, data, subresources...), &radixv1.RadixDNSAlias{}) if obj == nil { return nil, err } diff --git a/pkg/client/clientset/versioned/typed/radix/v1/radix_client.go b/pkg/client/clientset/versioned/typed/radix/v1/radix_client.go index 5bbd0af62..3a0da27d0 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/radix_client.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/radix_client.go @@ -55,8 +55,8 @@ func (c *RadixV1Client) RadixBatches(namespace string) RadixBatchInterface { return newRadixBatches(c, namespace) } -func (c *RadixV1Client) RadixDNSAliases(namespace string) RadixDNSAliasInterface { - return newRadixDNSAliases(c, namespace) +func (c *RadixV1Client) RadixDNSAliases() RadixDNSAliasInterface { + return newRadixDNSAliases(c) } func (c *RadixV1Client) RadixDeployments(namespace string) RadixDeploymentInterface { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/radixdnsalias.go b/pkg/client/clientset/versioned/typed/radix/v1/radixdnsalias.go index d24ff3ebe..13fc3e6a0 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/radixdnsalias.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/radixdnsalias.go @@ -33,7 +33,7 @@ import ( // RadixDNSAliasesGetter has a method to return a RadixDNSAliasInterface. // A group's client should implement this interface. type RadixDNSAliasesGetter interface { - RadixDNSAliases(namespace string) RadixDNSAliasInterface + RadixDNSAliases() RadixDNSAliasInterface } // RadixDNSAliasInterface has methods to work with RadixDNSAlias resources. @@ -53,14 +53,12 @@ type RadixDNSAliasInterface interface { // radixDNSAliases implements RadixDNSAliasInterface type radixDNSAliases struct { client rest.Interface - ns string } // newRadixDNSAliases returns a RadixDNSAliases -func newRadixDNSAliases(c *RadixV1Client, namespace string) *radixDNSAliases { +func newRadixDNSAliases(c *RadixV1Client) *radixDNSAliases { return &radixDNSAliases{ client: c.RESTClient(), - ns: namespace, } } @@ -68,7 +66,6 @@ func newRadixDNSAliases(c *RadixV1Client, namespace string) *radixDNSAliases { func (c *radixDNSAliases) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.RadixDNSAlias, err error) { result = &v1.RadixDNSAlias{} err = c.client.Get(). - Namespace(c.ns). Resource("radixdnsaliases"). Name(name). VersionedParams(&options, scheme.ParameterCodec). @@ -85,7 +82,6 @@ func (c *radixDNSAliases) List(ctx context.Context, opts metav1.ListOptions) (re } result = &v1.RadixDNSAliasList{} err = c.client.Get(). - Namespace(c.ns). Resource("radixdnsaliases"). VersionedParams(&opts, scheme.ParameterCodec). Timeout(timeout). @@ -102,7 +98,6 @@ func (c *radixDNSAliases) Watch(ctx context.Context, opts metav1.ListOptions) (w } opts.Watch = true return c.client.Get(). - Namespace(c.ns). Resource("radixdnsaliases"). VersionedParams(&opts, scheme.ParameterCodec). Timeout(timeout). @@ -113,7 +108,6 @@ func (c *radixDNSAliases) Watch(ctx context.Context, opts metav1.ListOptions) (w func (c *radixDNSAliases) Create(ctx context.Context, radixDNSAlias *v1.RadixDNSAlias, opts metav1.CreateOptions) (result *v1.RadixDNSAlias, err error) { result = &v1.RadixDNSAlias{} err = c.client.Post(). - Namespace(c.ns). Resource("radixdnsaliases"). VersionedParams(&opts, scheme.ParameterCodec). Body(radixDNSAlias). @@ -126,7 +120,6 @@ func (c *radixDNSAliases) Create(ctx context.Context, radixDNSAlias *v1.RadixDNS func (c *radixDNSAliases) Update(ctx context.Context, radixDNSAlias *v1.RadixDNSAlias, opts metav1.UpdateOptions) (result *v1.RadixDNSAlias, err error) { result = &v1.RadixDNSAlias{} err = c.client.Put(). - Namespace(c.ns). Resource("radixdnsaliases"). Name(radixDNSAlias.Name). VersionedParams(&opts, scheme.ParameterCodec). @@ -141,7 +134,6 @@ func (c *radixDNSAliases) Update(ctx context.Context, radixDNSAlias *v1.RadixDNS func (c *radixDNSAliases) UpdateStatus(ctx context.Context, radixDNSAlias *v1.RadixDNSAlias, opts metav1.UpdateOptions) (result *v1.RadixDNSAlias, err error) { result = &v1.RadixDNSAlias{} err = c.client.Put(). - Namespace(c.ns). Resource("radixdnsaliases"). Name(radixDNSAlias.Name). SubResource("status"). @@ -155,7 +147,6 @@ func (c *radixDNSAliases) UpdateStatus(ctx context.Context, radixDNSAlias *v1.Ra // Delete takes name of the radixDNSAlias and deletes it. Returns an error if one occurs. func (c *radixDNSAliases) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { return c.client.Delete(). - Namespace(c.ns). Resource("radixdnsaliases"). Name(name). Body(&opts). @@ -170,7 +161,6 @@ func (c *radixDNSAliases) DeleteCollection(ctx context.Context, opts metav1.Dele timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second } return c.client.Delete(). - Namespace(c.ns). Resource("radixdnsaliases"). VersionedParams(&listOpts, scheme.ParameterCodec). Timeout(timeout). @@ -183,7 +173,6 @@ func (c *radixDNSAliases) DeleteCollection(ctx context.Context, opts metav1.Dele func (c *radixDNSAliases) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.RadixDNSAlias, err error) { result = &v1.RadixDNSAlias{} err = c.client.Patch(pt). - Namespace(c.ns). Resource("radixdnsaliases"). Name(name). SubResource(subresources...). diff --git a/pkg/client/informers/externalversions/radix/v1/interface.go b/pkg/client/informers/externalversions/radix/v1/interface.go index a972aa91a..cdce54188 100644 --- a/pkg/client/informers/externalversions/radix/v1/interface.go +++ b/pkg/client/informers/externalversions/radix/v1/interface.go @@ -70,7 +70,7 @@ func (v *version) RadixBatches() RadixBatchInformer { // RadixDNSAliases returns a RadixDNSAliasInformer. func (v *version) RadixDNSAliases() RadixDNSAliasInformer { - return &radixDNSAliasInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} + return &radixDNSAliasInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} } // RadixDeployments returns a RadixDeploymentInformer. diff --git a/pkg/client/informers/externalversions/radix/v1/radixdnsalias.go b/pkg/client/informers/externalversions/radix/v1/radixdnsalias.go index 99cbfb298..7debc7f0e 100644 --- a/pkg/client/informers/externalversions/radix/v1/radixdnsalias.go +++ b/pkg/client/informers/externalversions/radix/v1/radixdnsalias.go @@ -42,33 +42,32 @@ type RadixDNSAliasInformer interface { type radixDNSAliasInformer struct { factory internalinterfaces.SharedInformerFactory tweakListOptions internalinterfaces.TweakListOptionsFunc - namespace string } // NewRadixDNSAliasInformer constructs a new informer for RadixDNSAlias 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 NewRadixDNSAliasInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredRadixDNSAliasInformer(client, namespace, resyncPeriod, indexers, nil) +func NewRadixDNSAliasInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredRadixDNSAliasInformer(client, resyncPeriod, indexers, nil) } // NewFilteredRadixDNSAliasInformer constructs a new informer for RadixDNSAlias 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 NewFilteredRadixDNSAliasInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { +func NewFilteredRadixDNSAliasInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { return cache.NewSharedIndexInformer( &cache.ListWatch{ ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.RadixV1().RadixDNSAliases(namespace).List(context.TODO(), options) + return client.RadixV1().RadixDNSAliases().List(context.TODO(), options) }, WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.RadixV1().RadixDNSAliases(namespace).Watch(context.TODO(), options) + return client.RadixV1().RadixDNSAliases().Watch(context.TODO(), options) }, }, &radixv1.RadixDNSAlias{}, @@ -78,7 +77,7 @@ func NewFilteredRadixDNSAliasInformer(client versioned.Interface, namespace stri } func (f *radixDNSAliasInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredRadixDNSAliasInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) + return NewFilteredRadixDNSAliasInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } func (f *radixDNSAliasInformer) Informer() cache.SharedIndexInformer { diff --git a/pkg/client/listers/radix/v1/expansion_generated.go b/pkg/client/listers/radix/v1/expansion_generated.go index 7d57021f6..5657b453a 100644 --- a/pkg/client/listers/radix/v1/expansion_generated.go +++ b/pkg/client/listers/radix/v1/expansion_generated.go @@ -46,10 +46,6 @@ type RadixBatchNamespaceListerExpansion interface{} // RadixDNSAliasLister. type RadixDNSAliasListerExpansion interface{} -// RadixDNSAliasNamespaceListerExpansion allows custom methods to be added to -// RadixDNSAliasNamespaceLister. -type RadixDNSAliasNamespaceListerExpansion interface{} - // RadixDeploymentListerExpansion allows custom methods to be added to // RadixDeploymentLister. type RadixDeploymentListerExpansion interface{} diff --git a/pkg/client/listers/radix/v1/radixdnsalias.go b/pkg/client/listers/radix/v1/radixdnsalias.go index 799234b4e..28915e9eb 100644 --- a/pkg/client/listers/radix/v1/radixdnsalias.go +++ b/pkg/client/listers/radix/v1/radixdnsalias.go @@ -31,8 +31,9 @@ type RadixDNSAliasLister interface { // List lists all RadixDNSAliases in the indexer. // Objects returned here must be treated as read-only. List(selector labels.Selector) (ret []*v1.RadixDNSAlias, err error) - // RadixDNSAliases returns an object that can list and get RadixDNSAliases. - RadixDNSAliases(namespace string) RadixDNSAliasNamespaceLister + // Get retrieves the RadixDNSAlias from the index for a given name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1.RadixDNSAlias, error) RadixDNSAliasListerExpansion } @@ -54,41 +55,9 @@ func (s *radixDNSAliasLister) List(selector labels.Selector) (ret []*v1.RadixDNS return ret, err } -// RadixDNSAliases returns an object that can list and get RadixDNSAliases. -func (s *radixDNSAliasLister) RadixDNSAliases(namespace string) RadixDNSAliasNamespaceLister { - return radixDNSAliasNamespaceLister{indexer: s.indexer, namespace: namespace} -} - -// RadixDNSAliasNamespaceLister helps list and get RadixDNSAliases. -// All objects returned here must be treated as read-only. -type RadixDNSAliasNamespaceLister interface { - // List lists all RadixDNSAliases in the indexer for a given namespace. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1.RadixDNSAlias, err error) - // Get retrieves the RadixDNSAlias from the indexer for a given namespace and name. - // Objects returned here must be treated as read-only. - Get(name string) (*v1.RadixDNSAlias, error) - RadixDNSAliasNamespaceListerExpansion -} - -// radixDNSAliasNamespaceLister implements the RadixDNSAliasNamespaceLister -// interface. -type radixDNSAliasNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all RadixDNSAliases in the indexer for a given namespace. -func (s radixDNSAliasNamespaceLister) List(selector labels.Selector) (ret []*v1.RadixDNSAlias, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1.RadixDNSAlias)) - }) - return ret, err -} - -// Get retrieves the RadixDNSAlias from the indexer for a given namespace and name. -func (s radixDNSAliasNamespaceLister) Get(name string) (*v1.RadixDNSAlias, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) +// Get retrieves the RadixDNSAlias from the index for a given name. +func (s *radixDNSAliasLister) Get(name string) (*v1.RadixDNSAlias, error) { + obj, exists, err := s.indexer.GetByKey(name) if err != nil { return nil, err } diff --git a/radix-operator/dnsalias/controller.go b/radix-operator/dnsalias/controller.go new file mode 100644 index 000000000..0457291ff --- /dev/null +++ b/radix-operator/dnsalias/controller.go @@ -0,0 +1,190 @@ +package dnsalias + +import ( + "context" + "reflect" + + "github.com/equinor/radix-operator/pkg/apis/metrics" + v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + informers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" + "github.com/equinor/radix-operator/radix-operator/common" + "github.com/sirupsen/logrus" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + kubeinformers "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" + "k8s.io/client-go/util/workqueue" +) + +const ( + controllerAgentName = "dns-alias-controller" + crType = "RadixDNSAlias" +) + +var logger *logrus.Entry + +func init() { + logger = logrus.WithFields(logrus.Fields{"radixOperatorComponent": "dns-alias-controller"}) +} + +// NewController creates a new controller that handles RadixDNSAlias +func NewController(client kubernetes.Interface, + radixClient radixclient.Interface, + handler common.Handler, + kubeInformerFactory kubeinformers.SharedInformerFactory, + radixInformerFactory informers.SharedInformerFactory, + waitForChildrenToSync bool, + recorder record.EventRecorder) *common.Controller { + + dnsAliasInformer := radixInformerFactory.Radix().V1().RadixDNSAliases() + applicationInformer := radixInformerFactory.Radix().V1().RadixApplications() + environmentInformer := radixInformerFactory.Radix().V1().RadixEnvironments() + namespaceInformer := kubeInformerFactory.Core().V1().Namespaces() + ingressInformer := kubeInformerFactory.Networking().V1().Ingresses() + + controller := &common.Controller{ + Name: controllerAgentName, + HandlerOf: crType, + KubeClient: client, + RadixClient: radixClient, + Informer: dnsAliasInformer.Informer(), + KubeInformerFactory: kubeInformerFactory, + WorkQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), crType), + Handler: handler, + Log: logger, + WaitForChildrenToSync: waitForChildrenToSync, + Recorder: recorder, + LockKeyAndIdentifier: common.NamePartitionKey, + } + + logger.Info("Setting up event handlers") + + dnsAliasInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: func(cur interface{}) { + controller.Enqueue(cur) + metrics.CustomResourceAdded(crType) + }, + UpdateFunc: func(old, cur interface{}) { + newRDA := cur.(*v1.RadixDNSAlias) + oldRDA := old.(*v1.RadixDNSAlias) + + if deepEqual(oldRDA, newRDA) { + logger.Debugf("RadixDNSAlias object is equal to old for %s. Do nothing", newRDA.GetName()) + metrics.CustomResourceUpdatedButSkipped(crType) + return + } + + controller.Enqueue(cur) + metrics.CustomResourceUpdated(crType) + }, + DeleteFunc: func(obj interface{}) { + // TODO delete ingresses + // radixDNSAlias, converted := obj.(*v1.RadixDNSAlias) + _, converted := obj.(*v1.RadixDNSAlias) + if !converted { + logger.Errorf("RadixDNSAlias object cast failed during deleted event received.") + return + } + // key, err := cache.MetaNamespaceKeyFunc(radixDNSAlias) + // if err != nil { + // logger.Errorf("RadixDNSAlias object deleted event received for %s. Do nothing", key) + // } + metrics.CustomResourceDeleted(crType) + }, + }) + + environmentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + DeleteFunc: func(obj interface{}) { + // TODO alert in events if missing ns + }, + }) + + namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + DeleteFunc: func(obj interface{}) { + // TODO alert in events if missing ns + }, + }) + + ingressInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + DeleteFunc: func(obj interface{}) { + // TODO restore ingress if missing + }, + }) + + applicationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + UpdateFunc: func(old, cur interface{}) { + newRa := cur.(*v1.RadixApplication) + oldRa := old.(*v1.RadixApplication) + if newRa.ResourceVersion == oldRa.ResourceVersion { + return + } + // TODO update SNS aliases + // dnsAliasesToResync := getAddedOrDroppedDNSAliasDomains(oldRa, newRa) + // for _, domain := range dnsAliasesToResync { + // uniqueName := utils.GetEnvironmentNamespace(oldRa.Name, envName) + // re, err := radixClient.RadixV1().RadixDNSAliases().Get(context.TODO(), uniqueName, metav1.GetOptions{}) + // if err == nil { + // controller.Enqueue(re) + // } + // } + }, + DeleteFunc: func(cur interface{}) { + // TODO delete DNS aliases + // radixApplication, converted := cur.(*v1.RadixApplication) + _, converted := cur.(*v1.RadixApplication) + if !converted { + logger.Errorf("RadixApplication object cast failed during deleted event received.") + return + } + // for _, env := range radixApplication.Spec.Environments { + // uniqueName := utils.GetEnvironmentNamespace(radixApplication.Name, env.Name) + // re, err := radixClient.RadixV1().RadixDNSAliases().Get(context.TODO(), uniqueName, metav1.GetOptions{}) + // if err == nil { + // controller.Enqueue(re) + // } + // } + }, + }) + + return controller +} + +func deepEqual(old, new *v1.RadixDNSAlias) bool { + if !reflect.DeepEqual(new.Spec, old.Spec) || + !reflect.DeepEqual(new.ObjectMeta.Labels, old.ObjectMeta.Labels) || + !reflect.DeepEqual(new.ObjectMeta.Annotations, old.ObjectMeta.Annotations) { + return false + } + + return true +} + +func getOwner(radixClient radixclient.Interface, namespace, name string) (interface{}, error) { + return radixClient.RadixV1().RadixDNSAliases().Get(context.TODO(), name, metav1.GetOptions{}) +} + +func getAddedOrDroppedDNSAliasDomains(oldRa *v1.RadixApplication, newRa *v1.RadixApplication) []string { + var dnsAliasDomains []string + dnsAliasDomains = append(dnsAliasDomains, getMissingDNSAliasDomains(oldRa.Spec.DNSAlias, newRa.Spec.DNSAlias)...) + dnsAliasDomains = append(dnsAliasDomains, getMissingDNSAliasDomains(newRa.Spec.DNSAlias, oldRa.Spec.DNSAlias)...) + return dnsAliasDomains +} + +// getMissingDNSAliasDomains returns dnsAlias domains that exists in source list but not in target list +func getMissingDNSAliasDomains(source []v1.DNSAlias, target []v1.DNSAlias) []string { + droppedDomains := make([]string, 0) + for _, oldDNSAlias := range source { + dropped := true + for _, newDnsAlias := range target { + if oldDNSAlias.Domain == newDnsAlias.Domain { + dropped = false + } + } + if dropped { + droppedDomains = append(droppedDomains, oldDNSAlias.Domain) + } + } + return droppedDomains +} diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go new file mode 100644 index 000000000..1ef295a29 --- /dev/null +++ b/radix-operator/dnsalias/handler.go @@ -0,0 +1,105 @@ +package dnsalias + +import ( + "context" + "fmt" + + "github.com/equinor/radix-operator/pkg/apis/kube" + radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + "github.com/equinor/radix-operator/radix-operator/common" + + "k8s.io/apimachinery/pkg/api/errors" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/record" +) + +const ( + // SuccessSynced is used as part of the Event 'reason' when a DNSAlias is synced + SuccessSynced = "Synced" + + // MessageResourceSynced is the message used for an Event fired when a DNSAlias + // is synced successfully + MessageResourceSynced = "Radix DNSAlias synced successfully" +) + +// Handler Handler for radix dns aliases +type Handler struct { + kubeclient kubernetes.Interface + kubeutil *kube.Kube + radixclient radixclient.Interface + hasSynced common.HasSynced +} + +// NewHandler creates a handler for managing RadixDNSAlias resources +func NewHandler( + kubeclient kubernetes.Interface, + kubeutil *kube.Kube, + radixclient radixclient.Interface, + hasSynced common.HasSynced) Handler { + + handler := Handler{ + kubeclient: kubeclient, + kubeutil: kubeutil, + radixclient: radixclient, + hasSynced: hasSynced, + } + + return handler +} + +// Sync is called by kubernetes after the Controller Enqueues a work-item +// and collects components and determines whether state must be reconciled. +func (t *Handler) Sync(namespace, name string, eventRecorder record.EventRecorder) error { + radixDNSAlias, err := t.radixclient.RadixV1().RadixDNSAliases().Get(context.TODO(), name, meta.GetOptions{}) + if err != nil { + // The DNSAlias resource may no longer exist, in which case we stop + // processing. + if errors.IsNotFound(err) { + utilruntime.HandleError(fmt.Errorf("radix dns alias %s in work queue no longer exists", name)) + return nil + } + + return err + } + + syncDNSAlias := radixDNSAlias.DeepCopy() + logger.Debugf("Sync dns alias %s", syncDNSAlias.Name) + + // TOD sync + // radixRegistration, err := t.kubeutil.GetRegistration(syncDNSAlias.Spec.AppName) + // if err != nil { + // // The Registration resource may no longer exist, in which case we stop + // // processing. + // if errors.IsNotFound(err) { + // utilruntime.HandleError(fmt.Errorf("failed to get RadixRegistartion object: %v", err)) + // return nil + // } + // return err + // } + // + // // get RA error is ignored because nil is accepted + // radixApplication, _ := t.radixclient.RadixV1().RadixApplications(utils.GetAppNamespace(syncDNSAlias.Spec.AppName)). + // Get(context.TODO(), syncDNSAlias.Spec.AppName, meta.GetOptions{}) + // + // nw, err := networkpolicy.NewNetworkPolicy(t.kubeclient, t.kubeutil, logger, syncDNSAlias.Spec.AppName) + // if err != nil { + // return err + // } + // + // env, err := dns alias.NewDNSAlias(t.kubeclient, t.kubeutil, t.radixclient, syncDNSAlias, radixRegistration, radixApplication, logger, &nw) + // + // if err != nil { + // return err + // } + // + // err = env.OnSync(meta.NewTime(time.Now().UTC())) + // if err != nil { + // return err + // } + + // t.hasSynced(true) + // eventRecorder.Event(env.GetConfig(), core.EventTypeNormal, SuccessSynced, MessageResourceSynced) + return nil +} diff --git a/radix-operator/main.go b/radix-operator/main.go index 17bfc9dcc..5c1b91ee2 100644 --- a/radix-operator/main.go +++ b/radix-operator/main.go @@ -10,11 +10,10 @@ import ( "syscall" "time" - jobUtil "github.com/equinor/radix-operator/pkg/apis/job" - errorUtils "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-operator/pkg/apis/defaults" deploymentAPI "github.com/equinor/radix-operator/pkg/apis/deployment" + jobUtil "github.com/equinor/radix-operator/pkg/apis/job" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -25,6 +24,7 @@ import ( "github.com/equinor/radix-operator/radix-operator/common" "github.com/equinor/radix-operator/radix-operator/config" "github.com/equinor/radix-operator/radix-operator/deployment" + dnsalias "github.com/equinor/radix-operator/radix-operator/dnsalias" "github.com/equinor/radix-operator/radix-operator/environment" "github.com/equinor/radix-operator/radix-operator/job" "github.com/equinor/radix-operator/radix-operator/registration" @@ -60,8 +60,8 @@ func main() { rateLimitConfig := utils.WithKubernetesClientRateLimiter(flowcontrol.NewTokenBucketRateLimiter(kubeClientRateLimitQPS, kubeClientRateLimitBurst)) client, radixClient, prometheusOperatorClient, secretProviderClient := utils.GetKubernetesClient(rateLimitConfig) - activeclusternameEnvVar := os.Getenv(defaults.ActiveClusternameEnvironmentVariable) - logger.Printf("Active cluster name: %v", activeclusternameEnvVar) + activeClusterNameEnvVar := os.Getenv(defaults.ActiveClusternameEnvironmentVariable) + logger.Printf("Active cluster name: %v", activeClusterNameEnvVar) stop := make(chan struct{}) defer close(stop) @@ -80,6 +80,7 @@ func main() { startController(createJobController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg.PipelineJobConfig), jobControllerThreads, stop) startController(createAlertController(client, radixClient, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), alertControllerThreads, stop) startController(createBatchController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), 1, stop) + startController(createDNSAliasesController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), environmentControllerThreads, stop) // Start informers when all controllers are running kubeInformerFactory.Start(stop) @@ -129,7 +130,7 @@ func createRegistrationController(client kubernetes.Interface, radixClient radix func(syncedOk bool) {}, // Not interested in getting notifications of synced ) - waitForChildrenToSync := true + const waitForChildrenToSync = true return registration.NewController( client, radixClient, @@ -155,7 +156,7 @@ func createApplicationController(client kubernetes.Interface, radixClient radixc func(syncedOk bool) {}, // Not interested in getting notifications of synced) ) - waitForChildrenToSync := true + const waitForChildrenToSync = true return application.NewController( client, radixClient, @@ -182,7 +183,7 @@ func createEnvironmentController(client kubernetes.Interface, radixClient radixc func(syncedOk bool) {}, // Not interested in getting notifications of synced ) - waitForChildrenToSync := true + const waitForChildrenToSync = true return environment.NewController( client, radixClient, @@ -193,6 +194,33 @@ func createEnvironmentController(client kubernetes.Interface, radixClient radixc recorder) } +func createDNSAliasesController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretProviderClient.Interface) *common.Controller { + kubeUtil, _ := kube.NewWithListers( + client, + radixClient, + secretProviderClient, + kubeInformerFactory, + radixInformerFactory, + ) + + handler := dnsalias.NewHandler( + client, + kubeUtil, + radixClient, + func(syncedOk bool) {}, // Not interested in getting notifications of synced + ) + + const waitForChildrenToSync = true + return dnsalias.NewController( + client, + radixClient, + &handler, + kubeInformerFactory, + radixInformerFactory, + waitForChildrenToSync, + recorder) +} + func createDeploymentController(client kubernetes.Interface, radixClient radixclient.Interface, prometheusOperatorClient monitoring.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretProviderClient.Interface) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, @@ -227,7 +255,7 @@ func createDeploymentController(client kubernetes.Interface, radixClient radixcl deployment.WithOAuth2ProxyDockerImage(oauth2DockerImage), ) - waitForChildrenToSync := true + const waitForChildrenToSync = true return deployment.NewController( client, radixClient, @@ -249,7 +277,7 @@ func createJobController(client kubernetes.Interface, radixClient radixclient.In handler := job.NewHandler(client, kubeUtil, radixClient, config, func(syncedOk bool) {}) // Not interested in getting notifications of synced) - waitForChildrenToSync := true + const waitForChildrenToSync = true return job.NewController(client, radixClient, &handler, kubeInformerFactory, radixInformerFactory, waitForChildrenToSync, recorder) } @@ -268,7 +296,7 @@ func createAlertController(client kubernetes.Interface, radixClient radixclient. prometheusOperatorClient, ) - waitForChildrenToSync := true + const waitForChildrenToSync = true return alert.NewController( client, radixClient, @@ -294,7 +322,7 @@ func createBatchController(client kubernetes.Interface, radixClient radixclient. radixClient, ) - waitForChildrenToSync := true + const waitForChildrenToSync = true return batch.NewController( client, radixClient, @@ -306,17 +334,17 @@ func createBatchController(client kubernetes.Interface, radixClient radixclient. } func loadIngressConfigFromMap(kubeutil *kube.Kube) (deploymentAPI.IngressConfiguration, error) { - config := deploymentAPI.IngressConfiguration{} + ingressConfig := deploymentAPI.IngressConfiguration{} configMap, err := kubeutil.GetConfigMap(metav1.NamespaceDefault, ingressConfigurationMap) if err != nil { - return config, err + return ingressConfig, err } - err = yaml.Unmarshal([]byte(configMap.Data["ingressConfiguration"]), &config) + err = yaml.Unmarshal([]byte(configMap.Data["ingressConfiguration"]), &ingressConfig) if err != nil { - return config, err + return ingressConfig, err } - return config, nil + return ingressConfig, nil } func startMetricsServer(stop <-chan struct{}) { @@ -342,7 +370,7 @@ type HealthStatus struct { } // Healthz The health endpoint -func Healthz(writer http.ResponseWriter, r *http.Request) { +func Healthz(writer http.ResponseWriter, _ *http.Request) { health := HealthStatus{ Status: http.StatusOK, } @@ -355,7 +383,7 @@ func Healthz(writer http.ResponseWriter, r *http.Request) { return } - fmt.Fprintf(writer, "%s", response) + _, _ = fmt.Fprintf(writer, "%s", response) } func setLogLevel(logLevel string) { From a298b10e2b629051f36a426765dd9c036637fc24 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 23 Oct 2023 14:18:18 +0200 Subject: [PATCH 003/121] Extended dns aliases controller and handler, added appName to the RadixDNSAlias --- .../applicationconfig/applicationconfig.go | 9 +- .../applicationconfig_test.go | 128 ++++++++++++------ pkg/apis/applicationconfig/dnsaliases.go | 44 ++++++ pkg/apis/dnsalias/dnsalias.go | 81 +++++++++++ ...radixdnsalias.go => radixdnsaliastypes.go} | 10 +- pkg/apis/radix/v1/register.go | 8 +- pkg/apis/utils/application_builder.go | 100 +++++++++----- radix-operator/dnsalias/handler.go | 67 ++++----- 8 files changed, 322 insertions(+), 125 deletions(-) create mode 100644 pkg/apis/applicationconfig/dnsaliases.go create mode 100644 pkg/apis/dnsalias/dnsalias.go rename pkg/apis/radix/v1/{radixdnsalias.go => radixdnsaliastypes.go} (80%) diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index 560493265..4e8230bf2 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -4,15 +4,14 @@ import ( "context" "encoding/json" "fmt" - "github.com/equinor/radix-operator/pkg/apis/defaults" "reflect" "strings" - "github.com/equinor/radix-operator/pkg/apis/utils/branch" - + "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" + "github.com/equinor/radix-operator/pkg/apis/utils/branch" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" radixTypes "github.com/equinor/radix-operator/pkg/client/clientset/versioned/typed/radix/v1" log "github.com/sirupsen/logrus" @@ -187,6 +186,10 @@ func (app *ApplicationConfig) OnSync() error { return err } + err = app.createOrUpdateDNSAliases() + if err != nil { + return fmt.Errorf("failed to process DNS aliases: %w", err) + } return nil } diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index c59f6db67..0c72b9215 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -15,6 +15,7 @@ import ( radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" radix "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -34,13 +35,13 @@ func init() { } func setupTest() (*test.Utils, kubernetes.Interface, *kube.Kube, radixclient.Interface) { - kubeclient := fake.NewSimpleClientset() - radixclient := radix.NewSimpleClientset() + kubeClient := fake.NewSimpleClientset() + radixClient := radix.NewSimpleClientset() secretproviderclient := secretproviderfake.NewSimpleClientset() - kubeUtil, _ := kube.New(kubeclient, radixclient, secretproviderclient) - handlerTestUtils := test.NewTestUtils(kubeclient, radixclient, secretproviderclient) + kubeUtil, _ := kube.New(kubeClient, radixClient, secretproviderclient) + handlerTestUtils := test.NewTestUtils(kubeClient, radixClient, secretproviderclient) handlerTestUtils.CreateClusterPrerequisites(clusterName, "0.0.0.0", "anysubid") - return &handlerTestUtils, kubeclient, kubeUtil, radixclient + return &handlerTestUtils, kubeClient, kubeUtil, radixClient } func getApplication(ra *radixv1.RadixApplication) *ApplicationConfig { @@ -50,17 +51,17 @@ func getApplication(ra *radixv1.RadixApplication) *ApplicationConfig { } func Test_Create_Radix_Environments(t *testing.T) { - _, client, kubeUtil, radixclient := setupTest() + _, client, kubeUtil, radixClient := setupTest() radixRegistration, _ := utils.GetRadixRegistrationFromFile(sampleRegistration) radixApp, _ := utils.GetRadixApplicationFromFile(sampleApp) - app, _ := NewApplicationConfig(client, kubeUtil, radixclient, radixRegistration, radixApp) + app, _ := NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, radixApp) label := fmt.Sprintf("%s=%s", kube.RadixAppLabel, radixRegistration.Name) t.Run("It can create environments", func(t *testing.T) { err := app.createEnvironments() assert.NoError(t, err) - environments, _ := radixclient.RadixV1().RadixEnvironments().List( + environments, _ := radixClient.RadixV1().RadixEnvironments().List( context.TODO(), metav1.ListOptions{ LabelSelector: label, @@ -71,7 +72,7 @@ func Test_Create_Radix_Environments(t *testing.T) { t.Run("It doesn't fail when re-running creation", func(t *testing.T) { err := app.createEnvironments() assert.NoError(t, err) - environments, _ := radixclient.RadixV1().RadixEnvironments().List( + environments, _ := radixClient.RadixV1().RadixEnvironments().List( context.TODO(), metav1.ListOptions{ LabelSelector: label, @@ -82,10 +83,10 @@ func Test_Create_Radix_Environments(t *testing.T) { func Test_Reconciles_Radix_Environments(t *testing.T) { // Setup - _, client, kubeUtil, radixclient := setupTest() + _, client, kubeUtil, radixClient := setupTest() // Create environments manually - radixclient.RadixV1().RadixEnvironments().Create( + radixClient.RadixV1().RadixEnvironments().Create( context.TODO(), &radixv1.RadixEnvironment{ ObjectMeta: metav1.ObjectMeta{ @@ -94,7 +95,7 @@ func Test_Reconciles_Radix_Environments(t *testing.T) { }, metav1.CreateOptions{}) - radixclient.RadixV1().RadixEnvironments().Create( + radixClient.RadixV1().RadixEnvironments().Create( context.TODO(), &radixv1.RadixEnvironment{ ObjectMeta: metav1.ObjectMeta{ @@ -115,12 +116,12 @@ func Test_Reconciles_Radix_Environments(t *testing.T) { WithEnvironment("prod", "master"). BuildRA() - app, _ := NewApplicationConfig(client, kubeUtil, radixclient, rr, ra) + app, _ := NewApplicationConfig(client, kubeUtil, radixClient, rr, ra) label := fmt.Sprintf("%s=%s", kube.RadixAppLabel, rr.Name) // Test app.createEnvironments() - environments, _ := radixclient.RadixV1().RadixEnvironments().List( + environments, _ := radixClient.RadixV1().RadixEnvironments().List( context.TODO(), metav1.ListOptions{ LabelSelector: label, @@ -273,10 +274,10 @@ func TestIsTargetEnvsEmpty_twoEntriesWithOneMapping(t *testing.T) { } func Test_WithBuildSecretsSet_SecretsCorrectlyAdded(t *testing.T) { - tu, client, kubeUtil, radixclient := setupTest() + tu, client, kubeUtil, radixClient := setupTest() appNamespace := "any-app-app" - applyApplicationWithSync(tu, client, kubeUtil, radixclient, + applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). @@ -299,7 +300,7 @@ func Test_WithBuildSecretsSet_SecretsCorrectlyAdded(t *testing.T) { assert.True(t, roleBindingByNameExists("radix-app-admin-build-secrets", rolebindings)) assert.True(t, roleBindingByNameExists("pipeline-build-secrets", rolebindings)) - applyApplicationWithSync(tu, client, kubeUtil, radixclient, + applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). @@ -315,9 +316,9 @@ func Test_WithBuildSecretsSet_SecretsCorrectlyAdded(t *testing.T) { } func Test_WithBuildSecretsDeleted_SecretsCorrectlyDeleted(t *testing.T) { - tu, client, kubeUtil, radixclient := setupTest() + tu, client, kubeUtil, radixClient := setupTest() - applyApplicationWithSync(tu, client, kubeUtil, radixclient, + applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). @@ -325,7 +326,7 @@ func Test_WithBuildSecretsDeleted_SecretsCorrectlyDeleted(t *testing.T) { // Delete secret appNamespace := "any-app-app" - applyApplicationWithSync(tu, client, kubeUtil, radixclient, + applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). @@ -341,7 +342,7 @@ func Test_WithBuildSecretsDeleted_SecretsCorrectlyDeleted(t *testing.T) { assert.Equal(t, defaultValue, buildSecrets.Data["secret2"]) // Delete secret - applyApplicationWithSync(tu, client, kubeUtil, radixclient, + applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). @@ -363,9 +364,9 @@ func Test_WithBuildSecretsDeleted_SecretsCorrectlyDeleted(t *testing.T) { } func Test_AppReaderBuildSecretsRoleAndRoleBindingExists(t *testing.T) { - tu, client, kubeUtil, radixclient := setupTest() + tu, client, kubeUtil, radixClient := setupTest() - applyApplicationWithSync(tu, client, kubeUtil, radixclient, + applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). @@ -378,7 +379,7 @@ func Test_AppReaderBuildSecretsRoleAndRoleBindingExists(t *testing.T) { assert.True(t, roleBindingByNameExists("radix-app-reader-build-secrets", rolebindings)) // Delete secret and verify that role and rolebinding is deleted - applyApplicationWithSync(tu, client, kubeUtil, radixclient, + applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master")) @@ -391,9 +392,9 @@ func Test_AppReaderBuildSecretsRoleAndRoleBindingExists(t *testing.T) { } func Test_AppReaderPrivateImageHubRoleAndRoleBindingExists(t *testing.T) { - tu, client, kubeUtil, radixclient := setupTest() + tu, client, kubeUtil, radixClient := setupTest() - applyApplicationWithSync(tu, client, kubeUtil, radixclient, + applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). @@ -555,15 +556,15 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_NoImageHubs(t *testing.T) { } func Test_RadixEnvironment(t *testing.T) { - tu, client, kubeUtil, radixclient := setupTest() + tu, client, kubeUtil, radixClient := setupTest() - applyApplicationWithSync(tu, client, kubeUtil, radixclient, + applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app")) - rr, _ := radixclient.RadixV1().RadixRegistrations().Get(context.TODO(), "any-app", metav1.GetOptions{}) + rr, _ := radixClient.RadixV1().RadixRegistrations().Get(context.TODO(), "any-app", metav1.GetOptions{}) - environments, err := radixclient.RadixV1().RadixEnvironments().List(context.TODO(), metav1.ListOptions{}) + environments, err := radixClient.RadixV1().RadixEnvironments().List(context.TODO(), metav1.ListOptions{}) t.Run("It creates a single environment", func(t *testing.T) { assert.NoError(t, err) @@ -605,16 +606,16 @@ func Test_UseBuildKit(t *testing.T) { expectedUseBuildKit: utils.BoolPtr(true), }, } - tu, client, kubeUtil, radixclient := setupTest() + tu, client, kubeUtil, radixClient := setupTest() for _, testScenario := range testScenarios { ra := utils.ARadixApplication().WithAppName(testScenario.appName) if testScenario.useBuildKit != nil { ra = ra.WithBuildKit(testScenario.useBuildKit) } - applyApplicationWithSync(tu, client, kubeUtil, radixclient, ra) + applyApplicationWithSync(tu, client, kubeUtil, radixClient, ra) - raAfterSync, _ := radixclient.RadixV1().RadixApplications(utils.GetAppNamespace(testScenario.appName)).Get(context.TODO(), testScenario.appName, metav1.GetOptions{}) + raAfterSync, _ := radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(testScenario.appName)).Get(context.TODO(), testScenario.appName, metav1.GetOptions{}) var useBuildKit *bool if raAfterSync.Spec.Build == nil { @@ -659,6 +660,46 @@ func Test_IsConfigBranch(t *testing.T) { }) } +func Test_DNSAliases(t *testing.T) { + appName := "any-app1" + var testScenarios = []struct { + name string + dnsAliases []radixv1.DNSAlias + existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec + expectedRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec + }{ + { + name: "no aliases", + }, + } + tu, client, kubeUtil, radixClient := setupTest() + + for _, ts := range testScenarios { + t.Run(ts.name, func(t *testing.T) { + ra := utils.ARadixApplication().WithAppName(appName).WithDNSAlias(ts.dnsAliases...) + applyApplicationWithSync(tu, client, kubeUtil, radixClient, ra) + + radixDNSAliases, err := radixClient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{}) + require.NoError(t, err) + + if ts.expectedRadixDNSAliases == nil { + require.Len(t, radixDNSAliases.Items, 0, "not expected Radix DNS aliases") + return + } + require.Len(t, radixDNSAliases.Items, len(ts.expectedRadixDNSAliases), "expected Radix DNS aliases count") + for _, radixDNSAlias := range radixDNSAliases.Items { + if expectedDNSAlias, ok := ts.expectedRadixDNSAliases[radixDNSAlias.Name]; ok { + assert.Equal(t, expectedDNSAlias.AppName, radixDNSAlias.Spec.AppName, "app name") + assert.Equal(t, expectedDNSAlias.Environment, radixDNSAlias.Spec.Environment, "environment") + assert.Equal(t, expectedDNSAlias.Component, radixDNSAlias.Spec.Component, "component") + } else { + assert.Failf(t, "found not expected RadixDNSAlias %s: env %s, component %s, appName %s", radixDNSAlias.GetName(), radixDNSAlias.Spec.Environment, radixDNSAlias.Spec.Component, radixDNSAlias.Spec.AppName) + } + } + }) + } +} + func rrAsOwnerReference(rr *radixv1.RadixRegistration) []metav1.OwnerReference { trueVar := true return []metav1.OwnerReference{ @@ -673,7 +714,7 @@ func rrAsOwnerReference(rr *radixv1.RadixRegistration) []metav1.OwnerReference { } func applyRadixAppWithPrivateImageHub(privateImageHubs radixv1.PrivateImageHubEntries) (kubernetes.Interface, *ApplicationConfig, error) { - tu, client, kubeUtil, radixclient := setupTest() + tu, client, kubeUtil, radixClient := setupTest() appBuilder := utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master") @@ -681,32 +722,35 @@ func applyRadixAppWithPrivateImageHub(privateImageHubs radixv1.PrivateImageHubEn appBuilder.WithPrivateImageRegistry(key, config.Username, config.Email) } - applyApplicationWithSync(tu, client, kubeUtil, radixclient, appBuilder) - appConfig, err := getAppConfig(client, kubeUtil, radixclient, appBuilder) + err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, appBuilder) + if err != nil { + return nil, nil, err + } + appConfig, err := getAppConfig(client, kubeUtil, radixClient, appBuilder) return client, appConfig, err } -func getAppConfig(client kubernetes.Interface, kubeUtil *kube.Kube, radixclient radixclient.Interface, applicationBuilder utils.ApplicationBuilder) (*ApplicationConfig, error) { +func getAppConfig(client kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, applicationBuilder utils.ApplicationBuilder) (*ApplicationConfig, error) { ra := applicationBuilder.BuildRA() - radixRegistration, _ := radixclient.RadixV1().RadixRegistrations().Get(context.TODO(), ra.Name, metav1.GetOptions{}) + radixRegistration, _ := radixClient.RadixV1().RadixRegistrations().Get(context.TODO(), ra.Name, metav1.GetOptions{}) - return NewApplicationConfig(client, kubeUtil, radixclient, radixRegistration, ra) + return NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra) } func applyApplicationWithSync(tu *test.Utils, client kubernetes.Interface, kubeUtil *kube.Kube, - radixclient radixclient.Interface, applicationBuilder utils.ApplicationBuilder) error { + radixClient radixclient.Interface, applicationBuilder utils.ApplicationBuilder) error { ra, err := tu.ApplyApplication(applicationBuilder) if err != nil { return err } - radixRegistration, err := radixclient.RadixV1().RadixRegistrations().Get(context.TODO(), ra.Name, metav1.GetOptions{}) + radixRegistration, err := radixClient.RadixV1().RadixRegistrations().Get(context.TODO(), ra.Name, metav1.GetOptions{}) if err != nil { return err } - applicationconfig, err := NewApplicationConfig(client, kubeUtil, radixclient, radixRegistration, ra) + applicationconfig, err := NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra) if err != nil { return err } diff --git a/pkg/apis/applicationconfig/dnsaliases.go b/pkg/apis/applicationconfig/dnsaliases.go new file mode 100644 index 000000000..270a4cb1b --- /dev/null +++ b/pkg/apis/applicationconfig/dnsaliases.go @@ -0,0 +1,44 @@ +package applicationconfig + +import ( + "context" + "fmt" + "strings" + + "github.com/equinor/radix-common/utils/slice" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/utils/labels" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func (app *ApplicationConfig) createOrUpdateDNSAliases() error { + appName := app.registration.Name + radixDNSAliasesMap, err := app.getRadixDNSAliasesMap(appName) + if err != nil { + return err + } + for _, dnsAlias := range app.config.Spec.DNSAlias { + if radixDNSAlias, ok := radixDNSAliasesMap[dnsAlias.Domain]; ok { + if !strings.EqualFold(appName, radixDNSAlias.Spec.AppName) { + return fmt.Errorf("existing DNS alias domain %s is used by the application %s", dnsAlias.Domain, radixDNSAlias.Spec.AppName) + } + if strings.EqualFold(dnsAlias.Environment, radixDNSAlias.Spec.Environment) && + strings.EqualFold(dnsAlias.Component, radixDNSAlias.Spec.Component) { + + } + } + } + fmt.Println(len(radixDNSAliasesMap)) + return nil +} + +func (app *ApplicationConfig) getRadixDNSAliasesMap(appName string) (map[string]*radixv1.RadixDNSAlias, error) { + dnsAliasList, err := app.radixclient.RadixV1().RadixDNSAliases().List(context.Background(), metav1.ListOptions{LabelSelector: labels.ForApplicationName(appName).String()}) + if err != nil { + return nil, err + } + return slice.Reduce(dnsAliasList.Items, make(map[string]*radixv1.RadixDNSAlias), func(acc map[string]*radixv1.RadixDNSAlias, dnsAlias radixv1.RadixDNSAlias) map[string]*radixv1.RadixDNSAlias { + acc[dnsAlias.Name] = &dnsAlias + return acc + }), err +} diff --git a/pkg/apis/dnsalias/dnsalias.go b/pkg/apis/dnsalias/dnsalias.go new file mode 100644 index 000000000..685a7bb03 --- /dev/null +++ b/pkg/apis/dnsalias/dnsalias.go @@ -0,0 +1,81 @@ +package dnsalias + +import ( + "context" + "fmt" + + "github.com/equinor/radix-operator/pkg/apis/kube" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + "github.com/sirupsen/logrus" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/util/retry" +) + +// DNSAlias is the aggregate-root for manipulating RadixDNSAliases +type DNSAlias struct { + kubeclient kubernetes.Interface + radixclient radixclient.Interface + kubeutil *kube.Kube + config *radixv1.RadixDNSAlias + appConfig *radixv1.RadixApplication + logger *logrus.Entry +} + +// NewDNSAlias is the constructor for DNSAlias +func NewDNSAlias( + kubeclient kubernetes.Interface, + kubeutil *kube.Kube, + radixclient radixclient.Interface, + config *radixv1.RadixDNSAlias, + appConfig *radixv1.RadixApplication, + logger *logrus.Entry) (DNSAlias, error) { + + return DNSAlias{ + kubeclient, + radixclient, + kubeutil, + config, + appConfig, + logger}, nil +} + +// OnSync is called by the handler when changes are applied and must be +// reconciled with current state. +func (dnsAlias *DNSAlias) OnSync(time metav1.Time) error { + + // TODO + err := dnsAlias.updateRadixDNSAliasStatus(dnsAlias.config, func(currStatus *radixv1.RadixDNSAliasStatus) { + // time is parameterized for testability + currStatus.Reconciled = time + }) + if err != nil { + return fmt.Errorf("failed to update status on DNS alias %s: %v", dnsAlias.config.GetName(), err) + } + dnsAlias.logger.Debugf("DNSAlias %s reconciled", dnsAlias.config.GetName()) + return nil +} + +func (dnsAlias *DNSAlias) updateRadixDNSAliasStatus(rEnv *radixv1.RadixDNSAlias, changeStatusFunc func(currStatus *radixv1.RadixDNSAliasStatus)) error { + radixDNSAliasInterface := dnsAlias.radixclient.RadixV1().RadixDNSAliases() + return retry.RetryOnConflict(retry.DefaultRetry, func() error { + currentEnv, err := radixDNSAliasInterface.Get(context.TODO(), rEnv.GetName(), metav1.GetOptions{}) + if err != nil { + return err + } + changeStatusFunc(¤tEnv.Status) + _, err = radixDNSAliasInterface.UpdateStatus(context.TODO(), currentEnv, metav1.UpdateOptions{}) + if err == nil && dnsAlias.config.GetName() == rEnv.GetName() { + currentEnv, err = radixDNSAliasInterface.Get(context.TODO(), rEnv.GetName(), metav1.GetOptions{}) + if err == nil { + dnsAlias.config = currentEnv + } + } + return err + }) +} + +func (dnsAlias *DNSAlias) GetConfig() *radixv1.RadixDNSAlias { + return dnsAlias.config +} diff --git a/pkg/apis/radix/v1/radixdnsalias.go b/pkg/apis/radix/v1/radixdnsaliastypes.go similarity index 80% rename from pkg/apis/radix/v1/radixdnsalias.go rename to pkg/apis/radix/v1/radixdnsaliastypes.go index f4a8eaf2a..369bbaed1 100644 --- a/pkg/apis/radix/v1/radixdnsalias.go +++ b/pkg/apis/radix/v1/radixdnsaliastypes.go @@ -26,17 +26,23 @@ type RadixDNSAliasList struct { // RadixDNSAliasSpec is the spec for an RadixDNSAlias type RadixDNSAliasSpec struct { + // Name of the application the DNS alias used in. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + AppName string `json:"appName" yaml:"appName"` + // Name of the environment for the component. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ - Environment string `json:"environment"` + Environment string `json:"environment" yaml:"environment"` // Name of the component that shall receive the incoming requests. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ - Component string `json:"component"` + Component string `json:"component" yaml:"component"` } // RadixDNSAliasStatus is the status for an RadixDNSAlias diff --git a/pkg/apis/radix/v1/register.go b/pkg/apis/radix/v1/register.go index 3eddf6c22..5f43fb2e8 100644 --- a/pkg/apis/radix/v1/register.go +++ b/pkg/apis/radix/v1/register.go @@ -14,10 +14,10 @@ var SchemeGroupVersion = schema.GroupVersion{ Version: "v1", } var ( - //SchemeBuilder builds a scheme + // SchemeBuilder builds a scheme SchemeBuilder runtime.SchemeBuilder localSchemeBuilder = &SchemeBuilder - //AddToScheme adds to scheme + // AddToScheme adds to scheme AddToScheme = localSchemeBuilder.AddToScheme ) @@ -31,7 +31,7 @@ func Resource(resource string) schema.GroupResource { } // addKnownTypes adds our types to the API scheme by registering -// RadixApplication, RadixApplicationList, RadixDeployment and RadixDeploymentList +// RadixApplication, RadixApplicationList, RadixDeployment, RadixDeploymentList, etc. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes( SchemeGroupVersion, @@ -49,6 +49,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &RadixAlertList{}, &RadixBatch{}, &RadixBatchList{}, + &RadixDNSAlias{}, + &RadixDNSAliasList{}, ) // register the type in the scheme diff --git a/pkg/apis/utils/application_builder.go b/pkg/apis/utils/application_builder.go index 64019f554..662370749 100644 --- a/pkg/apis/utils/application_builder.go +++ b/pkg/apis/utils/application_builder.go @@ -1,7 +1,9 @@ package utils import ( - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "strings" + + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils/numbers" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -9,20 +11,21 @@ import ( // ApplicationBuilder Handles construction of RA type ApplicationBuilder interface { WithRadixRegistration(RegistrationBuilder) ApplicationBuilder - WithAppName(string) ApplicationBuilder - WithBuildSecrets(...string) ApplicationBuilder - WithBuildKit(*bool) ApplicationBuilder - WithEnvironment(string, string) ApplicationBuilder - WithEnvironmentNoBranch(string) ApplicationBuilder - WithComponent(RadixApplicationComponentBuilder) ApplicationBuilder - WithComponents(...RadixApplicationComponentBuilder) ApplicationBuilder - WithJobComponent(RadixApplicationJobComponentBuilder) ApplicationBuilder - WithJobComponents(...RadixApplicationJobComponentBuilder) ApplicationBuilder - WithDNSAppAlias(string, string) ApplicationBuilder - WithDNSExternalAlias(string, string, string) ApplicationBuilder - WithPrivateImageRegistry(string, string, string) ApplicationBuilder + WithAppName(appName string) ApplicationBuilder + WithBuildSecrets(buildSecrets ...string) ApplicationBuilder + WithBuildKit(useBuildKit *bool) ApplicationBuilder + WithEnvironment(environment, buildFrom string) ApplicationBuilder + WithEnvironmentNoBranch(environment string) ApplicationBuilder + WithComponent(components RadixApplicationComponentBuilder) ApplicationBuilder + WithComponents(components ...RadixApplicationComponentBuilder) ApplicationBuilder + WithJobComponent(component RadixApplicationJobComponentBuilder) ApplicationBuilder + WithJobComponents(components ...RadixApplicationJobComponentBuilder) ApplicationBuilder + WithDNSAppAlias(env, component string) ApplicationBuilder + WithDNSAlias(dnsAliases ...radixv1.DNSAlias) ApplicationBuilder + WithDNSExternalAlias(alias, env, component string) ApplicationBuilder + WithPrivateImageRegistry(server, username, email string) ApplicationBuilder GetRegistrationBuilder() RegistrationBuilder - BuildRA() *v1.RadixApplication + BuildRA() *radixv1.RadixApplication } // ApplicationBuilderStruct Instance variables @@ -31,12 +34,13 @@ type ApplicationBuilderStruct struct { appName string buildSecrets []string useBuildKit *bool - environments []v1.Environment + environments []radixv1.Environment components []RadixApplicationComponentBuilder jobComponents []RadixApplicationJobComponentBuilder - dnsAppAlias v1.AppAlias - externalAppAlias []v1.ExternalAlias - privateImageHubs v1.PrivateImageHubEntries + dnsAppAlias radixv1.AppAlias + dnsAliases []radixv1.DNSAlias + externalAppAlias []radixv1.ExternalAlias + privateImageHubs radixv1.PrivateImageHubEntries } func (ap *ApplicationBuilderStruct) WithBuildKit(useBuildKit *bool) ApplicationBuilder { @@ -47,10 +51,10 @@ func (ap *ApplicationBuilderStruct) WithBuildKit(useBuildKit *bool) ApplicationB // WithPrivateImageRegistry adds a private image hub to application func (ap *ApplicationBuilderStruct) WithPrivateImageRegistry(server, username, email string) ApplicationBuilder { if ap.privateImageHubs == nil { - ap.privateImageHubs = v1.PrivateImageHubEntries(map[string]*v1.RadixPrivateImageHubCredential{}) + ap.privateImageHubs = radixv1.PrivateImageHubEntries(map[string]*radixv1.RadixPrivateImageHubCredential{}) } - ap.privateImageHubs[server] = &v1.RadixPrivateImageHubCredential{ + ap.privateImageHubs[server] = &radixv1.RadixPrivateImageHubCredential{ Username: username, Email: email, } @@ -81,9 +85,9 @@ func (ap *ApplicationBuilderStruct) WithBuildSecrets(buildSecrets ...string) App // WithEnvironment Appends to environment-build list func (ap *ApplicationBuilderStruct) WithEnvironment(environment, buildFrom string) ApplicationBuilder { - ap.environments = append(ap.environments, v1.Environment{ + ap.environments = append(ap.environments, radixv1.Environment{ Name: environment, - Build: v1.EnvBuild{ + Build: radixv1.EnvBuild{ From: buildFrom, }, }) @@ -93,29 +97,54 @@ func (ap *ApplicationBuilderStruct) WithEnvironment(environment, buildFrom strin // WithEnvironmentNoBranch Appends environment with no branch mapping to config func (ap *ApplicationBuilderStruct) WithEnvironmentNoBranch(environment string) ApplicationBuilder { - ap.environments = append(ap.environments, v1.Environment{ + ap.environments = append(ap.environments, radixv1.Environment{ Name: environment, }) return ap } -// WithDNSAppAlias Sets env + component to be the app alias -func (ap *ApplicationBuilderStruct) WithDNSAppAlias(env string, component string) ApplicationBuilder { - ap.dnsAppAlias = v1.AppAlias{ +// WithDNSAppAlias Sets env + component to be the app alias like "frontend-myapp-prod.radix.equinor.com" or "frontend-myapp-prod..radix.equinor.com" +func (ap *ApplicationBuilderStruct) WithDNSAppAlias(env, component string) ApplicationBuilder { + ap.dnsAppAlias = radixv1.AppAlias{ Environment: env, Component: component, } return ap } +// WithDNSAlias Sets domain for env and component to be the DNS alias like "my-domain.radix.equinor.com" or "my-domain..radix.equinor.com" +func (ap *ApplicationBuilderStruct) WithDNSAlias(dnsAliases ...radixv1.DNSAlias) ApplicationBuilder { + var dnsAliasesToAppend []radixv1.DNSAlias + for _, dnsAlias := range dnsAliases { + foundExistingAlias := false + for i := 0; i < len(ap.dnsAliases); i++ { + if strings.EqualFold(dnsAlias.Domain, ap.dnsAliases[i].Domain) { + ap.dnsAliases[i].Environment = dnsAlias.Environment + ap.dnsAliases[i].Component = dnsAlias.Component + foundExistingAlias = true + break + } + } + if foundExistingAlias { + continue + } + dnsAliasesToAppend = append(dnsAliasesToAppend, radixv1.DNSAlias{ + Environment: dnsAlias.Environment, + Component: dnsAlias.Component, + }) + } + ap.dnsAliases = append(ap.dnsAliases, dnsAliasesToAppend...) + return ap +} + // WithDNSExternalAlias Sets env + component to the external alias func (ap *ApplicationBuilderStruct) WithDNSExternalAlias(alias, env, component string) ApplicationBuilder { if ap.externalAppAlias == nil { - ap.externalAppAlias = make([]v1.ExternalAlias, 0) + ap.externalAppAlias = make([]radixv1.ExternalAlias, 0) } - externalAlias := v1.ExternalAlias{ + externalAlias := radixv1.ExternalAlias{ Alias: alias, Environment: env, Component: component, @@ -159,27 +188,27 @@ func (ap *ApplicationBuilderStruct) GetRegistrationBuilder() RegistrationBuilder } // BuildRA Builds RA -func (ap *ApplicationBuilderStruct) BuildRA() *v1.RadixApplication { - var components = make([]v1.RadixComponent, 0) +func (ap *ApplicationBuilderStruct) BuildRA() *radixv1.RadixApplication { + var components = make([]radixv1.RadixComponent, 0) for _, comp := range ap.components { components = append(components, comp.BuildComponent()) } - var jobComponents = make([]v1.RadixJobComponent, 0) + var jobComponents = make([]radixv1.RadixJobComponent, 0) for _, comp := range ap.jobComponents { jobComponents = append(jobComponents, comp.BuildJobComponent()) } - var build *v1.BuildSpec + var build *radixv1.BuildSpec if ap.useBuildKit == nil && ap.buildSecrets == nil { build = nil } else { - build = &v1.BuildSpec{ + build = &radixv1.BuildSpec{ Secrets: ap.buildSecrets, UseBuildKit: ap.useBuildKit, } } - radixApplication := &v1.RadixApplication{ + radixApplication := &radixv1.RadixApplication{ TypeMeta: metav1.TypeMeta{ APIVersion: "radix.equinor.com/v1", Kind: "RadixApplication", @@ -188,12 +217,13 @@ func (ap *ApplicationBuilderStruct) BuildRA() *v1.RadixApplication { Name: ap.appName, Namespace: GetAppNamespace(ap.appName), }, - Spec: v1.RadixApplicationSpec{ + Spec: radixv1.RadixApplicationSpec{ Build: build, Components: components, Jobs: jobComponents, Environments: ap.environments, DNSAppAlias: ap.dnsAppAlias, + DNSAlias: ap.dnsAliases, DNSExternalAlias: ap.externalAppAlias, PrivateImageHubs: ap.privateImageHubs, }, diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go index 1ef295a29..0b2a3f7b5 100644 --- a/radix-operator/dnsalias/handler.go +++ b/radix-operator/dnsalias/handler.go @@ -3,13 +3,16 @@ package dnsalias import ( "context" "fmt" + "time" + "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" + "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" - + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" - meta "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/record" @@ -52,54 +55,38 @@ func NewHandler( // Sync is called by kubernetes after the Controller Enqueues a work-item // and collects components and determines whether state must be reconciled. func (t *Handler) Sync(namespace, name string, eventRecorder record.EventRecorder) error { - radixDNSAlias, err := t.radixclient.RadixV1().RadixDNSAliases().Get(context.TODO(), name, meta.GetOptions{}) + radixDNSAlias, err := t.radixclient.RadixV1().RadixDNSAliases().Get(context.TODO(), name, metav1.GetOptions{}) if err != nil { - // The DNSAlias resource may no longer exist, in which case we stop + // The RadixDNSAlias resource may no longer exist, in which case we stop // processing. if errors.IsNotFound(err) { - utilruntime.HandleError(fmt.Errorf("radix dns alias %s in work queue no longer exists", name)) + utilruntime.HandleError(fmt.Errorf("radix DNS alias %s in work queue no longer exists", name)) return nil } - return err } syncDNSAlias := radixDNSAlias.DeepCopy() - logger.Debugf("Sync dns alias %s", syncDNSAlias.Name) + logger.Debugf("Sync DNS alias %s", name) - // TOD sync - // radixRegistration, err := t.kubeutil.GetRegistration(syncDNSAlias.Spec.AppName) - // if err != nil { - // // The Registration resource may no longer exist, in which case we stop - // // processing. - // if errors.IsNotFound(err) { - // utilruntime.HandleError(fmt.Errorf("failed to get RadixRegistartion object: %v", err)) - // return nil - // } - // return err - // } - // - // // get RA error is ignored because nil is accepted - // radixApplication, _ := t.radixclient.RadixV1().RadixApplications(utils.GetAppNamespace(syncDNSAlias.Spec.AppName)). - // Get(context.TODO(), syncDNSAlias.Spec.AppName, meta.GetOptions{}) - // - // nw, err := networkpolicy.NewNetworkPolicy(t.kubeclient, t.kubeutil, logger, syncDNSAlias.Spec.AppName) - // if err != nil { - // return err - // } - // - // env, err := dns alias.NewDNSAlias(t.kubeclient, t.kubeutil, t.radixclient, syncDNSAlias, radixRegistration, radixApplication, logger, &nw) - // - // if err != nil { - // return err - // } - // - // err = env.OnSync(meta.NewTime(time.Now().UTC())) - // if err != nil { - // return err - // } + appName := syncDNSAlias.Spec.AppName + radixApplication, err := t.radixclient.RadixV1().RadixApplications(utils.GetAppNamespace(appName)). + Get(context.TODO(), appName, metav1.GetOptions{}) + if err != nil { + return err + } + + dnsAlias, err := dnsalias.NewDNSAlias(t.kubeclient, t.kubeutil, t.radixclient, syncDNSAlias, radixApplication, logger) + if err != nil { + return err + } + + err = dnsAlias.OnSync(metav1.NewTime(time.Now().UTC())) + if err != nil { + return err + } - // t.hasSynced(true) - // eventRecorder.Event(env.GetConfig(), core.EventTypeNormal, SuccessSynced, MessageResourceSynced) + t.hasSynced(true) + eventRecorder.Event(dnsAlias.GetConfig(), corev1.EventTypeNormal, SuccessSynced, MessageResourceSynced) return nil } From 8b3bc0452a1efab481fa603c54a84532e4642fc0 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 23 Oct 2023 15:24:02 +0200 Subject: [PATCH 004/121] Added ingresses stubs to test --- .../applicationconfig_test.go | 116 ++++++++++++++++-- 1 file changed, 104 insertions(+), 12 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 0c72b9215..5d61a3b26 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -660,46 +661,137 @@ func Test_IsConfigBranch(t *testing.T) { }) } +type testIngress struct { + appName string + envName string + name string + host string + component string + port int32 +} + func Test_DNSAliases(t *testing.T) { appName := "any-app1" + var testScenarios = []struct { name string dnsAliases []radixv1.DNSAlias existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec expectedRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec + existingIngress []testIngress + expectedIngress map[string]testIngress }{ { - name: "no aliases", + name: "no aliases, no additional radix aliases, no additional ingresses", }, } - tu, client, kubeUtil, radixClient := setupTest() + tu, kubeClient, kubeUtil, radixClient := setupTest() for _, ts := range testScenarios { t.Run(ts.name, func(t *testing.T) { ra := utils.ARadixApplication().WithAppName(appName).WithDNSAlias(ts.dnsAliases...) - applyApplicationWithSync(tu, client, kubeUtil, radixClient, ra) + require.NoError(t, applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, ra), "register radix application") + require.NoError(t, registerExistingRadixDNSAliases(radixClient, ts.existingRadixDNSAliases), "create existing RadixDNSAlias") + require.NoError(t, registerExistingIngresses(kubeClient, ts.existingIngress), "create existing ingresses") radixDNSAliases, err := radixClient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{}) require.NoError(t, err) + ingresses, err := kubeClient.NetworkingV1().Ingresses("").List(context.TODO(), metav1.ListOptions{}) + require.NoError(t, err) + // assert RadixDNSAlias-es if ts.expectedRadixDNSAliases == nil { require.Len(t, radixDNSAliases.Items, 0, "not expected Radix DNS aliases") - return + } else { + require.Len(t, radixDNSAliases.Items, len(ts.expectedRadixDNSAliases), "expected Radix DNS aliases count") + for _, radixDNSAlias := range radixDNSAliases.Items { + if expectedDNSAlias, ok := ts.expectedRadixDNSAliases[radixDNSAlias.Name]; ok { + assert.Equal(t, expectedDNSAlias.AppName, radixDNSAlias.Spec.AppName, "app name") + assert.Equal(t, expectedDNSAlias.Environment, radixDNSAlias.Spec.Environment, "environment") + assert.Equal(t, expectedDNSAlias.Component, radixDNSAlias.Spec.Component, "component") + } else { + assert.Failf(t, "found not expected RadixDNSAlias %s: env %s, component %s, appName %s", radixDNSAlias.GetName(), radixDNSAlias.Spec.Environment, radixDNSAlias.Spec.Component, radixDNSAlias.Spec.AppName) + } + } } - require.Len(t, radixDNSAliases.Items, len(ts.expectedRadixDNSAliases), "expected Radix DNS aliases count") - for _, radixDNSAlias := range radixDNSAliases.Items { - if expectedDNSAlias, ok := ts.expectedRadixDNSAliases[radixDNSAlias.Name]; ok { - assert.Equal(t, expectedDNSAlias.AppName, radixDNSAlias.Spec.AppName, "app name") - assert.Equal(t, expectedDNSAlias.Environment, radixDNSAlias.Spec.Environment, "environment") - assert.Equal(t, expectedDNSAlias.Component, radixDNSAlias.Spec.Component, "component") - } else { - assert.Failf(t, "found not expected RadixDNSAlias %s: env %s, component %s, appName %s", radixDNSAlias.GetName(), radixDNSAlias.Spec.Environment, radixDNSAlias.Spec.Component, radixDNSAlias.Spec.AppName) + // assert ingresses + if ts.expectedIngress == nil { + require.Len(t, ingresses.Items, 0, "not expected ingresses") + } else { + require.Len(t, ingresses.Items, len(ts.expectedIngress), "expected ingresses count") + for _, ingress := range ingresses.Items { + if expectedIngress, ok := ts.expectedIngress[ingress.Name]; ok { + require.Len(t, ingress.Spec.Rules, 1, "rules count") + assert.Equal(t, expectedIngress.appName, ingress.GetLabels()[kube.RadixAppLabel], "app name") + assert.Equal(t, utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ingress.GetNamespace(), "namespace") + assert.Equal(t, expectedIngress.component, ingress.GetLabels()[kube.RadixComponentLabel], "component name") + assert.Equal(t, expectedIngress.host, ingress.Spec.Rules[0].Host, "rule host") + assert.Equal(t, "/", ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") + assert.Equal(t, expectedIngress.component, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend component name") + assert.Equal(t, expectedIngress.port, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port, "rule backend component port") + } else { + assert.Failf(t, "found not expected ingress %s: appName %s, host %s, service %s, port %d", ingress.GetName(), ingress.GetLabels()[kube.RadixAppLabel], ingress.Spec.Rules[0].Host, ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, &ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port) + } } } }) } } +func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses []testIngress) error { + for _, ing := range testIngresses { + pathTypeImplementationSpecific := networkingv1.PathTypeImplementationSpecific + _, err := kubeClient.NetworkingV1().Ingresses(utils.GetEnvironmentNamespace(ing.appName, ing.envName)).Create(context.TODO(), + &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: ing.name, + Labels: map[string]string{kube.RadixAppLabel: ing.appName}, + }, + Spec: networkingv1.IngressSpec{ + TLS: []networkingv1.IngressTLS{ + { + Hosts: []string{ing.host}, + SecretName: "radix-wildcard-tls-cert", + }, + }, + Rules: []networkingv1.IngressRule{ + { + Host: ing.host, + IngressRuleValue: networkingv1.IngressRuleValue{ + HTTP: &networkingv1.HTTPIngressRuleValue{Paths: []networkingv1.HTTPIngressPath{ + {Path: "/", PathType: &pathTypeImplementationSpecific, Backend: networkingv1.IngressBackend{ + Service: &networkingv1.IngressServiceBackend{Name: ing.component, Port: networkingv1.ServiceBackendPort{ + Number: ing.port, + }}, + }}}, + }}, + }, + }, + }}, metav1.CreateOptions{}) + if err != nil { + return err + } + } + return nil +} + +func registerExistingRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]radixv1.RadixDNSAliasSpec) error { + for domain, rdaSpec := range radixDNSAliasesMap { + _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.TODO(), + &radixv1.RadixDNSAlias{ + ObjectMeta: metav1.ObjectMeta{ + Name: domain, + Labels: map[string]string{kube.RadixAppLabel: rdaSpec.AppName}, + }, + Spec: rdaSpec, + }, metav1.CreateOptions{}) + if err != nil { + return err + } + } + return nil +} + func rrAsOwnerReference(rr *radixv1.RadixRegistration) []metav1.OwnerReference { trueVar := true return []metav1.OwnerReference{ From 8033711a30e41fe90129d37b9c37a32fdf94bdf7 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 23 Oct 2023 16:44:34 +0200 Subject: [PATCH 005/121] Creating, updating RadixDNSAliases --- .../applicationconfig/applicationconfig.go | 36 ++++---- .../applicationconfig_test.go | 84 +++++++++++++------ pkg/apis/applicationconfig/dnsaliases.go | 47 +++++++++-- 3 files changed, 113 insertions(+), 54 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index 4e8230bf2..346241513 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -7,6 +7,7 @@ import ( "reflect" "strings" + commonErrors "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -73,7 +74,7 @@ func GetComponent(ra *v1.RadixApplication, name string) v1.RadixCommonComponent return nil } -// GetComponentEnvironmentConfig Gets environment config of component +// GetComponentEnvironmentConfig Gets environment config of component. This method is used by radix-api func GetComponentEnvironmentConfig(ra *v1.RadixApplication, envName, componentName string) v1.RadixCommonEnvironmentConfig { // TODO: Add interface for RA + EnvConfig return GetEnvironment(GetComponent(ra, componentName), envName) @@ -157,37 +158,26 @@ func (app *ApplicationConfig) ApplyConfigToApplicationNamespace() error { // It compares the actual state with the desired, and attempts to // converge the two func (app *ApplicationConfig) OnSync() error { - err := app.createEnvironments() - if err != nil { + if err := app.createEnvironments(); err != nil { log.Errorf("Failed to create namespaces for app environments %s. %v", app.config.Name, err) return err } - - err = app.syncPrivateImageHubSecrets() - if err != nil { + if err := app.syncPrivateImageHubSecrets(); err != nil { log.Errorf("Failed to create private image hub secrets. %v", err) return err } - - err = utils.GrantAppReaderAccessToSecret(app.kubeutil, app.registration, defaults.PrivateImageHubReaderRoleName, defaults.PrivateImageHubSecretName) - if err != nil { + if err := utils.GrantAppReaderAccessToSecret(app.kubeutil, app.registration, defaults.PrivateImageHubReaderRoleName, defaults.PrivateImageHubSecretName); err != nil { log.Warnf("failed to grant reader access to private image hub secret %v", err) } - - err = utils.GrantAppAdminAccessToSecret(app.kubeutil, app.registration, defaults.PrivateImageHubSecretName, defaults.PrivateImageHubSecretName) - if err != nil { + if err := utils.GrantAppAdminAccessToSecret(app.kubeutil, app.registration, defaults.PrivateImageHubSecretName, defaults.PrivateImageHubSecretName); err != nil { log.Warnf("failed to grant access to private image hub secret %v", err) return err } - - err = app.syncBuildSecrets() - if err != nil { + if err := app.syncBuildSecrets(); err != nil { log.Errorf("Failed to create build secrets. %v", err) return err } - - err = app.createOrUpdateDNSAliases() - if err != nil { + if err := app.createOrUpdateDNSAliases(); err != nil { return fmt.Errorf("failed to process DNS aliases: %w", err) } return nil @@ -195,9 +185,9 @@ func (app *ApplicationConfig) OnSync() error { // createEnvironments Will create environments defined in the radix config func (app *ApplicationConfig) createEnvironments() error { - + var errs []error for _, env := range app.config.Spec.Environments { - app.applyEnvironment(utils.NewEnvironmentBuilder(). + err := app.applyEnvironment(utils.NewEnvironmentBuilder(). WithAppName(app.config.Name). WithAppLabel(). WithEnvironmentName(env.Name). @@ -209,9 +199,11 @@ func (app *ApplicationConfig) createEnvironments() error { // Only an explicit call to UpdateStatus can update status object, and this is only done by the RadixEnvironment controller. WithOrphaned(false). BuildRE()) + if err != nil { + errs = append(errs, err) + } } - - return nil + return commonErrors.Concat(errs) } func getTargetEnvironmentsAsMap(branchToBuild string, radixApplication *v1.RadixApplication) map[string]bool { diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 5d61a3b26..e36dd9285 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -12,6 +12,7 @@ import ( radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" + "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" radix "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" "github.com/stretchr/testify/assert" @@ -671,8 +672,13 @@ type testIngress struct { } func Test_DNSAliases(t *testing.T) { - appName := "any-app1" - + const ( + appName = "any-app1" + envDev = "dev" + componentNameServer1 = "server1" + server1Anyapp1DevDns = "server1-any-app1-dev.radix.equinor.com" + port = 8080 + ) var testScenarios = []struct { name string dnsAliases []radixv1.DNSAlias @@ -682,7 +688,27 @@ func Test_DNSAliases(t *testing.T) { expectedIngress map[string]testIngress }{ { - name: "no aliases, no additional radix aliases, no additional ingresses", + name: "no aliases, no existing RDA, no existing ingresses, no additional radix aliases, no additional ingresses", + }, + { + name: "no aliases, no existing RDA, exist ingresses, no additional radix aliases, no additional ingresses", + existingIngress: []testIngress{{appName: appName, envName: envDev, name: componentNameServer1, host: server1Anyapp1DevDns, component: componentNameServer1, port: port}}, + expectedIngress: map[string]testIngress{componentNameServer1: {appName: appName, envName: envDev, name: componentNameServer1, host: server1Anyapp1DevDns, component: componentNameServer1, port: port}}, + }, + { + name: "multiple aliases, no existing RDA, no existing ingresses, additional radix aliases, additional ingresses", + dnsAliases: []radixv1.DNSAlias{ + {Domain: "domain1", Environment: envDev, Component: componentNameServer1}, + {Domain: "domain2", Environment: envDev, Component: componentNameServer1}, + }, + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + "domain1": {AppName: appName, Environment: envDev, Component: componentNameServer1}, + "domain2": {AppName: appName, Environment: envDev, Component: componentNameServer1}, + }, + expectedIngress: map[string]testIngress{ + "server1.domain1.custom-domain": {appName: appName, envName: envDev, name: "server1.domain1.custom-domain", host: "domain1.custom-domain.radix.equinor.com", component: componentNameServer1, port: port}, + "server1.domain2.custom-domain": {appName: appName, envName: envDev, name: "server1.domain2.custom-domain", host: "domain2.custom-domain.radix.equinor.com", component: componentNameServer1, port: port}, + }, }, } tu, kubeClient, kubeUtil, radixClient := setupTest() @@ -701,36 +727,40 @@ func Test_DNSAliases(t *testing.T) { // assert RadixDNSAlias-es if ts.expectedRadixDNSAliases == nil { - require.Len(t, radixDNSAliases.Items, 0, "not expected Radix DNS aliases") + assert.Len(t, radixDNSAliases.Items, 0, "not expected Radix DNS aliases") } else { - require.Len(t, radixDNSAliases.Items, len(ts.expectedRadixDNSAliases), "expected Radix DNS aliases count") - for _, radixDNSAlias := range radixDNSAliases.Items { - if expectedDNSAlias, ok := ts.expectedRadixDNSAliases[radixDNSAlias.Name]; ok { - assert.Equal(t, expectedDNSAlias.AppName, radixDNSAlias.Spec.AppName, "app name") - assert.Equal(t, expectedDNSAlias.Environment, radixDNSAlias.Spec.Environment, "environment") - assert.Equal(t, expectedDNSAlias.Component, radixDNSAlias.Spec.Component, "component") - } else { - assert.Failf(t, "found not expected RadixDNSAlias %s: env %s, component %s, appName %s", radixDNSAlias.GetName(), radixDNSAlias.Spec.Environment, radixDNSAlias.Spec.Component, radixDNSAlias.Spec.AppName) + assert.Len(t, radixDNSAliases.Items, len(ts.expectedRadixDNSAliases), "not matching expected Radix DNS aliases count") + if len(radixDNSAliases.Items) == len(ts.expectedRadixDNSAliases) { + for _, radixDNSAlias := range radixDNSAliases.Items { + if expectedDNSAlias, ok := ts.expectedRadixDNSAliases[radixDNSAlias.Name]; ok { + assert.Equal(t, expectedDNSAlias.AppName, radixDNSAlias.Spec.AppName, "app name") + assert.Equal(t, expectedDNSAlias.Environment, radixDNSAlias.Spec.Environment, "environment") + assert.Equal(t, expectedDNSAlias.Component, radixDNSAlias.Spec.Component, "component") + } else { + assert.Failf(t, "found not expected RadixDNSAlias %s: env %s, component %s, appName %s", radixDNSAlias.GetName(), radixDNSAlias.Spec.Environment, radixDNSAlias.Spec.Component, radixDNSAlias.Spec.AppName) + } } } } // assert ingresses if ts.expectedIngress == nil { - require.Len(t, ingresses.Items, 0, "not expected ingresses") + assert.Len(t, ingresses.Items, 0, "not expected ingresses") } else { - require.Len(t, ingresses.Items, len(ts.expectedIngress), "expected ingresses count") - for _, ingress := range ingresses.Items { - if expectedIngress, ok := ts.expectedIngress[ingress.Name]; ok { - require.Len(t, ingress.Spec.Rules, 1, "rules count") - assert.Equal(t, expectedIngress.appName, ingress.GetLabels()[kube.RadixAppLabel], "app name") - assert.Equal(t, utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ingress.GetNamespace(), "namespace") - assert.Equal(t, expectedIngress.component, ingress.GetLabels()[kube.RadixComponentLabel], "component name") - assert.Equal(t, expectedIngress.host, ingress.Spec.Rules[0].Host, "rule host") - assert.Equal(t, "/", ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") - assert.Equal(t, expectedIngress.component, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend component name") - assert.Equal(t, expectedIngress.port, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port, "rule backend component port") - } else { - assert.Failf(t, "found not expected ingress %s: appName %s, host %s, service %s, port %d", ingress.GetName(), ingress.GetLabels()[kube.RadixAppLabel], ingress.Spec.Rules[0].Host, ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, &ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port) + assert.Len(t, ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") + if len(ingresses.Items) == len(ts.expectedIngress) { + for _, ingress := range ingresses.Items { + if expectedIngress, ok := ts.expectedIngress[ingress.Name]; ok { + require.Len(t, ingress.Spec.Rules, 1, "rules count") + assert.Equal(t, expectedIngress.appName, ingress.GetLabels()[kube.RadixAppLabel], "app name") + assert.Equal(t, utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ingress.GetNamespace(), "namespace") + assert.Equal(t, expectedIngress.component, ingress.GetLabels()[kube.RadixComponentLabel], "component name") + assert.Equal(t, expectedIngress.host, ingress.Spec.Rules[0].Host, "rule host") + assert.Equal(t, "/", ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") + assert.Equal(t, expectedIngress.component, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") + assert.Equal(t, expectedIngress.port, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") + } else { + assert.Failf(t, "found not expected ingress %s: appName %s, host %s, service %s, port %d", ingress.GetName(), ingress.GetLabels()[kube.RadixAppLabel], ingress.Spec.Rules[0].Host, ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, &ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port) + } } } } @@ -745,7 +775,7 @@ func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses [] &networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{ Name: ing.name, - Labels: map[string]string{kube.RadixAppLabel: ing.appName}, + Labels: labels.Merge(labels.ForApplicationName(ing.appName), labels.ForComponentName(ing.component)), }, Spec: networkingv1.IngressSpec{ TLS: []networkingv1.IngressTLS{ diff --git a/pkg/apis/applicationconfig/dnsaliases.go b/pkg/apis/applicationconfig/dnsaliases.go index 270a4cb1b..421247dfc 100644 --- a/pkg/apis/applicationconfig/dnsaliases.go +++ b/pkg/apis/applicationconfig/dnsaliases.go @@ -5,15 +5,22 @@ import ( "fmt" "strings" + "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-common/utils/slice" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils/labels" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +const ( + dnsAliasIngressNameTemplate = "%s.%s.custom-domain" // ..custom-domain +) + func (app *ApplicationConfig) createOrUpdateDNSAliases() error { appName := app.registration.Name - radixDNSAliasesMap, err := app.getRadixDNSAliasesMap(appName) + var errs []error + ctx := context.Background() + radixDNSAliasesMap, err := app.getRadixDNSAliasesMap(ctx, appName) if err != nil { return err } @@ -24,15 +31,45 @@ func (app *ApplicationConfig) createOrUpdateDNSAliases() error { } if strings.EqualFold(dnsAlias.Environment, radixDNSAlias.Spec.Environment) && strings.EqualFold(dnsAlias.Component, radixDNSAlias.Spec.Component) { - + continue // no changes } + if err = app.updateRadixDNSAlias(radixDNSAlias, dnsAlias, err, ctx); err != nil { + errs = append(errs, err) + } + continue + } + if err = app.createRadixDNSAlias(dnsAlias, appName, err, ctx); err != nil { + errs = append(errs, err) } } - fmt.Println(len(radixDNSAliasesMap)) - return nil + return errors.Concat(errs) +} + +func (app *ApplicationConfig) updateRadixDNSAlias(radixDNSAlias *radixv1.RadixDNSAlias, dnsAlias radixv1.DNSAlias, err error, ctx context.Context) error { + updatedRadixDNSAlias := radixDNSAlias.DeepCopy() + updatedRadixDNSAlias.Spec.Environment = dnsAlias.Environment + updatedRadixDNSAlias.Spec.Component = dnsAlias.Component + _, err = app.radixclient.RadixV1().RadixDNSAliases().Update(ctx, updatedRadixDNSAlias, metav1.UpdateOptions{}) + return err +} + +func (app *ApplicationConfig) createRadixDNSAlias(dnsAlias radixv1.DNSAlias, appName string, err error, ctx context.Context) error { + radixDNSAlias := radixv1.RadixDNSAlias{ + ObjectMeta: metav1.ObjectMeta{ + Name: dnsAlias.Domain, + Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(dnsAlias.Component)), + }, + Spec: radixv1.RadixDNSAliasSpec{ + AppName: appName, + Environment: dnsAlias.Environment, + Component: dnsAlias.Component, + }, + } + _, err = app.radixclient.RadixV1().RadixDNSAliases().Create(ctx, &radixDNSAlias, metav1.CreateOptions{}) + return err } -func (app *ApplicationConfig) getRadixDNSAliasesMap(appName string) (map[string]*radixv1.RadixDNSAlias, error) { +func (app *ApplicationConfig) getRadixDNSAliasesMap(ctx context.Context, appName string) (map[string]*radixv1.RadixDNSAlias, error) { dnsAliasList, err := app.radixclient.RadixV1().RadixDNSAliases().List(context.Background(), metav1.ListOptions{LabelSelector: labels.ForApplicationName(appName).String()}) if err != nil { return nil, err From 8ab98acdf2045f8260c19fd96f21e0c3e3a80c49 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 24 Oct 2023 16:52:46 +0200 Subject: [PATCH 006/121] Extended applicationconfig and RadixDNSAliases controllers --- .../applicationconfig/applicationconfig.go | 1 - .../applicationconfig_test.go | 62 ++++----- pkg/apis/applicationconfig/dnsaliases.go | 4 - pkg/apis/defaults/resources.go | 2 + pkg/apis/defaults/secrets.go | 5 +- pkg/apis/deployment/ingress.go | 10 +- pkg/apis/utils/application_builder.go | 2 + radix-operator/dnsalias/controller.go | 89 ++++-------- radix-operator/dnsalias/controller_test.go | 128 ++++++++++++++++++ radix-operator/dnsalias/handler_test.go | 121 +++++++++++++++++ radix-operator/dnsalias/internal/utils.go | 54 ++++++++ 11 files changed, 368 insertions(+), 110 deletions(-) create mode 100644 radix-operator/dnsalias/controller_test.go create mode 100644 radix-operator/dnsalias/handler_test.go create mode 100644 radix-operator/dnsalias/internal/utils.go diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index 346241513..8677b4477 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -183,7 +183,6 @@ func (app *ApplicationConfig) OnSync() error { return nil } -// createEnvironments Will create environments defined in the radix config func (app *ApplicationConfig) createEnvironments() error { var errs []error for _, env := range app.config.Spec.Environments { diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index e36dd9285..d5c68bce1 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -1,4 +1,4 @@ -package applicationconfig +package applicationconfig_test import ( "context" @@ -7,6 +7,7 @@ import ( "log" "testing" + "github.com/equinor/radix-operator/pkg/apis/applicationconfig" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -46,9 +47,9 @@ func setupTest() (*test.Utils, kubernetes.Interface, *kube.Kube, radixclient.Int return &handlerTestUtils, kubeClient, kubeUtil, radixClient } -func getApplication(ra *radixv1.RadixApplication) *ApplicationConfig { +func getApplication(ra *radixv1.RadixApplication) *applicationconfig.ApplicationConfig { // The other arguments are not relevant for this test - application, _ := NewApplicationConfig(nil, nil, nil, nil, ra) + application, _ := applicationconfig.NewApplicationConfig(nil, nil, nil, nil, ra) return application } @@ -57,11 +58,11 @@ func Test_Create_Radix_Environments(t *testing.T) { radixRegistration, _ := utils.GetRadixRegistrationFromFile(sampleRegistration) radixApp, _ := utils.GetRadixApplicationFromFile(sampleApp) - app, _ := NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, radixApp) + app, _ := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, radixApp) label := fmt.Sprintf("%s=%s", kube.RadixAppLabel, radixRegistration.Name) t.Run("It can create environments", func(t *testing.T) { - err := app.createEnvironments() + err := app.OnSync() assert.NoError(t, err) environments, _ := radixClient.RadixV1().RadixEnvironments().List( context.TODO(), @@ -72,7 +73,7 @@ func Test_Create_Radix_Environments(t *testing.T) { }) t.Run("It doesn't fail when re-running creation", func(t *testing.T) { - err := app.createEnvironments() + err := app.OnSync() assert.NoError(t, err) environments, _ := radixClient.RadixV1().RadixEnvironments().List( context.TODO(), @@ -118,11 +119,11 @@ func Test_Reconciles_Radix_Environments(t *testing.T) { WithEnvironment("prod", "master"). BuildRA() - app, _ := NewApplicationConfig(client, kubeUtil, radixClient, rr, ra) + app, _ := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, rr, ra) label := fmt.Sprintf("%s=%s", kube.RadixAppLabel, rr.Name) // Test - app.createEnvironments() + app.OnSync() environments, _ := radixClient.RadixV1().RadixEnvironments().List( context.TODO(), metav1.ListOptions{ @@ -247,32 +248,27 @@ func TestIsThereAnythingToDeploy_wildcardMatch_ListsBothButOnlyOneShouldBeBuilt( } func TestIsTargetEnvsEmpty_noEntry(t *testing.T) { - targetEnvs := map[string]bool{} - assert.Equal(t, true, isTargetEnvsEmpty(targetEnvs)) + ra := utils.NewRadixApplicationBuilder().BuildRA() + hasEnvToDeploy, _ := applicationconfig.IsThereAnythingToDeployForRadixApplication("main", ra) + assert.False(t, hasEnvToDeploy) } func TestIsTargetEnvsEmpty_twoEntriesWithBranchMapping(t *testing.T) { - targetEnvs := map[string]bool{ - "qa": true, - "prod": true, - } - assert.Equal(t, false, isTargetEnvsEmpty(targetEnvs)) + ra := utils.NewRadixApplicationBuilder().WithEnvironment("qa", "main").WithEnvironment("qa", "main").BuildRA() + hasEnvToDeploy, _ := applicationconfig.IsThereAnythingToDeployForRadixApplication("main", ra) + assert.True(t, hasEnvToDeploy) } func TestIsTargetEnvsEmpty_twoEntriesWithNoMapping(t *testing.T) { - targetEnvs := map[string]bool{ - "qa": false, - "prod": false, - } - assert.Equal(t, true, isTargetEnvsEmpty(targetEnvs)) + ra := utils.NewRadixApplicationBuilder().WithEnvironment("qa", "main").WithEnvironment("prod", "release").BuildRA() + hasEnvToDeploy, _ := applicationconfig.IsThereAnythingToDeployForRadixApplication("test", ra) + assert.False(t, hasEnvToDeploy) } func TestIsTargetEnvsEmpty_twoEntriesWithOneMapping(t *testing.T) { - targetEnvs := map[string]bool{ - "qa": true, - "prod": false, - } - assert.Equal(t, false, isTargetEnvsEmpty(targetEnvs)) + ra := utils.NewRadixApplicationBuilder().WithEnvironment("qa", "main").WithEnvironment("prod", "release").BuildRA() + hasEnvToDeploy, _ := applicationconfig.IsThereAnythingToDeployForRadixApplication("main", ra) + assert.True(t, hasEnvToDeploy) } func Test_WithBuildSecretsSet_SecretsCorrectlyAdded(t *testing.T) { @@ -633,7 +629,7 @@ func Test_GetConfigBranch_notSet(t *testing.T) { rr := utils.NewRegistrationBuilder(). BuildRR() - assert.Equal(t, ConfigBranchFallback, GetConfigBranch(rr)) + assert.Equal(t, applicationconfig.ConfigBranchFallback, applicationconfig.GetConfigBranch(rr)) } func Test_GetConfigBranch_set(t *testing.T) { @@ -643,7 +639,7 @@ func Test_GetConfigBranch_set(t *testing.T) { WithConfigBranch(configBranch). BuildRR() - assert.Equal(t, configBranch, GetConfigBranch(rr)) + assert.Equal(t, configBranch, applicationconfig.GetConfigBranch(rr)) } func Test_IsConfigBranch(t *testing.T) { @@ -654,11 +650,11 @@ func Test_IsConfigBranch(t *testing.T) { BuildRR() t.Run("Branch is configBranch", func(t *testing.T) { - assert.True(t, IsConfigBranch(configBranch, rr)) + assert.True(t, applicationconfig.IsConfigBranch(configBranch, rr)) }) t.Run("Branch is not configBranch", func(t *testing.T) { - assert.False(t, IsConfigBranch(otherBranch, rr)) + assert.False(t, applicationconfig.IsConfigBranch(otherBranch, rr)) }) } @@ -835,7 +831,7 @@ func rrAsOwnerReference(rr *radixv1.RadixRegistration) []metav1.OwnerReference { } } -func applyRadixAppWithPrivateImageHub(privateImageHubs radixv1.PrivateImageHubEntries) (kubernetes.Interface, *ApplicationConfig, error) { +func applyRadixAppWithPrivateImageHub(privateImageHubs radixv1.PrivateImageHubEntries) (kubernetes.Interface, *applicationconfig.ApplicationConfig, error) { tu, client, kubeUtil, radixClient := setupTest() appBuilder := utils.ARadixApplication(). WithAppName("any-app"). @@ -852,11 +848,11 @@ func applyRadixAppWithPrivateImageHub(privateImageHubs radixv1.PrivateImageHubEn return client, appConfig, err } -func getAppConfig(client kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, applicationBuilder utils.ApplicationBuilder) (*ApplicationConfig, error) { +func getAppConfig(client kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, applicationBuilder utils.ApplicationBuilder) (*applicationconfig.ApplicationConfig, error) { ra := applicationBuilder.BuildRA() radixRegistration, _ := radixClient.RadixV1().RadixRegistrations().Get(context.TODO(), ra.Name, metav1.GetOptions{}) - return NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra) + return applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra) } func applyApplicationWithSync(tu *test.Utils, client kubernetes.Interface, kubeUtil *kube.Kube, @@ -872,7 +868,7 @@ func applyApplicationWithSync(tu *test.Utils, client kubernetes.Interface, kubeU return err } - applicationconfig, err := NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra) + applicationconfig, err := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra) if err != nil { return err } diff --git a/pkg/apis/applicationconfig/dnsaliases.go b/pkg/apis/applicationconfig/dnsaliases.go index 421247dfc..6aece311a 100644 --- a/pkg/apis/applicationconfig/dnsaliases.go +++ b/pkg/apis/applicationconfig/dnsaliases.go @@ -12,10 +12,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -const ( - dnsAliasIngressNameTemplate = "%s.%s.custom-domain" // ..custom-domain -) - func (app *ApplicationConfig) createOrUpdateDNSAliases() error { appName := app.registration.Name var errs []error diff --git a/pkg/apis/defaults/resources.go b/pkg/apis/defaults/resources.go index 595aa037d..c44ac2500 100644 --- a/pkg/apis/defaults/resources.go +++ b/pkg/apis/defaults/resources.go @@ -9,6 +9,8 @@ import ( // Environment variables that define default resources (limits and requests) for containers and environments // See https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/memory-default-namespace/ const ( + RadixAPIVersion = "radix.equinor.com/v1" + RadixDNSAliasKind = "RadixDNSAlias" OperatorDefaultUserGroupEnvironmentVariable = "RADIXOPERATOR_DEFAULT_USER_GROUP" OperatorEnvLimitDefaultMemoryEnvironmentVariable = "RADIXOPERATOR_APP_ENV_LIMITS_DEFAULT_MEMORY" OperatorEnvLimitDefaultRequestMemoryEnvironmentVariable = "RADIXOPERATOR_APP_ENV_LIMITS_DEFAULT_REQUEST_MEMORY" diff --git a/pkg/apis/defaults/secrets.go b/pkg/apis/defaults/secrets.go index d818a1db8..47255b7e2 100644 --- a/pkg/apis/defaults/secrets.go +++ b/pkg/apis/defaults/secrets.go @@ -65,8 +65,11 @@ const ( // CsiAzureKeyVaultCredsClientSecretPart Client secret part of secret data for Azure Key Vault CsiAzureKeyVaultCredsClientSecretPart = "clientsecret" - //CsiSecretProviderClassParameterKeyVaultName Azure Key vault parameter name for a CSI SecretProviderClass + // CsiSecretProviderClassParameterKeyVaultName Azure Key vault parameter name for a CSI SecretProviderClass CsiSecretProviderClassParameterKeyVaultName = "keyvaultName" + + // TLSSecretName Secret name for the Radix wildcard TLS cert + TLSSecretName = "radix-wildcard-tls-cert" ) // GetBlobFuseCredsSecretName Helper method diff --git a/pkg/apis/deployment/ingress.go b/pkg/apis/deployment/ingress.go index 27a6f8aa3..0dcbe833c 100644 --- a/pkg/apis/deployment/ingress.go +++ b/pkg/apis/deployment/ingress.go @@ -27,10 +27,6 @@ type AnnotationConfiguration struct { Annotations map[string]string } -const ( - TLSSecretName = "radix-wildcard-tls-cert" -) - func (deploy *Deployment) createOrUpdateIngress(deployComponent radixv1.RadixCommonDeployComponent) error { namespace := deploy.radixDeployment.Namespace clustername, err := deploy.kubeutil.GetClusterName() @@ -230,7 +226,7 @@ func (deploy *Deployment) getAppAliasIngressConfig(appName string, ownerReferenc } hostname := fmt.Sprintf("%s.%s", appName, appAlias) - ingressSpec := getIngressSpec(hostname, component.GetName(), TLSSecretName, publicPortNumber) + ingressSpec := getIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) return deploy.getIngressConfig(appName, component, getAppAliasIngressName(appName), ownerReference, true, false, false, ingressSpec, namespace) } @@ -250,7 +246,7 @@ func (deploy *Deployment) getActiveClusterAliasIngressConfig( if hostname == "" { return nil, nil } - ingressSpec := getIngressSpec(hostname, component.GetName(), TLSSecretName, publicPortNumber) + ingressSpec := getIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) ingressName := getActiveClusterIngressName(component.GetName()) return deploy.getIngressConfig(appName, component, ingressName, ownerReference, false, false, true, ingressSpec, namespace) @@ -272,7 +268,7 @@ func (deploy *Deployment) getDefaultIngressConfig( return nil, nil } hostname := getHostName(component.GetName(), namespace, clustername, dnsZone) - ingressSpec := getIngressSpec(hostname, component.GetName(), TLSSecretName, publicPortNumber) + ingressSpec := getIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) return deploy.getIngressConfig(appName, component, getDefaultIngressName(component.GetName()), ownerReference, false, false, false, ingressSpec, namespace) } diff --git a/pkg/apis/utils/application_builder.go b/pkg/apis/utils/application_builder.go index 662370749..ce671831d 100644 --- a/pkg/apis/utils/application_builder.go +++ b/pkg/apis/utils/application_builder.go @@ -120,6 +120,7 @@ func (ap *ApplicationBuilderStruct) WithDNSAlias(dnsAliases ...radixv1.DNSAlias) foundExistingAlias := false for i := 0; i < len(ap.dnsAliases); i++ { if strings.EqualFold(dnsAlias.Domain, ap.dnsAliases[i].Domain) { + ap.dnsAliases[i].Domain = dnsAlias.Domain ap.dnsAliases[i].Environment = dnsAlias.Environment ap.dnsAliases[i].Component = dnsAlias.Component foundExistingAlias = true @@ -130,6 +131,7 @@ func (ap *ApplicationBuilderStruct) WithDNSAlias(dnsAliases ...radixv1.DNSAlias) continue } dnsAliasesToAppend = append(dnsAliasesToAppend, radixv1.DNSAlias{ + Domain: dnsAlias.Domain, Environment: dnsAlias.Environment, Component: dnsAlias.Component, }) diff --git a/radix-operator/dnsalias/controller.go b/radix-operator/dnsalias/controller.go index 0457291ff..7c5ec38c8 100644 --- a/radix-operator/dnsalias/controller.go +++ b/radix-operator/dnsalias/controller.go @@ -4,12 +4,14 @@ import ( "context" "reflect" + "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/metrics" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" informers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" "github.com/equinor/radix-operator/radix-operator/common" "github.com/sirupsen/logrus" + networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubeinformers "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" @@ -20,7 +22,6 @@ import ( const ( controllerAgentName = "dns-alias-controller" - crType = "RadixDNSAlias" ) var logger *logrus.Entry @@ -30,7 +31,7 @@ func init() { } // NewController creates a new controller that handles RadixDNSAlias -func NewController(client kubernetes.Interface, +func NewController(kubeClient kubernetes.Interface, radixClient radixclient.Interface, handler common.Handler, kubeInformerFactory kubeinformers.SharedInformerFactory, @@ -39,19 +40,16 @@ func NewController(client kubernetes.Interface, recorder record.EventRecorder) *common.Controller { dnsAliasInformer := radixInformerFactory.Radix().V1().RadixDNSAliases() - applicationInformer := radixInformerFactory.Radix().V1().RadixApplications() - environmentInformer := radixInformerFactory.Radix().V1().RadixEnvironments() - namespaceInformer := kubeInformerFactory.Core().V1().Namespaces() ingressInformer := kubeInformerFactory.Networking().V1().Ingresses() controller := &common.Controller{ Name: controllerAgentName, - HandlerOf: crType, - KubeClient: client, + HandlerOf: defaults.RadixDNSAliasKind, + KubeClient: kubeClient, RadixClient: radixClient, Informer: dnsAliasInformer.Informer(), KubeInformerFactory: kubeInformerFactory, - WorkQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), crType), + WorkQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), defaults.RadixDNSAliasKind), Handler: handler, Log: logger, WaitForChildrenToSync: waitForChildrenToSync, @@ -64,7 +62,7 @@ func NewController(client kubernetes.Interface, dnsAliasInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { controller.Enqueue(cur) - metrics.CustomResourceAdded(crType) + metrics.CustomResourceAdded(defaults.RadixDNSAliasKind) }, UpdateFunc: func(old, cur interface{}) { newRDA := cur.(*v1.RadixDNSAlias) @@ -72,82 +70,45 @@ func NewController(client kubernetes.Interface, if deepEqual(oldRDA, newRDA) { logger.Debugf("RadixDNSAlias object is equal to old for %s. Do nothing", newRDA.GetName()) - metrics.CustomResourceUpdatedButSkipped(crType) + metrics.CustomResourceUpdatedButSkipped(defaults.RadixDNSAliasKind) return } controller.Enqueue(cur) - metrics.CustomResourceUpdated(crType) + metrics.CustomResourceUpdated(defaults.RadixDNSAliasKind) }, DeleteFunc: func(obj interface{}) { - // TODO delete ingresses - // radixDNSAlias, converted := obj.(*v1.RadixDNSAlias) - _, converted := obj.(*v1.RadixDNSAlias) + radixDNSAlias, converted := obj.(*v1.RadixDNSAlias) if !converted { logger.Errorf("RadixDNSAlias object cast failed during deleted event received.") return } - // key, err := cache.MetaNamespaceKeyFunc(radixDNSAlias) - // if err != nil { - // logger.Errorf("RadixDNSAlias object deleted event received for %s. Do nothing", key) - // } - metrics.CustomResourceDeleted(crType) - }, - }) - - environmentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ - DeleteFunc: func(obj interface{}) { - // TODO alert in events if missing ns - }, - }) - - namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ - DeleteFunc: func(obj interface{}) { - // TODO alert in events if missing ns + key, err := cache.MetaNamespaceKeyFunc(radixDNSAlias) + if err != nil { + logger.Errorf("error on RadixDNSAlias object deleted event received for %s: %v", key, err) + } + metrics.CustomResourceDeleted(defaults.RadixDNSAliasKind) }, }) ingressInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ - DeleteFunc: func(obj interface{}) { - // TODO restore ingress if missing - }, - }) - - applicationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ - UpdateFunc: func(old, cur interface{}) { - newRa := cur.(*v1.RadixApplication) - oldRa := old.(*v1.RadixApplication) - if newRa.ResourceVersion == oldRa.ResourceVersion { + UpdateFunc: func(oldObj, newObj interface{}) { + oldMeta := oldObj.(metav1.Object) + newMeta := newObj.(metav1.Object) + if oldMeta.GetResourceVersion() == newMeta.GetResourceVersion() { return } - // TODO update SNS aliases - // dnsAliasesToResync := getAddedOrDroppedDNSAliasDomains(oldRa, newRa) - // for _, domain := range dnsAliasesToResync { - // uniqueName := utils.GetEnvironmentNamespace(oldRa.Name, envName) - // re, err := radixClient.RadixV1().RadixDNSAliases().Get(context.TODO(), uniqueName, metav1.GetOptions{}) - // if err == nil { - // controller.Enqueue(re) - // } - // } + controller.HandleObject(newObj, defaults.RadixDNSAliasKind, getOwner) }, - DeleteFunc: func(cur interface{}) { - // TODO delete DNS aliases - // radixApplication, converted := cur.(*v1.RadixApplication) - _, converted := cur.(*v1.RadixApplication) + DeleteFunc: func(obj interface{}) { + ing, converted := obj.(*networkingv1.Ingress) if !converted { - logger.Errorf("RadixApplication object cast failed during deleted event received.") + logger.Errorf("Ingress object cast failed during deleted event received.") return } - // for _, env := range radixApplication.Spec.Environments { - // uniqueName := utils.GetEnvironmentNamespace(radixApplication.Name, env.Name) - // re, err := radixClient.RadixV1().RadixDNSAliases().Get(context.TODO(), uniqueName, metav1.GetOptions{}) - // if err == nil { - // controller.Enqueue(re) - // } - // } + controller.HandleObject(ing, defaults.RadixDNSAliasKind, getOwner) }, }) - return controller } @@ -161,7 +122,7 @@ func deepEqual(old, new *v1.RadixDNSAlias) bool { return true } -func getOwner(radixClient radixclient.Interface, namespace, name string) (interface{}, error) { +func getOwner(radixClient radixclient.Interface, _, name string) (interface{}, error) { return radixClient.RadixV1().RadixDNSAliases().Get(context.TODO(), name, metav1.GetOptions{}) } diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go new file mode 100644 index 000000000..e16653dc7 --- /dev/null +++ b/radix-operator/dnsalias/controller_test.go @@ -0,0 +1,128 @@ +package dnsalias_test + +import ( + "context" + "testing" + + "github.com/equinor/radix-common/utils/pointers" + "github.com/equinor/radix-operator/pkg/apis/defaults" + v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/utils" + "github.com/equinor/radix-operator/pkg/apis/utils/labels" + "github.com/equinor/radix-operator/radix-operator/common" + "github.com/equinor/radix-operator/radix-operator/dnsalias" + "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" + "github.com/stretchr/testify/suite" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type controllerTestSuite struct { + common.ControllerTestSuite +} + +func TestControllerSuite(t *testing.T) { + suite.Run(t, new(controllerTestSuite)) +} + +func (s *controllerTestSuite) TearDownTest() { + s.MockCtrl.Finish() +} + +func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { + sut := dnsalias.NewController(s.KubeClient, s.RadixClient, s.Handler, s.KubeInformerFactory, s.RadixInformerFactory, false, s.EventRecorder) + s.RadixInformerFactory.Start(s.Stop) + s.KubeInformerFactory.Start(s.Stop) + go sut.Run(5, s.Stop) + + const ( + appName1 = "any-app1" + appName2 = "any-app2" + aliasName = "alias-1" + envName1 = "env1" + envName2 = "env2" + componentName1 = "server1" + componentName2 = "server2" + ) + alias := &v1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: aliasName, + Labels: labels.Merge(labels.ForApplicationName(appName1), labels.ForComponentName(componentName1))}, + Spec: v1.RadixDNSAliasSpec{ + AppName: appName1, + Environment: envName1, + Component: componentName1, + }} + + // Adding a RadixDNSAlias should trigger sync + s.Handler.EXPECT().Sync("", aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) + alias, err := s.RadixClient.RadixV1().RadixDNSAliases().Create(context.Background(), alias, metav1.CreateOptions{}) + s.Require().NoError(err) + s.WaitForSynced("Sync should be called on add RadixDNSAlias") + + // Updating the RadixDNSAlias with appName should trigger a sync + s.Handler.EXPECT().Sync("", aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) + alias.Spec.AppName = appName2 + alias, err = s.RadixClient.RadixV1().RadixDNSAliases().Update(context.TODO(), alias, metav1.UpdateOptions{}) + s.Require().NoError(err) + s.WaitForSynced("Sync should be called on update appName in the RadixDNSAlias") + + // Updating the RadixDNSAlias with environment should trigger a sync + s.Handler.EXPECT().Sync("", aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) + alias.Spec.Environment = envName2 + alias, err = s.RadixClient.RadixV1().RadixDNSAliases().Update(context.TODO(), alias, metav1.UpdateOptions{}) + s.Require().NoError(err) + s.WaitForSynced("Sync should be called on update environment in the RadixDNSAlias") + + // Updating the RadixDNSAlias with component should trigger a sync + s.Handler.EXPECT().Sync("", aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) + alias.Spec.Component = componentName2 + alias, err = s.RadixClient.RadixV1().RadixDNSAliases().Update(context.TODO(), alias, metav1.UpdateOptions{}) + s.Require().NoError(err) + s.WaitForSynced("Sync should be called on update component in the RadixDNSAlias") + + // Updating the RadixDNSAlias with no changes should not trigger a sync + s.Handler.EXPECT().Sync("", aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) + _, err = s.RadixClient.RadixV1().RadixDNSAliases().Update(context.TODO(), alias, metav1.UpdateOptions{}) + s.Require().NoError(err) + s.WaitForNotSynced("Sync should not be called when updating RadixDNSAlias with no changes") + + // Add Kubernetes Job with ownerreference to RadixDNSAlias should not trigger sync + ingress := internal.BuildRadixDNSAliasIngress(alias.Spec.AppName, alias.GetName(), alias.Spec.Component, int32(8080)) + ingress.ObjectMeta.OwnerReferences = []metav1.OwnerReference{{APIVersion: defaults.RadixAPIVersion, Kind: defaults.RadixDNSAliasKind, Name: aliasName, Controller: pointers.Ptr(true)}} + namespace := utils.GetEnvironmentNamespace(alias.Spec.AppName, alias.Spec.Environment) + s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) + ingress, err = internal.CreateRadixDNSAliasIngress(s.KubeClient, alias.Spec.AppName, alias.Spec.Environment, ingress) + s.Require().NoError(err) + s.WaitForNotSynced("Sync should not be called when adding k8s ingress") + /* + // Sync should not trigger on ingress update if resource version is unchanged + s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) + ingress, err = s.KubeClient.BatchV1().Jobs(namespace).Update(context.Background(), ingress, metav1.UpdateOptions{}) + s.Require().NoError(err) + s.WaitForNotSynced("Sync should not be called on k8s ingress update with no resource version change") + + // Sync should trigger on ingress update if resource version is changed + ingress.ResourceVersion = "2" + s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) + _, err = s.KubeClient.BatchV1().Jobs(namespace).Update(context.Background(), ingress, metav1.UpdateOptions{}) + s.Require().NoError(err) + s.WaitForSynced("Sync should be called on k8s ingress update with changed resource version") + + // Sync should trigger when deleting ingress + s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) + err = s.KubeClient.BatchV1().Jobs(namespace).Delete(context.Background(), jobName, metav1.DeleteOptions{}) + s.Require().NoError(err) + s.WaitForSynced("Sync should be called on k8s ingress deletion") + + // Sync should not trigger when deleting alias + s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) + err = s.RadixClient.RadixV1().RadixDNSAliases(namespace).Delete(context.Background(), aliasName, metav1.DeleteOptions{}) + s.Require().NoError(err) + s.WaitForNotSynced("Sync should not be called on alias deletion") + + */ + // Delete the RadixDNSAlias should trigger a sync + s.Handler.EXPECT().Sync("", aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) + err = s.RadixClient.RadixV1().RadixDNSAliases().Delete(context.TODO(), alias.GetName(), metav1.DeleteOptions{}) + s.Require().NoError(err) + s.WaitForNotSynced("Sync should be called when deleting RadixDNSAlias") + +} diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go new file mode 100644 index 000000000..421d7523b --- /dev/null +++ b/radix-operator/dnsalias/handler_test.go @@ -0,0 +1,121 @@ +package dnsalias_test + +import ( + "context" + "testing" + + "github.com/equinor/radix-operator/pkg/apis/kube" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/utils" + "github.com/equinor/radix-operator/radix-operator/common" + "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +type handlerTestSuite struct { + common.ControllerTestSuite +} + +func TestHandlerSuite(t *testing.T) { + suite.Run(t, new(handlerTestSuite)) +} + +func (s *handlerTestSuite) TearDownTest() { + s.MockCtrl.Finish() +} + +type testIngress struct { + appName string + envName string + name string + host string + component string + port int32 +} + +func (s *handlerTestSuite) Test_IngressesForRadixDNSAliases() { + const ( + appName = "any-app1" + envDev = "dev" + componentNameServer1 = "server1" + server1Anyapp1DevDns = "server1-any-app1-dev.radix.equinor.com" + port = 8080 + ) + var testScenarios = []struct { + name string + dnsAliases []radixv1.DNSAlias + existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec + existingIngress []testIngress + expectedIngress map[string]testIngress + }{ + { + name: "no aliases, no existing RDA, no existing ingresses, no additional radix aliases, no additional ingresses", + }, + { + name: "no aliases, no existing RDA, exist ingresses, no additional radix aliases, no additional ingresses", + existingIngress: []testIngress{{appName: appName, envName: envDev, name: componentNameServer1, host: server1Anyapp1DevDns, component: componentNameServer1, port: port}}, + expectedIngress: map[string]testIngress{componentNameServer1: {appName: appName, envName: envDev, name: componentNameServer1, host: server1Anyapp1DevDns, component: componentNameServer1, port: port}}, + }, + { + name: "multiple aliases, no existing RDA, no existing ingresses, additional radix aliases, additional ingresses", + dnsAliases: []radixv1.DNSAlias{ + {Domain: "domain1", Environment: envDev, Component: componentNameServer1}, + {Domain: "domain2", Environment: envDev, Component: componentNameServer1}, + }, + expectedIngress: map[string]testIngress{ + "server1.domain1.custom-domain": {appName: appName, envName: envDev, name: "server1.domain1.custom-domain", host: "domain1.custom-domain.radix.equinor.com", component: componentNameServer1, port: port}, + "server1.domain2.custom-domain": {appName: appName, envName: envDev, name: "server1.domain2.custom-domain", host: "domain2.custom-domain.radix.equinor.com", component: componentNameServer1, port: port}, + }, + }, + } + s.SetupTest() + + for _, ts := range testScenarios { + s.T().Run(ts.name, func(t *testing.T) { + ra := utils.ARadixApplication().WithAppName(appName).WithDNSAlias(ts.dnsAliases...).BuildRA() + _, err := s.RadixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName)).Create(context.Background(), ra, metav1.CreateOptions{}) + require.NoError(t, err) + require.NoError(t, registerExistingIngresses(s.KubeClient, ts.existingIngress), "create existing ingresses") + + ingresses, err := s.KubeClient.NetworkingV1().Ingresses("").List(context.TODO(), metav1.ListOptions{}) + require.NoError(t, err) + + // assert ingresses + if ts.expectedIngress == nil { + assert.Len(t, ingresses.Items, 0, "not expected ingresses") + } else { + assert.Len(t, ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") + if len(ingresses.Items) == len(ts.expectedIngress) { + for _, ingress := range ingresses.Items { + if expectedIngress, ok := ts.expectedIngress[ingress.Name]; ok { + require.Len(t, ingress.Spec.Rules, 1, "rules count") + assert.Equal(t, expectedIngress.appName, ingress.GetLabels()[kube.RadixAppLabel], "app name") + assert.Equal(t, utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ingress.GetNamespace(), "namespace") + assert.Equal(t, expectedIngress.component, ingress.GetLabels()[kube.RadixComponentLabel], "component name") + assert.Equal(t, expectedIngress.host, ingress.Spec.Rules[0].Host, "rule host") + assert.Equal(t, "/", ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") + assert.Equal(t, expectedIngress.component, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") + assert.Equal(t, expectedIngress.port, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") + } else { + assert.Failf(t, "found not expected ingress %s: appName %s, host %s, service %s, port %d", ingress.GetName(), ingress.GetLabels()[kube.RadixAppLabel], ingress.Spec.Rules[0].Host, ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, &ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port) + } + } + } + } + }) + } +} + +func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses []testIngress) error { + for _, ing := range testIngresses { + _, err := internal.CreateRadixDNSAliasIngress(kubeClient, ing.appName, ing.envName, internal.BuildRadixDNSAliasIngress(ing.appName, ing.name, ing.component, ing.port)) + if err != nil { + return err + } + } + return nil +} diff --git a/radix-operator/dnsalias/internal/utils.go b/radix-operator/dnsalias/internal/utils.go new file mode 100644 index 000000000..b5e33feff --- /dev/null +++ b/radix-operator/dnsalias/internal/utils.go @@ -0,0 +1,54 @@ +package internal + +import ( + "context" + "fmt" + + "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/utils" + "github.com/equinor/radix-operator/pkg/apis/utils/labels" + networkingv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +const ( + dnsAliasIngressNameTemplate = "%s.%s.custom-domain" // ..custom-domain +) + +// CreateRadixDNSAliasIngress Create an Ingress for a RadixDNSAlias +func CreateRadixDNSAliasIngress(kubeClient kubernetes.Interface, appName, envName string, ingress *networkingv1.Ingress) (*networkingv1.Ingress, error) { + return kubeClient.NetworkingV1().Ingresses(utils.GetEnvironmentNamespace(appName, envName)).Create(context.Background(), ingress, metav1.CreateOptions{}) +} + +// BuildRadixDNSAliasIngress Build an Ingress for a RadixDNSAlias +func BuildRadixDNSAliasIngress(appName, domain, service string, port int32) *networkingv1.Ingress { + pathTypeImplementationSpecific := networkingv1.PathTypeImplementationSpecific + host := fmt.Sprintf(dnsAliasIngressNameTemplate, service, domain) + return &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: domain, + Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(service)), + }, + Spec: networkingv1.IngressSpec{ + TLS: []networkingv1.IngressTLS{ + { + Hosts: []string{host}, + SecretName: defaults.TLSSecretName, + }, + }, + Rules: []networkingv1.IngressRule{ + { + Host: host, + IngressRuleValue: networkingv1.IngressRuleValue{ + HTTP: &networkingv1.HTTPIngressRuleValue{Paths: []networkingv1.HTTPIngressPath{ + {Path: "/", PathType: &pathTypeImplementationSpecific, Backend: networkingv1.IngressBackend{ + Service: &networkingv1.IngressServiceBackend{Name: service, Port: networkingv1.ServiceBackendPort{ + Number: port, + }}, + }}}, + }}, + }, + }, + }} +} From 6e63dfb779a7310b85eeaf345c3a0c7cee51f741 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 25 Oct 2023 17:03:59 +0200 Subject: [PATCH 007/121] Extended RadixDNSAliases controllers and handler, added ClusterConfig and Radix constants --- pkg/apis/alert/alert.go | 7 +- pkg/apis/alert/alert_test.go | 3 +- pkg/apis/application/ownerreference.go | 5 +- pkg/apis/application/roles.go | 3 +- .../applicationconfig_test.go | 89 ++----------------- pkg/apis/batch/utils.go | 5 +- pkg/apis/defaults/resources.go | 2 - pkg/apis/deployment/ownerreference.go | 7 +- pkg/apis/dnsalias/dnsalias.go | 31 +++---- pkg/apis/environment/environment.go | 5 +- pkg/apis/job/ownerreference.go | 5 +- pkg/apis/radix/register.go | 26 +++++- pkg/apis/radix/v1/register.go | 2 +- pkg/apis/utils/application_builder.go | 5 +- pkg/apis/utils/deployment_builder.go | 8 +- pkg/apis/utils/environment_builder.go | 9 +- pkg/apis/utils/environment_builder_test.go | 14 +-- pkg/apis/utils/job_builder.go | 5 +- pkg/apis/utils/registration_builder.go | 5 +- .../typed/radix/v1/fake/fake_radixalert.go | 5 +- .../radix/v1/fake/fake_radixapplication.go | 5 +- .../typed/radix/v1/fake/fake_radixbatch.go | 5 +- .../radix/v1/fake/fake_radixdeployment.go | 5 +- .../typed/radix/v1/fake/fake_radixdnsalias.go | 5 +- .../radix/v1/fake/fake_radixenvironment.go | 5 +- .../typed/radix/v1/fake/fake_radixjob.go | 7 +- .../radix/v1/fake/fake_radixregistration.go | 5 +- radix-operator/batch/controller.go | 5 +- radix-operator/batch/controller_test.go | 3 +- radix-operator/common/controller.go | 7 +- radix-operator/config/cluster_config.go | 8 ++ radix-operator/config/config.go | 13 +++ radix-operator/deployment/controller.go | 5 +- radix-operator/dnsalias/controller.go | 18 ++-- radix-operator/dnsalias/controller_test.go | 21 ++--- radix-operator/dnsalias/handler.go | 44 ++++----- radix-operator/dnsalias/handler_test.go | 71 ++++++++++----- radix-operator/dnsalias/internal/utils.go | 29 +++++- radix-operator/environment/controller.go | 7 +- radix-operator/job/controller.go | 7 +- radix-operator/main.go | 29 +++++- radix-operator/registration/controller.go | 7 +- 42 files changed, 301 insertions(+), 251 deletions(-) create mode 100644 radix-operator/config/cluster_config.go diff --git a/pkg/apis/alert/alert.go b/pkg/apis/alert/alert.go index 38a1171ab..b0455dbee 100644 --- a/pkg/apis/alert/alert.go +++ b/pkg/apis/alert/alert.go @@ -6,6 +6,7 @@ import ( commonUtils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-operator/pkg/apis/kube" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" monitoring "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned" @@ -15,7 +16,7 @@ import ( "k8s.io/client-go/util/retry" ) -//AlertSyncer defines interface for syncing a RadixAlert +// AlertSyncer defines interface for syncing a RadixAlert type AlertSyncer interface { OnSync() error } @@ -109,8 +110,8 @@ func (syncer *alertSyncer) updateRadixAlertStatus(changeStatusFunc func(currStat func (syncer *alertSyncer) getOwnerReference() []metav1.OwnerReference { return []metav1.OwnerReference{ { - APIVersion: "radix.equinor.com/v1", - Kind: "RadixAlert", + APIVersion: radix.APIVersion, + Kind: radix.KindRadixAlert, Name: syncer.radixAlert.Name, UID: syncer.radixAlert.UID, Controller: commonUtils.BoolPtr(true), diff --git a/pkg/apis/alert/alert_test.go b/pkg/apis/alert/alert_test.go index e58758110..ad28df714 100644 --- a/pkg/apis/alert/alert_test.go +++ b/pkg/apis/alert/alert_test.go @@ -8,6 +8,7 @@ import ( "github.com/equinor/radix-common/utils" "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/kube" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/test" fakeradix "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" @@ -82,7 +83,7 @@ func (s *alertTestSuite) createAlertSyncer(alert *radixv1.RadixAlert, options .. } func (s *alertTestSuite) getRadixAlertAsOwnerReference(radixAlert *radixv1.RadixAlert) metav1.OwnerReference { - return metav1.OwnerReference{Kind: "RadixAlert", Name: radixAlert.Name, UID: radixAlert.UID, APIVersion: "radix.equinor.com/v1", Controller: utils.BoolPtr(true)} + return metav1.OwnerReference{Kind: radix.KindRadixAlert, Name: radixAlert.Name, UID: radixAlert.UID, APIVersion: radix.APIVersion, Controller: utils.BoolPtr(true)} } func (s *alertTestSuite) Test_New() { diff --git a/pkg/apis/application/ownerreference.go b/pkg/apis/application/ownerreference.go index 992939bb8..63dbc72ee 100644 --- a/pkg/apis/application/ownerreference.go +++ b/pkg/apis/application/ownerreference.go @@ -1,6 +1,7 @@ package application import ( + "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -15,8 +16,8 @@ func GetOwnerReferenceOfRegistration(registration *v1.RadixRegistration) []metav trueVar := true return []metav1.OwnerReference{ { - APIVersion: "radix.equinor.com/v1", - Kind: "RadixRegistration", + APIVersion: radix.APIVersion, + Kind: radix.KindRadixRegistration, Name: registration.Name, UID: registration.UID, Controller: &trueVar, diff --git a/pkg/apis/application/roles.go b/pkg/apis/application/roles.go index 023bf936a..526247c87 100644 --- a/pkg/apis/application/roles.go +++ b/pkg/apis/application/roles.go @@ -5,6 +5,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults/k8s" "github.com/equinor/radix-operator/pkg/apis/kube" + "github.com/equinor/radix-operator/pkg/apis/radix" auth "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -38,7 +39,7 @@ func (app Application) rrClusterRole(clusterroleName string, verbs []string) *au }, Rules: []auth.PolicyRule{ { - APIGroups: []string{"radix.equinor.com"}, + APIGroups: []string{radix.GroupName}, Resources: []string{"radixregistrations"}, ResourceNames: []string{appName}, Verbs: verbs, diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index d5c68bce1..a165160f3 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -10,20 +10,19 @@ import ( "github.com/equinor/radix-operator/pkg/apis/applicationconfig" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" - "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" - radix "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" + radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" - networkingv1 "k8s.io/api/networking/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" - "k8s.io/client-go/kubernetes/fake" + kubefake "k8s.io/client-go/kubernetes/fake" secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake" ) @@ -38,8 +37,8 @@ func init() { } func setupTest() (*test.Utils, kubernetes.Interface, *kube.Kube, radixclient.Interface) { - kubeClient := fake.NewSimpleClientset() - radixClient := radix.NewSimpleClientset() + kubeClient := kubefake.NewSimpleClientset() + radixClient := radixfake.NewSimpleClientset() secretproviderclient := secretproviderfake.NewSimpleClientset() kubeUtil, _ := kube.New(kubeClient, radixClient, secretproviderclient) handlerTestUtils := test.NewTestUtils(kubeClient, radixClient, secretproviderclient) @@ -672,24 +671,18 @@ func Test_DNSAliases(t *testing.T) { appName = "any-app1" envDev = "dev" componentNameServer1 = "server1" - server1Anyapp1DevDns = "server1-any-app1-dev.radix.equinor.com" - port = 8080 ) var testScenarios = []struct { name string dnsAliases []radixv1.DNSAlias existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec expectedRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec - existingIngress []testIngress - expectedIngress map[string]testIngress }{ { name: "no aliases, no existing RDA, no existing ingresses, no additional radix aliases, no additional ingresses", }, { - name: "no aliases, no existing RDA, exist ingresses, no additional radix aliases, no additional ingresses", - existingIngress: []testIngress{{appName: appName, envName: envDev, name: componentNameServer1, host: server1Anyapp1DevDns, component: componentNameServer1, port: port}}, - expectedIngress: map[string]testIngress{componentNameServer1: {appName: appName, envName: envDev, name: componentNameServer1, host: server1Anyapp1DevDns, component: componentNameServer1, port: port}}, + name: "no aliases, no existing RDA, exist ingresses, no additional radix aliases, no additional ingresses", }, { name: "multiple aliases, no existing RDA, no existing ingresses, additional radix aliases, additional ingresses", @@ -701,10 +694,6 @@ func Test_DNSAliases(t *testing.T) { "domain1": {AppName: appName, Environment: envDev, Component: componentNameServer1}, "domain2": {AppName: appName, Environment: envDev, Component: componentNameServer1}, }, - expectedIngress: map[string]testIngress{ - "server1.domain1.custom-domain": {appName: appName, envName: envDev, name: "server1.domain1.custom-domain", host: "domain1.custom-domain.radix.equinor.com", component: componentNameServer1, port: port}, - "server1.domain2.custom-domain": {appName: appName, envName: envDev, name: "server1.domain2.custom-domain", host: "domain2.custom-domain.radix.equinor.com", component: componentNameServer1, port: port}, - }, }, } tu, kubeClient, kubeUtil, radixClient := setupTest() @@ -714,12 +703,9 @@ func Test_DNSAliases(t *testing.T) { ra := utils.ARadixApplication().WithAppName(appName).WithDNSAlias(ts.dnsAliases...) require.NoError(t, applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, ra), "register radix application") require.NoError(t, registerExistingRadixDNSAliases(radixClient, ts.existingRadixDNSAliases), "create existing RadixDNSAlias") - require.NoError(t, registerExistingIngresses(kubeClient, ts.existingIngress), "create existing ingresses") radixDNSAliases, err := radixClient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{}) require.NoError(t, err) - ingresses, err := kubeClient.NetworkingV1().Ingresses("").List(context.TODO(), metav1.ListOptions{}) - require.NoError(t, err) // assert RadixDNSAlias-es if ts.expectedRadixDNSAliases == nil { @@ -738,69 +724,10 @@ func Test_DNSAliases(t *testing.T) { } } } - // assert ingresses - if ts.expectedIngress == nil { - assert.Len(t, ingresses.Items, 0, "not expected ingresses") - } else { - assert.Len(t, ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") - if len(ingresses.Items) == len(ts.expectedIngress) { - for _, ingress := range ingresses.Items { - if expectedIngress, ok := ts.expectedIngress[ingress.Name]; ok { - require.Len(t, ingress.Spec.Rules, 1, "rules count") - assert.Equal(t, expectedIngress.appName, ingress.GetLabels()[kube.RadixAppLabel], "app name") - assert.Equal(t, utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ingress.GetNamespace(), "namespace") - assert.Equal(t, expectedIngress.component, ingress.GetLabels()[kube.RadixComponentLabel], "component name") - assert.Equal(t, expectedIngress.host, ingress.Spec.Rules[0].Host, "rule host") - assert.Equal(t, "/", ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") - assert.Equal(t, expectedIngress.component, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") - assert.Equal(t, expectedIngress.port, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") - } else { - assert.Failf(t, "found not expected ingress %s: appName %s, host %s, service %s, port %d", ingress.GetName(), ingress.GetLabels()[kube.RadixAppLabel], ingress.Spec.Rules[0].Host, ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, &ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port) - } - } - } - } }) } } -func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses []testIngress) error { - for _, ing := range testIngresses { - pathTypeImplementationSpecific := networkingv1.PathTypeImplementationSpecific - _, err := kubeClient.NetworkingV1().Ingresses(utils.GetEnvironmentNamespace(ing.appName, ing.envName)).Create(context.TODO(), - &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: ing.name, - Labels: labels.Merge(labels.ForApplicationName(ing.appName), labels.ForComponentName(ing.component)), - }, - Spec: networkingv1.IngressSpec{ - TLS: []networkingv1.IngressTLS{ - { - Hosts: []string{ing.host}, - SecretName: "radix-wildcard-tls-cert", - }, - }, - Rules: []networkingv1.IngressRule{ - { - Host: ing.host, - IngressRuleValue: networkingv1.IngressRuleValue{ - HTTP: &networkingv1.HTTPIngressRuleValue{Paths: []networkingv1.HTTPIngressPath{ - {Path: "/", PathType: &pathTypeImplementationSpecific, Backend: networkingv1.IngressBackend{ - Service: &networkingv1.IngressServiceBackend{Name: ing.component, Port: networkingv1.ServiceBackendPort{ - Number: ing.port, - }}, - }}}, - }}, - }, - }, - }}, metav1.CreateOptions{}) - if err != nil { - return err - } - } - return nil -} - func registerExistingRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]radixv1.RadixDNSAliasSpec) error { for domain, rdaSpec := range radixDNSAliasesMap { _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.TODO(), @@ -822,8 +749,8 @@ func rrAsOwnerReference(rr *radixv1.RadixRegistration) []metav1.OwnerReference { trueVar := true return []metav1.OwnerReference{ { - APIVersion: "radix.equinor.com/v1", - Kind: "RadixRegistration", + APIVersion: radix.APIVersion, + Kind: radix.KindRadixRegistration, Name: rr.Name, UID: rr.UID, Controller: &trueVar, diff --git a/pkg/apis/batch/utils.go b/pkg/apis/batch/utils.go index de221ca6f..29e61df01 100644 --- a/pkg/apis/batch/utils.go +++ b/pkg/apis/batch/utils.go @@ -5,6 +5,7 @@ import ( "github.com/equinor/radix-common/utils" "github.com/equinor/radix-common/utils/slice" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -52,8 +53,8 @@ func isBatchJobDone(batch *radixv1.RadixBatch, batchJobName string) bool { func ownerReference(job *radixv1.RadixBatch) []metav1.OwnerReference { return []metav1.OwnerReference{ { - APIVersion: "radix.equinor.com/v1", - Kind: "RadixBatch", + APIVersion: radix.APIVersion, + Kind: radix.KindRadixBatch, Name: job.Name, UID: job.UID, Controller: utils.BoolPtr(true), diff --git a/pkg/apis/defaults/resources.go b/pkg/apis/defaults/resources.go index c44ac2500..595aa037d 100644 --- a/pkg/apis/defaults/resources.go +++ b/pkg/apis/defaults/resources.go @@ -9,8 +9,6 @@ import ( // Environment variables that define default resources (limits and requests) for containers and environments // See https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/memory-default-namespace/ const ( - RadixAPIVersion = "radix.equinor.com/v1" - RadixDNSAliasKind = "RadixDNSAlias" OperatorDefaultUserGroupEnvironmentVariable = "RADIXOPERATOR_DEFAULT_USER_GROUP" OperatorEnvLimitDefaultMemoryEnvironmentVariable = "RADIXOPERATOR_APP_ENV_LIMITS_DEFAULT_MEMORY" OperatorEnvLimitDefaultRequestMemoryEnvironmentVariable = "RADIXOPERATOR_APP_ENV_LIMITS_DEFAULT_REQUEST_MEMORY" diff --git a/pkg/apis/deployment/ownerreference.go b/pkg/apis/deployment/ownerreference.go index 7c9c21428..8f7081ba0 100644 --- a/pkg/apis/deployment/ownerreference.go +++ b/pkg/apis/deployment/ownerreference.go @@ -2,6 +2,7 @@ package deployment import ( "github.com/equinor/radix-common/utils" + "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" secretsstorev1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1" @@ -9,8 +10,8 @@ import ( func getOwnerReferenceOfDeployment(radixDeployment *v1.RadixDeployment) metav1.OwnerReference { return metav1.OwnerReference{ - APIVersion: "radix.equinor.com/v1", //need to hardcode these values for now - seems they are missing from the CRD in k8s 1.8 - Kind: "RadixDeployment", + APIVersion: radix.APIVersion, + Kind: radix.KindRadixDeployment, Name: radixDeployment.Name, UID: radixDeployment.UID, Controller: utils.BoolPtr(true), @@ -23,7 +24,7 @@ func getOwnerReferenceOfSecretProviderClass(secretProviderClass *secretsstorev1. Kind: "SecretProviderClass", Name: secretProviderClass.Name, UID: secretProviderClass.UID, - //Controller is not set due too only one OwnerReference's controller can be set as `true` + // Controller is not set due too only one OwnerReference's controller can be set as `true` } } diff --git a/pkg/apis/dnsalias/dnsalias.go b/pkg/apis/dnsalias/dnsalias.go index 685a7bb03..682c5346c 100644 --- a/pkg/apis/dnsalias/dnsalias.go +++ b/pkg/apis/dnsalias/dnsalias.go @@ -15,12 +15,12 @@ import ( // DNSAlias is the aggregate-root for manipulating RadixDNSAliases type DNSAlias struct { - kubeclient kubernetes.Interface - radixclient radixclient.Interface - kubeutil *kube.Kube - config *radixv1.RadixDNSAlias - appConfig *radixv1.RadixApplication - logger *logrus.Entry + kubeclient kubernetes.Interface + radixclient radixclient.Interface + kubeutil *kube.Kube + radixDNSAlias *radixv1.RadixDNSAlias + appConfig *radixv1.RadixApplication + logger *logrus.Entry } // NewDNSAlias is the constructor for DNSAlias @@ -46,30 +46,31 @@ func NewDNSAlias( func (dnsAlias *DNSAlias) OnSync(time metav1.Time) error { // TODO - err := dnsAlias.updateRadixDNSAliasStatus(dnsAlias.config, func(currStatus *radixv1.RadixDNSAliasStatus) { + err := dnsAlias.updateRadixDNSAliasStatus(dnsAlias.radixDNSAlias, func(currStatus *radixv1.RadixDNSAliasStatus) { // time is parameterized for testability currStatus.Reconciled = time }) if err != nil { - return fmt.Errorf("failed to update status on DNS alias %s: %v", dnsAlias.config.GetName(), err) + return fmt.Errorf("failed to update status on DNS alias %s: %v", dnsAlias.radixDNSAlias.GetName(), err) } - dnsAlias.logger.Debugf("DNSAlias %s reconciled", dnsAlias.config.GetName()) + dnsAlias.logger.Debugf("DNSAlias %s reconciled", dnsAlias.radixDNSAlias.GetName()) return nil } func (dnsAlias *DNSAlias) updateRadixDNSAliasStatus(rEnv *radixv1.RadixDNSAlias, changeStatusFunc func(currStatus *radixv1.RadixDNSAliasStatus)) error { radixDNSAliasInterface := dnsAlias.radixclient.RadixV1().RadixDNSAliases() + ctx := context.Background() return retry.RetryOnConflict(retry.DefaultRetry, func() error { - currentEnv, err := radixDNSAliasInterface.Get(context.TODO(), rEnv.GetName(), metav1.GetOptions{}) + currentEnv, err := radixDNSAliasInterface.Get(ctx, rEnv.GetName(), metav1.GetOptions{}) if err != nil { return err } changeStatusFunc(¤tEnv.Status) - _, err = radixDNSAliasInterface.UpdateStatus(context.TODO(), currentEnv, metav1.UpdateOptions{}) - if err == nil && dnsAlias.config.GetName() == rEnv.GetName() { - currentEnv, err = radixDNSAliasInterface.Get(context.TODO(), rEnv.GetName(), metav1.GetOptions{}) + _, err = radixDNSAliasInterface.UpdateStatus(ctx, currentEnv, metav1.UpdateOptions{}) + if err == nil && dnsAlias.radixDNSAlias.GetName() == rEnv.GetName() { + currentEnv, err = radixDNSAliasInterface.Get(ctx, rEnv.GetName(), metav1.GetOptions{}) if err == nil { - dnsAlias.config = currentEnv + dnsAlias.radixDNSAlias = currentEnv } } return err @@ -77,5 +78,5 @@ func (dnsAlias *DNSAlias) updateRadixDNSAliasStatus(rEnv *radixv1.RadixDNSAlias, } func (dnsAlias *DNSAlias) GetConfig() *radixv1.RadixDNSAlias { - return dnsAlias.config + return dnsAlias.radixDNSAlias } diff --git a/pkg/apis/environment/environment.go b/pkg/apis/environment/environment.go index 3aebae37b..4328566fe 100644 --- a/pkg/apis/environment/environment.go +++ b/pkg/apis/environment/environment.go @@ -8,6 +8,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults/k8s" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/networkpolicy" + "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -255,8 +256,8 @@ func (env *Environment) AsOwnerReference() []metav1.OwnerReference { trueVar := true return []metav1.OwnerReference{ { - APIVersion: "radix.equinor.com/v1", - Kind: "RadixEnvironment", + APIVersion: radix.APIVersion, + Kind: radix.KindRadixEnvironment, Name: env.config.Name, UID: env.config.UID, Controller: &trueVar, diff --git a/pkg/apis/job/ownerreference.go b/pkg/apis/job/ownerreference.go index d52f48122..314db0d0a 100644 --- a/pkg/apis/job/ownerreference.go +++ b/pkg/apis/job/ownerreference.go @@ -3,6 +3,7 @@ package job import ( "context" + "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -13,8 +14,8 @@ func GetOwnerReference(radixJob *v1.RadixJob) []metav1.OwnerReference { trueVar := true return []metav1.OwnerReference{ { - APIVersion: "radix.equinor.com/v1", //need to hardcode these values for now - seems they are missing from the CRD in k8s 1.8 - Kind: "RadixJob", + APIVersion: radix.APIVersion, + Kind: radix.KindRadixJob, Name: radixJob.Name, UID: radixJob.UID, Controller: &trueVar, diff --git a/pkg/apis/radix/register.go b/pkg/apis/radix/register.go index eb0650170..2913f560a 100644 --- a/pkg/apis/radix/register.go +++ b/pkg/apis/radix/register.go @@ -1,4 +1,26 @@ package radix -// GroupName Group name for this API -const GroupName = "radix.equinor.com" +const ( + // GroupName Group name for this API + GroupName = "radix.equinor.com" + // APIVersion API version for Radix objects + APIVersion = "radix.equinor.com/v1" + // Version version for Radix objects + Version = "v1" + // KindRadixRegistration RadixRegistration object Kind + KindRadixRegistration = "RadixRegistration" + // KindRadixEnvironment RadixEnvironment object Kind + KindRadixEnvironment = "RadixEnvironment" + // KindRadixApplication RadixApplication object Kind + KindRadixApplication = "RadixApplication" + // KindRadixDeployment RadixDeployment object Kind + KindRadixDeployment = "RadixDeployment" + // KindRadixJob RadixJob object Kind + KindRadixJob = "RadixJob" + // KindRadixBatch RadixBatch object Kind + KindRadixBatch = "RadixBatch" + // KindRadixAlert RadixAlert object Kind + KindRadixAlert = "RadixAlert" + // KindRadixDNSAlias RadixDNSAlias object Kind + KindRadixDNSAlias = "RadixDNSAlias" +) diff --git a/pkg/apis/radix/v1/register.go b/pkg/apis/radix/v1/register.go index 5f43fb2e8..486f780e4 100644 --- a/pkg/apis/radix/v1/register.go +++ b/pkg/apis/radix/v1/register.go @@ -11,7 +11,7 @@ import ( // SchemeGroupVersion provides the group version var SchemeGroupVersion = schema.GroupVersion{ Group: radix.GroupName, - Version: "v1", + Version: radix.Version, } var ( // SchemeBuilder builds a scheme diff --git a/pkg/apis/utils/application_builder.go b/pkg/apis/utils/application_builder.go index ce671831d..5ef9307d6 100644 --- a/pkg/apis/utils/application_builder.go +++ b/pkg/apis/utils/application_builder.go @@ -3,6 +3,7 @@ package utils import ( "strings" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils/numbers" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -212,8 +213,8 @@ func (ap *ApplicationBuilderStruct) BuildRA() *radixv1.RadixApplication { radixApplication := &radixv1.RadixApplication{ TypeMeta: metav1.TypeMeta{ - APIVersion: "radix.equinor.com/v1", - Kind: "RadixApplication", + APIVersion: radix.APIVersion, + Kind: radix.KindRadixApplication, }, ObjectMeta: metav1.ObjectMeta{ Name: ap.appName, diff --git a/pkg/apis/utils/deployment_builder.go b/pkg/apis/utils/deployment_builder.go index 7a18f9608..d8e8432af 100644 --- a/pkg/apis/utils/deployment_builder.go +++ b/pkg/apis/utils/deployment_builder.go @@ -5,10 +5,10 @@ import ( "strconv" "time" - "github.com/equinor/radix-operator/pkg/apis/utils/numbers" - "github.com/equinor/radix-operator/pkg/apis/kube" + "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/utils/numbers" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" ) @@ -246,8 +246,8 @@ func (db *DeploymentBuilderStruct) BuildRD() *v1.RadixDeployment { radixDeployment := &v1.RadixDeployment{ TypeMeta: metav1.TypeMeta{ - APIVersion: "radix.equinor.com/v1", - Kind: "RadixDeployment", + APIVersion: radix.APIVersion, + Kind: radix.KindRadixDeployment, }, ObjectMeta: metav1.ObjectMeta{ Name: deployName, diff --git a/pkg/apis/utils/environment_builder.go b/pkg/apis/utils/environment_builder.go index 7684f8ce0..ce093dc7b 100644 --- a/pkg/apis/utils/environment_builder.go +++ b/pkg/apis/utils/environment_builder.go @@ -3,6 +3,7 @@ package utils import ( "time" + "github.com/equinor/radix-operator/pkg/apis/radix" rx "github.com/equinor/radix-operator/pkg/apis/radix/v1" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -99,8 +100,8 @@ func (eb *EnvironmentBuilderStruct) WithRegistrationOwner(registration *rx.Radix } trueVar := true return eb.WithOwner(meta.OwnerReference{ - APIVersion: "radix.equinor.com/v1", - Kind: "RadixRegistration", + APIVersion: radix.APIVersion, + Kind: radix.KindRadixRegistration, Name: registration.Name, UID: registration.UID, Controller: &trueVar, @@ -154,8 +155,8 @@ func (eb *EnvironmentBuilderStruct) BuildRE() *rx.RadixEnvironment { radixEnvironment := &rx.RadixEnvironment{ TypeMeta: meta.TypeMeta{ - APIVersion: "radix.equinor.com/v1", - Kind: "RadixEnvironment", + APIVersion: radix.APIVersion, + Kind: radix.KindRadixEnvironment, }, ObjectMeta: meta.ObjectMeta{ Name: uniqueName, diff --git a/pkg/apis/utils/environment_builder_test.go b/pkg/apis/utils/environment_builder_test.go index 95d1e0e5d..1008cde43 100644 --- a/pkg/apis/utils/environment_builder_test.go +++ b/pkg/apis/utils/environment_builder_test.go @@ -4,11 +4,11 @@ import ( "testing" "time" + "github.com/equinor/radix-operator/pkg/apis/radix" + "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/stretchr/testify/assert" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - "github.com/stretchr/testify/assert" ) func Test_RadixEnvironment_Defaults(t *testing.T) { @@ -19,8 +19,8 @@ func Test_RadixEnvironment_Defaults(t *testing.T) { nilTime := (*meta.Time)(nil) // TypeMeta - assert.Equal(t, "radix.equinor.com/v1", re.TypeMeta.APIVersion) - assert.Equal(t, "RadixEnvironment", re.TypeMeta.Kind) + assert.Equal(t, radix.APIVersion, re.TypeMeta.APIVersion) + assert.Equal(t, radix.KindRadixEnvironment, re.TypeMeta.Kind) // ObjectMeta assert.Len(t, re.ObjectMeta.Annotations, 0) @@ -110,7 +110,7 @@ func Test_WithRegistrationOwner(t *testing.T) { assert.Len(t, re.ObjectMeta.OwnerReferences, 1) assert.Equal(t, "RR", re.ObjectMeta.OwnerReferences[0].Name) - assert.Equal(t, "RadixRegistration", re.ObjectMeta.OwnerReferences[0].Kind) + assert.Equal(t, radix.KindRadixRegistration, re.ObjectMeta.OwnerReferences[0].Kind) } func Test_WithRegistrationBuilder(t *testing.T) { @@ -121,7 +121,7 @@ func Test_WithRegistrationBuilder(t *testing.T) { assert.Len(t, re.ObjectMeta.OwnerReferences, 1) assert.Equal(t, "RR", re.ObjectMeta.OwnerReferences[0].Name) - assert.Equal(t, "RadixRegistration", re.ObjectMeta.OwnerReferences[0].Kind) + assert.Equal(t, radix.KindRadixRegistration, re.ObjectMeta.OwnerReferences[0].Kind) } func Test_WithResourceVersion(t *testing.T) { diff --git a/pkg/apis/utils/job_builder.go b/pkg/apis/utils/job_builder.go index c3004e301..61d966275 100644 --- a/pkg/apis/utils/job_builder.go +++ b/pkg/apis/utils/job_builder.go @@ -5,6 +5,7 @@ import ( "time" "github.com/equinor/radix-operator/pkg/apis/kube" + "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -150,8 +151,8 @@ func (jb *JobBuilderStruct) GetApplicationBuilder() ApplicationBuilder { func (jb *JobBuilderStruct) BuildRJ() *v1.RadixJob { radixJob := &v1.RadixJob{ TypeMeta: metav1.TypeMeta{ - APIVersion: "radix.equinor.com/v1", - Kind: "RadixJob", + APIVersion: radix.APIVersion, + Kind: radix.KindRadixJob, }, ObjectMeta: metav1.ObjectMeta{ Name: jb.jobName, diff --git a/pkg/apis/utils/registration_builder.go b/pkg/apis/utils/registration_builder.go index b4118ca39..2cc60f4c3 100644 --- a/pkg/apis/utils/registration_builder.go +++ b/pkg/apis/utils/registration_builder.go @@ -4,6 +4,7 @@ import ( "strings" "time" + "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -180,8 +181,8 @@ func (rb *RegistrationBuilderStruct) BuildRR() *v1.RadixRegistration { radixRegistration := &v1.RadixRegistration{ TypeMeta: metav1.TypeMeta{ - APIVersion: "radix.equinor.com/v1", - Kind: "RadixRegistration", + APIVersion: radix.APIVersion, + Kind: radix.KindRadixRegistration, }, ObjectMeta: metav1.ObjectMeta{ Name: rb.name, diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixalert.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixalert.go index a19447b8d..d529039f3 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixalert.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixalert.go @@ -21,6 +21,7 @@ package fake import ( "context" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -36,9 +37,9 @@ type FakeRadixAlerts struct { ns string } -var radixalertsResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixalerts"} +var radixalertsResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixalerts"} -var radixalertsKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixAlert"} +var radixalertsKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: radix.KindRadixAlert} // Get takes name of the radixAlert, and returns the corresponding radixAlert object, and an error if there is any. func (c *FakeRadixAlerts) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixAlert, err error) { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixapplication.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixapplication.go index cb1b4ab81..29edfc8b9 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixapplication.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixapplication.go @@ -21,6 +21,7 @@ package fake import ( "context" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -36,9 +37,9 @@ type FakeRadixApplications struct { ns string } -var radixapplicationsResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixapplications"} +var radixapplicationsResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixapplications"} -var radixapplicationsKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixApplication"} +var radixapplicationsKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: radix.KindRadixApplication} // Get takes name of the radixApplication, and returns the corresponding radixApplication object, and an error if there is any. func (c *FakeRadixApplications) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixApplication, err error) { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixbatch.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixbatch.go index 91e0c7161..6a410b30f 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixbatch.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixbatch.go @@ -21,6 +21,7 @@ package fake import ( "context" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -36,9 +37,9 @@ type FakeRadixBatches struct { ns string } -var radixbatchesResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixbatches"} +var radixbatchesResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixbatches"} -var radixbatchesKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixBatch"} +var radixbatchesKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: radix.KindRadixBatch} // Get takes name of the radixBatch, and returns the corresponding radixBatch object, and an error if there is any. func (c *FakeRadixBatches) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixBatch, err error) { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdeployment.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdeployment.go index ae8f8cde9..01d842e07 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdeployment.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdeployment.go @@ -21,6 +21,7 @@ package fake import ( "context" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -36,9 +37,9 @@ type FakeRadixDeployments struct { ns string } -var radixdeploymentsResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixdeployments"} +var radixdeploymentsResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixdeployments"} -var radixdeploymentsKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixDeployment"} +var radixdeploymentsKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: radix.KindRadixDeployment} // Get takes name of the radixDeployment, and returns the corresponding radixDeployment object, and an error if there is any. func (c *FakeRadixDeployments) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixDeployment, err error) { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go index 863ed75b8..39963e49c 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go @@ -21,6 +21,7 @@ package fake import ( "context" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -35,9 +36,9 @@ type FakeRadixDNSAliases struct { Fake *FakeRadixV1 } -var radixdnsaliasesResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixdnsaliases"} +var radixdnsaliasesResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixdnsaliases"} -var radixdnsaliasesKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixDNSAlias"} +var radixdnsaliasesKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: "RadixDNSAlias"} // Get takes name of the radixDNSAlias, and returns the corresponding radixDNSAlias object, and an error if there is any. func (c *FakeRadixDNSAliases) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixDNSAlias, err error) { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixenvironment.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixenvironment.go index 55d6f0155..c7b277d18 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixenvironment.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixenvironment.go @@ -21,6 +21,7 @@ package fake import ( "context" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -35,9 +36,9 @@ type FakeRadixEnvironments struct { Fake *FakeRadixV1 } -var radixenvironmentsResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixenvironments"} +var radixenvironmentsResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixenvironments"} -var radixenvironmentsKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixEnvironment"} +var radixenvironmentsKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: radix.KindRadixEnvironment} // Get takes name of the radixEnvironment, and returns the corresponding radixEnvironment object, and an error if there is any. func (c *FakeRadixEnvironments) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixEnvironment, err error) { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixjob.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixjob.go index 61685adc9..0e91d1ab7 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixjob.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixjob.go @@ -21,8 +21,9 @@ package fake import ( "context" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/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" @@ -36,9 +37,9 @@ type FakeRadixJobs struct { ns string } -var radixjobsResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixjobs"} +var radixjobsResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixjobs"} -var radixjobsKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixJob"} +var radixjobsKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: radix.KindRadixJob} // Get takes name of the radixJob, and returns the corresponding radixJob object, and an error if there is any. func (c *FakeRadixJobs) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixJob, err error) { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixregistration.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixregistration.go index c47ce1303..543fd378e 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixregistration.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixregistration.go @@ -21,6 +21,7 @@ package fake import ( "context" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -35,9 +36,9 @@ type FakeRadixRegistrations struct { Fake *FakeRadixV1 } -var radixregistrationsResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixregistrations"} +var radixregistrationsResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixregistrations"} -var radixregistrationsKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixRegistration"} +var radixregistrationsKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: radix.KindRadixRegistration} // Get takes name of the radixRegistration, and returns the corresponding radixRegistration object, and an error if there is any. func (c *FakeRadixRegistrations) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixRegistration, err error) { diff --git a/radix-operator/batch/controller.go b/radix-operator/batch/controller.go index d661c58af..f4a4a5585 100644 --- a/radix-operator/batch/controller.go +++ b/radix-operator/batch/controller.go @@ -5,6 +5,7 @@ import ( "reflect" "github.com/equinor/radix-operator/pkg/apis/metrics" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" informers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" @@ -90,10 +91,10 @@ func NewController(client kubernetes.Interface, if oldMeta.GetResourceVersion() == newMeta.GetResourceVersion() { return } - controller.HandleObject(newObj, "RadixBatch", getOwner) + controller.HandleObject(newObj, radix.KindRadixBatch, getOwner) }, DeleteFunc: func(obj interface{}) { - controller.HandleObject(obj, "RadixBatch", getOwner) + controller.HandleObject(obj, radix.KindRadixBatch, getOwner) }, }) diff --git a/radix-operator/batch/controller_test.go b/radix-operator/batch/controller_test.go index 6927ad5b5..8f899f9b1 100644 --- a/radix-operator/batch/controller_test.go +++ b/radix-operator/batch/controller_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/equinor/radix-common/utils" + "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/radix-operator/common" "github.com/stretchr/testify/suite" @@ -56,7 +57,7 @@ func (s *controllerTestSuite) Test_RadixBatchEvents() { Namespace: namespace, ResourceVersion: "1", OwnerReferences: []metav1.OwnerReference{ - {APIVersion: "radix.equinor.com/v1", Kind: "RadixBatch", Name: batchName, Controller: utils.BoolPtr(true)}, + {APIVersion: radix.APIVersion, Kind: radix.KindRadixBatch, Name: batchName, Controller: utils.BoolPtr(true)}, }, }} s.Handler.EXPECT().Sync(namespace, batchName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) diff --git a/radix-operator/common/controller.go b/radix-operator/common/controller.go index a2c44ee8a..6e30af77a 100644 --- a/radix-operator/common/controller.go +++ b/radix-operator/common/controller.go @@ -3,21 +3,16 @@ package common import ( "errors" "fmt" - "time" - "golang.org/x/sync/errgroup" - "github.com/equinor/radix-operator/pkg/apis/metrics" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" - log "github.com/sirupsen/logrus" - + "golang.org/x/sync/errgroup" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilruntime "k8s.io/apimachinery/pkg/util/runtime" kubeinformers "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" diff --git a/radix-operator/config/cluster_config.go b/radix-operator/config/cluster_config.go new file mode 100644 index 000000000..cd512c219 --- /dev/null +++ b/radix-operator/config/cluster_config.go @@ -0,0 +1,8 @@ +package config + +// ClusterConfig Config settings for the cluster +type ClusterConfig struct { + // DNSZone Cluster DNS zone. + // Example radix.equinor.com, playground.radix.equinor.com + DNSZone string +} diff --git a/radix-operator/config/config.go b/radix-operator/config/config.go index 6155d22ca..3cea02c9f 100644 --- a/radix-operator/config/config.go +++ b/radix-operator/config/config.go @@ -36,6 +36,15 @@ func getDeploymentsHistoryLimitPerEnvironment() int { return getIntFromEnvVar(defaults.DeploymentsHistoryLimitEnvironmentVariable, 0) } +// Gets DNS zone +func getDNSZone() string { + envVar, err := defaults.GetEnvVar(defaults.OperatorDNSZoneEnvironmentVariable) + if err != nil { + panic(err) + } + return envVar +} + func getIntFromEnvVar(envVarName string, defaultValue int) int { val, err := strconv.Atoi(viper.GetString(envVarName)) if err != nil { @@ -47,6 +56,7 @@ func getIntFromEnvVar(envVarName string, defaultValue int) int { // Config from environment variables type Config struct { LogLevel string + ClusterConfig *ClusterConfig PipelineJobConfig *job.Config } @@ -55,6 +65,9 @@ func NewConfig() *Config { viper.AutomaticEnv() return &Config{ LogLevel: getLogLevel(), + ClusterConfig: &ClusterConfig{ + DNSZone: getDNSZone(), + }, PipelineJobConfig: &job.Config{ PipelineJobsHistoryLimit: getPipelineJobsHistoryLimit(), DeploymentsHistoryLimitPerEnvironment: getDeploymentsHistoryLimitPerEnvironment(), diff --git a/radix-operator/deployment/controller.go b/radix-operator/deployment/controller.go index a11a01a67..0434d0125 100644 --- a/radix-operator/deployment/controller.go +++ b/radix-operator/deployment/controller.go @@ -9,6 +9,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/deployment" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/metrics" + "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" informers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" @@ -120,10 +121,10 @@ func NewController(client kubernetes.Interface, if newService.ResourceVersion == oldService.ResourceVersion { return } - controller.HandleObject(cur, "RadixDeployment", getObject) + controller.HandleObject(cur, radix.KindRadixDeployment, getObject) }, DeleteFunc: func(obj interface{}) { - controller.HandleObject(obj, "RadixDeployment", getObject) + controller.HandleObject(obj, radix.KindRadixDeployment, getObject) }, }) diff --git a/radix-operator/dnsalias/controller.go b/radix-operator/dnsalias/controller.go index 7c5ec38c8..ea3e0b1b5 100644 --- a/radix-operator/dnsalias/controller.go +++ b/radix-operator/dnsalias/controller.go @@ -4,8 +4,8 @@ import ( "context" "reflect" - "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/metrics" + "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" informers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" @@ -44,12 +44,12 @@ func NewController(kubeClient kubernetes.Interface, controller := &common.Controller{ Name: controllerAgentName, - HandlerOf: defaults.RadixDNSAliasKind, + HandlerOf: radix.KindRadixDNSAlias, KubeClient: kubeClient, RadixClient: radixClient, Informer: dnsAliasInformer.Informer(), KubeInformerFactory: kubeInformerFactory, - WorkQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), defaults.RadixDNSAliasKind), + WorkQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), radix.KindRadixDNSAlias), Handler: handler, Log: logger, WaitForChildrenToSync: waitForChildrenToSync, @@ -62,7 +62,7 @@ func NewController(kubeClient kubernetes.Interface, dnsAliasInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { controller.Enqueue(cur) - metrics.CustomResourceAdded(defaults.RadixDNSAliasKind) + metrics.CustomResourceAdded(radix.KindRadixDNSAlias) }, UpdateFunc: func(old, cur interface{}) { newRDA := cur.(*v1.RadixDNSAlias) @@ -70,12 +70,12 @@ func NewController(kubeClient kubernetes.Interface, if deepEqual(oldRDA, newRDA) { logger.Debugf("RadixDNSAlias object is equal to old for %s. Do nothing", newRDA.GetName()) - metrics.CustomResourceUpdatedButSkipped(defaults.RadixDNSAliasKind) + metrics.CustomResourceUpdatedButSkipped(radix.KindRadixDNSAlias) return } controller.Enqueue(cur) - metrics.CustomResourceUpdated(defaults.RadixDNSAliasKind) + metrics.CustomResourceUpdated(radix.KindRadixDNSAlias) }, DeleteFunc: func(obj interface{}) { radixDNSAlias, converted := obj.(*v1.RadixDNSAlias) @@ -87,7 +87,7 @@ func NewController(kubeClient kubernetes.Interface, if err != nil { logger.Errorf("error on RadixDNSAlias object deleted event received for %s: %v", key, err) } - metrics.CustomResourceDeleted(defaults.RadixDNSAliasKind) + metrics.CustomResourceDeleted(radix.KindRadixDNSAlias) }, }) @@ -98,7 +98,7 @@ func NewController(kubeClient kubernetes.Interface, if oldMeta.GetResourceVersion() == newMeta.GetResourceVersion() { return } - controller.HandleObject(newObj, defaults.RadixDNSAliasKind, getOwner) + controller.HandleObject(newObj, radix.KindRadixDNSAlias, getOwner) }, DeleteFunc: func(obj interface{}) { ing, converted := obj.(*networkingv1.Ingress) @@ -106,7 +106,7 @@ func NewController(kubeClient kubernetes.Interface, logger.Errorf("Ingress object cast failed during deleted event received.") return } - controller.HandleObject(ing, defaults.RadixDNSAliasKind, getOwner) + controller.HandleObject(ing, radix.KindRadixDNSAlias, getOwner) }, }) return controller diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go index e16653dc7..67c220481 100644 --- a/radix-operator/dnsalias/controller_test.go +++ b/radix-operator/dnsalias/controller_test.go @@ -5,11 +5,10 @@ import ( "testing" "github.com/equinor/radix-common/utils/pointers" - "github.com/equinor/radix-operator/pkg/apis/defaults" - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/radix" "github.com/equinor/radix-operator/pkg/apis/utils" - "github.com/equinor/radix-operator/pkg/apis/utils/labels" "github.com/equinor/radix-operator/radix-operator/common" + "github.com/equinor/radix-operator/radix-operator/config" "github.com/equinor/radix-operator/radix-operator/dnsalias" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" "github.com/stretchr/testify/suite" @@ -37,19 +36,15 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { const ( appName1 = "any-app1" appName2 = "any-app2" - aliasName = "alias-1" + aliasName = "alias-domain-1" envName1 = "env1" envName2 = "env2" componentName1 = "server1" componentName2 = "server2" + dnsZone = "test.radix.equinor.com" ) - alias := &v1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: aliasName, - Labels: labels.Merge(labels.ForApplicationName(appName1), labels.ForComponentName(componentName1))}, - Spec: v1.RadixDNSAliasSpec{ - AppName: appName1, - Environment: envName1, - Component: componentName1, - }} + config := &config.ClusterConfig{DNSZone: dnsZone} + alias := internal.BuildRadixDNSAlias(appName1, componentName1, envName1, aliasName) // Adding a RadixDNSAlias should trigger sync s.Handler.EXPECT().Sync("", aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) @@ -85,8 +80,8 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { s.WaitForNotSynced("Sync should not be called when updating RadixDNSAlias with no changes") // Add Kubernetes Job with ownerreference to RadixDNSAlias should not trigger sync - ingress := internal.BuildRadixDNSAliasIngress(alias.Spec.AppName, alias.GetName(), alias.Spec.Component, int32(8080)) - ingress.ObjectMeta.OwnerReferences = []metav1.OwnerReference{{APIVersion: defaults.RadixAPIVersion, Kind: defaults.RadixDNSAliasKind, Name: aliasName, Controller: pointers.Ptr(true)}} + ingress := internal.BuildRadixDNSAliasIngress(alias.Spec.AppName, alias.GetName(), alias.Spec.Component, int32(8080), config) + ingress.SetOwnerReferences([]metav1.OwnerReference{{APIVersion: radix.APIVersion, Kind: radix.KindRadixDNSAlias, Name: aliasName, Controller: pointers.Ptr(true)}}) namespace := utils.GetEnvironmentNamespace(alias.Spec.AppName, alias.Spec.Environment) s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) ingress, err = internal.CreateRadixDNSAliasIngress(s.KubeClient, alias.Spec.AppName, alias.Spec.Environment, ingress) diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go index 0b2a3f7b5..b3226a189 100644 --- a/radix-operator/dnsalias/handler.go +++ b/radix-operator/dnsalias/handler.go @@ -10,6 +10,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" + "github.com/equinor/radix-operator/radix-operator/config" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -29,54 +30,47 @@ const ( // Handler Handler for radix dns aliases type Handler struct { - kubeclient kubernetes.Interface - kubeutil *kube.Kube - radixclient radixclient.Interface + kubeClient kubernetes.Interface + kubeUtil *kube.Kube + radixClient radixclient.Interface hasSynced common.HasSynced + config *config.ClusterConfig } // NewHandler creates a handler for managing RadixDNSAlias resources -func NewHandler( - kubeclient kubernetes.Interface, - kubeutil *kube.Kube, - radixclient radixclient.Interface, - hasSynced common.HasSynced) Handler { +func NewHandler(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, config *config.ClusterConfig, hasSynced common.HasSynced) *Handler { - handler := Handler{ - kubeclient: kubeclient, - kubeutil: kubeutil, - radixclient: radixclient, + return &Handler{ + kubeClient: kubeclient, + kubeUtil: kubeutil, + radixClient: radixclient, + config: config, hasSynced: hasSynced, } - - return handler } // Sync is called by kubernetes after the Controller Enqueues a work-item -// and collects components and determines whether state must be reconciled. -func (t *Handler) Sync(namespace, name string, eventRecorder record.EventRecorder) error { - radixDNSAlias, err := t.radixclient.RadixV1().RadixDNSAliases().Get(context.TODO(), name, metav1.GetOptions{}) +func (h *Handler) Sync(_, name string, eventRecorder record.EventRecorder) error { + radixDNSAlias, err := h.radixClient.RadixV1().RadixDNSAliases().Get(context.Background(), name, metav1.GetOptions{}) if err != nil { - // The RadixDNSAlias resource may no longer exist, in which case we stop - // processing. if errors.IsNotFound(err) { - utilruntime.HandleError(fmt.Errorf("radix DNS alias %s in work queue no longer exists", name)) + utilruntime.HandleError(fmt.Errorf("RadixDNSAlias %s in work queue no longer exists", name)) return nil } return err } syncDNSAlias := radixDNSAlias.DeepCopy() - logger.Debugf("Sync DNS alias %s", name) + logger.Debugf("Sync RadixDNSAlias %s", name) appName := syncDNSAlias.Spec.AppName - radixApplication, err := t.radixclient.RadixV1().RadixApplications(utils.GetAppNamespace(appName)). - Get(context.TODO(), appName, metav1.GetOptions{}) + radixApplication, err := h.radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName)). + Get(context.Background(), appName, metav1.GetOptions{}) if err != nil { return err } - dnsAlias, err := dnsalias.NewDNSAlias(t.kubeclient, t.kubeutil, t.radixclient, syncDNSAlias, radixApplication, logger) + dnsAlias, err := dnsalias.NewDNSAlias(h.kubeClient, h.kubeUtil, h.radixClient, syncDNSAlias, radixApplication, logger) if err != nil { return err } @@ -86,7 +80,7 @@ func (t *Handler) Sync(namespace, name string, eventRecorder record.EventRecorde return err } - t.hasSynced(true) + h.hasSynced(true) eventRecorder.Event(dnsAlias.GetConfig(), corev1.EventTypeNormal, SuccessSynced, MessageResourceSynced) return nil } diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index 421d7523b..1fa248ba4 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -7,7 +7,11 @@ import ( "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" + "github.com/equinor/radix-operator/pkg/apis/utils/labels" + radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" + "github.com/equinor/radix-operator/radix-operator/config" + "github.com/equinor/radix-operator/radix-operator/dnsalias" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -42,44 +46,48 @@ func (s *handlerTestSuite) Test_IngressesForRadixDNSAliases() { appName = "any-app1" envDev = "dev" componentNameServer1 = "server1" - server1Anyapp1DevDns = "server1-any-app1-dev.radix.equinor.com" - port = 8080 + componentPort1 = 8080 + dnsZone1 = "test.radix.equinor.com" ) var testScenarios = []struct { name string - dnsAliases []radixv1.DNSAlias + dnsAlias radixv1.DNSAlias + dnsZone string existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec existingIngress []testIngress expectedIngress map[string]testIngress }{ { - name: "no aliases, no existing RDA, no existing ingresses, no additional radix aliases, no additional ingresses", - }, - { - name: "no aliases, no existing RDA, exist ingresses, no additional radix aliases, no additional ingresses", - existingIngress: []testIngress{{appName: appName, envName: envDev, name: componentNameServer1, host: server1Anyapp1DevDns, component: componentNameServer1, port: port}}, - expectedIngress: map[string]testIngress{componentNameServer1: {appName: appName, envName: envDev, name: componentNameServer1, host: server1Anyapp1DevDns, component: componentNameServer1, port: port}}, - }, - { - name: "multiple aliases, no existing RDA, no existing ingresses, additional radix aliases, additional ingresses", - dnsAliases: []radixv1.DNSAlias{ - {Domain: "domain1", Environment: envDev, Component: componentNameServer1}, - {Domain: "domain2", Environment: envDev, Component: componentNameServer1}, - }, + name: "new alias, no existing RDA, no existing ingresses, additional radix aliases, additional ingresses", + dnsAlias: radixv1.DNSAlias{Domain: "domain1", Environment: envDev, Component: componentNameServer1}, + dnsZone: dnsZone1, expectedIngress: map[string]testIngress{ - "server1.domain1.custom-domain": {appName: appName, envName: envDev, name: "server1.domain1.custom-domain", host: "domain1.custom-domain.radix.equinor.com", component: componentNameServer1, port: port}, - "server1.domain2.custom-domain": {appName: appName, envName: envDev, name: "server1.domain2.custom-domain", host: "domain2.custom-domain.radix.equinor.com", component: componentNameServer1, port: port}, + "server1.domain1.custom-domain": {appName: appName, envName: envDev, name: "server1.domain1.custom-domain", host: internal.GetDNSAliasHost("domain1", dnsZone1), component: componentNameServer1, port: componentPort1}, + "server1.domain2.custom-domain": {appName: appName, envName: envDev, name: "server1.domain2.custom-domain", host: internal.GetDNSAliasHost("domain2", dnsZone1), component: componentNameServer1, port: componentPort1}, }, }, } - s.SetupTest() for _, ts := range testScenarios { s.T().Run(ts.name, func(t *testing.T) { - ra := utils.ARadixApplication().WithAppName(appName).WithDNSAlias(ts.dnsAliases...).BuildRA() + s.SetupTest() + config := &config.ClusterConfig{DNSZone: ts.dnsZone} + ra := utils.ARadixApplication().WithAppName(appName). + WithEnvironment(ts.dnsAlias.Environment, "branch1"). + WithComponent(utils.NewApplicationComponentBuilder().WithName(ts.dnsAlias.Component).WithPort("http", componentPort1)).BuildRA() _, err := s.RadixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName)).Create(context.Background(), ra, metav1.CreateOptions{}) require.NoError(t, err) - require.NoError(t, registerExistingIngresses(s.KubeClient, ts.existingIngress), "create existing ingresses") + require.NoError(t, registerExistingIngresses(s.KubeClient, ts.existingIngress, config), "create existing ingresses") + require.NoError(t, registerExistingRadixDNSAliases(s.RadixClient, ts.existingRadixDNSAliases), "create existing RadixDNSAlias") + + require.NoError(t, registerExistingRadixDNSAliases(s.RadixClient, + map[string]radixv1.RadixDNSAliasSpec{ts.dnsAlias.Domain: internal.BuildRadixDNSAlias(appName, ts.dnsAlias.Component, ts.dnsAlias.Environment, ts.dnsAlias.Domain).Spec}), + "create new or updated RadixDNSAlias") + handlerSynced := false + handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, nil, func(synced bool) { handlerSynced = synced }) + err = handler.Sync("", ts.dnsAlias.Domain, s.EventRecorder) + require.NoError(s.T(), err) + require.True(s.T(), handlerSynced, "Handler should be synced") ingresses, err := s.KubeClient.NetworkingV1().Ingresses("").List(context.TODO(), metav1.ListOptions{}) require.NoError(t, err) @@ -110,9 +118,26 @@ func (s *handlerTestSuite) Test_IngressesForRadixDNSAliases() { } } -func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses []testIngress) error { +func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses []testIngress, config *config.ClusterConfig) error { for _, ing := range testIngresses { - _, err := internal.CreateRadixDNSAliasIngress(kubeClient, ing.appName, ing.envName, internal.BuildRadixDNSAliasIngress(ing.appName, ing.name, ing.component, ing.port)) + _, err := internal.CreateRadixDNSAliasIngress(kubeClient, ing.appName, ing.envName, internal.BuildRadixDNSAliasIngress(ing.appName, ing.name, ing.component, ing.port, config)) + if err != nil { + return err + } + } + return nil +} + +func registerExistingRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]radixv1.RadixDNSAliasSpec) error { + for domain, rdaSpec := range radixDNSAliasesMap { + _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.TODO(), + &radixv1.RadixDNSAlias{ + ObjectMeta: metav1.ObjectMeta{ + Name: domain, + Labels: labels.Merge(labels.ForApplicationName(rdaSpec.AppName), labels.ForComponentName(rdaSpec.Component)), + }, + Spec: rdaSpec, + }, metav1.CreateOptions{}) if err != nil { return err } diff --git a/radix-operator/dnsalias/internal/utils.go b/radix-operator/dnsalias/internal/utils.go index b5e33feff..f8229d7a3 100644 --- a/radix-operator/dnsalias/internal/utils.go +++ b/radix-operator/dnsalias/internal/utils.go @@ -5,8 +5,10 @@ import ( "fmt" "github.com/equinor/radix-operator/pkg/apis/defaults" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/labels" + "github.com/equinor/radix-operator/radix-operator/config" networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -16,18 +18,33 @@ const ( dnsAliasIngressNameTemplate = "%s.%s.custom-domain" // ..custom-domain ) +// BuildRadixDNSAlias Build a RadixDNSAlias +func BuildRadixDNSAlias(appName, componentName, envName, domain string) *radixv1.RadixDNSAlias { + return &radixv1.RadixDNSAlias{ + ObjectMeta: metav1.ObjectMeta{ + Name: domain, + Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(componentName)), + }, + Spec: radixv1.RadixDNSAliasSpec{ + AppName: appName, + Environment: envName, + Component: componentName, + }} +} + // CreateRadixDNSAliasIngress Create an Ingress for a RadixDNSAlias func CreateRadixDNSAliasIngress(kubeClient kubernetes.Interface, appName, envName string, ingress *networkingv1.Ingress) (*networkingv1.Ingress, error) { return kubeClient.NetworkingV1().Ingresses(utils.GetEnvironmentNamespace(appName, envName)).Create(context.Background(), ingress, metav1.CreateOptions{}) } // BuildRadixDNSAliasIngress Build an Ingress for a RadixDNSAlias -func BuildRadixDNSAliasIngress(appName, domain, service string, port int32) *networkingv1.Ingress { +func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, config *config.ClusterConfig) *networkingv1.Ingress { pathTypeImplementationSpecific := networkingv1.PathTypeImplementationSpecific - host := fmt.Sprintf(dnsAliasIngressNameTemplate, service, domain) + name := fmt.Sprintf(dnsAliasIngressNameTemplate, service, domain) + host := GetDNSAliasHost(domain, config.DNSZone) return &networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{ - Name: domain, + Name: name, Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(service)), }, Spec: networkingv1.IngressSpec{ @@ -52,3 +69,9 @@ func BuildRadixDNSAliasIngress(appName, domain, service string, port int32) *net }, }} } + +// GetDNSAliasHost Gets DNS alias domain host. +// Example for the domain "my-app" and the cluster "Playground": my-app.playground.radix.equinor.com +func GetDNSAliasHost(domain string, dnsZone string) string { + return fmt.Sprintf("%s.%s", domain, dnsZone) +} diff --git a/radix-operator/environment/controller.go b/radix-operator/environment/controller.go index 5514f3a43..391c117f4 100644 --- a/radix-operator/environment/controller.go +++ b/radix-operator/environment/controller.go @@ -8,6 +8,7 @@ import ( radixutils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/metrics" + "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -99,7 +100,7 @@ func NewController(client kubernetes.Interface, namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ DeleteFunc: func(obj interface{}) { // attempt to sync environment if it is the owner of this namespace - controller.HandleObject(obj, "RadixEnvironment", getOwner) + controller.HandleObject(obj, radix.KindRadixEnvironment, getOwner) }, }) @@ -107,7 +108,7 @@ func NewController(client kubernetes.Interface, rolebindingInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ DeleteFunc: func(obj interface{}) { // attempt to sync environment if it is the owner of this role-binding - controller.HandleObject(obj, "RadixEnvironment", getOwner) + controller.HandleObject(obj, radix.KindRadixEnvironment, getOwner) }, }) @@ -115,7 +116,7 @@ func NewController(client kubernetes.Interface, limitrangeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ DeleteFunc: func(obj interface{}) { // attempt to sync environment if it is the owner of this limit-range - controller.HandleObject(obj, "RadixEnvironment", getOwner) + controller.HandleObject(obj, radix.KindRadixEnvironment, getOwner) }, }) diff --git a/radix-operator/job/controller.go b/radix-operator/job/controller.go index 9f0c2342a..f1204d986 100644 --- a/radix-operator/job/controller.go +++ b/radix-operator/job/controller.go @@ -6,6 +6,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/job" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/metrics" + "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" informers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" @@ -101,7 +102,7 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac if newJob.ResourceVersion == oldJob.ResourceVersion { return } - controller.HandleObject(cur, "RadixJob", getObject) + controller.HandleObject(cur, radix.KindRadixJob, getObject) }, DeleteFunc: func(obj interface{}) { job, converted := obj.(*batchv1.Job) @@ -111,7 +112,7 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac } // If a kubernetes job gets deleted for a running job, the running radix job should // take this into account. The running job will get restarted - controller.HandleObject(job, "RadixJob", getObject) + controller.HandleObject(job, radix.KindRadixJob, getObject) }, }) @@ -135,7 +136,7 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac return } - controller.HandleObject(job, "RadixJob", getObject) + controller.HandleObject(job, radix.KindRadixJob, getObject) } }, }) diff --git a/radix-operator/main.go b/radix-operator/main.go index 5c1b91ee2..fbda39dda 100644 --- a/radix-operator/main.go +++ b/radix-operator/main.go @@ -80,7 +80,7 @@ func main() { startController(createJobController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg.PipelineJobConfig), jobControllerThreads, stop) startController(createAlertController(client, radixClient, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), alertControllerThreads, stop) startController(createBatchController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), 1, stop) - startController(createDNSAliasesController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), environmentControllerThreads, stop) + startController(createDNSAliasesController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg.ClusterConfig), environmentControllerThreads, stop) // Start informers when all controllers are running kubeInformerFactory.Start(stop) @@ -194,7 +194,7 @@ func createEnvironmentController(client kubernetes.Interface, radixClient radixc recorder) } -func createDNSAliasesController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretProviderClient.Interface) *common.Controller { +func createDNSAliasesController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretProviderClient.Interface, clusterConfig *config.ClusterConfig) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, @@ -207,6 +207,7 @@ func createDNSAliasesController(client kubernetes.Interface, radixClient radixcl client, kubeUtil, radixClient, + clusterConfig, func(syncedOk bool) {}, // Not interested in getting notifications of synced ) @@ -214,7 +215,7 @@ func createDNSAliasesController(client kubernetes.Interface, radixClient radixcl return dnsalias.NewController( client, radixClient, - &handler, + handler, kubeInformerFactory, radixInformerFactory, waitForChildrenToSync, @@ -333,6 +334,28 @@ func createBatchController(client kubernetes.Interface, radixClient radixclient. recorder) } +func createDNSAliasController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretProviderClient.Interface) *common.Controller { + kubeUtil, _ := kube.NewWithListers( + client, + radixClient, + secretProviderClient, + kubeInformerFactory, + radixInformerFactory, + ) + + handler := dnsalias.NewHandler(client, kubeUtil, radixClient, nil, func(syncedOk bool) {}) + + const waitForChildrenToSync = true + return dnsalias.NewController( + client, + radixClient, + handler, + kubeInformerFactory, + radixInformerFactory, + waitForChildrenToSync, + recorder) +} + func loadIngressConfigFromMap(kubeutil *kube.Kube) (deploymentAPI.IngressConfiguration, error) { ingressConfig := deploymentAPI.IngressConfiguration{} configMap, err := kubeutil.GetConfigMap(metav1.NamespaceDefault, ingressConfigurationMap) diff --git a/radix-operator/registration/controller.go b/radix-operator/registration/controller.go index 71c666bfd..6a6775204 100644 --- a/radix-operator/registration/controller.go +++ b/radix-operator/registration/controller.go @@ -7,6 +7,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/metrics" + "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" informers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" @@ -94,7 +95,7 @@ func NewController(client kubernetes.Interface, namespaceInformer := kubeInformerFactory.Core().V1().Namespaces() namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ DeleteFunc: func(obj interface{}) { - controller.HandleObject(obj, "RadixRegistration", getObject) + controller.HandleObject(obj, radix.KindRadixRegistration, getObject) }, }) @@ -116,7 +117,7 @@ func NewController(client kubernetes.Interface, if isGitDeployKey(newSecret) && newSecret.Namespace != "" { // Resync, as deploy key is updated. Resync is triggered on namespace, since RR not directly own the // secret - controller.HandleObject(namespace, "RadixRegistration", getObject) + controller.HandleObject(namespace, radix.KindRadixRegistration, getObject) } }, DeleteFunc: func(obj interface{}) { @@ -138,7 +139,7 @@ func NewController(client kubernetes.Interface, if isGitDeployKey(secret) && namespace.Labels[kube.RadixAppLabel] != "" { // Resync, as deploy key is deleted. Resync is triggered on namespace, since RR not directly own the // secret - controller.HandleObject(namespace, "RadixRegistration", getObject) + controller.HandleObject(namespace, radix.KindRadixRegistration, getObject) } }, }) From 97aa2a1a5274cb9e285e3d6eb6165ad7044d8378 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 26 Oct 2023 09:43:46 +0200 Subject: [PATCH 008/121] Extended RadixDNSAliases syncer --- pkg/apis/batch/status.go | 4 +- pkg/apis/dnsalias/dnsalias.go | 82 ------------------------------ pkg/apis/dnsalias/status.go | 43 ++++++++++++++++ pkg/apis/dnsalias/syncer.go | 60 ++++++++++++++++++++++ radix-operator/batch/handler.go | 8 +-- radix-operator/dnsalias/handler.go | 6 +-- 6 files changed, 112 insertions(+), 91 deletions(-) delete mode 100644 pkg/apis/dnsalias/dnsalias.go create mode 100644 pkg/apis/dnsalias/status.go create mode 100644 pkg/apis/dnsalias/syncer.go diff --git a/pkg/apis/batch/status.go b/pkg/apis/batch/status.go index 21243bb54..19c1256e3 100644 --- a/pkg/apis/batch/status.go +++ b/pkg/apis/batch/status.go @@ -86,14 +86,14 @@ func (s *syncer) syncStatus(reconcileError error) error { func (s *syncer) updateStatus(changeStatusFunc func(currStatus *radixv1.RadixBatchStatus)) error { changeStatusFunc(&s.batch.Status) - updatedJob, err := s.radixclient. + updatedRadixBatch, err := s.radixclient. RadixV1(). RadixBatches(s.batch.GetNamespace()). UpdateStatus(context.TODO(), s.batch, metav1.UpdateOptions{}) if err != nil { return err } - s.batch = updatedJob + s.batch = updatedRadixBatch return nil } diff --git a/pkg/apis/dnsalias/dnsalias.go b/pkg/apis/dnsalias/dnsalias.go deleted file mode 100644 index 682c5346c..000000000 --- a/pkg/apis/dnsalias/dnsalias.go +++ /dev/null @@ -1,82 +0,0 @@ -package dnsalias - -import ( - "context" - "fmt" - - "github.com/equinor/radix-operator/pkg/apis/kube" - radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" - "github.com/sirupsen/logrus" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/util/retry" -) - -// DNSAlias is the aggregate-root for manipulating RadixDNSAliases -type DNSAlias struct { - kubeclient kubernetes.Interface - radixclient radixclient.Interface - kubeutil *kube.Kube - radixDNSAlias *radixv1.RadixDNSAlias - appConfig *radixv1.RadixApplication - logger *logrus.Entry -} - -// NewDNSAlias is the constructor for DNSAlias -func NewDNSAlias( - kubeclient kubernetes.Interface, - kubeutil *kube.Kube, - radixclient radixclient.Interface, - config *radixv1.RadixDNSAlias, - appConfig *radixv1.RadixApplication, - logger *logrus.Entry) (DNSAlias, error) { - - return DNSAlias{ - kubeclient, - radixclient, - kubeutil, - config, - appConfig, - logger}, nil -} - -// OnSync is called by the handler when changes are applied and must be -// reconciled with current state. -func (dnsAlias *DNSAlias) OnSync(time metav1.Time) error { - - // TODO - err := dnsAlias.updateRadixDNSAliasStatus(dnsAlias.radixDNSAlias, func(currStatus *radixv1.RadixDNSAliasStatus) { - // time is parameterized for testability - currStatus.Reconciled = time - }) - if err != nil { - return fmt.Errorf("failed to update status on DNS alias %s: %v", dnsAlias.radixDNSAlias.GetName(), err) - } - dnsAlias.logger.Debugf("DNSAlias %s reconciled", dnsAlias.radixDNSAlias.GetName()) - return nil -} - -func (dnsAlias *DNSAlias) updateRadixDNSAliasStatus(rEnv *radixv1.RadixDNSAlias, changeStatusFunc func(currStatus *radixv1.RadixDNSAliasStatus)) error { - radixDNSAliasInterface := dnsAlias.radixclient.RadixV1().RadixDNSAliases() - ctx := context.Background() - return retry.RetryOnConflict(retry.DefaultRetry, func() error { - currentEnv, err := radixDNSAliasInterface.Get(ctx, rEnv.GetName(), metav1.GetOptions{}) - if err != nil { - return err - } - changeStatusFunc(¤tEnv.Status) - _, err = radixDNSAliasInterface.UpdateStatus(ctx, currentEnv, metav1.UpdateOptions{}) - if err == nil && dnsAlias.radixDNSAlias.GetName() == rEnv.GetName() { - currentEnv, err = radixDNSAliasInterface.Get(ctx, rEnv.GetName(), metav1.GetOptions{}) - if err == nil { - dnsAlias.radixDNSAlias = currentEnv - } - } - return err - }) -} - -func (dnsAlias *DNSAlias) GetConfig() *radixv1.RadixDNSAlias { - return dnsAlias.radixDNSAlias -} diff --git a/pkg/apis/dnsalias/status.go b/pkg/apis/dnsalias/status.go new file mode 100644 index 000000000..492f1fdd5 --- /dev/null +++ b/pkg/apis/dnsalias/status.go @@ -0,0 +1,43 @@ +package dnsalias + +import ( + "context" + "encoding/json" + "fmt" + "reflect" + + "github.com/equinor/radix-operator/pkg/apis/kube" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func (s *syncer) updateStatus(changeStatusFunc func(currStatus *radixv1.RadixDNSAliasStatus)) error { + changeStatusFunc(&s.radixDNSAlias.Status) + updatedRadixDNSAlias, err := s.radixClient. + RadixV1(). + RadixDNSAliases(). + UpdateStatus(context.TODO(), s.radixDNSAlias, metav1.UpdateOptions{}) + if err != nil { + return err + } + s.radixDNSAlias = updatedRadixDNSAlias + return nil +} + +func (s *syncer) restoreStatus() error { + if restoredStatus, ok := s.radixDNSAlias.Annotations[kube.RestoredStatusAnnotation]; ok && len(restoredStatus) > 0 { + if reflect.ValueOf(s.radixDNSAlias.Status).IsZero() { + var status radixv1.RadixDNSAliasStatus + + if err := json.Unmarshal([]byte(restoredStatus), &status); err != nil { + return fmt.Errorf("unable to restore status for Radix DNS alias %s from annotation: %w", s.radixDNSAlias.GetName(), err) + } + + return s.updateStatus(func(currStatus *radixv1.RadixDNSAliasStatus) { + *currStatus = status + }) + } + } + + return nil +} diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go new file mode 100644 index 000000000..ee7dda1c9 --- /dev/null +++ b/pkg/apis/dnsalias/syncer.go @@ -0,0 +1,60 @@ +package dnsalias + +import ( + "fmt" + + "github.com/equinor/radix-operator/pkg/apis/kube" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + "github.com/sirupsen/logrus" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +// DNSAlias is the aggregate-root for manipulating RadixDNSAliases +type syncer struct { + kubeClient kubernetes.Interface + radixClient radixclient.Interface + kubeUtil *kube.Kube + radixDNSAlias *radixv1.RadixDNSAlias + appConfig *radixv1.RadixApplication + logger *logrus.Entry +} + +// NewDNSAliasSyncer is the constructor for RadixDNSAlias syncer +func NewDNSAliasSyncer( + kubeClient kubernetes.Interface, + kubeUtil *kube.Kube, + radixClient radixclient.Interface, + radixDNSAlias *radixv1.RadixDNSAlias, + appConfig *radixv1.RadixApplication, + logger *logrus.Entry) (syncer, error) { + + return syncer{ + kubeClient: kubeClient, + radixClient: radixClient, + kubeUtil: kubeUtil, + radixDNSAlias: radixDNSAlias, + appConfig: appConfig, + logger: logger}, nil +} + +// OnSync is called by the handler when changes are applied and must be +// reconciled with current state. +func (s *syncer) OnSync(time metav1.Time) error { + + // TODO + err := s.updateStatus(func(currStatus *radixv1.RadixDNSAliasStatus) { + currStatus.Reconciled = time // time is parameterized for testability + }) + if err != nil { + return fmt.Errorf("failed to update status on DNS alias %s: %v", s.radixDNSAlias.GetName(), err) + } + s.logger.Debugf("RadixDNSAlias %s reconciled", s.radixDNSAlias.GetName()) + return nil +} + +// GetRadixDNSAlias Gets RadixDNSAlias under sync +func (s *syncer) GetRadixDNSAlias() *radixv1.RadixDNSAlias { + return s.radixDNSAlias +} diff --git a/radix-operator/batch/handler.go b/radix-operator/batch/handler.go index d79c4270d..5b349c91e 100644 --- a/radix-operator/batch/handler.go +++ b/radix-operator/batch/handler.go @@ -81,16 +81,16 @@ func (h *Handler) Sync(namespace, name string, eventRecorder record.EventRecorde return err } - syncRSC := radixBatch.DeepCopy() - syncer := h.syncerFactory.CreateSyncer(h.kubeclient, h.kubeutil, h.radixclient, syncRSC) + syncBatch := radixBatch.DeepCopy() + syncer := h.syncerFactory.CreateSyncer(h.kubeclient, h.kubeutil, h.radixclient, syncBatch) err = syncer.OnSync() if err != nil { - eventRecorder.Event(syncRSC, corev1.EventTypeWarning, SyncFailed, err.Error()) + eventRecorder.Event(syncBatch, corev1.EventTypeWarning, SyncFailed, err.Error()) // Put back on queue return err } - eventRecorder.Event(syncRSC, corev1.EventTypeNormal, Synced, MessageResourceSynced) + eventRecorder.Event(syncBatch, corev1.EventTypeNormal, Synced, MessageResourceSynced) return nil } diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go index b3226a189..9f2b8e38b 100644 --- a/radix-operator/dnsalias/handler.go +++ b/radix-operator/dnsalias/handler.go @@ -70,17 +70,17 @@ func (h *Handler) Sync(_, name string, eventRecorder record.EventRecorder) error return err } - dnsAlias, err := dnsalias.NewDNSAlias(h.kubeClient, h.kubeUtil, h.radixClient, syncDNSAlias, radixApplication, logger) + syncer, err := dnsalias.NewDNSAliasSyncer(h.kubeClient, h.kubeUtil, h.radixClient, syncDNSAlias, radixApplication, logger) if err != nil { return err } - err = dnsAlias.OnSync(metav1.NewTime(time.Now().UTC())) + err = syncer.OnSync(metav1.NewTime(time.Now().UTC())) if err != nil { return err } h.hasSynced(true) - eventRecorder.Event(dnsAlias.GetConfig(), corev1.EventTypeNormal, SuccessSynced, MessageResourceSynced) + eventRecorder.Event(syncer.GetRadixDNSAlias(), corev1.EventTypeNormal, SuccessSynced, MessageResourceSynced) return nil } From d8303b59b8f167f33e34bd3c001fd6cfc9e4daea Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 26 Oct 2023 16:40:11 +0200 Subject: [PATCH 009/121] Extended RadixDNSAliases syncer and handler, unit-tests, added cluster config --- Makefile | 4 +- pkg/apis/batch/kubejob.go | 30 ++-- pkg/apis/batch/service.go | 8 +- pkg/apis/batch/status.go | 22 +-- pkg/apis/batch/syncer.go | 46 ++--- pkg/apis/batch/syncer_test.go | 2 +- pkg/apis/dnsalias/internal/utils.go | 62 +++++++ pkg/apis/dnsalias/status.go | 63 ++++--- pkg/apis/dnsalias/syncer.go | 59 ++++--- pkg/apis/dnsalias/syncer_mock.go | 48 ++++++ pkg/apis/dnsalias/syncer_test.go | 158 ++++++++++++++++++ pkg/apis/kube/kube.go | 1 + pkg/apis/test/utils.go | 15 ++ radix-operator/batch/handler.go | 35 ++-- radix-operator/batch/handler_test.go | 5 +- .../batch/internal}/syncerfactory.go | 23 +-- .../batch/internal}/syncerfactory_mock.go | 17 +- radix-operator/dnsalias/controller.go | 91 +++++----- radix-operator/dnsalias/handler.go | 73 ++++---- radix-operator/dnsalias/handler_test.go | 84 ++-------- .../dnsalias/internal/syncerfactory.go | 27 +++ .../dnsalias/internal/syncerfactory_mock.go | 53 ++++++ radix-operator/main.go | 3 +- 23 files changed, 644 insertions(+), 285 deletions(-) create mode 100644 pkg/apis/dnsalias/internal/utils.go create mode 100644 pkg/apis/dnsalias/syncer_mock.go create mode 100644 pkg/apis/dnsalias/syncer_test.go rename {pkg/apis/batch => radix-operator/batch/internal}/syncerfactory.go (53%) rename {pkg/apis/batch => radix-operator/batch/internal}/syncerfactory_mock.go (80%) create mode 100644 radix-operator/dnsalias/internal/syncerfactory.go create mode 100644 radix-operator/dnsalias/internal/syncerfactory_mock.go diff --git a/Makefile b/Makefile index c76ef732b..e804e8738 100644 --- a/Makefile +++ b/Makefile @@ -95,7 +95,9 @@ mocks: mockgen -source ./pkg/apis/alert/alert.go -destination ./pkg/apis/alert/alert_mock.go -package alert mockgen -source ./pkg/apis/alert/alertfactory.go -destination ./pkg/apis/alert/alertfactory_mock.go -package alert mockgen -source ./pkg/apis/batch/syncer.go -destination ./pkg/apis/batch/syncer_mock.go -package batch - mockgen -source ./pkg/apis/batch/syncerfactory.go -destination ./pkg/apis/batch/syncerfactory_mock.go -package batch + mockgen -source ./radix-operator/batch/internal/syncerfactory.go -destination ./radix-operator/batch/internal/syncerfactory_mock.go -package internal + mockgen -source ./pkg/apis/dnsalias/syncer.go -destination ./pkg/apis/dnsalias/syncer_mock.go -package dnsalias + mockgen -source ./radix-operator/dnsalias/internal/syncerfactory.go -destination ./radix-operator/dnsalias/internal/syncerfactory_mock.go -package internal mockgen -source ./radix-operator/common/handler.go -destination ./radix-operator/common/handler_mock.go -package common .PHONY: build-pipeline diff --git a/pkg/apis/batch/kubejob.go b/pkg/apis/batch/kubejob.go index f4029bb12..d944338b5 100644 --- a/pkg/apis/batch/kubejob.go +++ b/pkg/apis/batch/kubejob.go @@ -39,7 +39,7 @@ func (s *syncer) reconcileKubeJob(batchJob *radixv1.RadixBatchJob, rd *radixv1.R if err != nil { return err } - if !jobNeedToBeRestarted && (isBatchJobDone(s.batch, batchJob.Name) || + if !jobNeedToBeRestarted && (isBatchJobDone(s.radixBatch, batchJob.Name) || slice.Any(existingJobs, func(job *batchv1.Job) bool { return isResourceLabeledWithBatchJobName(batchJob.Name, job) })) { return nil } @@ -52,7 +52,7 @@ func (s *syncer) reconcileKubeJob(batchJob *radixv1.RadixBatchJob, rd *radixv1.R return err } return retry.RetryOnConflict(retry.DefaultRetry, func() error { - _, err = s.kubeclient.BatchV1().Jobs(s.batch.GetNamespace()).Create(context.TODO(), job, metav1.CreateOptions{}) + _, err = s.kubeClient.BatchV1().Jobs(s.radixBatch.GetNamespace()).Create(context.TODO(), job, metav1.CreateOptions{}) return err }) } @@ -61,24 +61,24 @@ func (s *syncer) validatePayloadSecretReference(batchJob *radixv1.RadixBatchJob, if batchJob.PayloadSecretRef == nil { return nil } - payloadSecret, err := s.kubeclient.CoreV1().Secrets(s.batch.GetNamespace()).Get(context.Background(), batchJob.PayloadSecretRef.Name, metav1.GetOptions{}) + payloadSecret, err := s.kubeClient.CoreV1().Secrets(s.radixBatch.GetNamespace()).Get(context.Background(), batchJob.PayloadSecretRef.Name, metav1.GetOptions{}) if err != nil { return err } if !radixlabels.GetRadixBatchDescendantsSelector(jobComponent.GetName()).Matches(labels.Set(payloadSecret.GetLabels())) { - return fmt.Errorf("secret %s, referenced in the job %s of the batch %s is not valid payload secret", batchJob.PayloadSecretRef.Name, batchJob.Name, s.batch.GetName()) + return fmt.Errorf("secret %s, referenced in the job %s of the batch %s is not valid payload secret", batchJob.PayloadSecretRef.Name, batchJob.Name, s.radixBatch.GetName()) } if payloadSecret.Data == nil || len(payloadSecret.Data) == 0 { - return fmt.Errorf("payload secret %s, in the job %s of the batch %s is empty", batchJob.PayloadSecretRef.Name, batchJob.Name, s.batch.GetName()) + return fmt.Errorf("payload secret %s, in the job %s of the batch %s is empty", batchJob.PayloadSecretRef.Name, batchJob.Name, s.radixBatch.GetName()) } if _, ok := payloadSecret.Data[batchJob.PayloadSecretRef.Key]; !ok { - return fmt.Errorf("payload secret %s, in the job %s of the batch %s has no entry %s for the job", batchJob.PayloadSecretRef.Name, batchJob.Name, s.batch.GetName(), batchJob.PayloadSecretRef.Key) + return fmt.Errorf("payload secret %s, in the job %s of the batch %s has no entry %s for the job", batchJob.PayloadSecretRef.Name, batchJob.Name, s.radixBatch.GetName(), batchJob.PayloadSecretRef.Key) } return nil } func (s *syncer) handleJobToRestart(batchJob *radixv1.RadixBatchJob, existingJobs []*batchv1.Job) (bool, error) { - jobStatusIdx := slice.FindIndex(s.batch.Status.JobStatuses, func(jobStatus radixv1.RadixBatchJobStatus) bool { + jobStatusIdx := slice.FindIndex(s.radixBatch.Status.JobStatuses, func(jobStatus radixv1.RadixBatchJobStatus) bool { return jobStatus.Name == batchJob.Name }) @@ -99,23 +99,23 @@ func (s *syncer) handleJobToRestart(batchJob *radixv1.RadixBatchJob, existingJob Restart: jobRestartTimestamp, } if jobStatusIdx >= 0 { - s.batch.Status.JobStatuses[jobStatusIdx] = jobStatus + s.radixBatch.Status.JobStatuses[jobStatusIdx] = jobStatus return true, nil } - s.batch.Status.JobStatuses = append(s.batch.Status.JobStatuses, jobStatus) + s.radixBatch.Status.JobStatuses = append(s.radixBatch.Status.JobStatuses, jobStatus) return true, nil } func (s *syncer) getJobRestartTimestamps(batchJob *radixv1.RadixBatchJob, jobStatusIdx int) (string, string) { if jobStatusIdx >= 0 { - return batchJob.Restart, s.batch.Status.JobStatuses[jobStatusIdx].Restart + return batchJob.Restart, s.radixBatch.Status.JobStatuses[jobStatusIdx].Restart } return batchJob.Restart, "" } func (s *syncer) deleteJobs(jobsToDelete []*batchv1.Job) error { for _, jobToDelete := range jobsToDelete { - err := s.kubeclient.BatchV1().Jobs(jobToDelete.GetNamespace()).Delete(context.Background(), jobToDelete.GetName(), metav1.DeleteOptions{PropagationPolicy: pointers.Ptr(metav1.DeletePropagationBackground)}) + err := s.kubeClient.BatchV1().Jobs(jobToDelete.GetNamespace()).Delete(context.Background(), jobToDelete.GetName(), metav1.DeleteOptions{PropagationPolicy: pointers.Ptr(metav1.DeletePropagationBackground)}) if err != nil && !errors.IsNotFound(err) { return err } @@ -136,7 +136,7 @@ func (s *syncer) buildJob(batchJob *radixv1.RadixBatchJob, jobComponent *radixv1 return nil, err } - kubeJobName := getKubeJobName(s.batch.GetName(), batchJob.Name) + kubeJobName := getKubeJobName(s.radixBatch.GetName(), batchJob.Name) containers, err := s.getContainers(rd, jobComponent, batchJob, kubeJobName) if err != nil { return nil, err @@ -166,7 +166,7 @@ func (s *syncer) buildJob(batchJob *radixv1.RadixBatchJob, jobComponent *radixv1 ObjectMeta: metav1.ObjectMeta{ Name: kubeJobName, Labels: jobLabels, - OwnerReferences: ownerReference(s.batch), + OwnerReferences: ownerReference(s.radixBatch), }, Spec: batchv1.JobSpec{ BackoffLimit: backoffLimit, @@ -195,7 +195,7 @@ func (s *syncer) buildJob(batchJob *radixv1.RadixBatchJob, jobComponent *radixv1 } func (s *syncer) getVolumes(namespace, environment string, batchJob *radixv1.RadixBatchJob, radixJobComponent *radixv1.RadixDeployJobComponent, radixDeploymentName string) ([]corev1.Volume, error) { - volumes, err := deployment.GetVolumes(s.kubeclient, s.kubeutil, namespace, environment, radixJobComponent, radixDeploymentName) + volumes, err := deployment.GetVolumes(s.kubeClient, s.kubeUtil, namespace, environment, radixJobComponent, radixDeploymentName) if err != nil { return nil, err } @@ -258,7 +258,7 @@ func getJobImage(jobComponent *radixv1.RadixDeployJobComponent, batchJob *radixv } func (s *syncer) getContainerEnvironmentVariables(rd *radixv1.RadixDeployment, jobComponent *radixv1.RadixDeployJobComponent, kubeJobName string) ([]corev1.EnvVar, error) { - environmentVariables, err := deployment.GetEnvironmentVariablesForRadixOperator(s.kubeutil, rd.Spec.AppName, rd, jobComponent) + environmentVariables, err := deployment.GetEnvironmentVariablesForRadixOperator(s.kubeUtil, rd.Spec.AppName, rd, jobComponent) if err != nil { return nil, err } diff --git a/pkg/apis/batch/service.go b/pkg/apis/batch/service.go index 93a5b1a65..50270c556 100644 --- a/pkg/apis/batch/service.go +++ b/pkg/apis/batch/service.go @@ -14,7 +14,7 @@ func (s *syncer) reconcileService(batchJob *radixv1.RadixBatchJob, rd *radixv1.R return nil } - if isBatchJobStopRequested(batchJob) || isBatchJobDone(s.batch, batchJob.Name) { + if isBatchJobStopRequested(batchJob) || isBatchJobDone(s.radixBatch, batchJob.Name) { return nil } @@ -23,18 +23,18 @@ func (s *syncer) reconcileService(batchJob *radixv1.RadixBatchJob, rd *radixv1.R } service := s.buildService(batchJob.Name, rd.Spec.AppName, jobComponent.GetPorts()) - return s.kubeutil.ApplyService(s.batch.GetNamespace(), service) + return s.kubeUtil.ApplyService(s.radixBatch.GetNamespace(), service) } func (s *syncer) buildService(batchJobName, appName string, componentPorts []radixv1.ComponentPort) *corev1.Service { - serviceName := getKubeServiceName(s.batch.GetName(), batchJobName) + serviceName := getKubeServiceName(s.radixBatch.GetName(), batchJobName) labels := s.batchJobIdentifierLabel(batchJobName, appName) selector := s.batchJobIdentifierLabel(batchJobName, appName) service := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: serviceName, Labels: labels, - OwnerReferences: ownerReference(s.batch), + OwnerReferences: ownerReference(s.radixBatch), }, Spec: corev1.ServiceSpec{ Type: corev1.ServiceTypeClusterIP, diff --git a/pkg/apis/batch/status.go b/pkg/apis/batch/status.go index 19c1256e3..9bc848a41 100644 --- a/pkg/apis/batch/status.go +++ b/pkg/apis/batch/status.go @@ -85,15 +85,15 @@ func (s *syncer) syncStatus(reconcileError error) error { } func (s *syncer) updateStatus(changeStatusFunc func(currStatus *radixv1.RadixBatchStatus)) error { - changeStatusFunc(&s.batch.Status) - updatedRadixBatch, err := s.radixclient. + changeStatusFunc(&s.radixBatch.Status) + updatedRadixBatch, err := s.radixClient. RadixV1(). - RadixBatches(s.batch.GetNamespace()). - UpdateStatus(context.TODO(), s.batch, metav1.UpdateOptions{}) + RadixBatches(s.radixBatch.GetNamespace()). + UpdateStatus(context.TODO(), s.radixBatch, metav1.UpdateOptions{}) if err != nil { return err } - s.batch = updatedRadixBatch + s.radixBatch = updatedRadixBatch return nil } @@ -106,12 +106,12 @@ func isJobStatusCondition(conditionType batchv1.JobConditionType) func(batchv1.J func (s *syncer) buildJobStatuses() ([]radixv1.RadixBatchJobStatus, error) { var jobStatuses []radixv1.RadixBatchJobStatus - jobs, err := s.kubeutil.ListJobsWithSelector(s.batch.GetNamespace(), s.batchIdentifierLabel().String()) + jobs, err := s.kubeUtil.ListJobsWithSelector(s.radixBatch.GetNamespace(), s.batchIdentifierLabel().String()) if err != nil { return nil, err } - for _, batchJob := range s.batch.Spec.Jobs { + for _, batchJob := range s.radixBatch.Spec.Jobs { jobStatuses = append(jobStatuses, s.buildBatchJobStatus(&batchJob, jobs)) } @@ -119,7 +119,7 @@ func (s *syncer) buildJobStatuses() ([]radixv1.RadixBatchJobStatus, error) { } func (s *syncer) buildBatchJobStatus(batchJob *radixv1.RadixBatchJob, allJobs []*batchv1.Job) radixv1.RadixBatchJobStatus { - currentStatus := slice.FindAll(s.batch.Status.JobStatuses, func(jobStatus radixv1.RadixBatchJobStatus) bool { + currentStatus := slice.FindAll(s.radixBatch.Status.JobStatuses, func(jobStatus radixv1.RadixBatchJobStatus) bool { return jobStatus.Name == batchJob.Name }) if len(currentStatus) > 0 && isBatchJobPhaseDone(currentStatus[0].Phase) { @@ -174,12 +174,12 @@ func (s *syncer) buildBatchJobStatus(batchJob *radixv1.RadixBatchJob, allJobs [] } func (s *syncer) restoreStatus() error { - if restoredStatus, ok := s.batch.Annotations[kube.RestoredStatusAnnotation]; ok && len(restoredStatus) > 0 { - if reflect.ValueOf(s.batch.Status).IsZero() { + if restoredStatus, ok := s.radixBatch.Annotations[kube.RestoredStatusAnnotation]; ok && len(restoredStatus) > 0 { + if reflect.ValueOf(s.radixBatch.Status).IsZero() { var status radixv1.RadixBatchStatus if err := json.Unmarshal([]byte(restoredStatus), &status); err != nil { - return fmt.Errorf("unable to restore status for batch %s.%s from annotation: %w", s.batch.GetNamespace(), s.batch.GetName(), err) + return fmt.Errorf("unable to restore status for batch %s.%s from annotation: %w", s.radixBatch.GetNamespace(), s.radixBatch.GetName(), err) } return s.updateStatus(func(currStatus *radixv1.RadixBatchStatus) { diff --git a/pkg/apis/batch/syncer.go b/pkg/apis/batch/syncer.go index 62780dd76..02f263347 100644 --- a/pkg/apis/batch/syncer.go +++ b/pkg/apis/batch/syncer.go @@ -10,35 +10,39 @@ import ( "k8s.io/client-go/kubernetes" ) +// Syncer of RadixBatch type Syncer interface { + // OnSync Syncs RadixBatch OnSync() error } +// NewSyncer Constructor os RadixBatches Syncer func NewSyncer(kubeclient kubernetes.Interface, - kubeutil *kube.Kube, - radixclient radixclient.Interface, - batch *radixv1.RadixBatch) Syncer { + kubeUtil *kube.Kube, + radixClient radixclient.Interface, + radixBatch *radixv1.RadixBatch) Syncer { return &syncer{ - kubeclient: kubeclient, - kubeutil: kubeutil, - radixclient: radixclient, - batch: batch, + kubeClient: kubeclient, + kubeUtil: kubeUtil, + radixClient: radixClient, + radixBatch: radixBatch, } } type syncer struct { - kubeclient kubernetes.Interface - kubeutil *kube.Kube - radixclient radixclient.Interface - batch *radixv1.RadixBatch + kubeClient kubernetes.Interface + kubeUtil *kube.Kube + radixClient radixclient.Interface + radixBatch *radixv1.RadixBatch } +// OnSync Syncs RadixBatches func (s *syncer) OnSync() error { if err := s.restoreStatus(); err != nil { return err } - if isBatchDone(s.batch) { + if isBatchDone(s.radixBatch) { return nil } @@ -53,17 +57,17 @@ func (s *syncer) reconcile() error { return err } - existingJobs, err := s.kubeutil.ListJobsWithSelector(s.batch.GetNamespace(), s.batchIdentifierLabel().String()) + existingJobs, err := s.kubeUtil.ListJobsWithSelector(s.radixBatch.GetNamespace(), s.batchIdentifierLabel().String()) if err != nil { return err } - existingServices, err := s.kubeutil.ListServicesWithSelector(s.batch.GetNamespace(), s.batchIdentifierLabel().String()) + existingServices, err := s.kubeUtil.ListServicesWithSelector(s.radixBatch.GetNamespace(), s.batchIdentifierLabel().String()) if err != nil { return err } - for i, batchJob := range s.batch.Spec.Jobs { + for i, batchJob := range s.radixBatch.Spec.Jobs { if err := s.reconcileService(&batchJob, rd, jobComponent, existingServices); err != nil { return err } @@ -86,33 +90,33 @@ func (s *syncer) getRadixDeploymentAndJobComponent() (*radixv1.RadixDeployment, rd, err := s.getRadixDeployment() if err != nil { if errors.IsNotFound(err) { - return nil, nil, newReconcileRadixDeploymentNotFoundError(s.batch.Spec.RadixDeploymentJobRef.Name) + return nil, nil, newReconcileRadixDeploymentNotFoundError(s.radixBatch.Spec.RadixDeploymentJobRef.Name) } return nil, nil, err } - jobComponent := rd.GetJobComponentByName(s.batch.Spec.RadixDeploymentJobRef.Job) + jobComponent := rd.GetJobComponentByName(s.radixBatch.Spec.RadixDeploymentJobRef.Job) if jobComponent == nil { - return nil, nil, newReconcileRadixDeploymentJobSpecNotFoundError(rd.GetName(), s.batch.Spec.RadixDeploymentJobRef.Job) + return nil, nil, newReconcileRadixDeploymentJobSpecNotFoundError(rd.GetName(), s.radixBatch.Spec.RadixDeploymentJobRef.Job) } return rd, jobComponent, nil } func (s *syncer) getRadixDeployment() (*radixv1.RadixDeployment, error) { - return s.kubeutil.GetRadixDeployment(s.batch.GetNamespace(), s.batch.Spec.RadixDeploymentJobRef.Name) + return s.kubeUtil.GetRadixDeployment(s.radixBatch.GetNamespace(), s.radixBatch.Spec.RadixDeploymentJobRef.Name) } func (s *syncer) batchIdentifierLabel() labels.Set { return radixlabels.Merge( - radixlabels.ForBatchName(s.batch.GetName()), + radixlabels.ForBatchName(s.radixBatch.GetName()), ) } func (s *syncer) batchJobIdentifierLabel(batchJobName, appName string) labels.Set { return radixlabels.Merge( radixlabels.ForApplicationName(appName), - radixlabels.ForComponentName(s.batch.Spec.RadixDeploymentJobRef.Job), + radixlabels.ForComponentName(s.radixBatch.Spec.RadixDeploymentJobRef.Job), s.batchIdentifierLabel(), radixlabels.ForJobScheduleJobType(), radixlabels.ForBatchJobName(batchJobName), diff --git a/pkg/apis/batch/syncer_test.go b/pkg/apis/batch/syncer_test.go index 03ff54435..447165599 100644 --- a/pkg/apis/batch/syncer_test.go +++ b/pkg/apis/batch/syncer_test.go @@ -47,7 +47,7 @@ func TestSyncerTestSuite(t *testing.T) { } func (s *syncerTestSuite) createSyncer(forJob *radixv1.RadixBatch) Syncer { - return &syncer{kubeclient: s.kubeClient, kubeutil: s.kubeUtil, radixclient: s.radixClient, batch: forJob} + return &syncer{kubeClient: s.kubeClient, kubeUtil: s.kubeUtil, radixClient: s.radixClient, radixBatch: forJob} } func (s *syncerTestSuite) applyRadixDeploymentEnvVarsConfigMaps(kubeUtil *kube.Kube, rd *radixv1.RadixDeployment) map[string]*corev1.ConfigMap { diff --git a/pkg/apis/dnsalias/internal/utils.go b/pkg/apis/dnsalias/internal/utils.go new file mode 100644 index 000000000..f8ad4e4c9 --- /dev/null +++ b/pkg/apis/dnsalias/internal/utils.go @@ -0,0 +1,62 @@ +package internal + +import ( + "context" + "fmt" + + "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/utils" + "github.com/equinor/radix-operator/pkg/apis/utils/labels" + "github.com/equinor/radix-operator/radix-operator/config" + networkingv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +const ( + dnsAliasIngressNameTemplate = "%s.%s.custom-domain" // ..custom-domain +) + +// CreateRadixDNSAliasIngress Create an Ingress for a RadixDNSAlias +func CreateRadixDNSAliasIngress(kubeClient kubernetes.Interface, appName, envName string, ingress *networkingv1.Ingress) (*networkingv1.Ingress, error) { + return kubeClient.NetworkingV1().Ingresses(utils.GetEnvironmentNamespace(appName, envName)).Create(context.Background(), ingress, metav1.CreateOptions{}) +} + +// BuildRadixDNSAliasIngress Build an Ingress for a RadixDNSAlias +func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, config *config.ClusterConfig) *networkingv1.Ingress { + pathTypeImplementationSpecific := networkingv1.PathTypeImplementationSpecific + name := fmt.Sprintf(dnsAliasIngressNameTemplate, service, domain) + host := GetDNSAliasHost(domain, config.DNSZone) + return &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(service)), + }, + Spec: networkingv1.IngressSpec{ + TLS: []networkingv1.IngressTLS{ + { + Hosts: []string{host}, + SecretName: defaults.TLSSecretName, + }, + }, + Rules: []networkingv1.IngressRule{ + { + Host: host, + IngressRuleValue: networkingv1.IngressRuleValue{ + HTTP: &networkingv1.HTTPIngressRuleValue{Paths: []networkingv1.HTTPIngressPath{ + {Path: "/", PathType: &pathTypeImplementationSpecific, Backend: networkingv1.IngressBackend{ + Service: &networkingv1.IngressServiceBackend{Name: service, Port: networkingv1.ServiceBackendPort{ + Number: port, + }}, + }}}, + }}, + }, + }, + }} +} + +// GetDNSAliasHost Gets DNS alias domain host. +// Example for the domain "my-app" and the cluster "Playground": my-app.playground.radix.equinor.com +func GetDNSAliasHost(domain string, dnsZone string) string { + return fmt.Sprintf("%s.%s", domain, dnsZone) +} diff --git a/pkg/apis/dnsalias/status.go b/pkg/apis/dnsalias/status.go index 492f1fdd5..e125e3986 100644 --- a/pkg/apis/dnsalias/status.go +++ b/pkg/apis/dnsalias/status.go @@ -9,35 +9,52 @@ import ( "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/util/retry" ) -func (s *syncer) updateStatus(changeStatusFunc func(currStatus *radixv1.RadixDNSAliasStatus)) error { - changeStatusFunc(&s.radixDNSAlias.Status) - updatedRadixDNSAlias, err := s.radixClient. - RadixV1(). - RadixDNSAliases(). - UpdateStatus(context.TODO(), s.radixDNSAlias, metav1.UpdateOptions{}) +func (s *syncer) restoreStatus() error { + restoredStatus, ok := s.radixDNSAlias.Annotations[kube.RestoredStatusAnnotation] + if !ok || len(restoredStatus) == 0 { + return nil + } + if !reflect.ValueOf(s.radixDNSAlias.Status).IsZero() { + return nil + } + var status radixv1.RadixDNSAliasStatus + if err := json.Unmarshal([]byte(restoredStatus), &status); err != nil { + return fmt.Errorf("unable to deserealise status from annotation: %w", err) + } + return s.updateStatus(func(currStatus *radixv1.RadixDNSAliasStatus) { + *currStatus = status + }) +} + +func (s *syncer) syncStatus() error { + syncCompleteTime := metav1.Now() + err := s.updateStatus(func(currStatus *radixv1.RadixDNSAliasStatus) { + currStatus.Reconciled = syncCompleteTime + }) if err != nil { - return err + return fmt.Errorf("failed to sync status: %v", err) } - s.radixDNSAlias = updatedRadixDNSAlias return nil } -func (s *syncer) restoreStatus() error { - if restoredStatus, ok := s.radixDNSAlias.Annotations[kube.RestoredStatusAnnotation]; ok && len(restoredStatus) > 0 { - if reflect.ValueOf(s.radixDNSAlias.Status).IsZero() { - var status radixv1.RadixDNSAliasStatus - - if err := json.Unmarshal([]byte(restoredStatus), &status); err != nil { - return fmt.Errorf("unable to restore status for Radix DNS alias %s from annotation: %w", s.radixDNSAlias.GetName(), err) - } - - return s.updateStatus(func(currStatus *radixv1.RadixDNSAliasStatus) { - *currStatus = status - }) +func (s *syncer) updateStatus(changeStatusFunc func(currStatus *radixv1.RadixDNSAliasStatus)) error { + return retry.RetryOnConflict(retry.DefaultRetry, func() error { + radixDNSAlias, err := s.radixClient.RadixV1().RadixDNSAliases().Get(context.Background(), s.radixDNSAlias.GetName(), metav1.GetOptions{}) + if err != nil { + return err } - } - - return nil + changeStatusFunc(&radixDNSAlias.Status) + updatedRadixDNSAlias, err := s.radixClient. + RadixV1(). + RadixDNSAliases(). + UpdateStatus(context.TODO(), radixDNSAlias, metav1.UpdateOptions{}) + if err != nil { + return err + } + s.radixDNSAlias = updatedRadixDNSAlias + return err + }) } diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index ee7dda1c9..a7724b9fc 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -1,60 +1,65 @@ package dnsalias import ( + "context" "fmt" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" - "github.com/sirupsen/logrus" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" ) +// Syncer of RadixDNSAliases +type Syncer interface { + // OnSync Syncs RadixDNSAliases + OnSync() error +} + // DNSAlias is the aggregate-root for manipulating RadixDNSAliases type syncer struct { kubeClient kubernetes.Interface radixClient radixclient.Interface kubeUtil *kube.Kube radixDNSAlias *radixv1.RadixDNSAlias - appConfig *radixv1.RadixApplication - logger *logrus.Entry } -// NewDNSAliasSyncer is the constructor for RadixDNSAlias syncer -func NewDNSAliasSyncer( - kubeClient kubernetes.Interface, - kubeUtil *kube.Kube, - radixClient radixclient.Interface, - radixDNSAlias *radixv1.RadixDNSAlias, - appConfig *radixv1.RadixApplication, - logger *logrus.Entry) (syncer, error) { - - return syncer{ +// NewSyncer is the constructor for RadixDNSAlias syncer +func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { + return &syncer{ kubeClient: kubeClient, radixClient: radixClient, kubeUtil: kubeUtil, radixDNSAlias: radixDNSAlias, - appConfig: appConfig, - logger: logger}, nil + } } // OnSync is called by the handler when changes are applied and must be // reconciled with current state. -func (s *syncer) OnSync(time metav1.Time) error { - - // TODO - err := s.updateStatus(func(currStatus *radixv1.RadixDNSAliasStatus) { - currStatus.Reconciled = time // time is parameterized for testability - }) - if err != nil { +func (s *syncer) OnSync() error { + if err := s.restoreStatus(); err != nil { return fmt.Errorf("failed to update status on DNS alias %s: %v", s.radixDNSAlias.GetName(), err) } - s.logger.Debugf("RadixDNSAlias %s reconciled", s.radixDNSAlias.GetName()) - return nil + if err := s.syncAlias(); err != nil { + return err + } + return s.syncStatus() } -// GetRadixDNSAlias Gets RadixDNSAlias under sync -func (s *syncer) GetRadixDNSAlias() *radixv1.RadixDNSAlias { - return s.radixDNSAlias +func (s *syncer) syncAlias() error { + appName := s.radixDNSAlias.Spec.AppName + radixApplication, err := s.radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName)). + Get(context.Background(), appName, metav1.GetOptions{}) + if err != nil { + if errors.IsNotFound(err) { + return fmt.Errorf("not found the Radix application %s for the DNS alias %s", appName, s.radixDNSAlias.GetName()) + } + return err + } + // TODO + fmt.Println(radixApplication) + return nil } diff --git a/pkg/apis/dnsalias/syncer_mock.go b/pkg/apis/dnsalias/syncer_mock.go new file mode 100644 index 000000000..e87e105bf --- /dev/null +++ b/pkg/apis/dnsalias/syncer_mock.go @@ -0,0 +1,48 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./pkg/apis/dnsalias/syncer.go + +// Package dnsalias is a generated GoMock package. +package dnsalias + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" +) + +// MockSyncer is a mock of Syncer interface. +type MockSyncer struct { + ctrl *gomock.Controller + recorder *MockSyncerMockRecorder +} + +// MockSyncerMockRecorder is the mock recorder for MockSyncer. +type MockSyncerMockRecorder struct { + mock *MockSyncer +} + +// NewMockSyncer creates a new mock instance. +func NewMockSyncer(ctrl *gomock.Controller) *MockSyncer { + mock := &MockSyncer{ctrl: ctrl} + mock.recorder = &MockSyncerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockSyncer) EXPECT() *MockSyncerMockRecorder { + return m.recorder +} + +// OnSync mocks base method. +func (m *MockSyncer) OnSync() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "OnSync") + ret0, _ := ret[0].(error) + return ret0 +} + +// OnSync indicates an expected call of OnSync. +func (mr *MockSyncerMockRecorder) OnSync() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OnSync", reflect.TypeOf((*MockSyncer)(nil).OnSync)) +} diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go new file mode 100644 index 000000000..92133eee2 --- /dev/null +++ b/pkg/apis/dnsalias/syncer_test.go @@ -0,0 +1,158 @@ +package dnsalias_test + +import ( + "context" + "testing" + + "github.com/equinor/radix-operator/pkg/apis/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" + "github.com/equinor/radix-operator/pkg/apis/kube" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/test" + "github.com/equinor/radix-operator/pkg/apis/utils" + radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" + "github.com/equinor/radix-operator/radix-operator/config" + prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + kubefake "k8s.io/client-go/kubernetes/fake" + secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake" +) + +type syncerTestSuite struct { + suite.Suite + kubeClient *kubefake.Clientset + radixClient *radixfake.Clientset + kubeUtil *kube.Kube + promClient *prometheusfake.Clientset +} + +func TestSyncerTestSuite(t *testing.T) { + suite.Run(t, new(syncerTestSuite)) +} + +func (s *syncerTestSuite) SetupTest() { + s.kubeClient = kubefake.NewSimpleClientset() + s.radixClient = radixfake.NewSimpleClientset() + s.promClient = prometheusfake.NewSimpleClientset() + s.kubeUtil, _ = kube.New(s.kubeClient, s.radixClient, secretproviderfake.NewSimpleClientset()) +} + +func (s *syncerTestSuite) createSyncer(radixDNSAlias *radixv1.RadixDNSAlias) dnsalias.Syncer { + return dnsalias.NewSyncer(s.kubeClient, s.kubeUtil, s.radixClient, radixDNSAlias) +} + +type testIngress struct { + appName string + envName string + name string + host string + component string + port int32 +} + +type scenario struct { + name string + expectedError string + missingRadixApplication bool + dnsAlias radixv1.DNSAlias + dnsZone string + existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec + existingIngress []testIngress + expectedIngress map[string]testIngress +} + +func (s *syncerTestSuite) Test_syncer_OnSync() { + const ( + appName1 = "app1" + envName1 = "env1" + component1 = "component1" + domain1 = "domain1" + domain2 = "domain2" + portHttp = "http" + port8080 = 8080 + dnsZone1 = "test.radix.equinor.com" + ) + scenarios := []scenario{ + { + name: "no radix application", + missingRadixApplication: true, + expectedError: "not found the Radix application app1 for the DNS alias domain1", + dnsAlias: radixv1.DNSAlias{Domain: "domain1", Environment: envName1, Component: component1}, + }, + { + name: "created an ingress", + dnsAlias: radixv1.DNSAlias{Domain: domain1, Environment: envName1, Component: component1}, + dnsZone: dnsZone1, + expectedIngress: map[string]testIngress{ + "server1.domain1.custom-domain": {appName: appName1, envName: envName1, name: "component1.domain1.custom-domain", host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + }, + }, + // { + // name: "created additional ingress", + // dnsAlias: radixv1.DNSAlias{Domain: domain1, Environment: envName1, Component: component1}, + // dnsZone: dnsZone1, + // expectedIngress: map[string]testIngress{ + // "server1.domain1.custom-domain": {appName: appName1, envName: envName1, name: "server1.domain1.custom-domain", host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + // "server1.domain2.custom-domain": {appName: appName1, envName: envName1, name: "server1.domain2.custom-domain", host: internal.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, + // }, + // }, + } + for _, ts := range scenarios { + s.T().Run(ts.name, func(t *testing.T) { + // s.SetupTest() + if !ts.missingRadixApplication { + ra := utils.NewRadixApplicationBuilder().WithAppName(appName1).WithEnvironment(envName1, "master"). + WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portHttp, port8080).WithPublicPort(portHttp)).BuildRA() + _, err := s.radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName1)).Create(context.Background(), ra, metav1.CreateOptions{}) + s.NoError(err) + } + config := &config.ClusterConfig{DNSZone: ts.dnsZone} + radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Domain}, + Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component}} + require.NoError(t, registerExistingIngresses(s.kubeClient, ts.existingIngress, config), "create existing ingresses") + syncer := s.createSyncer(radixDNSAlias) + err := syncer.OnSync() + test.AssertError(s.T(), ts.expectedError, err) + + ingresses, err := s.kubeClient.NetworkingV1().Ingresses("").List(context.Background(), metav1.ListOptions{}) + require.NoError(t, err) + + // assert ingresses + if ts.expectedIngress == nil { + assert.Len(t, ingresses.Items, 0, "not expected ingresses") + } else { + assert.Len(t, ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") + if len(ingresses.Items) == len(ts.expectedIngress) { + for _, ingress := range ingresses.Items { + if expectedIngress, ok := ts.expectedIngress[ingress.Name]; ok { + require.Len(t, ingress.Spec.Rules, 1, "rules count") + assert.Equal(t, expectedIngress.appName, ingress.GetLabels()[kube.RadixAppLabel], "app name") + assert.Equal(t, utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ingress.GetNamespace(), "namespace") + assert.Equal(t, expectedIngress.component, ingress.GetLabels()[kube.RadixComponentLabel], "component name") + assert.Equal(t, expectedIngress.host, ingress.Spec.Rules[0].Host, "rule host") + assert.Equal(t, "/", ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") + assert.Equal(t, expectedIngress.component, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") + assert.Equal(t, expectedIngress.port, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") + } else { + assert.Failf(t, "found not expected ingress %s: appName %s, host %s, service %s, port %d", ingress.GetName(), ingress.GetLabels()[kube.RadixAppLabel], ingress.Spec.Rules[0].Host, ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, &ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port) + } + } + } + } + }) + } +} + +func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses []testIngress, config *config.ClusterConfig) error { + for _, ing := range testIngresses { + _, err := internal.CreateRadixDNSAliasIngress(kubeClient, ing.appName, ing.envName, internal.BuildRadixDNSAliasIngress(ing.appName, ing.name, ing.component, ing.port, config)) + if err != nil { + return err + } + } + return nil +} diff --git a/pkg/apis/kube/kube.go b/pkg/apis/kube/kube.go index 05b4672d5..e4b8c594e 100644 --- a/pkg/apis/kube/kube.go +++ b/pkg/apis/kube/kube.go @@ -24,6 +24,7 @@ const ( RadixDeploymentNameAnnotation = "radix-deployment-name" RadixDeploymentPromotedFromDeploymentAnnotation = "radix.equinor.com/radix-deployment-promoted-from-deployment" RadixDeploymentPromotedFromEnvironmentAnnotation = "radix.equinor.com/radix-deployment-promoted-from-environment" + ManagedByRadixDNSAliasIngressAnnotation = "radix.equinor.com/managed-by-radix-dns-alias" // See https://github.com/equinor/radix-velero-plugin/blob/master/velero-plugins/deployment/restore.go RestoredStatusAnnotation = "equinor.com/velero-restored-status" diff --git a/pkg/apis/test/utils.go b/pkg/apis/test/utils.go index bf2514257..74a399875 100644 --- a/pkg/apis/test/utils.go +++ b/pkg/apis/test/utils.go @@ -3,6 +3,7 @@ package test import ( "context" "os" + "testing" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -10,6 +11,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" log "github.com/sirupsen/logrus" + "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -382,3 +384,16 @@ func GetAzureKeyVaultTypeSecrets(secrets *corev1.SecretList) *corev1.SecretList } return &corev1.SecretList{Items: azureKeyVaultSecrets} } + +func AssertError(t *testing.T, expectedError string, err error) { + switch { + case len(expectedError) > 0 && err == nil: + t.Errorf("missing expected OnSync() error %s", expectedError) + return + case len(expectedError) == 0 && err != nil: + t.Errorf("unexpected OnSync() error = %v", err) + return + case len(expectedError) > 0 && err != nil: + require.Equal(t, expectedError, err.Error()) + } +} diff --git a/radix-operator/batch/handler.go b/radix-operator/batch/handler.go index 5b349c91e..c402a6026 100644 --- a/radix-operator/batch/handler.go +++ b/radix-operator/batch/handler.go @@ -7,6 +7,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/batch" "github.com/equinor/radix-operator/pkg/apis/kube" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + "github.com/equinor/radix-operator/radix-operator/batch/internal" "github.com/equinor/radix-operator/radix-operator/common" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -28,48 +29,48 @@ const ( MessageResourceSynced = "RadixBatch synced successfully" ) -var _ common.Handler = &Handler{} +var _ common.Handler = &handler{} -// HandlerConfigOption defines a configuration function used for additional configuration of Handler -type HandlerConfigOption func(*Handler) +// HandlerConfigOption defines a configuration function used for additional configuration of handler +type HandlerConfigOption func(*handler) -// WithSyncerFactory configures the SyncerFactory for the Handler -func WithSyncerFactory(factory batch.SyncerFactory) HandlerConfigOption { - return func(h *Handler) { +// WithSyncerFactory configures the SyncerFactory for the handler +func WithSyncerFactory(factory internal.SyncerFactory) HandlerConfigOption { + return func(h *handler) { h.syncerFactory = factory } } -type Handler struct { +type handler struct { kubeclient kubernetes.Interface radixclient radixclient.Interface kubeutil *kube.Kube - syncerFactory batch.SyncerFactory + syncerFactory internal.SyncerFactory } func NewHandler( kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, - options ...HandlerConfigOption) *Handler { + options ...HandlerConfigOption) common.Handler { - handler := &Handler{ + h := &handler{ kubeclient: kubeclient, kubeutil: kubeutil, radixclient: radixclient, } - configureDefaultSyncerFactory(handler) + configureDefaultSyncerFactory(h) for _, option := range options { - option(handler) + option(h) } - return handler + return h } -func (h *Handler) Sync(namespace, name string, eventRecorder record.EventRecorder) error { - radixBatch, err := h.radixclient.RadixV1().RadixBatches(namespace).Get(context.TODO(), name, v1.GetOptions{}) +func (h *handler) Sync(namespace, name string, eventRecorder record.EventRecorder) error { + radixBatch, err := h.radixclient.RadixV1().RadixBatches(namespace).Get(context.Background(), name, v1.GetOptions{}) if err != nil { // The resource may no longer exist, in which case we stop // processing. @@ -94,6 +95,6 @@ func (h *Handler) Sync(namespace, name string, eventRecorder record.EventRecorde return nil } -func configureDefaultSyncerFactory(h *Handler) { - WithSyncerFactory(batch.SyncerFactoryFunc(batch.NewSyncer))(h) +func configureDefaultSyncerFactory(h *handler) { + WithSyncerFactory(internal.SyncerFactoryFunc(batch.NewSyncer))(h) } diff --git a/radix-operator/batch/handler_test.go b/radix-operator/batch/handler_test.go index 29f7a2e77..f655e4e4a 100644 --- a/radix-operator/batch/handler_test.go +++ b/radix-operator/batch/handler_test.go @@ -9,6 +9,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" fakeradix "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" + "github.com/equinor/radix-operator/radix-operator/batch/internal" "github.com/golang/mock/gomock" prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" "github.com/stretchr/testify/suite" @@ -27,7 +28,7 @@ type handlerTestSuite struct { kubeUtil *kube.Kube eventRecorder *record.FakeRecorder mockCtrl *gomock.Controller - syncerFactory *batch.MockSyncerFactory + syncerFactory *internal.MockSyncerFactory syncer *batch.MockSyncer } @@ -43,7 +44,7 @@ func (s *handlerTestSuite) SetupTest() { s.promClient = prometheusfake.NewSimpleClientset() s.eventRecorder = &record.FakeRecorder{} s.mockCtrl = gomock.NewController(s.T()) - s.syncerFactory = batch.NewMockSyncerFactory(s.mockCtrl) + s.syncerFactory = internal.NewMockSyncerFactory(s.mockCtrl) s.syncer = batch.NewMockSyncer(s.mockCtrl) } diff --git a/pkg/apis/batch/syncerfactory.go b/radix-operator/batch/internal/syncerfactory.go similarity index 53% rename from pkg/apis/batch/syncerfactory.go rename to radix-operator/batch/internal/syncerfactory.go index 1959239da..3d407e3af 100644 --- a/pkg/apis/batch/syncerfactory.go +++ b/radix-operator/batch/internal/syncerfactory.go @@ -1,35 +1,36 @@ -package batch +package internal import ( + "github.com/equinor/radix-operator/pkg/apis/batch" "github.com/equinor/radix-operator/pkg/apis/kube" - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "k8s.io/client-go/kubernetes" ) -// SyncerFactory defines a factory to create a DeploymentSyncer +// SyncerFactory defines a factory to create a RadixBatches Syncer type SyncerFactory interface { CreateSyncer( kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, - batch *v1.RadixBatch) Syncer + radixBatch *radixv1.RadixBatch) batch.Syncer } -// AlertSyncerFactoryFunc is an adapter that can be used to convert -// a function into a DeploymentSyncerFactory +// SyncerFactoryFunc is an adapter that can be used to convert +// a function into a SyncerFactory type SyncerFactoryFunc func( kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, - batch *v1.RadixBatch, -) Syncer + radixBatch *radixv1.RadixBatch, +) batch.Syncer func (f SyncerFactoryFunc) CreateSyncer( kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, - batch *v1.RadixBatch, -) Syncer { - return f(kubeclient, kubeutil, radixclient, batch) + radixBatch *radixv1.RadixBatch, +) batch.Syncer { + return f(kubeclient, kubeutil, radixclient, radixBatch) } diff --git a/pkg/apis/batch/syncerfactory_mock.go b/radix-operator/batch/internal/syncerfactory_mock.go similarity index 80% rename from pkg/apis/batch/syncerfactory_mock.go rename to radix-operator/batch/internal/syncerfactory_mock.go index bff88969f..bf5377438 100644 --- a/pkg/apis/batch/syncerfactory_mock.go +++ b/radix-operator/batch/internal/syncerfactory_mock.go @@ -1,12 +1,13 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: ./pkg/apis/batch/syncerfactory.go +// Source: ./radix-operator/batch/internal/syncerfactory.go -// Package batch is a generated GoMock package. -package batch +// Package internal is a generated GoMock package. +package internal import ( reflect "reflect" + batch "github.com/equinor/radix-operator/pkg/apis/batch" kube "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" versioned "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -38,15 +39,15 @@ func (m *MockSyncerFactory) EXPECT() *MockSyncerFactoryMockRecorder { } // CreateSyncer mocks base method. -func (m *MockSyncerFactory) CreateSyncer(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient versioned.Interface, batch *v1.RadixBatch) Syncer { +func (m *MockSyncerFactory) CreateSyncer(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient versioned.Interface, radixBatch *v1.RadixBatch) batch.Syncer { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateSyncer", kubeclient, kubeutil, radixclient, batch) - ret0, _ := ret[0].(Syncer) + ret := m.ctrl.Call(m, "CreateSyncer", kubeclient, kubeutil, radixclient, radixBatch) + ret0, _ := ret[0].(batch.Syncer) return ret0 } // CreateSyncer indicates an expected call of CreateSyncer. -func (mr *MockSyncerFactoryMockRecorder) CreateSyncer(kubeclient, kubeutil, radixclient, batch interface{}) *gomock.Call { +func (mr *MockSyncerFactoryMockRecorder) CreateSyncer(kubeclient, kubeutil, radixclient, radixBatch interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSyncer", reflect.TypeOf((*MockSyncerFactory)(nil).CreateSyncer), kubeclient, kubeutil, radixclient, batch) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSyncer", reflect.TypeOf((*MockSyncerFactory)(nil).CreateSyncer), kubeclient, kubeutil, radixclient, radixBatch) } diff --git a/radix-operator/dnsalias/controller.go b/radix-operator/dnsalias/controller.go index ea3e0b1b5..20d38caf0 100644 --- a/radix-operator/dnsalias/controller.go +++ b/radix-operator/dnsalias/controller.go @@ -4,6 +4,7 @@ import ( "context" "reflect" + "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/metrics" "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -61,29 +62,29 @@ func NewController(kubeClient kubernetes.Interface, dnsAliasInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { + alias := cur.(*v1.RadixDNSAlias) + logger.Debugf("added RadixDNSAlias %s. Do nothing", alias.GetName()) controller.Enqueue(cur) metrics.CustomResourceAdded(radix.KindRadixDNSAlias) }, UpdateFunc: func(old, cur interface{}) { - newRDA := cur.(*v1.RadixDNSAlias) - oldRDA := old.(*v1.RadixDNSAlias) - - if deepEqual(oldRDA, newRDA) { - logger.Debugf("RadixDNSAlias object is equal to old for %s. Do nothing", newRDA.GetName()) + newAlias := cur.(*v1.RadixDNSAlias) + oldAlias := old.(*v1.RadixDNSAlias) + if deepEqual(oldAlias, newAlias) { + logger.Debugf("RadixDNSAlias object is equal to old for %s. Do nothing", newAlias.GetName()) metrics.CustomResourceUpdatedButSkipped(radix.KindRadixDNSAlias) return } - controller.Enqueue(cur) metrics.CustomResourceUpdated(radix.KindRadixDNSAlias) }, DeleteFunc: func(obj interface{}) { - radixDNSAlias, converted := obj.(*v1.RadixDNSAlias) + alias, converted := obj.(*v1.RadixDNSAlias) if !converted { logger.Errorf("RadixDNSAlias object cast failed during deleted event received.") return } - key, err := cache.MetaNamespaceKeyFunc(radixDNSAlias) + key, err := cache.MetaNamespaceKeyFunc(alias) if err != nil { logger.Errorf("error on RadixDNSAlias object deleted event received for %s: %v", key, err) } @@ -93,12 +94,14 @@ func NewController(kubeClient kubernetes.Interface, ingressInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: func(oldObj, newObj interface{}) { - oldMeta := oldObj.(metav1.Object) - newMeta := newObj.(metav1.Object) - if oldMeta.GetResourceVersion() == newMeta.GetResourceVersion() { + oldIng := oldObj.(metav1.Object) + newIng := newObj.(metav1.Object) + if oldIng.GetResourceVersion() == newIng.GetResourceVersion() { return } - controller.HandleObject(newObj, radix.KindRadixDNSAlias, getOwner) + if radixDNSAliasName, managedByRadixDNSAlias := newIng.GetAnnotations()[kube.ManagedByRadixDNSAliasIngressAnnotation]; managedByRadixDNSAlias && len(radixDNSAliasName) > 0 { + controller.HandleObject(newObj, radix.KindRadixDNSAlias, getOwner) + } }, DeleteFunc: func(obj interface{}) { ing, converted := obj.(*networkingv1.Ingress) @@ -106,46 +109,46 @@ func NewController(kubeClient kubernetes.Interface, logger.Errorf("Ingress object cast failed during deleted event received.") return } - controller.HandleObject(ing, radix.KindRadixDNSAlias, getOwner) + radixDNSAliasName, managedByRadixDNSAlias := ing.GetAnnotations()[kube.ManagedByRadixDNSAliasIngressAnnotation] + if !managedByRadixDNSAlias || len(radixDNSAliasName) == 0 { + return + } + controller.Enqueue(radixDNSAliasName) // validate if ingress was deleted manually, but it should be restored }, }) return controller } func deepEqual(old, new *v1.RadixDNSAlias) bool { - if !reflect.DeepEqual(new.Spec, old.Spec) || - !reflect.DeepEqual(new.ObjectMeta.Labels, old.ObjectMeta.Labels) || - !reflect.DeepEqual(new.ObjectMeta.Annotations, old.ObjectMeta.Annotations) { - return false - } - - return true + return reflect.DeepEqual(new.Spec, old.Spec) && + reflect.DeepEqual(new.ObjectMeta.Labels, old.ObjectMeta.Labels) && + reflect.DeepEqual(new.ObjectMeta.Annotations, old.ObjectMeta.Annotations) } func getOwner(radixClient radixclient.Interface, _, name string) (interface{}, error) { - return radixClient.RadixV1().RadixDNSAliases().Get(context.TODO(), name, metav1.GetOptions{}) -} - -func getAddedOrDroppedDNSAliasDomains(oldRa *v1.RadixApplication, newRa *v1.RadixApplication) []string { - var dnsAliasDomains []string - dnsAliasDomains = append(dnsAliasDomains, getMissingDNSAliasDomains(oldRa.Spec.DNSAlias, newRa.Spec.DNSAlias)...) - dnsAliasDomains = append(dnsAliasDomains, getMissingDNSAliasDomains(newRa.Spec.DNSAlias, oldRa.Spec.DNSAlias)...) - return dnsAliasDomains + return radixClient.RadixV1().RadixDNSAliases().Get(context.Background(), name, metav1.GetOptions{}) } -// getMissingDNSAliasDomains returns dnsAlias domains that exists in source list but not in target list -func getMissingDNSAliasDomains(source []v1.DNSAlias, target []v1.DNSAlias) []string { - droppedDomains := make([]string, 0) - for _, oldDNSAlias := range source { - dropped := true - for _, newDnsAlias := range target { - if oldDNSAlias.Domain == newDnsAlias.Domain { - dropped = false - } - } - if dropped { - droppedDomains = append(droppedDomains, oldDNSAlias.Domain) - } - } - return droppedDomains -} +// func getAddedOrDroppedDNSAliasDomains(oldRa *v1.RadixApplication, newRa *v1.RadixApplication) []string { +// var dnsAliasDomains []string +// dnsAliasDomains = append(dnsAliasDomains, getMissingDNSAliasDomains(oldRa.Spec.DNSAlias, newRa.Spec.DNSAlias)...) +// dnsAliasDomains = append(dnsAliasDomains, getMissingDNSAliasDomains(newRa.Spec.DNSAlias, oldRa.Spec.DNSAlias)...) +// return dnsAliasDomains +// } +// +// // getMissingDNSAliasDomains returns dnsAlias domains that exists in source list but not in target list +// func getMissingDNSAliasDomains(source []v1.DNSAlias, target []v1.DNSAlias) []string { +// droppedDomains := make([]string, 0) +// for _, oldDNSAlias := range source { +// dropped := true +// for _, newDnsAlias := range target { +// if oldDNSAlias.Domain == newDnsAlias.Domain { +// dropped = false +// } +// } +// if dropped { +// droppedDomains = append(droppedDomains, oldDNSAlias.Domain) +// } +// } +// return droppedDomains +// } diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go index 9f2b8e38b..67f2802a9 100644 --- a/radix-operator/dnsalias/handler.go +++ b/radix-operator/dnsalias/handler.go @@ -3,14 +3,12 @@ package dnsalias import ( "context" "fmt" - "time" "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" - "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" - "github.com/equinor/radix-operator/radix-operator/config" + "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -29,28 +27,46 @@ const ( ) // Handler Handler for radix dns aliases -type Handler struct { - kubeClient kubernetes.Interface - kubeUtil *kube.Kube - radixClient radixclient.Interface - hasSynced common.HasSynced - config *config.ClusterConfig +type handler struct { + kubeClient kubernetes.Interface + kubeUtil *kube.Kube + radixClient radixclient.Interface + syncerFactory internal.SyncerFactory + hasSynced common.HasSynced } // NewHandler creates a handler for managing RadixDNSAlias resources -func NewHandler(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, config *config.ClusterConfig, hasSynced common.HasSynced) *Handler { - - return &Handler{ - kubeClient: kubeclient, - kubeUtil: kubeutil, - radixClient: radixclient, - config: config, +func NewHandler( + kubeClient kubernetes.Interface, + kubeUtil *kube.Kube, + radixClient radixclient.Interface, + hasSynced common.HasSynced, + options ...HandlerConfigOption) common.Handler { + h := &handler{ + kubeClient: kubeClient, + kubeUtil: kubeUtil, + radixClient: radixClient, hasSynced: hasSynced, } + configureDefaultSyncerFactory(h) + for _, option := range options { + option(h) + } + return h +} + +// HandlerConfigOption defines a configuration function used for additional configuration of handler +type HandlerConfigOption func(*handler) + +// WithSyncerFactory configures the SyncerFactory for the handler +func WithSyncerFactory(factory internal.SyncerFactory) HandlerConfigOption { + return func(h *handler) { + h.syncerFactory = factory + } } // Sync is called by kubernetes after the Controller Enqueues a work-item -func (h *Handler) Sync(_, name string, eventRecorder record.EventRecorder) error { +func (h *handler) Sync(_, name string, eventRecorder record.EventRecorder) error { radixDNSAlias, err := h.radixClient.RadixV1().RadixDNSAliases().Get(context.Background(), name, metav1.GetOptions{}) if err != nil { if errors.IsNotFound(err) { @@ -60,27 +76,20 @@ func (h *Handler) Sync(_, name string, eventRecorder record.EventRecorder) error return err } - syncDNSAlias := radixDNSAlias.DeepCopy() + syncingAlias := radixDNSAlias.DeepCopy() logger.Debugf("Sync RadixDNSAlias %s", name) - appName := syncDNSAlias.Spec.AppName - radixApplication, err := h.radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName)). - Get(context.Background(), appName, metav1.GetOptions{}) - if err != nil { - return err - } - - syncer, err := dnsalias.NewDNSAliasSyncer(h.kubeClient, h.kubeUtil, h.radixClient, syncDNSAlias, radixApplication, logger) - if err != nil { - return err - } - - err = syncer.OnSync(metav1.NewTime(time.Now().UTC())) + syncer := h.syncerFactory.CreateSyncer(h.kubeClient, h.kubeUtil, h.radixClient, syncingAlias) + err = syncer.OnSync() if err != nil { return err } h.hasSynced(true) - eventRecorder.Event(syncer.GetRadixDNSAlias(), corev1.EventTypeNormal, SuccessSynced, MessageResourceSynced) + eventRecorder.Event(syncingAlias, corev1.EventTypeNormal, SuccessSynced, MessageResourceSynced) return nil } + +func configureDefaultSyncerFactory(h *handler) { + WithSyncerFactory(internal.SyncerFactoryFunc(dnsalias.NewSyncer))(h) +} diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index 1fa248ba4..6647c6b4d 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -4,24 +4,29 @@ import ( "context" "testing" - "github.com/equinor/radix-operator/pkg/apis/kube" + dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" - "github.com/equinor/radix-operator/radix-operator/config" "github.com/equinor/radix-operator/radix-operator/dnsalias" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" ) type handlerTestSuite struct { common.ControllerTestSuite + syncerFactory *internal.MockSyncerFactory + syncer *dnsaliasapi.MockSyncer +} + +func (s *handlerTestSuite) SetupTest() { + s.ControllerTestSuite.SetupTest() + s.syncerFactory = internal.NewMockSyncerFactory(s.MockCtrl) + s.syncer = dnsaliasapi.NewMockSyncer(s.MockCtrl) } func TestHandlerSuite(t *testing.T) { @@ -32,102 +37,49 @@ func (s *handlerTestSuite) TearDownTest() { s.MockCtrl.Finish() } -type testIngress struct { - appName string - envName string - name string - host string - component string - port int32 -} - func (s *handlerTestSuite) Test_IngressesForRadixDNSAliases() { const ( - appName = "any-app1" - envDev = "dev" - componentNameServer1 = "server1" - componentPort1 = 8080 - dnsZone1 = "test.radix.equinor.com" + appName = "any-app1" + env1 = "env1" + componentPort1 = 8080 + component1 = "component1" ) var testScenarios = []struct { name string dnsAlias radixv1.DNSAlias - dnsZone string existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec - existingIngress []testIngress - expectedIngress map[string]testIngress }{ { name: "new alias, no existing RDA, no existing ingresses, additional radix aliases, additional ingresses", - dnsAlias: radixv1.DNSAlias{Domain: "domain1", Environment: envDev, Component: componentNameServer1}, - dnsZone: dnsZone1, - expectedIngress: map[string]testIngress{ - "server1.domain1.custom-domain": {appName: appName, envName: envDev, name: "server1.domain1.custom-domain", host: internal.GetDNSAliasHost("domain1", dnsZone1), component: componentNameServer1, port: componentPort1}, - "server1.domain2.custom-domain": {appName: appName, envName: envDev, name: "server1.domain2.custom-domain", host: internal.GetDNSAliasHost("domain2", dnsZone1), component: componentNameServer1, port: componentPort1}, - }, + dnsAlias: radixv1.DNSAlias{Domain: "domain1", Environment: env1, Component: component1}, }, } for _, ts := range testScenarios { s.T().Run(ts.name, func(t *testing.T) { - s.SetupTest() - config := &config.ClusterConfig{DNSZone: ts.dnsZone} + // s.SetupTest() ra := utils.ARadixApplication().WithAppName(appName). WithEnvironment(ts.dnsAlias.Environment, "branch1"). WithComponent(utils.NewApplicationComponentBuilder().WithName(ts.dnsAlias.Component).WithPort("http", componentPort1)).BuildRA() _, err := s.RadixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName)).Create(context.Background(), ra, metav1.CreateOptions{}) require.NoError(t, err) - require.NoError(t, registerExistingIngresses(s.KubeClient, ts.existingIngress, config), "create existing ingresses") require.NoError(t, registerExistingRadixDNSAliases(s.RadixClient, ts.existingRadixDNSAliases), "create existing RadixDNSAlias") + // TODO require.NoError(t, registerExistingRadixDNSAliases(s.RadixClient, map[string]radixv1.RadixDNSAliasSpec{ts.dnsAlias.Domain: internal.BuildRadixDNSAlias(appName, ts.dnsAlias.Component, ts.dnsAlias.Environment, ts.dnsAlias.Domain).Spec}), "create new or updated RadixDNSAlias") handlerSynced := false - handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, nil, func(synced bool) { handlerSynced = synced }) + handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, + func(synced bool) { handlerSynced = synced }, dnsalias.WithSyncerFactory(s.syncerFactory)) err = handler.Sync("", ts.dnsAlias.Domain, s.EventRecorder) require.NoError(s.T(), err) require.True(s.T(), handlerSynced, "Handler should be synced") - ingresses, err := s.KubeClient.NetworkingV1().Ingresses("").List(context.TODO(), metav1.ListOptions{}) - require.NoError(t, err) - - // assert ingresses - if ts.expectedIngress == nil { - assert.Len(t, ingresses.Items, 0, "not expected ingresses") - } else { - assert.Len(t, ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") - if len(ingresses.Items) == len(ts.expectedIngress) { - for _, ingress := range ingresses.Items { - if expectedIngress, ok := ts.expectedIngress[ingress.Name]; ok { - require.Len(t, ingress.Spec.Rules, 1, "rules count") - assert.Equal(t, expectedIngress.appName, ingress.GetLabels()[kube.RadixAppLabel], "app name") - assert.Equal(t, utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ingress.GetNamespace(), "namespace") - assert.Equal(t, expectedIngress.component, ingress.GetLabels()[kube.RadixComponentLabel], "component name") - assert.Equal(t, expectedIngress.host, ingress.Spec.Rules[0].Host, "rule host") - assert.Equal(t, "/", ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") - assert.Equal(t, expectedIngress.component, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") - assert.Equal(t, expectedIngress.port, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") - } else { - assert.Failf(t, "found not expected ingress %s: appName %s, host %s, service %s, port %d", ingress.GetName(), ingress.GetLabels()[kube.RadixAppLabel], ingress.Spec.Rules[0].Host, ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, &ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port) - } - } - } - } }) } } -func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses []testIngress, config *config.ClusterConfig) error { - for _, ing := range testIngresses { - _, err := internal.CreateRadixDNSAliasIngress(kubeClient, ing.appName, ing.envName, internal.BuildRadixDNSAliasIngress(ing.appName, ing.name, ing.component, ing.port, config)) - if err != nil { - return err - } - } - return nil -} - func registerExistingRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]radixv1.RadixDNSAliasSpec) error { for domain, rdaSpec := range radixDNSAliasesMap { _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.TODO(), diff --git a/radix-operator/dnsalias/internal/syncerfactory.go b/radix-operator/dnsalias/internal/syncerfactory.go new file mode 100644 index 000000000..f9b36fe17 --- /dev/null +++ b/radix-operator/dnsalias/internal/syncerfactory.go @@ -0,0 +1,27 @@ +package internal + +import ( + dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/kube" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + "k8s.io/client-go/kubernetes" +) + +// SyncerFactory defines a factory to create a DNS alias Syncer +type SyncerFactory interface { + CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer +} + +// SyncerFactoryFunc is an adapter that can be used to convert +// a function into a SyncerFactory +type SyncerFactoryFunc func( + kubeClient kubernetes.Interface, + kubeUtil *kube.Kube, + radixClient radixclient.Interface, + radixDNSAlias *radixv1.RadixDNSAlias, +) dnsaliasapi.Syncer + +func (f SyncerFactoryFunc) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer { + return f(kubeClient, kubeUtil, radixClient, radixDNSAlias) +} diff --git a/radix-operator/dnsalias/internal/syncerfactory_mock.go b/radix-operator/dnsalias/internal/syncerfactory_mock.go new file mode 100644 index 000000000..d5af9f815 --- /dev/null +++ b/radix-operator/dnsalias/internal/syncerfactory_mock.go @@ -0,0 +1,53 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./radix-operator/dnsalias/internal/syncerfactory.go + +// Package internal is a generated GoMock package. +package internal + +import ( + reflect "reflect" + + dnsalias "github.com/equinor/radix-operator/pkg/apis/dnsalias" + kube "github.com/equinor/radix-operator/pkg/apis/kube" + v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + versioned "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + gomock "github.com/golang/mock/gomock" + kubernetes "k8s.io/client-go/kubernetes" +) + +// MockSyncerFactory is a mock of SyncerFactory interface. +type MockSyncerFactory struct { + ctrl *gomock.Controller + recorder *MockSyncerFactoryMockRecorder +} + +// MockSyncerFactoryMockRecorder is the mock recorder for MockSyncerFactory. +type MockSyncerFactoryMockRecorder struct { + mock *MockSyncerFactory +} + +// NewMockSyncerFactory creates a new mock instance. +func NewMockSyncerFactory(ctrl *gomock.Controller) *MockSyncerFactory { + mock := &MockSyncerFactory{ctrl: ctrl} + mock.recorder = &MockSyncerFactoryMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockSyncerFactory) EXPECT() *MockSyncerFactoryMockRecorder { + return m.recorder +} + +// CreateSyncer mocks base method. +func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, radixDNSAlias *v1.RadixDNSAlias) dnsalias.Syncer { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateSyncer", kubeClient, kubeUtil, radixClient, radixDNSAlias) + ret0, _ := ret[0].(dnsalias.Syncer) + return ret0 +} + +// CreateSyncer indicates an expected call of CreateSyncer. +func (mr *MockSyncerFactoryMockRecorder) CreateSyncer(kubeClient, kubeUtil, radixClient, radixDNSAlias interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSyncer", reflect.TypeOf((*MockSyncerFactory)(nil).CreateSyncer), kubeClient, kubeUtil, radixClient, radixDNSAlias) +} diff --git a/radix-operator/main.go b/radix-operator/main.go index fbda39dda..4c2e8fb87 100644 --- a/radix-operator/main.go +++ b/radix-operator/main.go @@ -207,7 +207,6 @@ func createDNSAliasesController(client kubernetes.Interface, radixClient radixcl client, kubeUtil, radixClient, - clusterConfig, func(syncedOk bool) {}, // Not interested in getting notifications of synced ) @@ -343,7 +342,7 @@ func createDNSAliasController(client kubernetes.Interface, radixClient radixclie radixInformerFactory, ) - handler := dnsalias.NewHandler(client, kubeUtil, radixClient, nil, func(syncedOk bool) {}) + handler := dnsalias.NewHandler(client, kubeUtil, radixClient, func(syncedOk bool) {}) const waitForChildrenToSync = true return dnsalias.NewController( From 9fafa2468caf9d3ccea92c575c6a2ccf25902864 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 27 Oct 2023 16:33:41 +0200 Subject: [PATCH 010/121] Added config to syncers, added ingresses --- .../internal/{utils.go => ingress.go} | 22 ++-- pkg/apis/dnsalias/internal/ownerreference.go | 19 ++++ pkg/apis/dnsalias/syncer.go | 54 +++++++++- pkg/apis/dnsalias/syncer_test.go | 102 ++++++++++-------- radix-operator/dnsalias/handler.go | 14 ++- radix-operator/dnsalias/handler_test.go | 6 +- .../dnsalias/internal/syncerfactory.go | 9 +- .../dnsalias/internal/syncerfactory_mock.go | 9 +- radix-operator/main.go | 23 +--- 9 files changed, 168 insertions(+), 90 deletions(-) rename pkg/apis/dnsalias/internal/{utils.go => ingress.go} (77%) create mode 100644 pkg/apis/dnsalias/internal/ownerreference.go diff --git a/pkg/apis/dnsalias/internal/utils.go b/pkg/apis/dnsalias/internal/ingress.go similarity index 77% rename from pkg/apis/dnsalias/internal/utils.go rename to pkg/apis/dnsalias/internal/ingress.go index f8ad4e4c9..18357a070 100644 --- a/pkg/apis/dnsalias/internal/utils.go +++ b/pkg/apis/dnsalias/internal/ingress.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/equinor/radix-operator/pkg/apis/defaults" + v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/labels" "github.com/equinor/radix-operator/radix-operator/config" @@ -13,23 +14,19 @@ import ( "k8s.io/client-go/kubernetes" ) -const ( - dnsAliasIngressNameTemplate = "%s.%s.custom-domain" // ..custom-domain -) - // CreateRadixDNSAliasIngress Create an Ingress for a RadixDNSAlias func CreateRadixDNSAliasIngress(kubeClient kubernetes.Interface, appName, envName string, ingress *networkingv1.Ingress) (*networkingv1.Ingress, error) { return kubeClient.NetworkingV1().Ingresses(utils.GetEnvironmentNamespace(appName, envName)).Create(context.Background(), ingress, metav1.CreateOptions{}) } // BuildRadixDNSAliasIngress Build an Ingress for a RadixDNSAlias -func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, config *config.ClusterConfig) *networkingv1.Ingress { +func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, owner *v1.RadixDNSAlias, config *config.ClusterConfig) *networkingv1.Ingress { pathTypeImplementationSpecific := networkingv1.PathTypeImplementationSpecific - name := fmt.Sprintf(dnsAliasIngressNameTemplate, service, domain) + ingressName := GetDNSAliasIngressName(service, domain) host := GetDNSAliasHost(domain, config.DNSZone) - return &networkingv1.Ingress{ + ingress := networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{ - Name: name, + Name: ingressName, Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(service)), }, Spec: networkingv1.IngressSpec{ @@ -53,6 +50,15 @@ func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, conf }, }, }} + if owner != nil { + ingress.SetOwnerReferences([]metav1.OwnerReference{GetOwnerReference(owner)}) + } + return &ingress +} + +// GetDNSAliasIngressName Gets name of the ingress for the custom DNS alias +func GetDNSAliasIngressName(service string, domain string) string { + return fmt.Sprintf("%s.%s.custom-domain", service, domain) } // GetDNSAliasHost Gets DNS alias domain host. diff --git a/pkg/apis/dnsalias/internal/ownerreference.go b/pkg/apis/dnsalias/internal/ownerreference.go new file mode 100644 index 000000000..d5388b9e4 --- /dev/null +++ b/pkg/apis/dnsalias/internal/ownerreference.go @@ -0,0 +1,19 @@ +package internal + +import ( + "github.com/equinor/radix-common/utils/pointers" + "github.com/equinor/radix-operator/pkg/apis/radix" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// GetOwnerReference Gets RadixDNSAlias as an owner reference +func GetOwnerReference(alias *radixv1.RadixDNSAlias) metav1.OwnerReference { + return metav1.OwnerReference{ + APIVersion: radix.APIVersion, + Kind: radix.KindRadixDNSAlias, + Name: alias.Name, + UID: alias.UID, + Controller: pointers.Ptr(true), + } +} diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index a7724b9fc..ee17a8f2c 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -4,10 +4,13 @@ import ( "context" "fmt" + "github.com/equinor/radix-common/utils/slice" + "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + "github.com/equinor/radix-operator/radix-operator/config" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -25,14 +28,16 @@ type syncer struct { radixClient radixclient.Interface kubeUtil *kube.Kube radixDNSAlias *radixv1.RadixDNSAlias + clusterConfig *config.ClusterConfig } // NewSyncer is the constructor for RadixDNSAlias syncer -func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { +func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, clusterConfig *config.ClusterConfig, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { return &syncer{ kubeClient: kubeClient, radixClient: radixClient, kubeUtil: kubeUtil, + clusterConfig: clusterConfig, radixDNSAlias: radixDNSAlias, } } @@ -50,16 +55,57 @@ func (s *syncer) OnSync() error { } func (s *syncer) syncAlias() error { - appName := s.radixDNSAlias.Spec.AppName + aliasSpec := s.radixDNSAlias.Spec + appName := aliasSpec.AppName + domainName := s.radixDNSAlias.GetName() radixApplication, err := s.radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName)). Get(context.Background(), appName, metav1.GetOptions{}) if err != nil { if errors.IsNotFound(err) { - return fmt.Errorf("not found the Radix application %s for the DNS alias %s", appName, s.radixDNSAlias.GetName()) + return fmt.Errorf("not found the Radix application %s for the DNS alias %s", appName, domainName) + } + return err + } + envNamespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) + ingressName := internal.GetDNSAliasIngressName(aliasSpec.Component, domainName) + ingress, err := s.kubeClient.NetworkingV1().Ingresses(envNamespace).Get(context.Background(), ingressName, metav1.GetOptions{}) + if err != nil { + if errors.IsNotFound(err) { + return s.createIngress(radixApplication) } return err } // TODO - fmt.Println(radixApplication) + fmt.Println(radixApplication.GetName()) + fmt.Println(ingress.GetName()) return nil } + +func (s *syncer) createIngress(ra *radixv1.RadixApplication) error { + aliasSpec := s.radixDNSAlias.Spec + portNumber, err := getComponentPublicPortNumber(ra, aliasSpec.Component) + if err != nil { + return err + } + domain := s.radixDNSAlias.GetName() + _, err = internal.CreateRadixDNSAliasIngress(s.kubeClient, aliasSpec.AppName, aliasSpec.Environment, + internal.BuildRadixDNSAliasIngress(aliasSpec.AppName, domain, aliasSpec.Component, portNumber, s.radixDNSAlias, s.clusterConfig)) + return err +} + +func getComponentPublicPortNumber(ra *radixv1.RadixApplication, componentName string) (int32, error) { + component, componentExists := slice.FindFirst(ra.Spec.Components, func(c radixv1.RadixComponent) bool { + return c.Name == componentName + }) + if !componentExists { + return 0, fmt.Errorf("not found component %s in the application %s for the DNS alias", componentName, ra.GetName()) + } + componentPort, publicPortExists := slice.FindFirst(component.Ports, func(p radixv1.ComponentPort) bool { + return p.Name == component.PublicPort + }) + if !publicPortExists { + return 0, fmt.Errorf("not found component %s in the application %s for the DNS alias", componentName, ra.GetName()) + } + + return componentPort.Port, nil +} diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 92133eee2..3f66988f9 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -2,8 +2,10 @@ package dnsalias_test import ( "context" + "fmt" "testing" + commonUtils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -24,10 +26,11 @@ import ( type syncerTestSuite struct { suite.Suite - kubeClient *kubefake.Clientset - radixClient *radixfake.Clientset - kubeUtil *kube.Kube - promClient *prometheusfake.Clientset + kubeClient *kubefake.Clientset + radixClient *radixfake.Clientset + kubeUtil *kube.Kube + promClient *prometheusfake.Clientset + clusterConfig *config.ClusterConfig } func TestSyncerTestSuite(t *testing.T) { @@ -38,11 +41,12 @@ func (s *syncerTestSuite) SetupTest() { s.kubeClient = kubefake.NewSimpleClientset() s.radixClient = radixfake.NewSimpleClientset() s.promClient = prometheusfake.NewSimpleClientset() + s.clusterConfig = &config.ClusterConfig{DNSZone: "test.radix.equinor.com"} s.kubeUtil, _ = kube.New(s.kubeClient, s.radixClient, secretproviderfake.NewSimpleClientset()) } func (s *syncerTestSuite) createSyncer(radixDNSAlias *radixv1.RadixDNSAlias) dnsalias.Syncer { - return dnsalias.NewSyncer(s.kubeClient, s.kubeUtil, s.radixClient, radixDNSAlias) + return dnsalias.NewSyncer(s.kubeClient, s.kubeUtil, s.radixClient, s.clusterConfig, radixDNSAlias) } type testIngress struct { @@ -54,15 +58,18 @@ type testIngress struct { port int32 } +type modifyComponentBuilderFunc func(builder utils.RadixApplicationComponentBuilder) (utils.RadixApplicationComponentBuilder, bool) + type scenario struct { - name string - expectedError string - missingRadixApplication bool - dnsAlias radixv1.DNSAlias - dnsZone string - existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec - existingIngress []testIngress - expectedIngress map[string]testIngress + name string + expectedError string + missingRadixApplication bool + dnsAlias radixv1.DNSAlias + dnsZone string + existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec + existingIngress []testIngress + expectedIngress map[string]testIngress + applicationComponentBuilder utils.RadixApplicationComponentBuilder } func (s *syncerTestSuite) Test_syncer_OnSync() { @@ -76,19 +83,22 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { port8080 = 8080 dnsZone1 = "test.radix.equinor.com" ) + scenarios := []scenario{ { - name: "no radix application", - missingRadixApplication: true, - expectedError: "not found the Radix application app1 for the DNS alias domain1", - dnsAlias: radixv1.DNSAlias{Domain: "domain1", Environment: envName1, Component: component1}, + name: "no radix application", + missingRadixApplication: true, + applicationComponentBuilder: getRandomComponentBuilder(), + expectedError: "not found the Radix application app1 for the DNS alias domain1", + dnsAlias: radixv1.DNSAlias{Domain: "domain1", Environment: envName1, Component: component1}, }, { - name: "created an ingress", - dnsAlias: radixv1.DNSAlias{Domain: domain1, Environment: envName1, Component: component1}, - dnsZone: dnsZone1, + name: "created an ingress", + dnsAlias: radixv1.DNSAlias{Domain: domain1, Environment: envName1, Component: component1}, + dnsZone: dnsZone1, + applicationComponentBuilder: utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portHttp, port8080).WithPublicPort(portHttp), expectedIngress: map[string]testIngress{ - "server1.domain1.custom-domain": {appName: appName1, envName: envName1, name: "component1.domain1.custom-domain", host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, name: "component1.domain1.custom-domain", host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, }, }, // { @@ -96,8 +106,8 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { // dnsAlias: radixv1.DNSAlias{Domain: domain1, Environment: envName1, Component: component1}, // dnsZone: dnsZone1, // expectedIngress: map[string]testIngress{ - // "server1.domain1.custom-domain": {appName: appName1, envName: envName1, name: "server1.domain1.custom-domain", host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, - // "server1.domain2.custom-domain": {appName: appName1, envName: envName1, name: "server1.domain2.custom-domain", host: internal.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, + // "component1.domain1.custom-domain": {appName: appName1, envName: envName1, name: "component1.domain1.custom-domain", host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + // "component1.domain2.custom-domain": {appName: appName1, envName: envName1, name: "component1.domain2.custom-domain", host: internal.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, // }, // }, } @@ -106,7 +116,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { // s.SetupTest() if !ts.missingRadixApplication { ra := utils.NewRadixApplicationBuilder().WithAppName(appName1).WithEnvironment(envName1, "master"). - WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portHttp, port8080).WithPublicPort(portHttp)).BuildRA() + WithComponents(ts.applicationComponentBuilder, getRandomComponentBuilder()).BuildRA() _, err := s.radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName1)).Create(context.Background(), ra, metav1.CreateOptions{}) s.NoError(err) } @@ -123,36 +133,44 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { // assert ingresses if ts.expectedIngress == nil { - assert.Len(t, ingresses.Items, 0, "not expected ingresses") - } else { - assert.Len(t, ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") - if len(ingresses.Items) == len(ts.expectedIngress) { - for _, ingress := range ingresses.Items { - if expectedIngress, ok := ts.expectedIngress[ingress.Name]; ok { - require.Len(t, ingress.Spec.Rules, 1, "rules count") - assert.Equal(t, expectedIngress.appName, ingress.GetLabels()[kube.RadixAppLabel], "app name") - assert.Equal(t, utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ingress.GetNamespace(), "namespace") - assert.Equal(t, expectedIngress.component, ingress.GetLabels()[kube.RadixComponentLabel], "component name") - assert.Equal(t, expectedIngress.host, ingress.Spec.Rules[0].Host, "rule host") - assert.Equal(t, "/", ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") - assert.Equal(t, expectedIngress.component, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") - assert.Equal(t, expectedIngress.port, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") - } else { - assert.Failf(t, "found not expected ingress %s: appName %s, host %s, service %s, port %d", ingress.GetName(), ingress.GetLabels()[kube.RadixAppLabel], ingress.Spec.Rules[0].Host, ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, &ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port) - } + require.Len(t, ingresses.Items, 0, "not expected ingresses") + return + } + + require.Len(t, ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") + if len(ingresses.Items) == len(ts.expectedIngress) { + for _, ingress := range ingresses.Items { + if expectedIngress, ok := ts.expectedIngress[ingress.Name]; ok { + require.Len(t, ingress.Spec.Rules, 1, "rules count") + assert.Equal(t, expectedIngress.appName, ingress.GetLabels()[kube.RadixAppLabel], "app name") + assert.Equal(t, utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ingress.GetNamespace(), "namespace") + assert.Equal(t, expectedIngress.component, ingress.GetLabels()[kube.RadixComponentLabel], "component name") + assert.Equal(t, expectedIngress.host, ingress.Spec.Rules[0].Host, "rule host") + assert.Equal(t, "/", ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") + assert.Equal(t, expectedIngress.component, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") + assert.Equal(t, expectedIngress.port, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") + continue } + assert.Fail(t, fmt.Sprintf("found not expected ingress %s for: appName %s, host %s, service %s, port %d", + ingress.GetName(), ingress.GetLabels()[kube.RadixAppLabel], ingress.Spec.Rules[0].Host, ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, + &ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port.Number)) } } + }) } } func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses []testIngress, config *config.ClusterConfig) error { for _, ing := range testIngresses { - _, err := internal.CreateRadixDNSAliasIngress(kubeClient, ing.appName, ing.envName, internal.BuildRadixDNSAliasIngress(ing.appName, ing.name, ing.component, ing.port, config)) + _, err := internal.CreateRadixDNSAliasIngress(kubeClient, ing.appName, ing.envName, internal.BuildRadixDNSAliasIngress(ing.appName, ing.name, ing.component, ing.port, nil, config)) if err != nil { return err } } return nil } + +func getRandomComponentBuilder() utils.RadixApplicationComponentBuilder { + return utils.NewApplicationComponentBuilder().WithName(commonUtils.RandString(20)).WithPort("p", 9000).WithPublicPort("s") +} diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go index 67f2802a9..8221e6cab 100644 --- a/radix-operator/dnsalias/handler.go +++ b/radix-operator/dnsalias/handler.go @@ -8,6 +8,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/kube" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" + "github.com/equinor/radix-operator/radix-operator/config" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -33,6 +34,7 @@ type handler struct { radixClient radixclient.Interface syncerFactory internal.SyncerFactory hasSynced common.HasSynced + clusterConfig *config.ClusterConfig } // NewHandler creates a handler for managing RadixDNSAlias resources @@ -40,13 +42,15 @@ func NewHandler( kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, + clusterConfig *config.ClusterConfig, hasSynced common.HasSynced, options ...HandlerConfigOption) common.Handler { h := &handler{ - kubeClient: kubeClient, - kubeUtil: kubeUtil, - radixClient: radixClient, - hasSynced: hasSynced, + kubeClient: kubeClient, + kubeUtil: kubeUtil, + radixClient: radixClient, + hasSynced: hasSynced, + clusterConfig: clusterConfig, } configureDefaultSyncerFactory(h) for _, option := range options { @@ -79,7 +83,7 @@ func (h *handler) Sync(_, name string, eventRecorder record.EventRecorder) error syncingAlias := radixDNSAlias.DeepCopy() logger.Debugf("Sync RadixDNSAlias %s", name) - syncer := h.syncerFactory.CreateSyncer(h.kubeClient, h.kubeUtil, h.radixClient, syncingAlias) + syncer := h.syncerFactory.CreateSyncer(h.kubeClient, h.kubeUtil, h.radixClient, h.clusterConfig, syncingAlias) err = syncer.OnSync() if err != nil { return err diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index 6647c6b4d..7d549c447 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -10,6 +10,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" + "github.com/equinor/radix-operator/radix-operator/config" "github.com/equinor/radix-operator/radix-operator/dnsalias" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" "github.com/stretchr/testify/require" @@ -37,13 +38,14 @@ func (s *handlerTestSuite) TearDownTest() { s.MockCtrl.Finish() } -func (s *handlerTestSuite) Test_IngressesForRadixDNSAliases() { +func (s *handlerTestSuite) Test_RadixDNSAliases() { const ( appName = "any-app1" env1 = "env1" componentPort1 = 8080 component1 = "component1" ) + clusterConfig := &config.ClusterConfig{DNSZone: "test.radix.equinor.com"} var testScenarios = []struct { name string dnsAlias radixv1.DNSAlias @@ -70,7 +72,7 @@ func (s *handlerTestSuite) Test_IngressesForRadixDNSAliases() { map[string]radixv1.RadixDNSAliasSpec{ts.dnsAlias.Domain: internal.BuildRadixDNSAlias(appName, ts.dnsAlias.Component, ts.dnsAlias.Environment, ts.dnsAlias.Domain).Spec}), "create new or updated RadixDNSAlias") handlerSynced := false - handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, + handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, clusterConfig, func(synced bool) { handlerSynced = synced }, dnsalias.WithSyncerFactory(s.syncerFactory)) err = handler.Sync("", ts.dnsAlias.Domain, s.EventRecorder) require.NoError(s.T(), err) diff --git a/radix-operator/dnsalias/internal/syncerfactory.go b/radix-operator/dnsalias/internal/syncerfactory.go index f9b36fe17..e9aace1e9 100644 --- a/radix-operator/dnsalias/internal/syncerfactory.go +++ b/radix-operator/dnsalias/internal/syncerfactory.go @@ -5,12 +5,13 @@ import ( "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + "github.com/equinor/radix-operator/radix-operator/config" "k8s.io/client-go/kubernetes" ) // SyncerFactory defines a factory to create a DNS alias Syncer type SyncerFactory interface { - CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer + CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, clusterConfig *config.ClusterConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer } // SyncerFactoryFunc is an adapter that can be used to convert @@ -19,9 +20,11 @@ type SyncerFactoryFunc func( kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, + clusterConfig *config.ClusterConfig, radixDNSAlias *radixv1.RadixDNSAlias, ) dnsaliasapi.Syncer -func (f SyncerFactoryFunc) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer { - return f(kubeClient, kubeUtil, radixClient, radixDNSAlias) +// CreateSyncer Create a DNS alias Syncer +func (f SyncerFactoryFunc) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, clusterConfig *config.ClusterConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer { + return f(kubeClient, kubeUtil, radixClient, clusterConfig, radixDNSAlias) } diff --git a/radix-operator/dnsalias/internal/syncerfactory_mock.go b/radix-operator/dnsalias/internal/syncerfactory_mock.go index d5af9f815..d456488db 100644 --- a/radix-operator/dnsalias/internal/syncerfactory_mock.go +++ b/radix-operator/dnsalias/internal/syncerfactory_mock.go @@ -11,6 +11,7 @@ import ( kube "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" versioned "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + config "github.com/equinor/radix-operator/radix-operator/config" gomock "github.com/golang/mock/gomock" kubernetes "k8s.io/client-go/kubernetes" ) @@ -39,15 +40,15 @@ func (m *MockSyncerFactory) EXPECT() *MockSyncerFactoryMockRecorder { } // CreateSyncer mocks base method. -func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, radixDNSAlias *v1.RadixDNSAlias) dnsalias.Syncer { +func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, clusterConfig *config.ClusterConfig, radixDNSAlias *v1.RadixDNSAlias) dnsalias.Syncer { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateSyncer", kubeClient, kubeUtil, radixClient, radixDNSAlias) + ret := m.ctrl.Call(m, "CreateSyncer", kubeClient, kubeUtil, radixClient, clusterConfig, radixDNSAlias) ret0, _ := ret[0].(dnsalias.Syncer) return ret0 } // CreateSyncer indicates an expected call of CreateSyncer. -func (mr *MockSyncerFactoryMockRecorder) CreateSyncer(kubeClient, kubeUtil, radixClient, radixDNSAlias interface{}) *gomock.Call { +func (mr *MockSyncerFactoryMockRecorder) CreateSyncer(kubeClient, kubeUtil, radixClient, clusterConfig, radixDNSAlias interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSyncer", reflect.TypeOf((*MockSyncerFactory)(nil).CreateSyncer), kubeClient, kubeUtil, radixClient, radixDNSAlias) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSyncer", reflect.TypeOf((*MockSyncerFactory)(nil).CreateSyncer), kubeClient, kubeUtil, radixClient, clusterConfig, radixDNSAlias) } diff --git a/radix-operator/main.go b/radix-operator/main.go index 4c2e8fb87..0fae4615c 100644 --- a/radix-operator/main.go +++ b/radix-operator/main.go @@ -207,6 +207,7 @@ func createDNSAliasesController(client kubernetes.Interface, radixClient radixcl client, kubeUtil, radixClient, + clusterConfig, func(syncedOk bool) {}, // Not interested in getting notifications of synced ) @@ -333,28 +334,6 @@ func createBatchController(client kubernetes.Interface, radixClient radixclient. recorder) } -func createDNSAliasController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretProviderClient.Interface) *common.Controller { - kubeUtil, _ := kube.NewWithListers( - client, - radixClient, - secretProviderClient, - kubeInformerFactory, - radixInformerFactory, - ) - - handler := dnsalias.NewHandler(client, kubeUtil, radixClient, func(syncedOk bool) {}) - - const waitForChildrenToSync = true - return dnsalias.NewController( - client, - radixClient, - handler, - kubeInformerFactory, - radixInformerFactory, - waitForChildrenToSync, - recorder) -} - func loadIngressConfigFromMap(kubeutil *kube.Kube) (deploymentAPI.IngressConfiguration, error) { ingressConfig := deploymentAPI.IngressConfiguration{} configMap, err := kubeutil.GetConfigMap(metav1.NamespaceDefault, ingressConfigurationMap) From 6211ea6c0af931174b7af8a2957b95a656bc57ee Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 30 Oct 2023 09:27:56 +0100 Subject: [PATCH 011/121] Fixed unit-test --- pkg/apis/applicationconfig/applicationconfig_test.go | 2 +- pkg/apis/dnsalias/syncer_test.go | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index a165160f3..3593b5a67 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -730,7 +730,7 @@ func Test_DNSAliases(t *testing.T) { func registerExistingRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]radixv1.RadixDNSAliasSpec) error { for domain, rdaSpec := range radixDNSAliasesMap { - _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.TODO(), + _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), &radixv1.RadixDNSAlias{ ObjectMeta: metav1.ObjectMeta{ Name: domain, diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 3f66988f9..3ba63560e 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -12,6 +12,7 @@ import ( radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" + radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" "github.com/equinor/radix-operator/radix-operator/config" prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" @@ -113,7 +114,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { } for _, ts := range scenarios { s.T().Run(ts.name, func(t *testing.T) { - // s.SetupTest() + s.SetupTest() if !ts.missingRadixApplication { ra := utils.NewRadixApplicationBuilder().WithAppName(appName1).WithEnvironment(envName1, "master"). WithComponents(ts.applicationComponentBuilder, getRandomComponentBuilder()).BuildRA() @@ -123,6 +124,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { config := &config.ClusterConfig{DNSZone: ts.dnsZone} radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Domain}, Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component}} + require.NoError(t, registerExistingRadixDNSAlias(s.radixClient, radixDNSAlias), "create existing alias") require.NoError(t, registerExistingIngresses(s.kubeClient, ts.existingIngress, config), "create existing ingresses") syncer := s.createSyncer(radixDNSAlias) err := syncer.OnSync() @@ -174,3 +176,9 @@ func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses [] func getRandomComponentBuilder() utils.RadixApplicationComponentBuilder { return utils.NewApplicationComponentBuilder().WithName(commonUtils.RandString(20)).WithPort("p", 9000).WithPublicPort("s") } + +func registerExistingRadixDNSAlias(radixClient radixclient.Interface, radixDNSAlias *radixv1.RadixDNSAlias) error { + _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.TODO(), + radixDNSAlias, metav1.CreateOptions{}) + return err +} From be95c7a2144989be9b4ea0e556efd926c822ada3 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 30 Oct 2023 09:40:54 +0100 Subject: [PATCH 012/121] Added unit-test --- pkg/apis/dnsalias/syncer_test.go | 48 +++++++++++++++++--------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 3ba63560e..77fcbb50a 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -17,7 +17,6 @@ import ( "github.com/equinor/radix-operator/radix-operator/config" prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -53,14 +52,12 @@ func (s *syncerTestSuite) createSyncer(radixDNSAlias *radixv1.RadixDNSAlias) dns type testIngress struct { appName string envName string - name string + domain string host string component string port int32 } -type modifyComponentBuilderFunc func(builder utils.RadixApplicationComponentBuilder) (utils.RadixApplicationComponentBuilder, bool) - type scenario struct { name string expectedError string @@ -91,7 +88,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { missingRadixApplication: true, applicationComponentBuilder: getRandomComponentBuilder(), expectedError: "not found the Radix application app1 for the DNS alias domain1", - dnsAlias: radixv1.DNSAlias{Domain: "domain1", Environment: envName1, Component: component1}, + dnsAlias: radixv1.DNSAlias{Domain: domain1, Environment: envName1, Component: component1}, }, { name: "created an ingress", @@ -99,51 +96,56 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { dnsZone: dnsZone1, applicationComponentBuilder: utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portHttp, port8080).WithPublicPort(portHttp), expectedIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, name: "component1.domain1.custom-domain", host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + }, + }, + { + name: "created additional ingress", + dnsAlias: radixv1.DNSAlias{Domain: domain1, Environment: envName1, Component: component1}, + dnsZone: dnsZone1, + applicationComponentBuilder: utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portHttp, port8080).WithPublicPort(portHttp), + existingIngress: []testIngress{ + {appName: appName1, envName: envName1, domain: domain2, host: internal.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + "component1.domain2.custom-domain": {appName: appName1, envName: envName1, domain: domain2, host: internal.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, }, }, - // { - // name: "created additional ingress", - // dnsAlias: radixv1.DNSAlias{Domain: domain1, Environment: envName1, Component: component1}, - // dnsZone: dnsZone1, - // expectedIngress: map[string]testIngress{ - // "component1.domain1.custom-domain": {appName: appName1, envName: envName1, name: "component1.domain1.custom-domain", host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, - // "component1.domain2.custom-domain": {appName: appName1, envName: envName1, name: "component1.domain2.custom-domain", host: internal.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, - // }, - // }, } for _, ts := range scenarios { s.T().Run(ts.name, func(t *testing.T) { s.SetupTest() if !ts.missingRadixApplication { + s.Require().NotNil(ts.applicationComponentBuilder) ra := utils.NewRadixApplicationBuilder().WithAppName(appName1).WithEnvironment(envName1, "master"). WithComponents(ts.applicationComponentBuilder, getRandomComponentBuilder()).BuildRA() _, err := s.radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName1)).Create(context.Background(), ra, metav1.CreateOptions{}) s.NoError(err) } - config := &config.ClusterConfig{DNSZone: ts.dnsZone} radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Domain}, Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component}} - require.NoError(t, registerExistingRadixDNSAlias(s.radixClient, radixDNSAlias), "create existing alias") - require.NoError(t, registerExistingIngresses(s.kubeClient, ts.existingIngress, config), "create existing ingresses") + s.Require().NoError(registerExistingRadixDNSAlias(s.radixClient, radixDNSAlias), "create existing alias") + cfg := &config.ClusterConfig{DNSZone: ts.dnsZone} + s.Require().NoError(registerExistingIngresses(s.kubeClient, ts.existingIngress, cfg), "create existing ingresses") syncer := s.createSyncer(radixDNSAlias) err := syncer.OnSync() test.AssertError(s.T(), ts.expectedError, err) ingresses, err := s.kubeClient.NetworkingV1().Ingresses("").List(context.Background(), metav1.ListOptions{}) - require.NoError(t, err) + s.Require().NoError(err) // assert ingresses if ts.expectedIngress == nil { - require.Len(t, ingresses.Items, 0, "not expected ingresses") + s.Require().Len(ingresses.Items, 0, "not expected ingresses") return } - require.Len(t, ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") + s.Require().Len(ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") if len(ingresses.Items) == len(ts.expectedIngress) { for _, ingress := range ingresses.Items { if expectedIngress, ok := ts.expectedIngress[ingress.Name]; ok { - require.Len(t, ingress.Spec.Rules, 1, "rules count") + s.Require().Len(ingress.Spec.Rules, 1, "rules count") assert.Equal(t, expectedIngress.appName, ingress.GetLabels()[kube.RadixAppLabel], "app name") assert.Equal(t, utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ingress.GetNamespace(), "namespace") assert.Equal(t, expectedIngress.component, ingress.GetLabels()[kube.RadixComponentLabel], "component name") @@ -165,7 +167,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses []testIngress, config *config.ClusterConfig) error { for _, ing := range testIngresses { - _, err := internal.CreateRadixDNSAliasIngress(kubeClient, ing.appName, ing.envName, internal.BuildRadixDNSAliasIngress(ing.appName, ing.name, ing.component, ing.port, nil, config)) + _, err := internal.CreateRadixDNSAliasIngress(kubeClient, ing.appName, ing.envName, internal.BuildRadixDNSAliasIngress(ing.appName, ing.domain, ing.component, ing.port, nil, config)) if err != nil { return err } From a03156123f4034eb8d71e3a858bf6f184ecf77ad Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 30 Oct 2023 12:09:20 +0100 Subject: [PATCH 013/121] Added unit-test, updating of an ingress port --- pkg/apis/dnsalias/internal/ingress.go | 6 ++- pkg/apis/dnsalias/syncer.go | 34 ++++++++++---- pkg/apis/dnsalias/syncer_test.go | 46 +++++++++++++++++-- pkg/apis/kube/ingress.go | 18 ++++++-- pkg/apis/utils/annotations/annotations.go | 5 ++ .../utils/annotations/annotations_test.go | 6 +++ 6 files changed, 95 insertions(+), 20 deletions(-) diff --git a/pkg/apis/dnsalias/internal/ingress.go b/pkg/apis/dnsalias/internal/ingress.go index 18357a070..170470f72 100644 --- a/pkg/apis/dnsalias/internal/ingress.go +++ b/pkg/apis/dnsalias/internal/ingress.go @@ -7,6 +7,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" + "github.com/equinor/radix-operator/pkg/apis/utils/annotations" "github.com/equinor/radix-operator/pkg/apis/utils/labels" "github.com/equinor/radix-operator/radix-operator/config" networkingv1 "k8s.io/api/networking/v1" @@ -26,8 +27,9 @@ func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, owne host := GetDNSAliasHost(domain, config.DNSZone) ingress := networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{ - Name: ingressName, - Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(service)), + Name: ingressName, + Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(service)), + Annotations: annotations.ForManagedByRadixDNSAliasIngress(domain), }, Spec: networkingv1.IngressSpec{ TLS: []networkingv1.IngressTLS{ diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index ee17a8f2c..0eb0855a4 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -11,6 +11,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/config" + networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -58,7 +59,7 @@ func (s *syncer) syncAlias() error { aliasSpec := s.radixDNSAlias.Spec appName := aliasSpec.AppName domainName := s.radixDNSAlias.GetName() - radixApplication, err := s.radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName)). + ra, err := s.radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName)). Get(context.Background(), appName, metav1.GetOptions{}) if err != nil { if errors.IsNotFound(err) { @@ -68,29 +69,42 @@ func (s *syncer) syncAlias() error { } envNamespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) ingressName := internal.GetDNSAliasIngressName(aliasSpec.Component, domainName) - ingress, err := s.kubeClient.NetworkingV1().Ingresses(envNamespace).Get(context.Background(), ingressName, metav1.GetOptions{}) + existingIngress, err := s.kubeUtil.GetIngress(envNamespace, ingressName) if err != nil { if errors.IsNotFound(err) { - return s.createIngress(radixApplication) + return s.createIngress(ra) } return err } - // TODO - fmt.Println(radixApplication.GetName()) - fmt.Println(ingress.GetName()) + updatedIngress, err := s.buildIngress(ra) + if err != nil { + return err + } + err = s.kubeUtil.PatchIngress(envNamespace, existingIngress, updatedIngress) + if err != nil { + return fmt.Errorf("failed to patch an ingress %s: %w", ingressName, err) + } return nil } func (s *syncer) createIngress(ra *radixv1.RadixApplication) error { + ingress, err := s.buildIngress(ra) + if err != nil { + return err + } + aliasSpec := s.radixDNSAlias.Spec + _, err = internal.CreateRadixDNSAliasIngress(s.kubeClient, aliasSpec.AppName, aliasSpec.Environment, ingress) + return err +} + +func (s *syncer) buildIngress(ra *radixv1.RadixApplication) (*networkingv1.Ingress, error) { aliasSpec := s.radixDNSAlias.Spec portNumber, err := getComponentPublicPortNumber(ra, aliasSpec.Component) if err != nil { - return err + return nil, err } domain := s.radixDNSAlias.GetName() - _, err = internal.CreateRadixDNSAliasIngress(s.kubeClient, aliasSpec.AppName, aliasSpec.Environment, - internal.BuildRadixDNSAliasIngress(aliasSpec.AppName, domain, aliasSpec.Component, portNumber, s.radixDNSAlias, s.clusterConfig)) - return err + return internal.BuildRadixDNSAliasIngress(aliasSpec.AppName, domain, aliasSpec.Component, portNumber, s.radixDNSAlias, s.clusterConfig), nil } func getComponentPublicPortNumber(ra *radixv1.RadixApplication, componentName string) (int32, error) { diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 77fcbb50a..f50668d21 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -15,10 +15,12 @@ import ( radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" "github.com/equinor/radix-operator/radix-operator/config" + "github.com/google/uuid" prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" kubefake "k8s.io/client-go/kubernetes/fake" secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake" @@ -75,10 +77,13 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { appName1 = "app1" envName1 = "env1" component1 = "component1" + component2 = "component2" domain1 = "domain1" domain2 = "domain2" portHttp = "http" + portAbc = "abc" port8080 = 8080 + port9090 = 9090 dnsZone1 = "test.radix.equinor.com" ) @@ -100,12 +105,40 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { }, }, { - name: "created additional ingress", + name: "created additional ingress for another component", dnsAlias: radixv1.DNSAlias{Domain: domain1, Environment: envName1, Component: component1}, dnsZone: dnsZone1, applicationComponentBuilder: utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portHttp, port8080).WithPublicPort(portHttp), existingIngress: []testIngress{ - {appName: appName1, envName: envName1, domain: domain2, host: internal.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, + {appName: appName1, envName: envName1, domain: domain2, host: internal.GetDNSAliasHost(domain2, dnsZone1), component: component2, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + "component2.domain2.custom-domain": {appName: appName1, envName: envName1, domain: domain2, host: internal.GetDNSAliasHost(domain2, dnsZone1), component: component2, port: port8080}, + }, + }, + { + name: "changed public port on component changes port in existing ingress", + dnsAlias: radixv1.DNSAlias{Domain: domain1, Environment: envName1, Component: component1}, + dnsZone: dnsZone1, + applicationComponentBuilder: utils.NewApplicationComponentBuilder().WithName(component1).WithPorts([]radixv1.ComponentPort{ + {Name: portHttp, Port: port8080}, + {Name: portAbc, Port: port9090}, + }).WithPublicPort(portAbc), + existingIngress: []testIngress{ + {appName: appName1, envName: envName1, domain: domain1, host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port9090}, + }, + }, + { + name: "created additional ingress on another domain for the same component", + dnsAlias: radixv1.DNSAlias{Domain: domain2, Environment: envName1, Component: component1}, + dnsZone: dnsZone1, + applicationComponentBuilder: utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portHttp, port8080).WithPublicPort(portHttp), + existingIngress: []testIngress{ + {appName: appName1, envName: envName1, domain: domain1, host: internal.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, }, expectedIngress: map[string]testIngress{ "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, @@ -123,7 +156,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { _, err := s.radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName1)).Create(context.Background(), ra, metav1.CreateOptions{}) s.NoError(err) } - radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Domain}, + radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Domain, UID: getUuid()}, Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component}} s.Require().NoError(registerExistingRadixDNSAlias(s.radixClient, radixDNSAlias), "create existing alias") cfg := &config.ClusterConfig{DNSZone: ts.dnsZone} @@ -157,7 +190,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { } assert.Fail(t, fmt.Sprintf("found not expected ingress %s for: appName %s, host %s, service %s, port %d", ingress.GetName(), ingress.GetLabels()[kube.RadixAppLabel], ingress.Spec.Rules[0].Host, ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, - &ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port.Number)) + ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port.Number)) } } @@ -165,6 +198,11 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { } } +func getUuid() types.UID { + newUUID, _ := uuid.NewUUID() + return types.UID(newUUID.String()) +} + func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses []testIngress, config *config.ClusterConfig) error { for _, ing := range testIngresses { _, err := internal.CreateRadixDNSAliasIngress(kubeClient, ing.appName, ing.envName, internal.BuildRadixDNSAliasIngress(ing.appName, ing.domain, ing.component, ing.port, nil, config)) diff --git a/pkg/apis/kube/ingress.go b/pkg/apis/kube/ingress.go index 5a0e564aa..774ba8a8c 100644 --- a/pkg/apis/kube/ingress.go +++ b/pkg/apis/kube/ingress.go @@ -15,14 +15,19 @@ import ( "k8s.io/apimachinery/pkg/util/strategicpatch" ) +// GetIngress Gets an ingress by its name +func (kubeutil *Kube) GetIngress(namespace, name string) (*networkingv1.Ingress, error) { + return kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).Get(context.Background(), name, metav1.GetOptions{}) +} + // ApplyIngress Will create or update ingress in provided namespace func (kubeutil *Kube) ApplyIngress(namespace string, ingress *networkingv1.Ingress) error { ingressName := ingress.GetName() log.Debugf("Creating Ingress object %s in namespace %s", ingressName, namespace) - oldIngress, err := kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).Get(context.TODO(), ingressName, metav1.GetOptions{}) + oldIngress, err := kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).Get(context.Background(), ingressName, metav1.GetOptions{}) if err != nil && errors.IsNotFound(err) { - _, err := kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).Create(context.TODO(), ingress, metav1.CreateOptions{}) + _, err := kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).Create(context.Background(), ingress, metav1.CreateOptions{}) if err != nil { return fmt.Errorf("failed to create Ingress object: %v", err) } @@ -37,7 +42,12 @@ func (kubeutil *Kube) ApplyIngress(namespace string, ingress *networkingv1.Ingre newIngress.ObjectMeta.Annotations = ingress.ObjectMeta.Annotations newIngress.ObjectMeta.OwnerReferences = ingress.ObjectMeta.OwnerReferences newIngress.Spec = ingress.Spec + return kubeutil.PatchIngress(namespace, oldIngress, newIngress) +} +// PatchIngress Patches an ingress, if there are changes +func (kubeutil *Kube) PatchIngress(namespace string, oldIngress *networkingv1.Ingress, newIngress *networkingv1.Ingress) error { + ingressName := oldIngress.GetName() oldIngressJSON, err := json.Marshal(oldIngress) if err != nil { return fmt.Errorf("failed to marshal old Ingress object: %v", err) @@ -54,7 +64,7 @@ func (kubeutil *Kube) ApplyIngress(namespace string, ingress *networkingv1.Ingre } if !IsEmptyPatch(patchBytes) { - patchedIngress, err := kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).Patch(context.TODO(), ingressName, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{}) + patchedIngress, err := kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).Patch(context.Background(), ingressName, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{}) if err != nil { return fmt.Errorf("failed to patch Ingress object: %v", err) } @@ -90,7 +100,7 @@ func (kubeutil *Kube) ListIngressesWithSelector(namespace string, labelSelectorS LabelSelector: labelSelectorString, } - list, err := kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).List(context.TODO(), listOptions) + list, err := kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).List(context.Background(), listOptions) if err != nil { return nil, err } diff --git a/pkg/apis/utils/annotations/annotations.go b/pkg/apis/utils/annotations/annotations.go index 0a5bab490..83bbe77e2 100644 --- a/pkg/apis/utils/annotations/annotations.go +++ b/pkg/apis/utils/annotations/annotations.go @@ -53,6 +53,11 @@ func ForClusterAutoscalerSafeToEvict(safeToEvict bool) map[string]string { return map[string]string{clusterAutoscaleSafeToEvictAnnotation: fmt.Sprint(safeToEvict)} } +// ForManagedByRadixDNSAliasIngress returns annotation with a name of a RadixDNSAlias, managed an ingresses +func ForManagedByRadixDNSAliasIngress(dnsAliasName string) map[string]string { + return map[string]string{kube.ManagedByRadixDNSAliasIngressAnnotation: dnsAliasName} +} + func forAzureWorkloadIdentityClientId(clientId string) map[string]string { return map[string]string{azureWorkloadIdentityClientIdAnnotation: clientId} } diff --git a/pkg/apis/utils/annotations/annotations_test.go b/pkg/apis/utils/annotations/annotations_test.go index b3e8da4c1..4975495e3 100644 --- a/pkg/apis/utils/annotations/annotations_test.go +++ b/pkg/apis/utils/annotations/annotations_test.go @@ -50,3 +50,9 @@ func Test_ForClusterAutoscalerSafeToEvict(t *testing.T) { expected = map[string]string{"cluster-autoscaler.kubernetes.io/safe-to-evict": "true"} assert.Equal(t, expected, actual) } + +func Test_ForManagedByRadixDNSAliasIngress(t *testing.T) { + actual := ForManagedByRadixDNSAliasIngress("test-alias") + expected := map[string]string{"radix.equinor.com/managed-by-radix-dns-alias": "test-alias"} + assert.Equal(t, expected, actual) +} From d506fc919f3fbd1388afe93a234cce03f0eaee6e Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 30 Oct 2023 12:15:35 +0100 Subject: [PATCH 014/121] Added unit-test for owner ref --- pkg/apis/dnsalias/syncer_test.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index f50668d21..e5345f765 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -9,6 +9,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" "github.com/equinor/radix-operator/pkg/apis/kube" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -179,13 +180,21 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { for _, ingress := range ingresses.Items { if expectedIngress, ok := ts.expectedIngress[ingress.Name]; ok { s.Require().Len(ingress.Spec.Rules, 1, "rules count") - assert.Equal(t, expectedIngress.appName, ingress.GetLabels()[kube.RadixAppLabel], "app name") - assert.Equal(t, utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ingress.GetNamespace(), "namespace") - assert.Equal(t, expectedIngress.component, ingress.GetLabels()[kube.RadixComponentLabel], "component name") - assert.Equal(t, expectedIngress.host, ingress.Spec.Rules[0].Host, "rule host") - assert.Equal(t, "/", ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") - assert.Equal(t, expectedIngress.component, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") - assert.Equal(t, expectedIngress.port, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") + s.Assert().Equal(expectedIngress.appName, ingress.GetLabels()[kube.RadixAppLabel], "app name") + s.Assert().Equal(utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ingress.GetNamespace(), "namespace") + s.Assert().Equal(expectedIngress.component, ingress.GetLabels()[kube.RadixComponentLabel], "component name") + s.Assert().Equal(expectedIngress.host, ingress.Spec.Rules[0].Host, "rule host") + s.Assert().Equal("/", ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") + s.Assert().Equal(expectedIngress.component, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") + s.Assert().Equal(expectedIngress.port, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") + if len(ingress.ObjectMeta.OwnerReferences) > 0 { + ownerRef := ingress.ObjectMeta.OwnerReferences[0] + s.Assert().Equal(radix.APIVersion, ownerRef.APIVersion, "ownerRef.APIVersion") + s.Assert().Equal(radix.KindRadixDNSAlias, ownerRef.Kind, "ownerRef.Kind") + s.Assert().Equal(radixDNSAlias.GetName(), ownerRef.Name, "ownerRef.Name") + s.Assert().Equal(radixDNSAlias.GetUID(), ownerRef.UID, "ownerRef.UID") + s.Assert().True(ownerRef.Controller != nil && *ownerRef.Controller, "ownerRef.Controller") + } continue } assert.Fail(t, fmt.Sprintf("found not expected ingress %s for: appName %s, host %s, service %s, port %d", From b1461a61e91aa4dbdcf173478fe9da99a2dedf65 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 30 Oct 2023 13:51:59 +0100 Subject: [PATCH 015/121] Added unit-test for header --- radix-operator/dnsalias/handler_test.go | 109 ++++++++++++------------ 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index 7d549c447..d421c8f6e 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -2,18 +2,18 @@ package dnsalias_test import ( "context" + "fmt" "testing" dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" "github.com/equinor/radix-operator/radix-operator/config" "github.com/equinor/radix-operator/radix-operator/dnsalias" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" - "github.com/stretchr/testify/require" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/suite" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -24,6 +24,13 @@ type handlerTestSuite struct { syncer *dnsaliasapi.MockSyncer } +const ( + appName1 = "appName1" + env1 = "env1" + component1 = "component1" + domain1 = "domain1" +) + func (s *handlerTestSuite) SetupTest() { s.ControllerTestSuite.SetupTest() s.syncerFactory = internal.NewMockSyncerFactory(s.MockCtrl) @@ -38,63 +45,55 @@ func (s *handlerTestSuite) TearDownTest() { s.MockCtrl.Finish() } -func (s *handlerTestSuite) Test_RadixDNSAliases() { - const ( - appName = "any-app1" - env1 = "env1" - componentPort1 = 8080 - component1 = "component1" - ) +func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { clusterConfig := &config.ClusterConfig{DNSZone: "test.radix.equinor.com"} - var testScenarios = []struct { - name string - dnsAlias radixv1.DNSAlias - existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec - }{ - { - name: "new alias, no existing RDA, no existing ingresses, additional radix aliases, additional ingresses", - dnsAlias: radixv1.DNSAlias{Domain: "domain1", Environment: env1, Component: component1}, - }, - } + handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, clusterConfig, + func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) - for _, ts := range testScenarios { - s.T().Run(ts.name, func(t *testing.T) { - // s.SetupTest() - ra := utils.ARadixApplication().WithAppName(appName). - WithEnvironment(ts.dnsAlias.Environment, "branch1"). - WithComponent(utils.NewApplicationComponentBuilder().WithName(ts.dnsAlias.Component).WithPort("http", componentPort1)).BuildRA() - _, err := s.RadixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName)).Create(context.Background(), ra, metav1.CreateOptions{}) - require.NoError(t, err) - require.NoError(t, registerExistingRadixDNSAliases(s.RadixClient, ts.existingRadixDNSAliases), "create existing RadixDNSAlias") + s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), clusterConfig, gomock.Any()).Times(0) + s.syncer.EXPECT().OnSync().Times(0) - // TODO - require.NoError(t, registerExistingRadixDNSAliases(s.RadixClient, - map[string]radixv1.RadixDNSAliasSpec{ts.dnsAlias.Domain: internal.BuildRadixDNSAlias(appName, ts.dnsAlias.Component, ts.dnsAlias.Environment, ts.dnsAlias.Domain).Spec}), - "create new or updated RadixDNSAlias") - handlerSynced := false - handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, clusterConfig, - func(synced bool) { handlerSynced = synced }, dnsalias.WithSyncerFactory(s.syncerFactory)) - err = handler.Sync("", ts.dnsAlias.Domain, s.EventRecorder) - require.NoError(s.T(), err) - require.True(s.T(), handlerSynced, "Handler should be synced") + err := handler.Sync("", domain1, s.EventRecorder) + s.Require().NoError(err) +} + +func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { + clusterConfig := &config.ClusterConfig{DNSZone: "test.radix.equinor.com"} + s.Require().NoError(registerExistingRadixDNSAliases(s.RadixClient, appName1, env1, component1, domain1), "create existing RadixDNSAlias") + handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, clusterConfig, + func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) + expectedError := fmt.Errorf("some error") + s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), clusterConfig, gomock.Any()).Return(s.syncer).Times(1) + s.syncer.EXPECT().OnSync().Return(expectedError).Times(1) + + actualError := handler.Sync("", domain1, s.EventRecorder) + s.Equal(expectedError, actualError) +} + +func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsNoError() { + clusterConfig := &config.ClusterConfig{DNSZone: "test.radix.equinor.com"} + s.Require().NoError(registerExistingRadixDNSAliases(s.RadixClient, appName1, env1, component1, domain1), "create existing RadixDNSAlias") + handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, clusterConfig, + func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) + s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), clusterConfig, gomock.Any()).Return(s.syncer).Times(1) + s.syncer.EXPECT().OnSync().Return(nil).Times(1) - }) - } + err := handler.Sync("", domain1, s.EventRecorder) + s.Require().Nil(err) } -func registerExistingRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]radixv1.RadixDNSAliasSpec) error { - for domain, rdaSpec := range radixDNSAliasesMap { - _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.TODO(), - &radixv1.RadixDNSAlias{ - ObjectMeta: metav1.ObjectMeta{ - Name: domain, - Labels: labels.Merge(labels.ForApplicationName(rdaSpec.AppName), labels.ForComponentName(rdaSpec.Component)), - }, - Spec: rdaSpec, - }, metav1.CreateOptions{}) - if err != nil { - return err - } - } - return nil +func registerExistingRadixDNSAliases(radixClient radixclient.Interface, appName, envName, component, domain string) error { + _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), + &radixv1.RadixDNSAlias{ + ObjectMeta: metav1.ObjectMeta{ + Name: domain, + Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(component)), + }, + Spec: radixv1.RadixDNSAliasSpec{ + AppName: appName, + Environment: envName, + Component: component, + }, + }, metav1.CreateOptions{}) + return err } From f585e69973eaf943ddc99cd2411e51d884c642f7 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 30 Oct 2023 15:11:31 +0100 Subject: [PATCH 016/121] Updated unit-test for controller --- radix-operator/dnsalias/controller_test.go | 52 +++++++++------------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go index 67c220481..0ce9ce19a 100644 --- a/radix-operator/dnsalias/controller_test.go +++ b/radix-operator/dnsalias/controller_test.go @@ -79,45 +79,37 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { s.Require().NoError(err) s.WaitForNotSynced("Sync should not be called when updating RadixDNSAlias with no changes") - // Add Kubernetes Job with ownerreference to RadixDNSAlias should not trigger sync + // Add Ingress with owner reference to RadixDNSAlias should not trigger sync ingress := internal.BuildRadixDNSAliasIngress(alias.Spec.AppName, alias.GetName(), alias.Spec.Component, int32(8080), config) ingress.SetOwnerReferences([]metav1.OwnerReference{{APIVersion: radix.APIVersion, Kind: radix.KindRadixDNSAlias, Name: aliasName, Controller: pointers.Ptr(true)}}) namespace := utils.GetEnvironmentNamespace(alias.Spec.AppName, alias.Spec.Environment) s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) ingress, err = internal.CreateRadixDNSAliasIngress(s.KubeClient, alias.Spec.AppName, alias.Spec.Environment, ingress) s.Require().NoError(err) - s.WaitForNotSynced("Sync should not be called when adding k8s ingress") - /* - // Sync should not trigger on ingress update if resource version is unchanged - s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) - ingress, err = s.KubeClient.BatchV1().Jobs(namespace).Update(context.Background(), ingress, metav1.UpdateOptions{}) - s.Require().NoError(err) - s.WaitForNotSynced("Sync should not be called on k8s ingress update with no resource version change") - - // Sync should trigger on ingress update if resource version is changed - ingress.ResourceVersion = "2" - s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) - _, err = s.KubeClient.BatchV1().Jobs(namespace).Update(context.Background(), ingress, metav1.UpdateOptions{}) - s.Require().NoError(err) - s.WaitForSynced("Sync should be called on k8s ingress update with changed resource version") - - // Sync should trigger when deleting ingress - s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) - err = s.KubeClient.BatchV1().Jobs(namespace).Delete(context.Background(), jobName, metav1.DeleteOptions{}) - s.Require().NoError(err) - s.WaitForSynced("Sync should be called on k8s ingress deletion") - - // Sync should not trigger when deleting alias - s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) - err = s.RadixClient.RadixV1().RadixDNSAliases(namespace).Delete(context.Background(), aliasName, metav1.DeleteOptions{}) - s.Require().NoError(err) - s.WaitForNotSynced("Sync should not be called on alias deletion") - - */ - // Delete the RadixDNSAlias should trigger a sync + s.WaitForNotSynced("Sync should not be called when adding ingress") + + // Delete the RadixDNSAlias should not trigger a sync s.Handler.EXPECT().Sync("", aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) err = s.RadixClient.RadixV1().RadixDNSAliases().Delete(context.TODO(), alias.GetName(), metav1.DeleteOptions{}) s.Require().NoError(err) s.WaitForNotSynced("Sync should be called when deleting RadixDNSAlias") + // Sync should not trigger on ingress update if resource version is unchanged + s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) + ingress, err = s.KubeClient.NetworkingV1().Ingresses(namespace).Update(context.Background(), ingress, metav1.UpdateOptions{}) + s.Require().NoError(err) + s.WaitForNotSynced("Sync should not be called on ingress update with no resource version change") + + // Sync should not trigger on ingress update if resource version is changed + ingress.ResourceVersion = "2" + s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) + _, err = s.KubeClient.NetworkingV1().Ingresses(namespace).Update(context.Background(), ingress, metav1.UpdateOptions{}) + s.Require().NoError(err) + s.WaitForNotSynced("Sync should not be called on k8s ingress update with changed resource version") + + // Sync should not trigger when deleting ingress + s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) + err = s.KubeClient.NetworkingV1().Ingresses(namespace).Delete(context.Background(), ingress.GetName(), metav1.DeleteOptions{}) + s.Require().NoError(err) + s.WaitForNotSynced("Sync should be called on ingress deletion") } From 0917810058b629e50984bcd4f12a21228b9ed85a Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 30 Oct 2023 15:48:10 +0100 Subject: [PATCH 017/121] Updated unit-test for app controller --- .../applicationconfig_test.go | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 3593b5a67..63eec6e35 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -7,6 +7,7 @@ import ( "log" "testing" + commonUtils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-operator/pkg/apis/applicationconfig" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -668,31 +669,32 @@ type testIngress struct { func Test_DNSAliases(t *testing.T) { const ( - appName = "any-app1" - envDev = "dev" - componentNameServer1 = "server1" + appName = "any-app1" + env1 = "dev" + component1 = "server1" + branch1 = "branch1" + portA = "port-a" + port8080 = 8080 + domain1 = "domain1" ) var testScenarios = []struct { name string - dnsAliases []radixv1.DNSAlias + applicationBuilder utils.ApplicationBuilder existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec expectedRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec }{ { - name: "no aliases, no existing RDA, no existing ingresses, no additional radix aliases, no additional ingresses", + name: "no aliases, no existing RDA, no expected RDA", + applicationBuilder: utils.ARadixApplication().WithAppName(appName).WithEnvironment(env1, branch1). + WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), }, { - name: "no aliases, no existing RDA, exist ingresses, no additional radix aliases, no additional ingresses", - }, - { - name: "multiple aliases, no existing RDA, no existing ingresses, additional radix aliases, additional ingresses", - dnsAliases: []radixv1.DNSAlias{ - {Domain: "domain1", Environment: envDev, Component: componentNameServer1}, - {Domain: "domain2", Environment: envDev, Component: componentNameServer1}, - }, + name: "one alias, no existing RDA, one expected RDA", + applicationBuilder: utils.ARadixApplication().WithAppName(appName).WithEnvironment(env1, branch1). + WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). + WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - "domain1": {AppName: appName, Environment: envDev, Component: componentNameServer1}, - "domain2": {AppName: appName, Environment: envDev, Component: componentNameServer1}, + domain1: {AppName: appName, Environment: env1, Component: component1}, }, }, } @@ -700,9 +702,8 @@ func Test_DNSAliases(t *testing.T) { for _, ts := range testScenarios { t.Run(ts.name, func(t *testing.T) { - ra := utils.ARadixApplication().WithAppName(appName).WithDNSAlias(ts.dnsAliases...) - require.NoError(t, applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, ra), "register radix application") require.NoError(t, registerExistingRadixDNSAliases(radixClient, ts.existingRadixDNSAliases), "create existing RadixDNSAlias") + require.NoError(t, applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, ts.applicationBuilder), "register radix application") radixDNSAliases, err := radixClient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{}) require.NoError(t, err) @@ -849,3 +850,13 @@ func getRoleBindingByName(name string, roleBindings *rbacv1.RoleBindingList) *rb func roleBindingByNameExists(name string, roleBindings *rbacv1.RoleBindingList) bool { return getRoleBindingByName(name, roleBindings) != nil } + +func getRandomComponentBuilder() utils.RadixApplicationComponentBuilder { + return utils.NewApplicationComponentBuilder().WithName(commonUtils.RandString(20)).WithPort("p", 9000).WithPublicPort("s") +} + +func registerExistingRadixDNSAlias(radixClient radixclient.Interface, radixDNSAlias *radixv1.RadixDNSAlias) error { + _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.TODO(), + radixDNSAlias, metav1.CreateOptions{}) + return err +} From eceba1b7ceea4cb0f142128b57c5e827a5d778a8 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 30 Oct 2023 15:55:07 +0100 Subject: [PATCH 018/121] Updated unit-test for app controller --- .../applicationconfig_test.go | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 63eec6e35..5ab409a15 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -670,12 +670,16 @@ type testIngress struct { func Test_DNSAliases(t *testing.T) { const ( appName = "any-app1" - env1 = "dev" + env1 = "env1" + env2 = "env2" component1 = "server1" + component2 = "server2" branch1 = "branch1" + branch2 = "branch2" portA = "port-a" port8080 = 8080 domain1 = "domain1" + domain2 = "domain2" ) var testScenarios = []struct { name string @@ -697,6 +701,38 @@ func Test_DNSAliases(t *testing.T) { domain1: {AppName: appName, Environment: env1, Component: component1}, }, }, + { + name: "aliases for multiple components, no existing RDA", + applicationBuilder: utils.ARadixApplication().WithAppName(appName).WithEnvironment(env1, branch1). + WithDNSAlias( + radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Domain: domain2, Environment: env1, Component: component2}, + ). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), + ), + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName, Environment: env1, Component: component1}, + domain2: {AppName: appName, Environment: env1, Component: component2}, + }, + }, + { + name: "aliases for multiple environments, no existing RDA", + applicationBuilder: utils.ARadixApplication().WithAppName(appName).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithDNSAlias( + radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Domain: domain2, Environment: env2, Component: component1}, + ). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), + ), + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName, Environment: env1, Component: component1}, + domain2: {AppName: appName, Environment: env2, Component: component1}, + }, + }, } tu, kubeClient, kubeUtil, radixClient := setupTest() From d8ead9bf63f5a34f20ce9cf78227df55a4aa653a Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 31 Oct 2023 12:47:59 +0100 Subject: [PATCH 019/121] Handled changed, new a dn deleted aliases app-config --- .../applicationconfig_test.go | 185 ++++++++++++++---- pkg/apis/applicationconfig/dnsaliases.go | 53 ++--- pkg/apis/kube/kube.go | 11 +- pkg/apis/kube/radix_alert.go | 2 +- pkg/apis/kube/radix_dns_alias.go | 70 +++++++ radix-operator/dnsalias/handler.go | 4 +- 6 files changed, 248 insertions(+), 77 deletions(-) create mode 100644 pkg/apis/kube/radix_dns_alias.go diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 5ab409a15..531634b05 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -7,7 +7,6 @@ import ( "log" "testing" - commonUtils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-operator/pkg/apis/applicationconfig" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -669,7 +668,8 @@ type testIngress struct { func Test_DNSAliases(t *testing.T) { const ( - appName = "any-app1" + appName1 = "any-app1" + appName2 = "any-app2" env1 = "env1" env2 = "env2" component1 = "server1" @@ -680,6 +680,8 @@ func Test_DNSAliases(t *testing.T) { port8080 = 8080 domain1 = "domain1" domain2 = "domain2" + domain3 = "domain3" + domain4 = "domain4" ) var testScenarios = []struct { name string @@ -688,22 +690,23 @@ func Test_DNSAliases(t *testing.T) { expectedRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec }{ { - name: "no aliases, no existing RDA, no expected RDA", - applicationBuilder: utils.ARadixApplication().WithAppName(appName).WithEnvironment(env1, branch1). + name: "no aliases", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{}, }, { - name: "one alias, no existing RDA, one expected RDA", - applicationBuilder: utils.ARadixApplication().WithAppName(appName).WithEnvironment(env1, branch1). + name: "one alias", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName, Environment: env1, Component: component1}, + domain1: {AppName: appName1, Environment: env1, Component: component1}, }, }, { - name: "aliases for multiple components, no existing RDA", - applicationBuilder: utils.ARadixApplication().WithAppName(appName).WithEnvironment(env1, branch1). + name: "aliases for multiple components", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). WithDNSAlias( radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, radixv1.DNSAlias{Domain: domain2, Environment: env1, Component: component2}, @@ -713,13 +716,13 @@ func Test_DNSAliases(t *testing.T) { utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), ), expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName, Environment: env1, Component: component1}, - domain2: {AppName: appName, Environment: env1, Component: component2}, + domain1: {AppName: appName1, Environment: env1, Component: component1}, + domain2: {AppName: appName1, Environment: env1, Component: component2}, }, }, { - name: "aliases for multiple environments, no existing RDA", - applicationBuilder: utils.ARadixApplication().WithAppName(appName).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + name: "aliases for multiple environments", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). WithDNSAlias( radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, radixv1.DNSAlias{Domain: domain2, Environment: env2, Component: component1}, @@ -729,36 +732,146 @@ func Test_DNSAliases(t *testing.T) { utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), ), expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName, Environment: env1, Component: component1}, - domain2: {AppName: appName, Environment: env2, Component: component1}, + domain1: {AppName: appName1, Environment: env1, Component: component1}, + domain2: {AppName: appName1, Environment: env2, Component: component1}, + }, + }, + { + name: "multiple aliases for one component and enironment", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithDNSAlias( + radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Domain: domain2, Environment: env1, Component: component1}, + ). + WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1}, + domain2: {AppName: appName1, Environment: env1, Component: component1}, + }, + }, + { + name: "aliases for multiple components in different environments", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithDNSAlias( + radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Domain: domain2, Environment: env2, Component: component2}, + ). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), + ), + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1}, + domain2: {AppName: appName1, Environment: env2, Component: component2}, + }, + }, + { + name: "one alias, exist other RDA, two expected RDA", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). + WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain2: {AppName: appName2, Environment: env1, Component: component1}, + }, + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain2: {AppName: appName2, Environment: env1, Component: component1}, + domain1: {AppName: appName1, Environment: env1, Component: component1}, + }, + }, + { + name: "change env and component for existing RDA", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env2, Component: component2}). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), + ), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1}, + }, + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env2, Component: component2}, + }, + }, + { + name: "swap env and component for existing RDA-s", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithDNSAlias( + radixv1.DNSAlias{Domain: domain1, Environment: env2, Component: component2}, + radixv1.DNSAlias{Domain: domain2, Environment: env1, Component: component1}, + ). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), + ), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1}, + domain2: {AppName: appName1, Environment: env2, Component: component2}, + }, + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env2, Component: component2}, + domain2: {AppName: appName1, Environment: env1, Component: component1}, + }, + }, + { + name: "remove single alias", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1}, + }, + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{}, + }, + { + name: "remove multiple aliases, keep other", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithDNSAlias( + radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Domain: domain3, Environment: env2, Component: component1}, + ). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), + ), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1}, + domain2: {AppName: appName1, Environment: env1, Component: component2}, + domain3: {AppName: appName1, Environment: env2, Component: component1}, + domain4: {AppName: appName2, Environment: env1, Component: component1}, + }, + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1}, + domain3: {AppName: appName1, Environment: env2, Component: component1}, + domain4: {AppName: appName2, Environment: env1, Component: component1}, }, }, } - tu, kubeClient, kubeUtil, radixClient := setupTest() for _, ts := range testScenarios { t.Run(ts.name, func(t *testing.T) { + tu, kubeClient, kubeUtil, radixClient := setupTest() + require.NoError(t, registerExistingRadixDNSAliases(radixClient, ts.existingRadixDNSAliases), "create existing RadixDNSAlias") require.NoError(t, applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, ts.applicationBuilder), "register radix application") radixDNSAliases, err := radixClient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{}) require.NoError(t, err) - // assert RadixDNSAlias-es if ts.expectedRadixDNSAliases == nil { - assert.Len(t, radixDNSAliases.Items, 0, "not expected Radix DNS aliases") - } else { - assert.Len(t, radixDNSAliases.Items, len(ts.expectedRadixDNSAliases), "not matching expected Radix DNS aliases count") - if len(radixDNSAliases.Items) == len(ts.expectedRadixDNSAliases) { - for _, radixDNSAlias := range radixDNSAliases.Items { - if expectedDNSAlias, ok := ts.expectedRadixDNSAliases[radixDNSAlias.Name]; ok { - assert.Equal(t, expectedDNSAlias.AppName, radixDNSAlias.Spec.AppName, "app name") - assert.Equal(t, expectedDNSAlias.Environment, radixDNSAlias.Spec.Environment, "environment") - assert.Equal(t, expectedDNSAlias.Component, radixDNSAlias.Spec.Component, "component") - } else { - assert.Failf(t, "found not expected RadixDNSAlias %s: env %s, component %s, appName %s", radixDNSAlias.GetName(), radixDNSAlias.Spec.Environment, radixDNSAlias.Spec.Component, radixDNSAlias.Spec.AppName) - } + require.Len(t, radixDNSAliases.Items, 0, "not expected Radix DNS aliases") + return + } + + require.Len(t, radixDNSAliases.Items, len(ts.expectedRadixDNSAliases), "not matching expected Radix DNS aliases count") + if len(radixDNSAliases.Items) == len(ts.expectedRadixDNSAliases) { + for _, radixDNSAlias := range radixDNSAliases.Items { + if expectedDNSAlias, ok := ts.expectedRadixDNSAliases[radixDNSAlias.Name]; ok { + assert.Equal(t, expectedDNSAlias.AppName, radixDNSAlias.Spec.AppName, "app name") + assert.Equal(t, expectedDNSAlias.Environment, radixDNSAlias.Spec.Environment, "environment") + assert.Equal(t, expectedDNSAlias.Component, radixDNSAlias.Spec.Component, "component") + continue } + assert.Fail(t, fmt.Sprintf("found not expected RadixDNSAlias %s: env %s, component %s, appName %s", radixDNSAlias.GetName(), radixDNSAlias.Spec.Environment, radixDNSAlias.Spec.Component, radixDNSAlias.Spec.AppName)) } } }) @@ -832,12 +945,12 @@ func applyApplicationWithSync(tu *test.Utils, client kubernetes.Interface, kubeU return err } - applicationconfig, err := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra) + applicationConfig, err := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra) if err != nil { return err } - err = applicationconfig.OnSync() + err = applicationConfig.OnSync() if err != nil { return err } @@ -886,13 +999,3 @@ func getRoleBindingByName(name string, roleBindings *rbacv1.RoleBindingList) *rb func roleBindingByNameExists(name string, roleBindings *rbacv1.RoleBindingList) bool { return getRoleBindingByName(name, roleBindings) != nil } - -func getRandomComponentBuilder() utils.RadixApplicationComponentBuilder { - return utils.NewApplicationComponentBuilder().WithName(commonUtils.RandString(20)).WithPort("p", 9000).WithPublicPort("s") -} - -func registerExistingRadixDNSAlias(radixClient radixclient.Interface, radixDNSAlias *radixv1.RadixDNSAlias) error { - _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.TODO(), - radixDNSAlias, metav1.CreateOptions{}) - return err -} diff --git a/pkg/apis/applicationconfig/dnsaliases.go b/pkg/apis/applicationconfig/dnsaliases.go index 6aece311a..366cf83d3 100644 --- a/pkg/apis/applicationconfig/dnsaliases.go +++ b/pkg/apis/applicationconfig/dnsaliases.go @@ -1,7 +1,6 @@ package applicationconfig import ( - "context" "fmt" "strings" @@ -14,42 +13,49 @@ import ( func (app *ApplicationConfig) createOrUpdateDNSAliases() error { appName := app.registration.Name - var errs []error - ctx := context.Background() - radixDNSAliasesMap, err := app.getRadixDNSAliasesMap(ctx, appName) + radixDNSAliasesMap, err := app.getRadixDNSAliasesMap(appName) if err != nil { return err } + var errs []error for _, dnsAlias := range app.config.Spec.DNSAlias { if radixDNSAlias, ok := radixDNSAliasesMap[dnsAlias.Domain]; ok { - if !strings.EqualFold(appName, radixDNSAlias.Spec.AppName) { - return fmt.Errorf("existing DNS alias domain %s is used by the application %s", dnsAlias.Domain, radixDNSAlias.Spec.AppName) - } - if strings.EqualFold(dnsAlias.Environment, radixDNSAlias.Spec.Environment) && - strings.EqualFold(dnsAlias.Component, radixDNSAlias.Spec.Component) { - continue // no changes - } - if err = app.updateRadixDNSAlias(radixDNSAlias, dnsAlias, err, ctx); err != nil { - errs = append(errs, err) + switch { + case !strings.EqualFold(appName, radixDNSAlias.Spec.AppName): + // TODO test + errs = append(errs, fmt.Errorf("existing DNS alias domain %s is used by the application %s", dnsAlias.Domain, radixDNSAlias.Spec.AppName)) + case strings.EqualFold(dnsAlias.Environment, radixDNSAlias.Spec.Environment) && strings.EqualFold(dnsAlias.Component, radixDNSAlias.Spec.Component): + // TODO test + // Do nothing + default: + // TODO test + if err = app.updateRadixDNSAlias(radixDNSAlias, dnsAlias); err != nil { + errs = append(errs, err) + } } + delete(radixDNSAliasesMap, dnsAlias.Domain) continue } - if err = app.createRadixDNSAlias(dnsAlias, appName, err, ctx); err != nil { + if err = app.createRadixDNSAlias(appName, dnsAlias); err != nil { + errs = append(errs, err) + } + } + for _, radixDNSAlias := range radixDNSAliasesMap { + if err = app.kubeutil.DeleteRadixDNSAlias(radixDNSAlias); err != nil { errs = append(errs, err) } } return errors.Concat(errs) } -func (app *ApplicationConfig) updateRadixDNSAlias(radixDNSAlias *radixv1.RadixDNSAlias, dnsAlias radixv1.DNSAlias, err error, ctx context.Context) error { +func (app *ApplicationConfig) updateRadixDNSAlias(radixDNSAlias *radixv1.RadixDNSAlias, dnsAlias radixv1.DNSAlias) error { updatedRadixDNSAlias := radixDNSAlias.DeepCopy() updatedRadixDNSAlias.Spec.Environment = dnsAlias.Environment updatedRadixDNSAlias.Spec.Component = dnsAlias.Component - _, err = app.radixclient.RadixV1().RadixDNSAliases().Update(ctx, updatedRadixDNSAlias, metav1.UpdateOptions{}) - return err + return app.kubeutil.UpdateRadixDNSAlias(updatedRadixDNSAlias) } -func (app *ApplicationConfig) createRadixDNSAlias(dnsAlias radixv1.DNSAlias, appName string, err error, ctx context.Context) error { +func (app *ApplicationConfig) createRadixDNSAlias(appName string, dnsAlias radixv1.DNSAlias) error { radixDNSAlias := radixv1.RadixDNSAlias{ ObjectMeta: metav1.ObjectMeta{ Name: dnsAlias.Domain, @@ -61,17 +67,16 @@ func (app *ApplicationConfig) createRadixDNSAlias(dnsAlias radixv1.DNSAlias, app Component: dnsAlias.Component, }, } - _, err = app.radixclient.RadixV1().RadixDNSAliases().Create(ctx, &radixDNSAlias, metav1.CreateOptions{}) - return err + return app.kubeutil.CreateRadixDNSAlias(&radixDNSAlias) } -func (app *ApplicationConfig) getRadixDNSAliasesMap(ctx context.Context, appName string) (map[string]*radixv1.RadixDNSAlias, error) { - dnsAliasList, err := app.radixclient.RadixV1().RadixDNSAliases().List(context.Background(), metav1.ListOptions{LabelSelector: labels.ForApplicationName(appName).String()}) +func (app *ApplicationConfig) getRadixDNSAliasesMap(appName string) (map[string]*radixv1.RadixDNSAlias, error) { + dnsAliases, err := app.kubeutil.ListRadixDNSAliasWithSelector(labels.ForApplicationName(appName).String()) if err != nil { return nil, err } - return slice.Reduce(dnsAliasList.Items, make(map[string]*radixv1.RadixDNSAlias), func(acc map[string]*radixv1.RadixDNSAlias, dnsAlias radixv1.RadixDNSAlias) map[string]*radixv1.RadixDNSAlias { - acc[dnsAlias.Name] = &dnsAlias + return slice.Reduce(dnsAliases, make(map[string]*radixv1.RadixDNSAlias), func(acc map[string]*radixv1.RadixDNSAlias, dnsAlias *radixv1.RadixDNSAlias) map[string]*radixv1.RadixDNSAlias { + acc[dnsAlias.Name] = dnsAlias return acc }), err } diff --git a/pkg/apis/kube/kube.go b/pkg/apis/kube/kube.go index e4b8c594e..aaceb5874 100644 --- a/pkg/apis/kube/kube.go +++ b/pkg/apis/kube/kube.go @@ -47,7 +47,6 @@ const ( RadixJobTypeLabel = "radix-job-type" RadixJobTypeJob = "job" // Outer job RadixJobTypeBuild = "build" - RadixJobTypeCloneConfig = "clone-config" RadixJobTypePreparePipelines = "prepare-pipelines" RadixJobTypeRunPipelines = "run-pipelines" RadixJobTypeJobSchedule = "job-scheduler" @@ -79,9 +78,6 @@ const ( // Pods required to run on nodes with this taint must add a toleration with effect NoSchedule NodeTaintGpuCountKey = "radix-node-gpu-count" NodeTaintJobsKey = "nodepooltasks" - - // RadixBranchDeprecated Only for backward compatibility - RadixBranchDeprecated = "radix-branch" ) // RadixBatchType defines value for use with label RadixBatchTypeLabel @@ -96,6 +92,7 @@ const ( type RadixSecretType string const ( + // RadixSecretJobPayload Used by radix-job-scheduler to label secrets with payloads RadixSecretJobPayload RadixSecretType = "scheduler-job-payload" ) @@ -109,10 +106,6 @@ const ( EnvVarsMetadataConfigMap RadixConfigMapType = "env-vars-metadata" // RadixPipelineResultConfigMap Label of a ConfigMap, which keeps a Radix pipeline result RadixPipelineResultConfigMap RadixConfigMapType = "radix-pipeline-result" - // RadixPipelineConfigConfigMap Label of a ConfigMap, which keeps a Radix pipeline configuration - RadixPipelineConfigConfigMap RadixConfigMapType = "radix-pipeline-config" - // RadixPipelineGitInformationConfigMap Label of a ConfigMap, which keeps a Radix pipeline Git information - RadixPipelineGitInformationConfigMap RadixConfigMapType = "radix-pipeline-git-information" ) // Kube Struct for accessing lower level kubernetes functions @@ -125,6 +118,7 @@ type Kube struct { RdLister v1Lister.RadixDeploymentLister RbLister v1Lister.RadixBatchLister RadixAlertLister v1Lister.RadixAlertLister + RadixDNSAliasLister v1Lister.RadixDNSAliasLister NamespaceLister coreListers.NamespaceLister SecretLister coreListers.SecretLister DeploymentLister appsv1Listers.DeploymentLister @@ -171,6 +165,7 @@ func NewWithListers(client kubernetes.Interface, RdLister: radixInformerFactory.Radix().V1().RadixDeployments().Lister(), RbLister: radixInformerFactory.Radix().V1().RadixBatches().Lister(), RadixAlertLister: radixInformerFactory.Radix().V1().RadixAlerts().Lister(), + RadixDNSAliasLister: radixInformerFactory.Radix().V1().RadixDNSAliases().Lister(), NamespaceLister: kubeInformerFactory.Core().V1().Namespaces().Lister(), SecretLister: kubeInformerFactory.Core().V1().Secrets().Lister(), DeploymentLister: kubeInformerFactory.Apps().V1().Deployments().Lister(), diff --git a/pkg/apis/kube/radix_alert.go b/pkg/apis/kube/radix_alert.go index 5b6ac011b..daa79ae57 100644 --- a/pkg/apis/kube/radix_alert.go +++ b/pkg/apis/kube/radix_alert.go @@ -10,7 +10,7 @@ import ( "k8s.io/apimachinery/pkg/labels" ) -// GetRadixDeployment Gets radix alert using lister if present +// GetRadixAlert Gets radix alert using lister if present func (kubeutil *Kube) GetRadixAlert(namespace, name string) (*v1.RadixAlert, error) { var alert *v1.RadixAlert var err error diff --git a/pkg/apis/kube/radix_dns_alias.go b/pkg/apis/kube/radix_dns_alias.go new file mode 100644 index 000000000..2f314e546 --- /dev/null +++ b/pkg/apis/kube/radix_dns_alias.go @@ -0,0 +1,70 @@ +package kube + +import ( + "context" + "fmt" + + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/utils/slice" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" +) + +// CreateRadixDNSAlias Creates RadixDNSAlias +func (kubeutil *Kube) CreateRadixDNSAlias(radixDNSAlias *radixv1.RadixDNSAlias) error { + _, err := kubeutil.radixclient.RadixV1().RadixDNSAliases().Create(context.Background(), radixDNSAlias, metav1.CreateOptions{}) + return err +} + +// GetRadixDNSAlias Gets RadixDNSAlias using lister if present +func (kubeutil *Kube) GetRadixDNSAlias(name string) (*radixv1.RadixDNSAlias, error) { + var alias *radixv1.RadixDNSAlias + var err error + if kubeutil.RadixDNSAliasLister != nil { + if alias, err = kubeutil.RadixDNSAliasLister.Get(name); err != nil { + return nil, err + } + return alias, nil + } + if alias, err = kubeutil.radixclient.RadixV1().RadixDNSAliases().Get(context.TODO(), name, metav1.GetOptions{}); err != nil { + return nil, err + } + return alias, nil +} + +// ListRadixDNSAlias List RadixDNSAliases using lister if present +func (kubeutil *Kube) ListRadixDNSAlias() ([]*radixv1.RadixDNSAlias, error) { + return kubeutil.ListRadixDNSAliasWithSelector("") +} + +// ListRadixDNSAliasWithSelector List radix DNS aliases with selector +func (kubeutil *Kube) ListRadixDNSAliasWithSelector(labelSelectorString string) ([]*radixv1.RadixDNSAlias, error) { + if kubeutil.RadixDNSAliasLister != nil { + selector, err := labels.Parse(labelSelectorString) + if err != nil { + return nil, err + } + aliases, err := kubeutil.RadixDNSAliasLister.List(selector) + if err != nil { + return nil, fmt.Errorf("failed to get all RadixDNSAliases. Error was %v", err) + } + return aliases, nil + } + + aliasList, err := kubeutil.radixclient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{LabelSelector: labelSelectorString}) + if err != nil { + return nil, fmt.Errorf("failed to get all RadixDNSAliases. Error was %v", err) + } + return slice.PointersOf(aliasList.Items).([]*radixv1.RadixDNSAlias), nil +} + +// UpdateRadixDNSAlias Update RadixDNSAlias +func (kubeutil *Kube) UpdateRadixDNSAlias(radixDNSAlias *radixv1.RadixDNSAlias) error { + _, err := kubeutil.radixclient.RadixV1().RadixDNSAliases().Update(context.Background(), radixDNSAlias, metav1.UpdateOptions{}) + return err +} + +// DeleteRadixDNSAlias Delete RadixDNSAliases +func (kubeutil *Kube) DeleteRadixDNSAlias(radixDNSAlias *radixv1.RadixDNSAlias) error { + return kubeutil.radixclient.RadixV1().RadixDNSAliases().Delete(context.Background(), radixDNSAlias.GetName(), metav1.DeleteOptions{}) +} diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go index 8221e6cab..2a5e9304d 100644 --- a/radix-operator/dnsalias/handler.go +++ b/radix-operator/dnsalias/handler.go @@ -1,7 +1,6 @@ package dnsalias import ( - "context" "fmt" "github.com/equinor/radix-operator/pkg/apis/dnsalias" @@ -12,7 +11,6 @@ import ( "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/record" @@ -71,7 +69,7 @@ func WithSyncerFactory(factory internal.SyncerFactory) HandlerConfigOption { // Sync is called by kubernetes after the Controller Enqueues a work-item func (h *handler) Sync(_, name string, eventRecorder record.EventRecorder) error { - radixDNSAlias, err := h.radixClient.RadixV1().RadixDNSAliases().Get(context.Background(), name, metav1.GetOptions{}) + radixDNSAlias, err := h.kubeUtil.GetRadixDNSAlias(name) if err != nil { if errors.IsNotFound(err) { utilruntime.HandleError(fmt.Errorf("RadixDNSAlias %s in work queue no longer exists", name)) From eb3d087b73fce23e7556c1b05f0a7f747611a960 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 31 Oct 2023 13:12:39 +0100 Subject: [PATCH 020/121] Added unit-tests for dns aliases in app-config --- .../applicationconfig_test.go | 60 +++++++++++++++---- pkg/apis/applicationconfig/dnsaliases.go | 5 +- 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 531634b05..caa101df5 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -657,16 +657,7 @@ func Test_IsConfigBranch(t *testing.T) { }) } -type testIngress struct { - appName string - envName string - name string - host string - component string - port int32 -} - -func Test_DNSAliases(t *testing.T) { +func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { const ( appName1 = "any-app1" appName2 = "any-app2" @@ -845,6 +836,28 @@ func Test_DNSAliases(t *testing.T) { domain4: {AppName: appName2, Environment: env1, Component: component1}, }, }, + { + name: "create new, remove some, change other aliases", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithDNSAlias( + radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component2}, + radixv1.DNSAlias{Domain: domain3, Environment: env2, Component: component1}, + ). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), + ), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1}, + domain2: {AppName: appName1, Environment: env1, Component: component2}, + domain4: {AppName: appName2, Environment: env1, Component: component1}, + }, + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component2}, + domain3: {AppName: appName1, Environment: env2, Component: component1}, + domain4: {AppName: appName2, Environment: env1, Component: component1}, + }, + }, } for _, ts := range testScenarios { @@ -878,6 +891,33 @@ func Test_DNSAliases(t *testing.T) { } } +func Test_DNSAliases_FileOndInvalidAppName(t *testing.T) { + const ( + appName1 = "any-app1" + appName2 = "any-app2" + env1 = "env1" + component1 = "server1" + domain1 = "domain1" + branch1 = "branch1" + portA = "port-a" + port8080 = 8080 + ) + tu, kubeClient, kubeUtil, radixClient := setupTest() + + _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), + &radixv1.RadixDNSAlias{ + ObjectMeta: metav1.ObjectMeta{Name: domain1, Labels: map[string]string{kube.RadixAppLabel: appName1}}, + Spec: radixv1.RadixDNSAliasSpec{AppName: appName2, Environment: env1, Component: component1}, + }, metav1.CreateOptions{}) + require.NoError(t, err, "create existing RadixDNSAlias") + + applicationBuilder := utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). + WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)) + err = applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, applicationBuilder) + require.Error(t, err, "register radix application") +} + func registerExistingRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]radixv1.RadixDNSAliasSpec) error { for domain, rdaSpec := range radixDNSAliasesMap { _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), diff --git a/pkg/apis/applicationconfig/dnsaliases.go b/pkg/apis/applicationconfig/dnsaliases.go index 366cf83d3..d2b66a5c1 100644 --- a/pkg/apis/applicationconfig/dnsaliases.go +++ b/pkg/apis/applicationconfig/dnsaliases.go @@ -22,13 +22,10 @@ func (app *ApplicationConfig) createOrUpdateDNSAliases() error { if radixDNSAlias, ok := radixDNSAliasesMap[dnsAlias.Domain]; ok { switch { case !strings.EqualFold(appName, radixDNSAlias.Spec.AppName): - // TODO test errs = append(errs, fmt.Errorf("existing DNS alias domain %s is used by the application %s", dnsAlias.Domain, radixDNSAlias.Spec.AppName)) case strings.EqualFold(dnsAlias.Environment, radixDNSAlias.Spec.Environment) && strings.EqualFold(dnsAlias.Component, radixDNSAlias.Spec.Component): - // TODO test - // Do nothing + // No changes default: - // TODO test if err = app.updateRadixDNSAlias(radixDNSAlias, dnsAlias); err != nil { errs = append(errs, err) } From 3f307aaaa63a381a10d41ad274744a465a08add3 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 31 Oct 2023 16:50:31 +0100 Subject: [PATCH 021/121] Added port to the Radix DNS Alias --- .../templates/radixdnsalias.yaml | 14 +++ json-schema/radixdnsalias.json | 18 ++- .../applicationconfig/applicationconfig.go | 55 +++++++--- .../applicationconfig_test.go | 95 +++++++++------- pkg/apis/applicationconfig/dnsaliases.go | 30 +++-- pkg/apis/applicationconfig/ownerreference.go | 18 +++ pkg/apis/dnsalias/{internal => }/ingress.go | 5 +- pkg/apis/dnsalias/syncer.go | 50 ++------- pkg/apis/dnsalias/syncer_test.go | 103 ++++++------------ pkg/apis/radix/v1/radixapptypes.go | 1 + pkg/apis/radix/v1/radixdnsaliastypes.go | 5 + pkg/apis/radixvalidators/validate_ra.go | 28 +++-- pkg/apis/test/utils.go | 3 +- .../typed/radix/v1/fake/fake_radixalert.go | 5 +- .../radix/v1/fake/fake_radixapplication.go | 5 +- .../typed/radix/v1/fake/fake_radixbatch.go | 5 +- .../radix/v1/fake/fake_radixdeployment.go | 5 +- .../typed/radix/v1/fake/fake_radixdnsalias.go | 5 +- .../radix/v1/fake/fake_radixenvironment.go | 5 +- .../typed/radix/v1/fake/fake_radixjob.go | 7 +- .../radix/v1/fake/fake_radixregistration.go | 5 +- radix-operator/dnsalias/controller.go | 11 +- radix-operator/dnsalias/controller_test.go | 38 ++++--- .../dnsalias/internal/radix_dns_alias.go | 29 +++++ radix-operator/dnsalias/internal/utils.go | 77 ------------- 25 files changed, 310 insertions(+), 312 deletions(-) create mode 100644 pkg/apis/applicationconfig/ownerreference.go rename pkg/apis/dnsalias/{internal => }/ingress.go (94%) create mode 100644 radix-operator/dnsalias/internal/radix_dns_alias.go delete mode 100644 radix-operator/dnsalias/internal/utils.go diff --git a/charts/radix-operator/templates/radixdnsalias.yaml b/charts/radix-operator/templates/radixdnsalias.yaml index a40d70a90..8bf8a1361 100644 --- a/charts/radix-operator/templates/radixdnsalias.yaml +++ b/charts/radix-operator/templates/radixdnsalias.yaml @@ -37,6 +37,12 @@ spec: spec: description: RadixDNSAliasSpec is the spec for an RadixDNSAlias properties: + appName: + description: Name of the application the DNS alias used in. + maxLength: 253 + minLength: 1 + pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + type: string component: description: Name of the component that shall receive the incoming requests. @@ -50,9 +56,17 @@ spec: minLength: 1 pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ type: string + port: + description: Port number. + format: int32 + maximum: 65535 + minimum: 1024 + type: integer required: + - appName - component - environment + - port type: object status: description: RadixDNSAliasStatus is the status for an RadixDNSAlias diff --git a/json-schema/radixdnsalias.json b/json-schema/radixdnsalias.json index dd74c60ee..ddd004d94 100644 --- a/json-schema/radixdnsalias.json +++ b/json-schema/radixdnsalias.json @@ -15,6 +15,13 @@ "spec": { "description": "RadixDNSAliasSpec is the spec for an RadixDNSAlias", "properties": { + "appName": { + "description": "Name of the application the DNS alias used in.", + "maxLength": 253, + "minLength": 1, + "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "type": "string" + }, "component": { "description": "Name of the component that shall receive the incoming requests.", "maxLength": 63, @@ -28,11 +35,20 @@ "minLength": 1, "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", "type": "string" + }, + "port": { + "description": "Port number.", + "format": "int32", + "maximum": 65535, + "minimum": 1024, + "type": "integer" } }, "required": [ + "appName", "component", - "environment" + "environment", + "port" ], "type": "object" }, diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index 8677b4477..24e94a4f9 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -8,9 +8,10 @@ import ( "strings" commonErrors "github.com/equinor/radix-common/utils/errors" + "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/branch" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -30,8 +31,8 @@ type ApplicationConfig struct { kubeclient kubernetes.Interface radixclient radixclient.Interface kubeutil *kube.Kube - registration *v1.RadixRegistration - config *v1.RadixApplication + registration *radixv1.RadixRegistration + config *radixv1.RadixApplication } // NewApplicationConfig Constructor @@ -39,8 +40,8 @@ func NewApplicationConfig( kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, - registration *v1.RadixRegistration, - config *v1.RadixApplication) (*ApplicationConfig, error) { + registration *radixv1.RadixRegistration, + config *radixv1.RadixApplication) (*ApplicationConfig, error) { return &ApplicationConfig{ kubeclient, radixclient, @@ -50,17 +51,17 @@ func NewApplicationConfig( } // GetRadixApplicationConfig returns the provided config -func (app *ApplicationConfig) GetRadixApplicationConfig() *v1.RadixApplication { +func (app *ApplicationConfig) GetRadixApplicationConfig() *radixv1.RadixApplication { return app.config } // GetRadixRegistration returns the provided radix registration -func (app *ApplicationConfig) GetRadixRegistration() *v1.RadixRegistration { +func (app *ApplicationConfig) GetRadixRegistration() *radixv1.RadixRegistration { return app.registration } // GetComponent Gets the component for a provided name -func GetComponent(ra *v1.RadixApplication, name string) v1.RadixCommonComponent { +func GetComponent(ra *radixv1.RadixApplication, name string) radixv1.RadixCommonComponent { for _, component := range ra.Spec.Components { if strings.EqualFold(component.Name, name) { return &component @@ -75,13 +76,13 @@ func GetComponent(ra *v1.RadixApplication, name string) v1.RadixCommonComponent } // GetComponentEnvironmentConfig Gets environment config of component. This method is used by radix-api -func GetComponentEnvironmentConfig(ra *v1.RadixApplication, envName, componentName string) v1.RadixCommonEnvironmentConfig { +func GetComponentEnvironmentConfig(ra *radixv1.RadixApplication, envName, componentName string) radixv1.RadixCommonEnvironmentConfig { // TODO: Add interface for RA + EnvConfig return GetEnvironment(GetComponent(ra, componentName), envName) } // GetEnvironment Gets environment config of component -func GetEnvironment(component v1.RadixCommonComponent, envName string) v1.RadixCommonEnvironmentConfig { +func GetEnvironment(component radixv1.RadixCommonComponent, envName string) radixv1.RadixCommonEnvironmentConfig { if component == nil { return nil } @@ -95,12 +96,12 @@ func GetEnvironment(component v1.RadixCommonComponent, envName string) v1.RadixC } // GetConfigBranch Returns config branch name from radix registration, or "master" if not set. -func GetConfigBranch(rr *v1.RadixRegistration) string { +func GetConfigBranch(rr *radixv1.RadixRegistration) string { return utils.TernaryString(strings.TrimSpace(rr.Spec.ConfigBranch) == "", ConfigBranchFallback, rr.Spec.ConfigBranch) } // IsConfigBranch Checks if given branch is where radix config lives -func IsConfigBranch(branch string, rr *v1.RadixRegistration) bool { +func IsConfigBranch(branch string, rr *radixv1.RadixRegistration) bool { return strings.EqualFold(branch, GetConfigBranch(rr)) } @@ -110,7 +111,7 @@ func (app *ApplicationConfig) IsThereAnythingToDeploy(branch string) (bool, map[ } // IsThereAnythingToDeployForRadixApplication Checks if given branch requires deployment to environments -func IsThereAnythingToDeployForRadixApplication(branch string, ra *v1.RadixApplication) (bool, map[string]bool) { +func IsThereAnythingToDeployForRadixApplication(branch string, ra *radixv1.RadixApplication) (bool, map[string]bool) { targetEnvs := getTargetEnvironmentsAsMap(branch, ra) if isTargetEnvsEmpty(targetEnvs) { return false, targetEnvs @@ -205,7 +206,7 @@ func (app *ApplicationConfig) createEnvironments() error { return commonErrors.Concat(errs) } -func getTargetEnvironmentsAsMap(branchToBuild string, radixApplication *v1.RadixApplication) map[string]bool { +func getTargetEnvironmentsAsMap(branchToBuild string, radixApplication *radixv1.RadixApplication) map[string]bool { targetEnvs := make(map[string]bool) for _, env := range radixApplication.Spec.Environments { if env.Build.From != "" && branch.MatchesPattern(env.Build.From, branchToBuild) { @@ -235,7 +236,7 @@ func isTargetEnvsEmpty(targetEnvs map[string]bool) bool { } // applyEnvironment creates an environment or applies changes if it exists -func (app *ApplicationConfig) applyEnvironment(newRe *v1.RadixEnvironment) error { +func (app *ApplicationConfig) applyEnvironment(newRe *radixv1.RadixEnvironment) error { logger := log.WithFields(log.Fields{"environment": newRe.ObjectMeta.Name}) logger.Debugf("Apply environment %s", newRe.Name) @@ -267,8 +268,28 @@ func (app *ApplicationConfig) applyEnvironment(newRe *v1.RadixEnvironment) error return nil } +func (app *ApplicationConfig) getPortForDNSAlias(dnsAlias radixv1.DNSAlias) (int32, error) { + component, componentFound := slice.FindFirst(app.config.Spec.Components, func(c radixv1.RadixComponent) bool { + return c.Name == dnsAlias.Component + }) + if !componentFound { + // TODO test + return 0, fmt.Errorf("component %s does not exist in the application %s", dnsAlias.Component, app.config.GetName()) + } + if !component.GetEnabledForAnyEnvironment([]string{dnsAlias.Environment}) { + // TODO test + return 0, fmt.Errorf("component %s is not enabled for the environment %s in the application %s", dnsAlias.Component, dnsAlias.Environment, app.config.GetName()) + } + componentPublicPort := getComponentPublicPort(&component) + if componentPublicPort == nil { + // TODO test + return 0, fmt.Errorf("component %s does not have public port in the application %s", dnsAlias.Component, app.config.GetName()) + } + return componentPublicPort.Port, nil +} + // patchDifference creates a mergepatch, comparing old and new RadixEnvironments and issues the patch to radix -func patchDifference(repository radixTypes.RadixEnvironmentInterface, oldRe *v1.RadixEnvironment, newRe *v1.RadixEnvironment, logger *log.Entry) error { +func patchDifference(repository radixTypes.RadixEnvironmentInterface, oldRe *radixv1.RadixEnvironment, newRe *radixv1.RadixEnvironment, logger *log.Entry) error { radixEnvironment := oldRe.DeepCopy() radixEnvironment.ObjectMeta.Labels = newRe.ObjectMeta.Labels radixEnvironment.ObjectMeta.OwnerReferences = newRe.ObjectMeta.OwnerReferences @@ -286,7 +307,7 @@ func patchDifference(repository radixTypes.RadixEnvironmentInterface, oldRe *v1. return fmt.Errorf("failed to marshal new RadixEnvironment object: %v", err) } - patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldReJSON, radixEnvironmentJSON, v1.RadixEnvironment{}) + patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldReJSON, radixEnvironmentJSON, radixv1.RadixEnvironment{}) if err != nil { return fmt.Errorf("failed to create patch document for RadixEnvironment object: %v", err) } diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index caa101df5..b65b94dfa 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -669,6 +669,7 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { branch2 = "branch2" portA = "port-a" port8080 = 8080 + port9090 = 9090 domain1 = "domain1" domain2 = "domain2" domain3 = "domain3" @@ -692,7 +693,7 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1}, + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, }, { @@ -704,11 +705,11 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { ). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), - utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1}, - domain2: {AppName: appName1, Environment: env1, Component: component2}, + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, }, }, { @@ -720,15 +721,15 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { ). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), - utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1}, - domain2: {AppName: appName1, Environment: env2, Component: component1}, + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain2: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, }, }, { - name: "multiple aliases for one component and enironment", + name: "multiple aliases for one component and environment", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). WithDNSAlias( radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, @@ -736,8 +737,8 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { ). WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1}, - domain2: {AppName: appName1, Environment: env1, Component: component1}, + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain2: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, }, { @@ -749,11 +750,11 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { ). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), - utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1}, - domain2: {AppName: appName1, Environment: env2, Component: component2}, + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain2: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, }, }, { @@ -762,11 +763,11 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain2: {AppName: appName2, Environment: env1, Component: component1}, + domain2: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, }, expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain2: {AppName: appName2, Environment: env1, Component: component1}, - domain1: {AppName: appName1, Environment: env1, Component: component1}, + domain2: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, }, { @@ -775,13 +776,13 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env2, Component: component2}). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), - utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1}, + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env2, Component: component2}, + domain1: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, }, }, { @@ -793,15 +794,15 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { ). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), - utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1}, - domain2: {AppName: appName1, Environment: env2, Component: component2}, + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain2: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, }, expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env2, Component: component2}, - domain2: {AppName: appName1, Environment: env1, Component: component1}, + domain1: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, + domain2: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, }, { @@ -809,7 +810,7 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1}, + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{}, }, @@ -822,18 +823,18 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { ). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), - utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1}, - domain2: {AppName: appName1, Environment: env1, Component: component2}, - domain3: {AppName: appName1, Environment: env2, Component: component1}, - domain4: {AppName: appName2, Environment: env1, Component: component1}, + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, + domain3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, + domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, }, expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1}, - domain3: {AppName: appName1, Environment: env2, Component: component1}, - domain4: {AppName: appName2, Environment: env1, Component: component1}, + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, + domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, }, }, { @@ -845,17 +846,17 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { ). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), - utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1}, - domain2: {AppName: appName1, Environment: env1, Component: component2}, - domain4: {AppName: appName2, Environment: env1, Component: component1}, + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, + domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, }, expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component2}, - domain3: {AppName: appName1, Environment: env2, Component: component1}, - domain4: {AppName: appName2, Environment: env1, Component: component1}, + domain1: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, + domain3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, + domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, }, }, } @@ -882,9 +883,21 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { assert.Equal(t, expectedDNSAlias.AppName, radixDNSAlias.Spec.AppName, "app name") assert.Equal(t, expectedDNSAlias.Environment, radixDNSAlias.Spec.Environment, "environment") assert.Equal(t, expectedDNSAlias.Component, radixDNSAlias.Spec.Component, "component") + assert.Equal(t, expectedDNSAlias.Port, radixDNSAlias.Spec.Port, "port") + if _, itWasExistingAlias := ts.existingRadixDNSAliases[radixDNSAlias.Name]; !itWasExistingAlias { + ownerReferences := radixDNSAlias.GetOwnerReferences() + require.Len(t, ownerReferences, 1) + ownerReference := ownerReferences[0] + assert.Equal(t, radixDNSAlias.Spec.AppName, ownerReference.Name, "invalid or empty ownerReference.Name") + assert.Equal(t, radix.KindRadixApplication, ownerReference.Kind, "invalid or empty ownerReference.Kind") + assert.NotEmpty(t, ownerReference.UID, "ownerReference.UID is empty") + require.NotNil(t, ownerReference.Controller, "ownerReference.Controller is nil") + assert.True(t, *ownerReference.Controller, "ownerReference.Controller is false") + } continue } - assert.Fail(t, fmt.Sprintf("found not expected RadixDNSAlias %s: env %s, component %s, appName %s", radixDNSAlias.GetName(), radixDNSAlias.Spec.Environment, radixDNSAlias.Spec.Component, radixDNSAlias.Spec.AppName)) + assert.Fail(t, fmt.Sprintf("found not expected RadixDNSAlias %s: env %s, component %s, port %d, appName %s", + radixDNSAlias.GetName(), radixDNSAlias.Spec.Environment, radixDNSAlias.Spec.Component, radixDNSAlias.Spec.Port, radixDNSAlias.Spec.AppName)) } } }) diff --git a/pkg/apis/applicationconfig/dnsaliases.go b/pkg/apis/applicationconfig/dnsaliases.go index d2b66a5c1..5efe9ff44 100644 --- a/pkg/apis/applicationconfig/dnsaliases.go +++ b/pkg/apis/applicationconfig/dnsaliases.go @@ -19,21 +19,27 @@ func (app *ApplicationConfig) createOrUpdateDNSAliases() error { } var errs []error for _, dnsAlias := range app.config.Spec.DNSAlias { + port, err := app.getPortForDNSAlias(dnsAlias) + if err != nil { + return err + } if radixDNSAlias, ok := radixDNSAliasesMap[dnsAlias.Domain]; ok { switch { case !strings.EqualFold(appName, radixDNSAlias.Spec.AppName): errs = append(errs, fmt.Errorf("existing DNS alias domain %s is used by the application %s", dnsAlias.Domain, radixDNSAlias.Spec.AppName)) - case strings.EqualFold(dnsAlias.Environment, radixDNSAlias.Spec.Environment) && strings.EqualFold(dnsAlias.Component, radixDNSAlias.Spec.Component): + case strings.EqualFold(dnsAlias.Environment, radixDNSAlias.Spec.Environment) && + strings.EqualFold(dnsAlias.Component, radixDNSAlias.Spec.Component) && + port == radixDNSAlias.Spec.Port: // No changes default: - if err = app.updateRadixDNSAlias(radixDNSAlias, dnsAlias); err != nil { + if err = app.updateRadixDNSAlias(radixDNSAlias, dnsAlias, port); err != nil { errs = append(errs, err) } } delete(radixDNSAliasesMap, dnsAlias.Domain) continue } - if err = app.createRadixDNSAlias(appName, dnsAlias); err != nil { + if err = app.createRadixDNSAlias(appName, dnsAlias, port); err != nil { errs = append(errs, err) } } @@ -45,23 +51,33 @@ func (app *ApplicationConfig) createOrUpdateDNSAliases() error { return errors.Concat(errs) } -func (app *ApplicationConfig) updateRadixDNSAlias(radixDNSAlias *radixv1.RadixDNSAlias, dnsAlias radixv1.DNSAlias) error { +func getComponentPublicPort(component *radixv1.RadixComponent) *radixv1.ComponentPort { + if port, ok := slice.FindFirst(component.GetPorts(), func(p radixv1.ComponentPort) bool { return p.Name == component.PublicPort }); ok { + return &port + } + return nil +} + +func (app *ApplicationConfig) updateRadixDNSAlias(radixDNSAlias *radixv1.RadixDNSAlias, dnsAlias radixv1.DNSAlias, port int32) error { updatedRadixDNSAlias := radixDNSAlias.DeepCopy() updatedRadixDNSAlias.Spec.Environment = dnsAlias.Environment updatedRadixDNSAlias.Spec.Component = dnsAlias.Component + updatedRadixDNSAlias.Spec.Port = port return app.kubeutil.UpdateRadixDNSAlias(updatedRadixDNSAlias) } -func (app *ApplicationConfig) createRadixDNSAlias(appName string, dnsAlias radixv1.DNSAlias) error { +func (app *ApplicationConfig) createRadixDNSAlias(appName string, dnsAlias radixv1.DNSAlias, port int32) error { radixDNSAlias := radixv1.RadixDNSAlias{ ObjectMeta: metav1.ObjectMeta{ - Name: dnsAlias.Domain, - Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(dnsAlias.Component)), + Name: dnsAlias.Domain, + Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(dnsAlias.Component)), + OwnerReferences: []metav1.OwnerReference{getOwnerReferenceOfApplication(app.config)}, }, Spec: radixv1.RadixDNSAliasSpec{ AppName: appName, Environment: dnsAlias.Environment, Component: dnsAlias.Component, + Port: port, }, } return app.kubeutil.CreateRadixDNSAlias(&radixDNSAlias) diff --git a/pkg/apis/applicationconfig/ownerreference.go b/pkg/apis/applicationconfig/ownerreference.go new file mode 100644 index 000000000..798512f71 --- /dev/null +++ b/pkg/apis/applicationconfig/ownerreference.go @@ -0,0 +1,18 @@ +package applicationconfig + +import ( + "github.com/equinor/radix-common/utils" + "github.com/equinor/radix-operator/pkg/apis/radix" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func getOwnerReferenceOfApplication(radixApplication *radixv1.RadixApplication) metav1.OwnerReference { + return metav1.OwnerReference{ + APIVersion: radix.APIVersion, + Kind: radix.KindRadixApplication, + Name: radixApplication.Name, + UID: radixApplication.UID, + Controller: utils.BoolPtr(true), + } +} diff --git a/pkg/apis/dnsalias/internal/ingress.go b/pkg/apis/dnsalias/ingress.go similarity index 94% rename from pkg/apis/dnsalias/internal/ingress.go rename to pkg/apis/dnsalias/ingress.go index 170470f72..41c2e8991 100644 --- a/pkg/apis/dnsalias/internal/ingress.go +++ b/pkg/apis/dnsalias/ingress.go @@ -1,10 +1,11 @@ -package internal +package dnsalias import ( "context" "fmt" "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/annotations" @@ -53,7 +54,7 @@ func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, owne }, }} if owner != nil { - ingress.SetOwnerReferences([]metav1.OwnerReference{GetOwnerReference(owner)}) + ingress.SetOwnerReferences([]metav1.OwnerReference{internal.GetOwnerReference(owner)}) } return &ingress } diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 0eb0855a4..abd62f525 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -1,11 +1,8 @@ package dnsalias import ( - "context" "fmt" - "github.com/equinor/radix-common/utils/slice" - "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -13,7 +10,6 @@ import ( "github.com/equinor/radix-operator/radix-operator/config" networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" ) @@ -57,26 +53,17 @@ func (s *syncer) OnSync() error { func (s *syncer) syncAlias() error { aliasSpec := s.radixDNSAlias.Spec - appName := aliasSpec.AppName domainName := s.radixDNSAlias.GetName() - ra, err := s.radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName)). - Get(context.Background(), appName, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - return fmt.Errorf("not found the Radix application %s for the DNS alias %s", appName, domainName) - } - return err - } envNamespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) - ingressName := internal.GetDNSAliasIngressName(aliasSpec.Component, domainName) + ingressName := GetDNSAliasIngressName(aliasSpec.Component, domainName) existingIngress, err := s.kubeUtil.GetIngress(envNamespace, ingressName) if err != nil { if errors.IsNotFound(err) { - return s.createIngress(ra) + return s.createIngress() } return err } - updatedIngress, err := s.buildIngress(ra) + updatedIngress, err := s.buildIngress() if err != nil { return err } @@ -87,39 +74,18 @@ func (s *syncer) syncAlias() error { return nil } -func (s *syncer) createIngress(ra *radixv1.RadixApplication) error { - ingress, err := s.buildIngress(ra) +func (s *syncer) createIngress() error { + ingress, err := s.buildIngress() if err != nil { return err } aliasSpec := s.radixDNSAlias.Spec - _, err = internal.CreateRadixDNSAliasIngress(s.kubeClient, aliasSpec.AppName, aliasSpec.Environment, ingress) + _, err = CreateRadixDNSAliasIngress(s.kubeClient, aliasSpec.AppName, aliasSpec.Environment, ingress) return err } -func (s *syncer) buildIngress(ra *radixv1.RadixApplication) (*networkingv1.Ingress, error) { +func (s *syncer) buildIngress() (*networkingv1.Ingress, error) { aliasSpec := s.radixDNSAlias.Spec - portNumber, err := getComponentPublicPortNumber(ra, aliasSpec.Component) - if err != nil { - return nil, err - } domain := s.radixDNSAlias.GetName() - return internal.BuildRadixDNSAliasIngress(aliasSpec.AppName, domain, aliasSpec.Component, portNumber, s.radixDNSAlias, s.clusterConfig), nil -} - -func getComponentPublicPortNumber(ra *radixv1.RadixApplication, componentName string) (int32, error) { - component, componentExists := slice.FindFirst(ra.Spec.Components, func(c radixv1.RadixComponent) bool { - return c.Name == componentName - }) - if !componentExists { - return 0, fmt.Errorf("not found component %s in the application %s for the DNS alias", componentName, ra.GetName()) - } - componentPort, publicPortExists := slice.FindFirst(component.Ports, func(p radixv1.ComponentPort) bool { - return p.Name == component.PublicPort - }) - if !publicPortExists { - return 0, fmt.Errorf("not found component %s in the application %s for the DNS alias", componentName, ra.GetName()) - } - - return componentPort.Port, nil + return BuildRadixDNSAliasIngress(aliasSpec.AppName, domain, aliasSpec.Component, aliasSpec.Port, s.radixDNSAlias, s.clusterConfig), nil } diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index e5345f765..341b22dcd 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -5,9 +5,7 @@ import ( "fmt" "testing" - commonUtils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-operator/pkg/apis/dnsalias" - "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -16,12 +14,11 @@ import ( radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" "github.com/equinor/radix-operator/radix-operator/config" - "github.com/google/uuid" prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/client-go/kubernetes" kubefake "k8s.io/client-go/kubernetes/fake" secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake" @@ -60,17 +57,21 @@ type testIngress struct { component string port int32 } +type testDNSAlias struct { + Domain string + Environment string + Component string + Port int32 +} type scenario struct { - name string - expectedError string - missingRadixApplication bool - dnsAlias radixv1.DNSAlias - dnsZone string - existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec - existingIngress []testIngress - expectedIngress map[string]testIngress - applicationComponentBuilder utils.RadixApplicationComponentBuilder + name string + expectedError string + dnsAlias testDNSAlias + dnsZone string + existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec + existingIngress []testIngress + expectedIngress map[string]testIngress } func (s *syncerTestSuite) Test_syncer_OnSync() { @@ -81,8 +82,6 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { component2 = "component2" domain1 = "domain1" domain2 = "domain2" - portHttp = "http" - portAbc = "abc" port8080 = 8080 port9090 = 9090 dnsZone1 = "test.radix.equinor.com" @@ -90,75 +89,54 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { scenarios := []scenario{ { - name: "no radix application", - missingRadixApplication: true, - applicationComponentBuilder: getRandomComponentBuilder(), - expectedError: "not found the Radix application app1 for the DNS alias domain1", - dnsAlias: radixv1.DNSAlias{Domain: domain1, Environment: envName1, Component: component1}, - }, - { - name: "created an ingress", - dnsAlias: radixv1.DNSAlias{Domain: domain1, Environment: envName1, Component: component1}, - dnsZone: dnsZone1, - applicationComponentBuilder: utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portHttp, port8080).WithPublicPort(portHttp), + name: "created an ingress", + dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, expectedIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, }, }, { - name: "created additional ingress for another component", - dnsAlias: radixv1.DNSAlias{Domain: domain1, Environment: envName1, Component: component1}, - dnsZone: dnsZone1, - applicationComponentBuilder: utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portHttp, port8080).WithPublicPort(portHttp), + name: "created additional ingress for another component", + dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, existingIngress: []testIngress{ - {appName: appName1, envName: envName1, domain: domain2, host: internal.GetDNSAliasHost(domain2, dnsZone1), component: component2, port: port8080}, + {appName: appName1, envName: envName1, domain: domain2, host: dnsalias.GetDNSAliasHost(domain2, dnsZone1), component: component2, port: port8080}, }, expectedIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, - "component2.domain2.custom-domain": {appName: appName1, envName: envName1, domain: domain2, host: internal.GetDNSAliasHost(domain2, dnsZone1), component: component2, port: port8080}, + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + "component2.domain2.custom-domain": {appName: appName1, envName: envName1, domain: domain2, host: dnsalias.GetDNSAliasHost(domain2, dnsZone1), component: component2, port: port8080}, }, }, { name: "changed public port on component changes port in existing ingress", - dnsAlias: radixv1.DNSAlias{Domain: domain1, Environment: envName1, Component: component1}, + dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port9090}, dnsZone: dnsZone1, - applicationComponentBuilder: utils.NewApplicationComponentBuilder().WithName(component1).WithPorts([]radixv1.ComponentPort{ - {Name: portHttp, Port: port8080}, - {Name: portAbc, Port: port9090}, - }).WithPublicPort(portAbc), existingIngress: []testIngress{ - {appName: appName1, envName: envName1, domain: domain1, host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, }, expectedIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port9090}, + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port9090}, }, }, { - name: "created additional ingress on another domain for the same component", - dnsAlias: radixv1.DNSAlias{Domain: domain2, Environment: envName1, Component: component1}, - dnsZone: dnsZone1, - applicationComponentBuilder: utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portHttp, port8080).WithPublicPort(portHttp), + name: "created additional ingress on another domain for the same component", + dnsAlias: testDNSAlias{Domain: domain2, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, existingIngress: []testIngress{ - {appName: appName1, envName: envName1, domain: domain1, host: internal.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, + {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, }, expectedIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: internal.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, - "component1.domain2.custom-domain": {appName: appName1, envName: envName1, domain: domain2, host: internal.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + "component1.domain2.custom-domain": {appName: appName1, envName: envName1, domain: domain2, host: dnsalias.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, }, }, } for _, ts := range scenarios { s.T().Run(ts.name, func(t *testing.T) { s.SetupTest() - if !ts.missingRadixApplication { - s.Require().NotNil(ts.applicationComponentBuilder) - ra := utils.NewRadixApplicationBuilder().WithAppName(appName1).WithEnvironment(envName1, "master"). - WithComponents(ts.applicationComponentBuilder, getRandomComponentBuilder()).BuildRA() - _, err := s.radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(appName1)).Create(context.Background(), ra, metav1.CreateOptions{}) - s.NoError(err) - } - radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Domain, UID: getUuid()}, - Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component}} + radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Domain, UID: uuid.NewUUID()}, + Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component, Port: ts.dnsAlias.Port}} s.Require().NoError(registerExistingRadixDNSAlias(s.radixClient, radixDNSAlias), "create existing alias") cfg := &config.ClusterConfig{DNSZone: ts.dnsZone} s.Require().NoError(registerExistingIngresses(s.kubeClient, ts.existingIngress, cfg), "create existing ingresses") @@ -207,14 +185,9 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { } } -func getUuid() types.UID { - newUUID, _ := uuid.NewUUID() - return types.UID(newUUID.String()) -} - func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses []testIngress, config *config.ClusterConfig) error { for _, ing := range testIngresses { - _, err := internal.CreateRadixDNSAliasIngress(kubeClient, ing.appName, ing.envName, internal.BuildRadixDNSAliasIngress(ing.appName, ing.domain, ing.component, ing.port, nil, config)) + _, err := dnsalias.CreateRadixDNSAliasIngress(kubeClient, ing.appName, ing.envName, dnsalias.BuildRadixDNSAliasIngress(ing.appName, ing.domain, ing.component, ing.port, nil, config)) if err != nil { return err } @@ -222,10 +195,6 @@ func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses [] return nil } -func getRandomComponentBuilder() utils.RadixApplicationComponentBuilder { - return utils.NewApplicationComponentBuilder().WithName(commonUtils.RandString(20)).WithPort("p", 9000).WithPublicPort("s") -} - func registerExistingRadixDNSAlias(radixClient radixclient.Interface, radixDNSAlias *radixv1.RadixDNSAlias) error { _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.TODO(), radixDNSAlias, metav1.CreateOptions{}) diff --git a/pkg/apis/radix/v1/radixapptypes.go b/pkg/apis/radix/v1/radixapptypes.go index e5d71abbe..714930c8d 100644 --- a/pkg/apis/radix/v1/radixapptypes.go +++ b/pkg/apis/radix/v1/radixapptypes.go @@ -1309,6 +1309,7 @@ type RadixCommonComponent interface { GetEnabledForEnv(RadixCommonEnvironmentConfig) bool // GetEnvironmentConfigByName Gets component environment configuration by its name GetEnvironmentConfigByName(environment string) RadixCommonEnvironmentConfig + // GetEnabledForAnyEnvironment Gets status Enabled of the component for any environment from the environment name list GetEnabledForAnyEnvironment(environments []string) bool } diff --git a/pkg/apis/radix/v1/radixdnsaliastypes.go b/pkg/apis/radix/v1/radixdnsaliastypes.go index 369bbaed1..7909f0955 100644 --- a/pkg/apis/radix/v1/radixdnsaliastypes.go +++ b/pkg/apis/radix/v1/radixdnsaliastypes.go @@ -43,6 +43,11 @@ type RadixDNSAliasSpec struct { // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ Component string `json:"component" yaml:"component"` + + // Port number. + // +kubebuilder:validation:Minimum=1024 + // +kubebuilder:validation:Maximum=65535 + Port int32 `json:"port"` } // RadixDNSAliasStatus is the status for an RadixDNSAlias diff --git a/pkg/apis/radixvalidators/validate_ra.go b/pkg/apis/radixvalidators/validate_ra.go index ec3c1e656..9243865c8 100644 --- a/pkg/apis/radixvalidators/validate_ra.go +++ b/pkg/apis/radixvalidators/validate_ra.go @@ -174,17 +174,31 @@ func RAContainsOldPublic(app *radixv1.RadixApplication) bool { } func validateDNSAppAlias(app *radixv1.RadixApplication) []error { - var errs []error alias := app.Spec.DNSAppAlias - if alias.Component == "" && alias.Environment == "" { - return errs + return validateComponentAndEnvironmentAvailable(app, alias.Component, alias.Environment) +} + +func validateDNSAlias(app *radixv1.RadixApplication) []error { + dnsAliases := app.Spec.DNSAlias + var errs []error + for _, dnsAlias := range dnsAliases { + if err := validateComponentAndEnvironmentAvailable(app, dnsAlias.Component, dnsAlias.Environment); err != nil { + errs = append(errs, err...) + } } + return errs +} - if !doesEnvExist(app, alias.Environment) { - errs = append(errs, EnvForDNSAppAliasNotDefinedError(alias.Environment)) +func validateComponentAndEnvironmentAvailable(app *radixv1.RadixApplication, component string, environment string) []error { + var errs []error + if component == "" && environment == "" { + return errs + } + if !doesEnvExist(app, environment) { + errs = append(errs, EnvForDNSAppAliasNotDefinedError(environment)) } - if !doesComponentExistInEnvironment(app, alias.Component, alias.Environment) { - errs = append(errs, ComponentForDNSAppAliasNotDefinedError(alias.Component)) + if !doesComponentExistInEnvironment(app, component, environment) { + errs = append(errs, ComponentForDNSAppAliasNotDefinedError(component)) } return errs } diff --git a/pkg/apis/test/utils.go b/pkg/apis/test/utils.go index 74a399875..511254fd9 100644 --- a/pkg/apis/test/utils.go +++ b/pkg/apis/test/utils.go @@ -15,6 +15,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/client-go/kubernetes" secretProviderClient "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned" ) @@ -95,7 +96,7 @@ func (tu *Utils) ApplyApplication(applicationBuilder utils.ApplicationBuilder) ( return ra, err } - + ra.ObjectMeta.UID = uuid.NewUUID() // imitate new UID, assigned by Kubernetes // Note: rr may be nil if not found but that is fine for _, env := range ra.Spec.Environments { tu.ApplyEnvironment(utils.NewEnvironmentBuilder(). diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixalert.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixalert.go index d529039f3..a19447b8d 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixalert.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixalert.go @@ -21,7 +21,6 @@ package fake import ( "context" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -37,9 +36,9 @@ type FakeRadixAlerts struct { ns string } -var radixalertsResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixalerts"} +var radixalertsResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixalerts"} -var radixalertsKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: radix.KindRadixAlert} +var radixalertsKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixAlert"} // Get takes name of the radixAlert, and returns the corresponding radixAlert object, and an error if there is any. func (c *FakeRadixAlerts) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixAlert, err error) { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixapplication.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixapplication.go index 29edfc8b9..cb1b4ab81 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixapplication.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixapplication.go @@ -21,7 +21,6 @@ package fake import ( "context" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -37,9 +36,9 @@ type FakeRadixApplications struct { ns string } -var radixapplicationsResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixapplications"} +var radixapplicationsResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixapplications"} -var radixapplicationsKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: radix.KindRadixApplication} +var radixapplicationsKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixApplication"} // Get takes name of the radixApplication, and returns the corresponding radixApplication object, and an error if there is any. func (c *FakeRadixApplications) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixApplication, err error) { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixbatch.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixbatch.go index 6a410b30f..91e0c7161 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixbatch.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixbatch.go @@ -21,7 +21,6 @@ package fake import ( "context" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -37,9 +36,9 @@ type FakeRadixBatches struct { ns string } -var radixbatchesResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixbatches"} +var radixbatchesResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixbatches"} -var radixbatchesKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: radix.KindRadixBatch} +var radixbatchesKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixBatch"} // Get takes name of the radixBatch, and returns the corresponding radixBatch object, and an error if there is any. func (c *FakeRadixBatches) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixBatch, err error) { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdeployment.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdeployment.go index 01d842e07..ae8f8cde9 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdeployment.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdeployment.go @@ -21,7 +21,6 @@ package fake import ( "context" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -37,9 +36,9 @@ type FakeRadixDeployments struct { ns string } -var radixdeploymentsResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixdeployments"} +var radixdeploymentsResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixdeployments"} -var radixdeploymentsKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: radix.KindRadixDeployment} +var radixdeploymentsKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixDeployment"} // Get takes name of the radixDeployment, and returns the corresponding radixDeployment object, and an error if there is any. func (c *FakeRadixDeployments) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixDeployment, err error) { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go index 39963e49c..863ed75b8 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixdnsalias.go @@ -21,7 +21,6 @@ package fake import ( "context" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -36,9 +35,9 @@ type FakeRadixDNSAliases struct { Fake *FakeRadixV1 } -var radixdnsaliasesResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixdnsaliases"} +var radixdnsaliasesResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixdnsaliases"} -var radixdnsaliasesKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: "RadixDNSAlias"} +var radixdnsaliasesKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixDNSAlias"} // Get takes name of the radixDNSAlias, and returns the corresponding radixDNSAlias object, and an error if there is any. func (c *FakeRadixDNSAliases) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixDNSAlias, err error) { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixenvironment.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixenvironment.go index c7b277d18..55d6f0155 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixenvironment.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixenvironment.go @@ -21,7 +21,6 @@ package fake import ( "context" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -36,9 +35,9 @@ type FakeRadixEnvironments struct { Fake *FakeRadixV1 } -var radixenvironmentsResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixenvironments"} +var radixenvironmentsResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixenvironments"} -var radixenvironmentsKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: radix.KindRadixEnvironment} +var radixenvironmentsKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixEnvironment"} // Get takes name of the radixEnvironment, and returns the corresponding radixEnvironment object, and an error if there is any. func (c *FakeRadixEnvironments) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixEnvironment, err error) { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixjob.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixjob.go index 0e91d1ab7..61685adc9 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixjob.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixjob.go @@ -21,9 +21,8 @@ package fake import ( "context" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1" + 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" @@ -37,9 +36,9 @@ type FakeRadixJobs struct { ns string } -var radixjobsResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixjobs"} +var radixjobsResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixjobs"} -var radixjobsKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: radix.KindRadixJob} +var radixjobsKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixJob"} // Get takes name of the radixJob, and returns the corresponding radixJob object, and an error if there is any. func (c *FakeRadixJobs) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixJob, err error) { diff --git a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixregistration.go b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixregistration.go index 543fd378e..c47ce1303 100644 --- a/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixregistration.go +++ b/pkg/client/clientset/versioned/typed/radix/v1/fake/fake_radixregistration.go @@ -21,7 +21,6 @@ package fake import ( "context" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" @@ -36,9 +35,9 @@ type FakeRadixRegistrations struct { Fake *FakeRadixV1 } -var radixregistrationsResource = schema.GroupVersionResource{Group: radix.GroupName, Version: radix.Version, Resource: "radixregistrations"} +var radixregistrationsResource = schema.GroupVersionResource{Group: "radix.equinor.com", Version: "v1", Resource: "radixregistrations"} -var radixregistrationsKind = schema.GroupVersionKind{Group: radix.GroupName, Version: radix.Version, Kind: radix.KindRadixRegistration} +var radixregistrationsKind = schema.GroupVersionKind{Group: "radix.equinor.com", Version: "v1", Kind: "RadixRegistration"} // Get takes name of the radixRegistration, and returns the corresponding radixRegistration object, and an error if there is any. func (c *FakeRadixRegistrations) Get(ctx context.Context, name string, options v1.GetOptions) (result *radixv1.RadixRegistration, err error) { diff --git a/radix-operator/dnsalias/controller.go b/radix-operator/dnsalias/controller.go index 20d38caf0..bfdf30211 100644 --- a/radix-operator/dnsalias/controller.go +++ b/radix-operator/dnsalias/controller.go @@ -4,7 +4,6 @@ import ( "context" "reflect" - "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/metrics" "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -99,9 +98,7 @@ func NewController(kubeClient kubernetes.Interface, if oldIng.GetResourceVersion() == newIng.GetResourceVersion() { return } - if radixDNSAliasName, managedByRadixDNSAlias := newIng.GetAnnotations()[kube.ManagedByRadixDNSAliasIngressAnnotation]; managedByRadixDNSAlias && len(radixDNSAliasName) > 0 { - controller.HandleObject(newObj, radix.KindRadixDNSAlias, getOwner) - } + controller.HandleObject(newObj, radix.KindRadixDNSAlias, getOwner) // restore ingress if it does not correspond to RadixDNSAlias }, DeleteFunc: func(obj interface{}) { ing, converted := obj.(*networkingv1.Ingress) @@ -109,11 +106,7 @@ func NewController(kubeClient kubernetes.Interface, logger.Errorf("Ingress object cast failed during deleted event received.") return } - radixDNSAliasName, managedByRadixDNSAlias := ing.GetAnnotations()[kube.ManagedByRadixDNSAliasIngressAnnotation] - if !managedByRadixDNSAlias || len(radixDNSAliasName) == 0 { - return - } - controller.Enqueue(radixDNSAliasName) // validate if ingress was deleted manually, but it should be restored + controller.HandleObject(ing, radix.KindRadixDNSAlias, getOwner) // restore ingress if RadixDNSAlias exist }, }) return controller diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go index 0ce9ce19a..30545b92e 100644 --- a/radix-operator/dnsalias/controller_test.go +++ b/radix-operator/dnsalias/controller_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/equinor/radix-common/utils/pointers" + dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/radix" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/radix-operator/common" @@ -31,7 +32,12 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { sut := dnsalias.NewController(s.KubeClient, s.RadixClient, s.Handler, s.KubeInformerFactory, s.RadixInformerFactory, false, s.EventRecorder) s.RadixInformerFactory.Start(s.Stop) s.KubeInformerFactory.Start(s.Stop) - go sut.Run(5, s.Stop) + go func() { + err := sut.Run(5, s.Stop) + if err != nil { + panic(err) + } + }() const ( appName1 = "any-app1" @@ -43,7 +49,6 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { componentName2 = "server2" dnsZone = "test.radix.equinor.com" ) - config := &config.ClusterConfig{DNSZone: dnsZone} alias := internal.BuildRadixDNSAlias(appName1, componentName1, envName1, aliasName) // Adding a RadixDNSAlias should trigger sync @@ -80,36 +85,37 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { s.WaitForNotSynced("Sync should not be called when updating RadixDNSAlias with no changes") // Add Ingress with owner reference to RadixDNSAlias should not trigger sync - ingress := internal.BuildRadixDNSAliasIngress(alias.Spec.AppName, alias.GetName(), alias.Spec.Component, int32(8080), config) + cfg := &config.ClusterConfig{DNSZone: dnsZone} + ingress := dnsaliasapi.BuildRadixDNSAliasIngress(alias.Spec.AppName, alias.GetName(), alias.Spec.Component, int32(8080), alias, cfg) ingress.SetOwnerReferences([]metav1.OwnerReference{{APIVersion: radix.APIVersion, Kind: radix.KindRadixDNSAlias, Name: aliasName, Controller: pointers.Ptr(true)}}) namespace := utils.GetEnvironmentNamespace(alias.Spec.AppName, alias.Spec.Environment) s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) - ingress, err = internal.CreateRadixDNSAliasIngress(s.KubeClient, alias.Spec.AppName, alias.Spec.Environment, ingress) + ingress, err = dnsaliasapi.CreateRadixDNSAliasIngress(s.KubeClient, alias.Spec.AppName, alias.Spec.Environment, ingress) s.Require().NoError(err) s.WaitForNotSynced("Sync should not be called when adding ingress") - // Delete the RadixDNSAlias should not trigger a sync - s.Handler.EXPECT().Sync("", aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) - err = s.RadixClient.RadixV1().RadixDNSAliases().Delete(context.TODO(), alias.GetName(), metav1.DeleteOptions{}) - s.Require().NoError(err) - s.WaitForNotSynced("Sync should be called when deleting RadixDNSAlias") - // Sync should not trigger on ingress update if resource version is unchanged s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) ingress, err = s.KubeClient.NetworkingV1().Ingresses(namespace).Update(context.Background(), ingress, metav1.UpdateOptions{}) s.Require().NoError(err) s.WaitForNotSynced("Sync should not be called on ingress update with no resource version change") - // Sync should not trigger on ingress update if resource version is changed + // Sync should trigger on ingress update if resource version is changed ingress.ResourceVersion = "2" - s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) + s.Handler.EXPECT().Sync("", aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) _, err = s.KubeClient.NetworkingV1().Ingresses(namespace).Update(context.Background(), ingress, metav1.UpdateOptions{}) s.Require().NoError(err) - s.WaitForNotSynced("Sync should not be called on k8s ingress update with changed resource version") + s.WaitForSynced("Sync should be called on k8s ingress update with changed resource version") - // Sync should not trigger when deleting ingress - s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) + // Sync should trigger when deleting ingress + s.Handler.EXPECT().Sync("", aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) err = s.KubeClient.NetworkingV1().Ingresses(namespace).Delete(context.Background(), ingress.GetName(), metav1.DeleteOptions{}) s.Require().NoError(err) - s.WaitForNotSynced("Sync should be called on ingress deletion") + s.WaitForSynced("Sync should be called on ingress deletion") + + // Delete the RadixDNSAlias should not trigger a sync + s.Handler.EXPECT().Sync("", aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) + err = s.RadixClient.RadixV1().RadixDNSAliases().Delete(context.TODO(), alias.GetName(), metav1.DeleteOptions{}) + s.Require().NoError(err) + s.WaitForNotSynced("Sync should be called when deleting RadixDNSAlias") } diff --git a/radix-operator/dnsalias/internal/radix_dns_alias.go b/radix-operator/dnsalias/internal/radix_dns_alias.go new file mode 100644 index 000000000..4d76450ef --- /dev/null +++ b/radix-operator/dnsalias/internal/radix_dns_alias.go @@ -0,0 +1,29 @@ +package internal + +import ( + "fmt" + + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/utils/labels" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// BuildRadixDNSAlias Build a RadixDNSAlias +func BuildRadixDNSAlias(appName, componentName, envName, domain string) *radixv1.RadixDNSAlias { + return &radixv1.RadixDNSAlias{ + ObjectMeta: metav1.ObjectMeta{ + Name: domain, + Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(componentName)), + }, + Spec: radixv1.RadixDNSAliasSpec{ + AppName: appName, + Environment: envName, + Component: componentName, + }} +} + +// GetDNSAliasHost Gets DNS alias domain host. +// Example for the domain "my-app" and the cluster "Playground": my-app.playground.radix.equinor.com +func GetDNSAliasHost(domain string, dnsZone string) string { + return fmt.Sprintf("%s.%s", domain, dnsZone) +} diff --git a/radix-operator/dnsalias/internal/utils.go b/radix-operator/dnsalias/internal/utils.go deleted file mode 100644 index f8229d7a3..000000000 --- a/radix-operator/dnsalias/internal/utils.go +++ /dev/null @@ -1,77 +0,0 @@ -package internal - -import ( - "context" - "fmt" - - "github.com/equinor/radix-operator/pkg/apis/defaults" - radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - "github.com/equinor/radix-operator/pkg/apis/utils" - "github.com/equinor/radix-operator/pkg/apis/utils/labels" - "github.com/equinor/radix-operator/radix-operator/config" - networkingv1 "k8s.io/api/networking/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" -) - -const ( - dnsAliasIngressNameTemplate = "%s.%s.custom-domain" // ..custom-domain -) - -// BuildRadixDNSAlias Build a RadixDNSAlias -func BuildRadixDNSAlias(appName, componentName, envName, domain string) *radixv1.RadixDNSAlias { - return &radixv1.RadixDNSAlias{ - ObjectMeta: metav1.ObjectMeta{ - Name: domain, - Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(componentName)), - }, - Spec: radixv1.RadixDNSAliasSpec{ - AppName: appName, - Environment: envName, - Component: componentName, - }} -} - -// CreateRadixDNSAliasIngress Create an Ingress for a RadixDNSAlias -func CreateRadixDNSAliasIngress(kubeClient kubernetes.Interface, appName, envName string, ingress *networkingv1.Ingress) (*networkingv1.Ingress, error) { - return kubeClient.NetworkingV1().Ingresses(utils.GetEnvironmentNamespace(appName, envName)).Create(context.Background(), ingress, metav1.CreateOptions{}) -} - -// BuildRadixDNSAliasIngress Build an Ingress for a RadixDNSAlias -func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, config *config.ClusterConfig) *networkingv1.Ingress { - pathTypeImplementationSpecific := networkingv1.PathTypeImplementationSpecific - name := fmt.Sprintf(dnsAliasIngressNameTemplate, service, domain) - host := GetDNSAliasHost(domain, config.DNSZone) - return &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(service)), - }, - Spec: networkingv1.IngressSpec{ - TLS: []networkingv1.IngressTLS{ - { - Hosts: []string{host}, - SecretName: defaults.TLSSecretName, - }, - }, - Rules: []networkingv1.IngressRule{ - { - Host: host, - IngressRuleValue: networkingv1.IngressRuleValue{ - HTTP: &networkingv1.HTTPIngressRuleValue{Paths: []networkingv1.HTTPIngressPath{ - {Path: "/", PathType: &pathTypeImplementationSpecific, Backend: networkingv1.IngressBackend{ - Service: &networkingv1.IngressServiceBackend{Name: service, Port: networkingv1.ServiceBackendPort{ - Number: port, - }}, - }}}, - }}, - }, - }, - }} -} - -// GetDNSAliasHost Gets DNS alias domain host. -// Example for the domain "my-app" and the cluster "Playground": my-app.playground.radix.equinor.com -func GetDNSAliasHost(domain string, dnsZone string) string { - return fmt.Sprintf("%s.%s", domain, dnsZone) -} From ca2d1e7c03e011416d75e03ffbebb79ade44d5bc Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 1 Nov 2023 12:29:03 +0100 Subject: [PATCH 022/121] Update unit-tests --- .../applicationconfig_test.go | 292 ---------------- .../{dnsaliases.go => dns_alias.go} | 0 pkg/apis/applicationconfig/dns_alias_test.go | 321 ++++++++++++++++++ pkg/apis/dnsalias/syncer_test.go | 37 +- 4 files changed, 357 insertions(+), 293 deletions(-) rename pkg/apis/applicationconfig/{dnsaliases.go => dns_alias.go} (100%) create mode 100644 pkg/apis/applicationconfig/dns_alias_test.go diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index b65b94dfa..766b0f291 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -17,7 +17,6 @@ import ( radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -657,297 +656,6 @@ func Test_IsConfigBranch(t *testing.T) { }) } -func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { - const ( - appName1 = "any-app1" - appName2 = "any-app2" - env1 = "env1" - env2 = "env2" - component1 = "server1" - component2 = "server2" - branch1 = "branch1" - branch2 = "branch2" - portA = "port-a" - port8080 = 8080 - port9090 = 9090 - domain1 = "domain1" - domain2 = "domain2" - domain3 = "domain3" - domain4 = "domain4" - ) - var testScenarios = []struct { - name string - applicationBuilder utils.ApplicationBuilder - existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec - expectedRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec - }{ - { - name: "no aliases", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{}, - }, - { - name: "one alias", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). - WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - }, - }, - { - name: "aliases for multiple components", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithDNSAlias( - radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, - radixv1.DNSAlias{Domain: domain2, Environment: env1, Component: component2}, - ). - WithComponents( - utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), - utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), - ), - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, - }, - }, - { - name: "aliases for multiple environments", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). - WithDNSAlias( - radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, - radixv1.DNSAlias{Domain: domain2, Environment: env2, Component: component1}, - ). - WithComponents( - utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), - utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), - ), - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain2: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, - }, - }, - { - name: "multiple aliases for one component and environment", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithDNSAlias( - radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, - radixv1.DNSAlias{Domain: domain2, Environment: env1, Component: component1}, - ). - WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain2: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - }, - }, - { - name: "aliases for multiple components in different environments", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). - WithDNSAlias( - radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, - radixv1.DNSAlias{Domain: domain2, Environment: env2, Component: component2}, - ). - WithComponents( - utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), - utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), - ), - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain2: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, - }, - }, - { - name: "one alias, exist other RDA, two expected RDA", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). - WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain2: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, - }, - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain2: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - }, - }, - { - name: "change env and component for existing RDA", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). - WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env2, Component: component2}). - WithComponents( - utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), - utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), - ), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - }, - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, - }, - }, - { - name: "swap env and component for existing RDA-s", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). - WithDNSAlias( - radixv1.DNSAlias{Domain: domain1, Environment: env2, Component: component2}, - radixv1.DNSAlias{Domain: domain2, Environment: env1, Component: component1}, - ). - WithComponents( - utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), - utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), - ), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain2: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, - }, - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, - domain2: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - }, - }, - { - name: "remove single alias", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). - WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - }, - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{}, - }, - { - name: "remove multiple aliases, keep other", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). - WithDNSAlias( - radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, - radixv1.DNSAlias{Domain: domain3, Environment: env2, Component: component1}, - ). - WithComponents( - utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), - utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), - ), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, - domain3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, - domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, - }, - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, - domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, - }, - }, - { - name: "create new, remove some, change other aliases", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). - WithDNSAlias( - radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component2}, - radixv1.DNSAlias{Domain: domain3, Environment: env2, Component: component1}, - ). - WithComponents( - utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), - utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), - ), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, - domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, - }, - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, - domain3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, - domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, - }, - }, - } - - for _, ts := range testScenarios { - t.Run(ts.name, func(t *testing.T) { - tu, kubeClient, kubeUtil, radixClient := setupTest() - - require.NoError(t, registerExistingRadixDNSAliases(radixClient, ts.existingRadixDNSAliases), "create existing RadixDNSAlias") - require.NoError(t, applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, ts.applicationBuilder), "register radix application") - - radixDNSAliases, err := radixClient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{}) - require.NoError(t, err) - - if ts.expectedRadixDNSAliases == nil { - require.Len(t, radixDNSAliases.Items, 0, "not expected Radix DNS aliases") - return - } - - require.Len(t, radixDNSAliases.Items, len(ts.expectedRadixDNSAliases), "not matching expected Radix DNS aliases count") - if len(radixDNSAliases.Items) == len(ts.expectedRadixDNSAliases) { - for _, radixDNSAlias := range radixDNSAliases.Items { - if expectedDNSAlias, ok := ts.expectedRadixDNSAliases[radixDNSAlias.Name]; ok { - assert.Equal(t, expectedDNSAlias.AppName, radixDNSAlias.Spec.AppName, "app name") - assert.Equal(t, expectedDNSAlias.Environment, radixDNSAlias.Spec.Environment, "environment") - assert.Equal(t, expectedDNSAlias.Component, radixDNSAlias.Spec.Component, "component") - assert.Equal(t, expectedDNSAlias.Port, radixDNSAlias.Spec.Port, "port") - if _, itWasExistingAlias := ts.existingRadixDNSAliases[radixDNSAlias.Name]; !itWasExistingAlias { - ownerReferences := radixDNSAlias.GetOwnerReferences() - require.Len(t, ownerReferences, 1) - ownerReference := ownerReferences[0] - assert.Equal(t, radixDNSAlias.Spec.AppName, ownerReference.Name, "invalid or empty ownerReference.Name") - assert.Equal(t, radix.KindRadixApplication, ownerReference.Kind, "invalid or empty ownerReference.Kind") - assert.NotEmpty(t, ownerReference.UID, "ownerReference.UID is empty") - require.NotNil(t, ownerReference.Controller, "ownerReference.Controller is nil") - assert.True(t, *ownerReference.Controller, "ownerReference.Controller is false") - } - continue - } - assert.Fail(t, fmt.Sprintf("found not expected RadixDNSAlias %s: env %s, component %s, port %d, appName %s", - radixDNSAlias.GetName(), radixDNSAlias.Spec.Environment, radixDNSAlias.Spec.Component, radixDNSAlias.Spec.Port, radixDNSAlias.Spec.AppName)) - } - } - }) - } -} - -func Test_DNSAliases_FileOndInvalidAppName(t *testing.T) { - const ( - appName1 = "any-app1" - appName2 = "any-app2" - env1 = "env1" - component1 = "server1" - domain1 = "domain1" - branch1 = "branch1" - portA = "port-a" - port8080 = 8080 - ) - tu, kubeClient, kubeUtil, radixClient := setupTest() - - _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), - &radixv1.RadixDNSAlias{ - ObjectMeta: metav1.ObjectMeta{Name: domain1, Labels: map[string]string{kube.RadixAppLabel: appName1}}, - Spec: radixv1.RadixDNSAliasSpec{AppName: appName2, Environment: env1, Component: component1}, - }, metav1.CreateOptions{}) - require.NoError(t, err, "create existing RadixDNSAlias") - - applicationBuilder := utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). - WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)) - err = applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, applicationBuilder) - require.Error(t, err, "register radix application") -} - -func registerExistingRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]radixv1.RadixDNSAliasSpec) error { - for domain, rdaSpec := range radixDNSAliasesMap { - _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), - &radixv1.RadixDNSAlias{ - ObjectMeta: metav1.ObjectMeta{ - Name: domain, - Labels: map[string]string{kube.RadixAppLabel: rdaSpec.AppName}, - }, - Spec: rdaSpec, - }, metav1.CreateOptions{}) - if err != nil { - return err - } - } - return nil -} - func rrAsOwnerReference(rr *radixv1.RadixRegistration) []metav1.OwnerReference { trueVar := true return []metav1.OwnerReference{ diff --git a/pkg/apis/applicationconfig/dnsaliases.go b/pkg/apis/applicationconfig/dns_alias.go similarity index 100% rename from pkg/apis/applicationconfig/dnsaliases.go rename to pkg/apis/applicationconfig/dns_alias.go diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go new file mode 100644 index 000000000..d14a88e6f --- /dev/null +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -0,0 +1,321 @@ +package applicationconfig_test + +import ( + "context" + "fmt" + "testing" + + "github.com/equinor/radix-operator/pkg/apis/kube" + "github.com/equinor/radix-operator/pkg/apis/radix" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/utils" + radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { + const ( + appName1 = "any-app1" + appName2 = "any-app2" + env1 = "env1" + env2 = "env2" + component1 = "server1" + component2 = "server2" + branch1 = "branch1" + branch2 = "branch2" + portA = "port-a" + port8080 = 8080 + port9090 = 9090 + domain1 = "domain1" + domain2 = "domain2" + domain3 = "domain3" + domain4 = "domain4" + ) + var testScenarios = []struct { + name string + applicationBuilder utils.ApplicationBuilder + existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec + expectedRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec + }{ + { + name: "no aliases", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{}, + }, + { + name: "one alias", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). + WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + }, + }, + { + name: "aliases for multiple components", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithDNSAlias( + radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Domain: domain2, Environment: env1, Component: component2}, + ). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), + ), + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, + }, + }, + { + name: "aliases for multiple environments", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithDNSAlias( + radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Domain: domain2, Environment: env2, Component: component1}, + ). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), + ), + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain2: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, + }, + }, + { + name: "multiple aliases for one component and environment", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithDNSAlias( + radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Domain: domain2, Environment: env1, Component: component1}, + ). + WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain2: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + }, + }, + { + name: "aliases for multiple components in different environments", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithDNSAlias( + radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Domain: domain2, Environment: env2, Component: component2}, + ). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), + ), + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain2: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, + }, + }, + { + name: "one alias, exist other aliases, two expected aliases", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). + WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain2: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, + }, + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain2: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + }, + }, + { + name: "change env and component for existing aliases", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env2, Component: component2}). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), + ), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + }, + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, + }, + }, + { + name: "change port for existing aliases", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port9090).WithPublicPort(portA), + ), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + }, + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port9090}, + }, + }, + { + name: "swap env and component for existing aliases-s", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithDNSAlias( + radixv1.DNSAlias{Domain: domain1, Environment: env2, Component: component2}, + radixv1.DNSAlias{Domain: domain2, Environment: env1, Component: component1}, + ). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), + ), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain2: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, + }, + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, + domain2: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + }, + }, + { + name: "remove single alias", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + }, + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{}, + }, + { + name: "remove multiple aliases, keep other", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithDNSAlias( + radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Domain: domain3, Environment: env2, Component: component1}, + ). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), + ), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, + domain3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, + domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, + }, + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, + domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, + }, + }, + { + name: "create new, remove some, change other aliases", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). + WithDNSAlias( + radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component2}, + radixv1.DNSAlias{Domain: domain3, Environment: env2, Component: component1}, + ). + WithComponents( + utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), + utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), + ), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + domain2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, + domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, + }, + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, + domain3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, + domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, + }, + }, + } + + for _, ts := range testScenarios { + t.Run(ts.name, func(t *testing.T) { + tu, kubeClient, kubeUtil, radixClient := setupTest() + + require.NoError(t, registerExistingRadixDNSAliases(radixClient, ts.existingRadixDNSAliases), "create existing RadixDNSAlias") + require.NoError(t, applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, ts.applicationBuilder), "register radix application") + + radixDNSAliases, err := radixClient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{}) + require.NoError(t, err) + + if ts.expectedRadixDNSAliases == nil { + require.Len(t, radixDNSAliases.Items, 0, "not expected Radix DNS aliases") + return + } + + require.Len(t, radixDNSAliases.Items, len(ts.expectedRadixDNSAliases), "not matching expected Radix DNS aliases count") + if len(radixDNSAliases.Items) == len(ts.expectedRadixDNSAliases) { + for _, radixDNSAlias := range radixDNSAliases.Items { + if expectedDNSAlias, ok := ts.expectedRadixDNSAliases[radixDNSAlias.Name]; ok { + assert.Equal(t, expectedDNSAlias.AppName, radixDNSAlias.Spec.AppName, "app name") + assert.Equal(t, expectedDNSAlias.Environment, radixDNSAlias.Spec.Environment, "environment") + assert.Equal(t, expectedDNSAlias.Component, radixDNSAlias.Spec.Component, "component") + assert.Equal(t, expectedDNSAlias.Port, radixDNSAlias.Spec.Port, "port") + if _, itWasExistingAlias := ts.existingRadixDNSAliases[radixDNSAlias.Name]; !itWasExistingAlias { + ownerReferences := radixDNSAlias.GetOwnerReferences() + require.Len(t, ownerReferences, 1) + ownerReference := ownerReferences[0] + assert.Equal(t, radixDNSAlias.Spec.AppName, ownerReference.Name, "invalid or empty ownerReference.Name") + assert.Equal(t, radix.KindRadixApplication, ownerReference.Kind, "invalid or empty ownerReference.Kind") + assert.NotEmpty(t, ownerReference.UID, "ownerReference.UID is empty") + require.NotNil(t, ownerReference.Controller, "ownerReference.Controller is nil") + assert.True(t, *ownerReference.Controller, "ownerReference.Controller is false") + } + continue + } + assert.Fail(t, fmt.Sprintf("found not expected RadixDNSAlias %s: env %s, component %s, port %d, appName %s", + radixDNSAlias.GetName(), radixDNSAlias.Spec.Environment, radixDNSAlias.Spec.Component, radixDNSAlias.Spec.Port, radixDNSAlias.Spec.AppName)) + } + } + }) + } +} + +func Test_DNSAliases_FileOndInvalidAppName(t *testing.T) { + const ( + appName1 = "any-app1" + appName2 = "any-app2" + env1 = "env1" + component1 = "server1" + domain1 = "domain1" + branch1 = "branch1" + portA = "port-a" + port8080 = 8080 + ) + tu, kubeClient, kubeUtil, radixClient := setupTest() + + _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), + &radixv1.RadixDNSAlias{ + ObjectMeta: metav1.ObjectMeta{Name: domain1, Labels: map[string]string{kube.RadixAppLabel: appName1}}, + Spec: radixv1.RadixDNSAliasSpec{AppName: appName2, Environment: env1, Component: component1}, + }, metav1.CreateOptions{}) + require.NoError(t, err, "create existing RadixDNSAlias") + + applicationBuilder := utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). + WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)) + err = applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, applicationBuilder) + require.Error(t, err, "register radix application") +} + +func registerExistingRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]radixv1.RadixDNSAliasSpec) error { + for domain, aliasesSpec := range radixDNSAliasesMap { + _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), + &radixv1.RadixDNSAlias{ + ObjectMeta: metav1.ObjectMeta{ + Name: domain, + Labels: map[string]string{kube.RadixAppLabel: aliasesSpec.AppName}, + }, + Spec: aliasesSpec, + }, metav1.CreateOptions{}) + if err != nil { + return err + } + } + return nil +} diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 341b22dcd..1599c198e 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -77,7 +77,9 @@ type scenario struct { func (s *syncerTestSuite) Test_syncer_OnSync() { const ( appName1 = "app1" + appName2 = "app2" envName1 = "env1" + envName2 = "env2" component1 = "component1" component2 = "component2" domain1 = "domain1" @@ -109,7 +111,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { }, }, { - name: "changed public port on component changes port in existing ingress", + name: "changed port changes port in existing ingress", dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port9090}, dnsZone: dnsZone1, existingIngress: []testIngress{ @@ -131,6 +133,39 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { "component1.domain2.custom-domain": {appName: appName1, envName: envName1, domain: domain2, host: dnsalias.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, }, }, + { + name: "manually changed component repaired", + dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: []testIngress{ + {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component2, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + }, + }, + { + name: "manually changed port repaired", + dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: []testIngress{ + {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port9090}, + }, + expectedIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + }, + }, + { + name: "manually changed host repaired", + dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: []testIngress{ + {appName: appName1, envName: envName1, domain: domain1, host: "/manually/edited/host", component: component1, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + }, + }, } for _, ts := range scenarios { s.T().Run(ts.name, func(t *testing.T) { From 7ba6fd8bef17a582786554a89010f98ad990eb3b Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 1 Nov 2023 15:52:00 +0100 Subject: [PATCH 023/121] Update unit-tests --- pkg/apis/dnsalias/syncer_test.go | 58 ++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 1599c198e..f097b80a2 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -70,7 +70,7 @@ type scenario struct { dnsAlias testDNSAlias dnsZone string existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec - existingIngress []testIngress + existingIngress map[string]testIngress expectedIngress map[string]testIngress } @@ -102,8 +102,8 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { name: "created additional ingress for another component", dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, dnsZone: dnsZone1, - existingIngress: []testIngress{ - {appName: appName1, envName: envName1, domain: domain2, host: dnsalias.GetDNSAliasHost(domain2, dnsZone1), component: component2, port: port8080}, + existingIngress: map[string]testIngress{ + "component2.domain2.custom-domain": {appName: appName1, envName: envName1, domain: domain2, host: dnsalias.GetDNSAliasHost(domain2, dnsZone1), component: component2, port: port8080}, }, expectedIngress: map[string]testIngress{ "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, @@ -114,8 +114,8 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { name: "changed port changes port in existing ingress", dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port9090}, dnsZone: dnsZone1, - existingIngress: []testIngress{ - {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + existingIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, }, expectedIngress: map[string]testIngress{ "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port9090}, @@ -125,20 +125,42 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { name: "created additional ingress on another domain for the same component", dnsAlias: testDNSAlias{Domain: domain2, Environment: envName1, Component: component1, Port: port8080}, dnsZone: dnsZone1, - existingIngress: []testIngress{ - {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, + existingIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, }, expectedIngress: map[string]testIngress{ "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, "component1.domain2.custom-domain": {appName: appName1, envName: envName1, domain: domain2, host: dnsalias.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, }, }, + { + name: "manually changed appName repaired", + dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName2, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component2, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + }, + }, + { + name: "manually changed envName repaired", + dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName1, envName: envName2, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component2, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + }, + }, { name: "manually changed component repaired", dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, dnsZone: dnsZone1, - existingIngress: []testIngress{ - {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component2, port: port8080}, + existingIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component2, port: port8080}, }, expectedIngress: map[string]testIngress{ "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, @@ -148,8 +170,8 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { name: "manually changed port repaired", dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, dnsZone: dnsZone1, - existingIngress: []testIngress{ - {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port9090}, + existingIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port9090}, }, expectedIngress: map[string]testIngress{ "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, @@ -159,8 +181,8 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { name: "manually changed host repaired", dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, dnsZone: dnsZone1, - existingIngress: []testIngress{ - {appName: appName1, envName: envName1, domain: domain1, host: "/manually/edited/host", component: component1, port: port8080}, + existingIngress: map[string]testIngress{ + "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: "/manually/edited/host", component: component1, port: port8080}, }, expectedIngress: map[string]testIngress{ "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, @@ -174,7 +196,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component, Port: ts.dnsAlias.Port}} s.Require().NoError(registerExistingRadixDNSAlias(s.radixClient, radixDNSAlias), "create existing alias") cfg := &config.ClusterConfig{DNSZone: ts.dnsZone} - s.Require().NoError(registerExistingIngresses(s.kubeClient, ts.existingIngress, cfg), "create existing ingresses") + s.Require().NoError(registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1, cfg), "create existing ingresses") syncer := s.createSyncer(radixDNSAlias) err := syncer.OnSync() test.AssertError(s.T(), ts.expectedError, err) @@ -220,9 +242,11 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { } } -func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses []testIngress, config *config.ClusterConfig) error { - for _, ing := range testIngresses { - _, err := dnsalias.CreateRadixDNSAliasIngress(kubeClient, ing.appName, ing.envName, dnsalias.BuildRadixDNSAliasIngress(ing.appName, ing.domain, ing.component, ing.port, nil, config)) +func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses map[string]testIngress, appNameForNamespace, envNameForNamespace string, config *config.ClusterConfig) error { + for name, ing := range testIngresses { + ingress := dnsalias.BuildRadixDNSAliasIngress(ing.appName, ing.domain, ing.component, ing.port, nil, config) + ingress.SetName(name) // override built name with expected name for test purpose + _, err := dnsalias.CreateRadixDNSAliasIngress(kubeClient, appNameForNamespace, envNameForNamespace, ingress) if err != nil { return err } From c8619e1e28ad0d5a21f0d029b57175e957c5735f Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 1 Nov 2023 16:53:40 +0100 Subject: [PATCH 024/121] Added DNS alias validation --- pkg/apis/radixvalidators/errors.go | 17 +++++++- .../radixvalidators/testdata/radixconfig.yaml | 6 ++- pkg/apis/radixvalidators/validate_ra.go | 43 ++++++++++++++++--- pkg/apis/radixvalidators/validate_ra_test.go | 30 +++++++++++-- 4 files changed, 84 insertions(+), 12 deletions(-) diff --git a/pkg/apis/radixvalidators/errors.go b/pkg/apis/radixvalidators/errors.go index 812ae9cd1..40cf72b19 100644 --- a/pkg/apis/radixvalidators/errors.go +++ b/pkg/apis/radixvalidators/errors.go @@ -13,12 +13,27 @@ func MissingPrivateImageHubUsernameError(server string) error { return fmt.Errorf("username is required for private image hub %s", server) } +// DomainForDNSAliasNotDefinedError Error when domain is not valid +func DomainForDNSAliasNotDefinedError() error { + return fmt.Errorf("invalid or missing domain for dnsAlias") +} + +// EnvForDNSAliasNotDefinedError Error when env not defined +func EnvForDNSAliasNotDefinedError(env string) error { + return fmt.Errorf("environment %s referred to by dnsAlias is not defined", env) +} + +// ComponentForDNSAliasNotDefinedError Error when component not defined +func ComponentForDNSAliasNotDefinedError(component string) error { + return fmt.Errorf("component %s referred to by dnsAlias is not defined", component) +} + // EnvForDNSAppAliasNotDefinedError Error when env not defined func EnvForDNSAppAliasNotDefinedError(env string) error { return fmt.Errorf("env %s referred to by dnsAppAlias is not defined", env) } -// ComponentForDNSAppAliasNotDefinedError Error when env not defined +// ComponentForDNSAppAliasNotDefinedError Error when component not defined func ComponentForDNSAppAliasNotDefinedError(component string) error { return fmt.Errorf("component %s referred to by dnsAppAlias is not defined", component) } diff --git a/pkg/apis/radixvalidators/testdata/radixconfig.yaml b/pkg/apis/radixvalidators/testdata/radixconfig.yaml index 013828190..1e1c15987 100644 --- a/pkg/apis/radixvalidators/testdata/radixconfig.yaml +++ b/pkg/apis/radixvalidators/testdata/radixconfig.yaml @@ -140,4 +140,8 @@ spec: port: 8099 dnsAppAlias: environment: prod - component: app \ No newline at end of file + component: app + dnsAlias: + - environment: prod + component: app + domain: my-domain \ No newline at end of file diff --git a/pkg/apis/radixvalidators/validate_ra.go b/pkg/apis/radixvalidators/validate_ra.go index 1cafc6a56..7185d0c8c 100644 --- a/pkg/apis/radixvalidators/validate_ra.go +++ b/pkg/apis/radixvalidators/validate_ra.go @@ -31,6 +31,7 @@ const ( maximumPortNumber = 65535 cpuRegex = "^[0-9]+m$" azureClientIdResourceName = "identity.azure.clientId" + componentNameTemplate = `^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$` ) var ( @@ -114,6 +115,10 @@ func CanRadixApplicationBeInsertedErrors(client radixclient.Interface, app *radi errs = append(errs, err) } + if dnsAliasErrs := validateDNSAlias(app); len(dnsAliasErrs) > 0 { + errs = append(errs, dnsAliasErrs...) + } + dnsErrors := validateDNSAppAlias(app) if len(dnsErrors) > 0 { errs = append(errs, dnsErrors...) @@ -172,21 +177,34 @@ func RAContainsOldPublic(app *radixv1.RadixApplication) bool { func validateDNSAppAlias(app *radixv1.RadixApplication) []error { alias := app.Spec.DNSAppAlias - return validateComponentAndEnvironmentAvailable(app, alias.Component, alias.Environment) + return validateDNSAppAliasComponentAndEnvironmentAvailable(app, alias.Component, alias.Environment) } func validateDNSAlias(app *radixv1.RadixApplication) []error { - dnsAliases := app.Spec.DNSAlias var errs []error - for _, dnsAlias := range dnsAliases { - if err := validateComponentAndEnvironmentAvailable(app, dnsAlias.Component, dnsAlias.Environment); err != nil { - errs = append(errs, err...) + for _, dnsAlias := range app.Spec.DNSAlias { + if err := validateResourceNameByRegex("dnsAlias domain", dnsAlias.Domain, componentNameTemplate); err != nil { + errs = append(errs, err) + } + componentNameIsValid, environmentNameIsValid := true, true + if err := validateResourceNameByRegex("dnsAlias component", dnsAlias.Component, componentNameTemplate); err != nil { + errs = append(errs, err) + componentNameIsValid = false + } + if err := validateRequiredResourceName("dnsAlias environment", dnsAlias.Environment); err != nil { + errs = append(errs, err) + environmentNameIsValid = false + } + if componentNameIsValid && environmentNameIsValid { + if err := validateDNSAliasComponentAndEnvironmentAvailable(app, dnsAlias.Component, dnsAlias.Environment); err != nil { + errs = append(errs, err...) + } } } return errs } -func validateComponentAndEnvironmentAvailable(app *radixv1.RadixApplication, component string, environment string) []error { +func validateDNSAppAliasComponentAndEnvironmentAvailable(app *radixv1.RadixApplication, component string, environment string) []error { var errs []error if component == "" && environment == "" { return errs @@ -200,6 +218,17 @@ func validateComponentAndEnvironmentAvailable(app *radixv1.RadixApplication, com return errs } +func validateDNSAliasComponentAndEnvironmentAvailable(app *radixv1.RadixApplication, component string, environment string) []error { + var errs []error + if !doesEnvExist(app, environment) { + errs = append(errs, EnvForDNSAliasNotDefinedError(environment)) + } + if !doesComponentExistInEnvironment(app, component, environment) { + errs = append(errs, ComponentForDNSAliasNotDefinedError(component)) + } + return errs +} + func validateDNSExternalAlias(app *radixv1.RadixApplication) []error { var errs []error @@ -1396,7 +1425,7 @@ func doesComponentHaveAPublicPort(app *radixv1.RadixApplication, name string) bo } func validateComponentName(componentName, componentType string) error { - if err := validateResourceNameByRegex(fmt.Sprintf("%s name", componentType), componentName, `^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$`); err != nil { + if err := validateResourceNameByRegex(fmt.Sprintf("%s name", componentType), componentName, componentNameTemplate); err != nil { return err } diff --git a/pkg/apis/radixvalidators/validate_ra_test.go b/pkg/apis/radixvalidators/validate_ra_test.go index 668fb7796..76c8105cb 100644 --- a/pkg/apis/radixvalidators/validate_ra_test.go +++ b/pkg/apis/radixvalidators/validate_ra_test.go @@ -90,7 +90,7 @@ func Test_invalid_ra(t *testing.T) { noReleatedRRAppName := "no related rr" noExistingEnvironment := "nonexistingenv" invalidUpperCaseResourceName := "invalidUPPERCASE.resourcename" - nonExistingComponent := "non existing" + nonExistingComponent := "nonexisting" unsupportedResource := "unsupportedResource" invalidResourceValue := "asdfasd" conflictingVariableName := "some-variable" @@ -200,12 +200,36 @@ func Test_invalid_ra(t *testing.T) { {"too long branch name", radixvalidators.InvalidStringValueMaxLengthError("branch from", wayTooLongName, 253), func(ra *v1.RadixApplication) { ra.Spec.Environments[0].Build.From = wayTooLongName }}, - {"dns alias non existing component", radixvalidators.ComponentForDNSAppAliasNotDefinedError(nonExistingComponent), func(ra *v1.RadixApplication) { + {"dns app alias non existing component", radixvalidators.ComponentForDNSAppAliasNotDefinedError(nonExistingComponent), func(ra *v1.RadixApplication) { ra.Spec.DNSAppAlias.Component = nonExistingComponent }}, - {"dns alias non existing env", radixvalidators.EnvForDNSAppAliasNotDefinedError(noExistingEnvironment), func(ra *v1.RadixApplication) { + {"dns app alias non existing env", radixvalidators.EnvForDNSAppAliasNotDefinedError(noExistingEnvironment), func(ra *v1.RadixApplication) { ra.Spec.DNSAppAlias.Environment = noExistingEnvironment }}, + {"dns alias is empty", radixvalidators.ResourceNameCannotBeEmptyError("dnsAlias component"), func(ra *v1.RadixApplication) { + ra.Spec.DNSAlias[0].Component = "" + }}, + {"dns alias is empty", radixvalidators.ResourceNameCannotBeEmptyError("dnsAlias environment"), func(ra *v1.RadixApplication) { + ra.Spec.DNSAlias[0].Environment = "" + }}, + {"dns alias is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDotDashResourceNameError("dnsAlias component", "component.abc"), func(ra *v1.RadixApplication) { + ra.Spec.DNSAlias[0].Component = "component.abc" + }}, + {"dns alias is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDotDashResourceNameError("dnsAlias environment", "environment.abc"), func(ra *v1.RadixApplication) { + ra.Spec.DNSAlias[0].Environment = "environment.abc" + }}, + {"dns alias non existing component", radixvalidators.ComponentForDNSAliasNotDefinedError(nonExistingComponent), func(ra *v1.RadixApplication) { + ra.Spec.DNSAlias[0].Component = nonExistingComponent + }}, + {"dns alias non existing env", radixvalidators.EnvForDNSAliasNotDefinedError(noExistingEnvironment), func(ra *v1.RadixApplication) { + ra.Spec.DNSAlias[0].Environment = noExistingEnvironment + }}, + {"dns alias domain is empty", radixvalidators.ResourceNameCannotBeEmptyError("dnsAlias domain"), func(ra *v1.RadixApplication) { + ra.Spec.DNSAlias[0].Domain = "" + }}, + {"dns alias domain is invalid", radixvalidators.DomainForDNSAliasNotDefinedError(), func(ra *v1.RadixApplication) { + ra.Spec.DNSAlias[0].Domain = "my.domain" + }}, {"dns external alias non existing component", radixvalidators.ComponentForDNSExternalAliasNotDefinedError(nonExistingComponent), func(ra *v1.RadixApplication) { ra.Spec.DNSExternalAlias = []v1.ExternalAlias{ { From aca8f6bbdb7dcff45f6f77078abbd1898263b8b4 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 2 Nov 2023 12:35:24 +0100 Subject: [PATCH 025/121] Added DNS alias validation tests. Removed dot from validation of resources --- .../templates/radixapplication.yaml | 22 ++++++++-------- .../templates/radixdnsalias.yaml | 4 +-- json-schema/radixapplication.json | 22 ++++++++-------- json-schema/radixdnsalias.json | 4 +-- pkg/apis/radix/v1/radixapptypes.go | 18 ++++++------- pkg/apis/radix/v1/radixdnsaliastypes.go | 4 +-- pkg/apis/radixvalidators/defaults.go | 9 +++++++ pkg/apis/radixvalidators/errors.go | 15 +++++++---- pkg/apis/radixvalidators/validate_ra.go | 19 +++++++------- pkg/apis/radixvalidators/validate_ra_test.go | 25 +++++++++---------- pkg/apis/radixvalidators/validate_rr.go | 8 ++---- 11 files changed, 80 insertions(+), 70 deletions(-) create mode 100644 pkg/apis/radixvalidators/defaults.go diff --git a/charts/radix-operator/templates/radixapplication.yaml b/charts/radix-operator/templates/radixapplication.yaml index 578e56512..69efb725d 100644 --- a/charts/radix-operator/templates/radixapplication.yaml +++ b/charts/radix-operator/templates/radixapplication.yaml @@ -374,7 +374,7 @@ spec: applies to. maxLength: 63 minLength: 1 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string horizontalScaling: description: 'Configuration for automatic horizontal scaling @@ -880,7 +880,7 @@ spec: description: Defines which port in the ports list where metrics is served. maxLength: 15 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string type: object name: @@ -910,7 +910,7 @@ spec: description: Name of the port. maxLength: 15 minLength: 1 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string port: description: Port number. @@ -934,7 +934,7 @@ spec: description: 'Defines which port (name) from the ports list that shall be accessible from the internet. More info: https://www.radix.equinor.com/references/reference-radix-config/#publicport' maxLength: 15 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string resources: description: 'Configures CPU and memory resources for the component. @@ -1104,7 +1104,7 @@ spec: description: Name of the environment for the component. maxLength: 63 minLength: 1 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string required: - component @@ -1130,7 +1130,7 @@ spec: description: Name of the environment for the component. maxLength: 63 minLength: 1 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string type: object dnsExternalAlias: @@ -1157,7 +1157,7 @@ spec: description: Name of the environment for the component. maxLength: 63 minLength: 1 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string required: - alias @@ -1246,7 +1246,7 @@ spec: description: Name of the environment. maxLength: 63 minLength: 1 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string required: - name @@ -1300,7 +1300,7 @@ spec: applies to. maxLength: 63 minLength: 1 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string identity: description: 'Environment specific configuration for workload @@ -1762,7 +1762,7 @@ spec: description: Defines which port in the ports list where metrics is served. maxLength: 15 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string type: object name: @@ -1815,7 +1815,7 @@ spec: description: Name of the port. maxLength: 15 minLength: 1 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string port: description: Port number. diff --git a/charts/radix-operator/templates/radixdnsalias.yaml b/charts/radix-operator/templates/radixdnsalias.yaml index 8bf8a1361..3bdbe5a6f 100644 --- a/charts/radix-operator/templates/radixdnsalias.yaml +++ b/charts/radix-operator/templates/radixdnsalias.yaml @@ -41,7 +41,7 @@ spec: description: Name of the application the DNS alias used in. maxLength: 253 minLength: 1 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string component: description: Name of the component that shall receive the incoming @@ -54,7 +54,7 @@ spec: description: Name of the environment for the component. maxLength: 63 minLength: 1 - pattern: ^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string port: description: Port number. diff --git a/json-schema/radixapplication.json b/json-schema/radixapplication.json index 4bd2f5dc4..ad7ed56d3 100644 --- a/json-schema/radixapplication.json +++ b/json-schema/radixapplication.json @@ -361,7 +361,7 @@ "description": "Name of the environment which the settings applies to.", "maxLength": 63, "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" }, "horizontalScaling": { @@ -866,7 +866,7 @@ "portName": { "description": "Defines which port in the ports list where metrics is served.", "maxLength": 15, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" } }, @@ -902,7 +902,7 @@ "description": "Name of the port.", "maxLength": 15, "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" }, "port": { @@ -933,7 +933,7 @@ "publicPort": { "description": "Defines which port (name) from the ports list that shall be accessible from the internet. More info: https://www.radix.equinor.com/references/reference-radix-config/#publicport", "maxLength": 15, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" }, "resources": { @@ -1110,7 +1110,7 @@ "description": "Name of the environment for the component.", "maxLength": 63, "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" } }, @@ -1141,7 +1141,7 @@ "description": "Name of the environment for the component.", "maxLength": 63, "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" } }, @@ -1170,7 +1170,7 @@ "description": "Name of the environment for the component.", "maxLength": 63, "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" } }, @@ -1279,7 +1279,7 @@ "description": "Name of the environment.", "maxLength": 63, "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" } }, @@ -1333,7 +1333,7 @@ "description": "Name of the environment which the settings applies to.", "maxLength": 63, "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" }, "identity": { @@ -1786,7 +1786,7 @@ "portName": { "description": "Defines which port in the ports list where metrics is served.", "maxLength": 15, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" } }, @@ -1848,7 +1848,7 @@ "description": "Name of the port.", "maxLength": 15, "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" }, "port": { diff --git a/json-schema/radixdnsalias.json b/json-schema/radixdnsalias.json index ddd004d94..2db076223 100644 --- a/json-schema/radixdnsalias.json +++ b/json-schema/radixdnsalias.json @@ -19,7 +19,7 @@ "description": "Name of the application the DNS alias used in.", "maxLength": 253, "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" }, "component": { @@ -33,7 +33,7 @@ "description": "Name of the environment for the component.", "maxLength": 63, "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$", + "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" }, "port": { diff --git a/pkg/apis/radix/v1/radixapptypes.go b/pkg/apis/radix/v1/radixapptypes.go index b1cd0810c..b26068730 100644 --- a/pkg/apis/radix/v1/radixapptypes.go +++ b/pkg/apis/radix/v1/radixapptypes.go @@ -119,7 +119,7 @@ type Environment struct { // Name of the environment. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 - // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ Name string `json:"name"` // Build configuration for the environment. @@ -191,7 +191,7 @@ type AppAlias struct { // Name of the environment for the component. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 - // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ Environment string `json:"environment,omitempty"` // Name of the component that shall receive the incoming requests. @@ -212,7 +212,7 @@ type ExternalAlias struct { // Name of the environment for the component. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 - // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ Environment string `json:"environment"` // Name of the component that shall receive the incoming requests. @@ -233,7 +233,7 @@ type DNSAlias struct { // Name of the environment for the component. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 - // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ Environment string `json:"environment"` // Name of the component that shall receive the incoming requests. @@ -248,7 +248,7 @@ type ComponentPort struct { // Name of the port. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=15 - // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ Name string `json:"name"` // Port number. @@ -317,7 +317,7 @@ type RadixComponent struct { // Defines which port (name) from the ports list that shall be accessible from the internet. // More info: https://www.radix.equinor.com/references/reference-radix-config/#publicport // +kubebuilder:validation:MaxLength=15 - // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ // +optional PublicPort string `json:"publicPort,omitempty"` @@ -384,7 +384,7 @@ type RadixEnvironmentConfig struct { // Name of the environment which the settings applies to. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 - // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ Environment string `json:"environment"` // Number of desired replicas. @@ -566,7 +566,7 @@ type RadixJobComponentEnvironmentConfig struct { // Name of the environment which the settings applies to. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 - // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ Environment string `json:"environment"` // Enabled or disables collection of custom Prometheus metrics. @@ -970,7 +970,7 @@ type RadixNode struct { type MonitoringConfig struct { // Defines which port in the ports list where metrics is served. // +kubebuilder:validation:MaxLength=15 - // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ PortName string `json:"portName,omitempty"` // Defines the path where metrics is served. diff --git a/pkg/apis/radix/v1/radixdnsaliastypes.go b/pkg/apis/radix/v1/radixdnsaliastypes.go index 7909f0955..b390de928 100644 --- a/pkg/apis/radix/v1/radixdnsaliastypes.go +++ b/pkg/apis/radix/v1/radixdnsaliastypes.go @@ -29,13 +29,13 @@ type RadixDNSAliasSpec struct { // Name of the application the DNS alias used in. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 - // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ AppName string `json:"appName" yaml:"appName"` // Name of the environment for the component. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 - // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$ + // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ Environment string `json:"environment" yaml:"environment"` // Name of the component that shall receive the incoming requests. diff --git a/pkg/apis/radixvalidators/defaults.go b/pkg/apis/radixvalidators/defaults.go new file mode 100644 index 000000000..9f0e59376 --- /dev/null +++ b/pkg/apis/radixvalidators/defaults.go @@ -0,0 +1,9 @@ +package radixvalidators + +const ( + maxPortNameLength = 15 + minimumPortNumber = 1024 + maximumPortNumber = 65535 + cpuRegex = "^[0-9]+m$" + resourceNameTemplate = `^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$` +) diff --git a/pkg/apis/radixvalidators/errors.go b/pkg/apis/radixvalidators/errors.go index 40cf72b19..e503071c3 100644 --- a/pkg/apis/radixvalidators/errors.go +++ b/pkg/apis/radixvalidators/errors.go @@ -18,6 +18,11 @@ func DomainForDNSAliasNotDefinedError() error { return fmt.Errorf("invalid or missing domain for dnsAlias") } +// DuplicateDomainForDNSAliasError Error when domains are duplicate +func DuplicateDomainForDNSAliasError(domain string) error { + return fmt.Errorf("duplicate domains %s in dnsAlias-es are not allowed", domain) +} + // EnvForDNSAliasNotDefinedError Error when env not defined func EnvForDNSAliasNotDefinedError(env string) error { return fmt.Errorf("environment %s referred to by dnsAlias is not defined", env) @@ -30,7 +35,7 @@ func ComponentForDNSAliasNotDefinedError(component string) error { // EnvForDNSAppAliasNotDefinedError Error when env not defined func EnvForDNSAppAliasNotDefinedError(env string) error { - return fmt.Errorf("env %s referred to by dnsAppAlias is not defined", env) + return fmt.Errorf("environment %s referred to by dnsAppAlias is not defined", env) } // ComponentForDNSAppAliasNotDefinedError Error when component not defined @@ -265,12 +270,12 @@ func InvalidEmailError(resourceName, email string) error { // InvalidResourceNameError Invalid resource name func InvalidResourceNameError(resourceName, value string) error { - return fmt.Errorf("%s %s can only consist of alphanumeric characters, '.' and '-'", resourceName, value) + return fmt.Errorf("%s %s can only consist of alphanumeric characters and '-'", resourceName, value) } -// InvalidLowerCaseAlphaNumericDotDashResourceNameError Invalid lower case alpha-numeric, dot, dash resource name error -func InvalidLowerCaseAlphaNumericDotDashResourceNameError(resourceName, value string) error { - return fmt.Errorf("%s %s can only consist of lower case alphanumeric characters, '.' and '-'", resourceName, value) +// InvalidLowerCaseAlphaNumericDashResourceNameError Invalid lower case alpha-numeric, dot, dash resource name error +func InvalidLowerCaseAlphaNumericDashResourceNameError(resourceName, value string) error { + return fmt.Errorf("%s %s can only consist of lower case alphanumeric characters and '-'", resourceName, value) } // NoRegistrationExistsForApplicationError No registration exists diff --git a/pkg/apis/radixvalidators/validate_ra.go b/pkg/apis/radixvalidators/validate_ra.go index 7185d0c8c..b2c4519f0 100644 --- a/pkg/apis/radixvalidators/validate_ra.go +++ b/pkg/apis/radixvalidators/validate_ra.go @@ -26,12 +26,7 @@ import ( const ( maximumNumberOfEgressRules = 1000 - maxPortNameLength = 15 - minimumPortNumber = 1024 - maximumPortNumber = 65535 - cpuRegex = "^[0-9]+m$" azureClientIdResourceName = "identity.azure.clientId" - componentNameTemplate = `^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$` ) var ( @@ -182,12 +177,18 @@ func validateDNSAppAlias(app *radixv1.RadixApplication) []error { func validateDNSAlias(app *radixv1.RadixApplication) []error { var errs []error + domainSet := make(map[string]struct{}) for _, dnsAlias := range app.Spec.DNSAlias { - if err := validateResourceNameByRegex("dnsAlias domain", dnsAlias.Domain, componentNameTemplate); err != nil { - errs = append(errs, err) + if _, ok := domainSet[dnsAlias.Domain]; ok { + errs = append(errs, DuplicateDomainForDNSAliasError(dnsAlias.Domain)) + } else { + if err := validateRequiredResourceName("dnsAlias domain", dnsAlias.Domain); err != nil { + errs = append(errs, err) + } } + domainSet[dnsAlias.Domain] = struct{}{} componentNameIsValid, environmentNameIsValid := true, true - if err := validateResourceNameByRegex("dnsAlias component", dnsAlias.Component, componentNameTemplate); err != nil { + if err := validateRequiredResourceName("dnsAlias component", dnsAlias.Component); err != nil { errs = append(errs, err) componentNameIsValid = false } @@ -1425,7 +1426,7 @@ func doesComponentHaveAPublicPort(app *radixv1.RadixApplication, name string) bo } func validateComponentName(componentName, componentType string) error { - if err := validateResourceNameByRegex(fmt.Sprintf("%s name", componentType), componentName, componentNameTemplate); err != nil { + if err := validateRequiredResourceName(fmt.Sprintf("%s name", componentType), componentName); err != nil { return err } diff --git a/pkg/apis/radixvalidators/validate_ra_test.go b/pkg/apis/radixvalidators/validate_ra_test.go index 76c8105cb..e8de47422 100644 --- a/pkg/apis/radixvalidators/validate_ra_test.go +++ b/pkg/apis/radixvalidators/validate_ra_test.go @@ -106,7 +106,7 @@ func Test_invalid_ra(t *testing.T) { {"too long app name", radixvalidators.InvalidAppNameLengthError(wayTooLongName), func(ra *v1.RadixApplication) { ra.Name = wayTooLongName }}, - {"invalid app name", radixvalidators.InvalidLowerCaseAlphaNumericDotDashResourceNameError("app name", invalidResourceName), func(ra *v1.RadixApplication) { + {"invalid app name", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameError("app name", invalidResourceName), func(ra *v1.RadixApplication) { ra.Name = invalidResourceName }}, {"empty name", radixvalidators.AppNameCannotBeEmptyError(), func(ra *v1.RadixApplication) { @@ -122,10 +122,10 @@ func Test_invalid_ra(t *testing.T) { }, } }}, - {"invalid component name", radixvalidators.InvalidLowerCaseAlphaNumericDotDashResourceNameError("component name", invalidResourceName), func(ra *v1.RadixApplication) { + {"invalid component name", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameError("component name", invalidResourceName), func(ra *v1.RadixApplication) { ra.Spec.Components[0].Name = invalidResourceName }}, - {"uppercase component name", radixvalidators.InvalidLowerCaseAlphaNumericDotDashResourceNameError("component name", invalidUpperCaseResourceName), func(ra *v1.RadixApplication) { + {"uppercase component name", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameError("component name", invalidUpperCaseResourceName), func(ra *v1.RadixApplication) { ra.Spec.Components[0].Name = invalidUpperCaseResourceName }}, {"duplicate component name", radixvalidators.DuplicateComponentOrJobNameError([]string{validRAFirstComponentName}), func(ra *v1.RadixApplication) { @@ -140,7 +140,7 @@ func Test_invalid_ra(t *testing.T) { {"invalid port specification. Empty value", radixvalidators.PortSpecificationCannotBeEmptyForComponentError(validRAFirstComponentName), func(ra *v1.RadixApplication) { ra.Spec.Components[0].Ports = []v1.ComponentPort{} }}, - {"invalid port name", radixvalidators.InvalidLowerCaseAlphaNumericDotDashResourceNameError("port name", invalidResourceName), func(ra *v1.RadixApplication) { + {"invalid port name", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameError("port name", invalidResourceName), func(ra *v1.RadixApplication) { ra.Spec.Components[0].Ports[0].Name = invalidResourceName }}, {"too long port name", radixvalidators.InvalidPortNameLengthError(tooLongPortName), func(ra *v1.RadixApplication) { @@ -191,7 +191,7 @@ func Test_invalid_ra(t *testing.T) { {"invalid number of replicas", radixvalidators.InvalidNumberOfReplicaError(radixvalidators.MaxReplica + 1), func(ra *v1.RadixApplication) { *ra.Spec.Components[0].EnvironmentConfig[0].Replicas = radixvalidators.MaxReplica + 1 }}, - {"invalid env name", radixvalidators.InvalidLowerCaseAlphaNumericDotDashResourceNameError("env name", invalidResourceName), func(ra *v1.RadixApplication) { + {"invalid env name", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameError("env name", invalidResourceName), func(ra *v1.RadixApplication) { ra.Spec.Environments[0].Name = invalidResourceName }}, {"invalid branch name", radixvalidators.InvalidBranchNameError(invalidBranchName), func(ra *v1.RadixApplication) { @@ -212,10 +212,10 @@ func Test_invalid_ra(t *testing.T) { {"dns alias is empty", radixvalidators.ResourceNameCannotBeEmptyError("dnsAlias environment"), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias[0].Environment = "" }}, - {"dns alias is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDotDashResourceNameError("dnsAlias component", "component.abc"), func(ra *v1.RadixApplication) { + {"dns alias is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameError("dnsAlias component", "component.abc"), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias[0].Component = "component.abc" }}, - {"dns alias is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDotDashResourceNameError("dnsAlias environment", "environment.abc"), func(ra *v1.RadixApplication) { + {"dns alias is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameError("dnsAlias environment", "environment.abc"), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias[0].Environment = "environment.abc" }}, {"dns alias non existing component", radixvalidators.ComponentForDNSAliasNotDefinedError(nonExistingComponent), func(ra *v1.RadixApplication) { @@ -227,7 +227,7 @@ func Test_invalid_ra(t *testing.T) { {"dns alias domain is empty", radixvalidators.ResourceNameCannotBeEmptyError("dnsAlias domain"), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias[0].Domain = "" }}, - {"dns alias domain is invalid", radixvalidators.DomainForDNSAliasNotDefinedError(), func(ra *v1.RadixApplication) { + {"dns alias domain is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameError("dnsAlias domain", "my.domain"), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias[0].Domain = "my.domain" }}, {"dns external alias non existing component", radixvalidators.ComponentForDNSExternalAliasNotDefinedError(nonExistingComponent), func(ra *v1.RadixApplication) { @@ -661,12 +661,11 @@ func Test_invalid_ra(t *testing.T) { if testcase.expectedError != nil { assert.False(t, isValid) assert.NotNil(t, errs) - - assert.Truef(t, errors.Contains(errs, testcase.expectedError), "Expected error is not contained in list of errors") - } else { - assert.True(t, isValid) - assert.Nil(t, errs) + assert.Truef(t, errors.Contains(errs, testcase.expectedError), fmt.Sprintf("Expected error is not contained in list of errors. \n Expected:\n'%s'\n Actual:\n%s", testcase.expectedError, errors.Concat(errs))) + return } + assert.True(t, isValid) + assert.Nil(t, errs) }) } } diff --git a/pkg/apis/radixvalidators/validate_rr.go b/pkg/apis/radixvalidators/validate_rr.go index 947b9f164..50326a332 100644 --- a/pkg/apis/radixvalidators/validate_rr.go +++ b/pkg/apis/radixvalidators/validate_rr.go @@ -120,10 +120,6 @@ func validateConfigurationItem(value string) error { } func validateRequiredResourceName(resourceName, value string) error { - return validateResourceNameByRegex(resourceName, value, `^(([a-z0-9][-a-z0-9.]*)?[a-z0-9])?$`) -} - -func validateResourceNameByRegex(resourceName string, value string, expression string) error { if len(value) > 253 { return InvalidStringValueMaxLengthError(resourceName, value, 253) } @@ -132,11 +128,11 @@ func validateResourceNameByRegex(resourceName string, value string, expression s return ResourceNameCannotBeEmptyError(resourceName) } - re := regexp.MustCompile(expression) + re := regexp.MustCompile(resourceNameTemplate) isValid := re.MatchString(value) if !isValid { - return InvalidLowerCaseAlphaNumericDotDashResourceNameError(resourceName, value) + return InvalidLowerCaseAlphaNumericDashResourceNameError(resourceName, value) } return nil From fd2a696211d3c6921e5408930c10eaf6549d1878 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 2 Nov 2023 13:03:03 +0100 Subject: [PATCH 026/121] Extended DNS alias validation --- pkg/apis/radixvalidators/errors.go | 5 +++++ pkg/apis/radixvalidators/testdata/radixconfig.yaml | 8 +++++++- pkg/apis/radixvalidators/validate_ra.go | 13 +++++++++---- pkg/apis/radixvalidators/validate_ra_test.go | 13 +++++++++++++ 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/pkg/apis/radixvalidators/errors.go b/pkg/apis/radixvalidators/errors.go index e503071c3..4529d89bb 100644 --- a/pkg/apis/radixvalidators/errors.go +++ b/pkg/apis/radixvalidators/errors.go @@ -33,6 +33,11 @@ func ComponentForDNSAliasNotDefinedError(component string) error { return fmt.Errorf("component %s referred to by dnsAlias is not defined", component) } +// ComponentForDNSAliasIsNotMarkedAsPublicError Component is not marked as public +func ComponentForDNSAliasIsNotMarkedAsPublicError(component string) error { + return fmt.Errorf("component %s referred to by dnsAlias is not marked as public", component) +} + // EnvForDNSAppAliasNotDefinedError Error when env not defined func EnvForDNSAppAliasNotDefinedError(env string) error { return fmt.Errorf("environment %s referred to by dnsAppAlias is not defined", env) diff --git a/pkg/apis/radixvalidators/testdata/radixconfig.yaml b/pkg/apis/radixvalidators/testdata/radixconfig.yaml index 1e1c15987..da6de23ca 100644 --- a/pkg/apis/radixvalidators/testdata/radixconfig.yaml +++ b/pkg/apis/radixvalidators/testdata/radixconfig.yaml @@ -87,6 +87,12 @@ spec: ports: - name: http port: 8090 + - name: app2 + src: . + ports: + - name: http + port: 8080 + publicPort: http jobs: - name: job src: job/ @@ -143,5 +149,5 @@ spec: component: app dnsAlias: - environment: prod - component: app + component: app2 domain: my-domain \ No newline at end of file diff --git a/pkg/apis/radixvalidators/validate_ra.go b/pkg/apis/radixvalidators/validate_ra.go index b2c4519f0..c767d3c49 100644 --- a/pkg/apis/radixvalidators/validate_ra.go +++ b/pkg/apis/radixvalidators/validate_ra.go @@ -196,10 +196,15 @@ func validateDNSAlias(app *radixv1.RadixApplication) []error { errs = append(errs, err) environmentNameIsValid = false } - if componentNameIsValid && environmentNameIsValid { - if err := validateDNSAliasComponentAndEnvironmentAvailable(app, dnsAlias.Component, dnsAlias.Environment); err != nil { - errs = append(errs, err...) - } + if !componentNameIsValid || !environmentNameIsValid { + continue + } + if err := validateDNSAliasComponentAndEnvironmentAvailable(app, dnsAlias.Component, dnsAlias.Environment); err != nil { + errs = append(errs, err...) + continue + } + if !doesComponentHaveAPublicPort(app, dnsAlias.Component) { + errs = append(errs, ComponentForDNSAliasIsNotMarkedAsPublicError(dnsAlias.Component)) } } return errs diff --git a/pkg/apis/radixvalidators/validate_ra_test.go b/pkg/apis/radixvalidators/validate_ra_test.go index e8de47422..8b9dc3230 100644 --- a/pkg/apis/radixvalidators/validate_ra_test.go +++ b/pkg/apis/radixvalidators/validate_ra_test.go @@ -79,6 +79,7 @@ func Test_invalid_ra(t *testing.T) { validRAFirstComponentName := "app" validRAFirstJobName := "job" validRASecondComponentName := "redis" + validRAComponentNameApp2 := "app2" wayTooLongName := "waytoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooolongname" tooLongPortName := "abcdefghijklmnop" @@ -230,6 +231,18 @@ func Test_invalid_ra(t *testing.T) { {"dns alias domain is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameError("dnsAlias domain", "my.domain"), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias[0].Domain = "my.domain" }}, + {"dns alias domain is invalid", radixvalidators.DuplicateDomainForDNSAliasError("my-domain"), func(ra *v1.RadixApplication) { + ra.Spec.DNSAlias = append(ra.Spec.DNSAlias, ra.Spec.DNSAlias[0]) + }}, + {"dns alias with no public port", radixvalidators.ComponentForDNSAliasIsNotMarkedAsPublicError(validRAComponentNameApp2), func(ra *v1.RadixApplication) { + ra.Spec.Components[3].PublicPort = "" + ra.Spec.Components[3].Public = false + ra.Spec.DNSAlias[0] = v1.DNSAlias{ + Domain: "my-domain", + Component: ra.Spec.Components[3].Name, + Environment: ra.Spec.Environments[0].Name, + } + }}, {"dns external alias non existing component", radixvalidators.ComponentForDNSExternalAliasNotDefinedError(nonExistingComponent), func(ra *v1.RadixApplication) { ra.Spec.DNSExternalAlias = []v1.ExternalAlias{ { From 641901b371bc0d2a8e07e74725ae06be3f9acbaf Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 2 Nov 2023 15:19:01 +0100 Subject: [PATCH 027/121] Added validation on existing RadixDNSAliases on applying RadixApplication --- .../applicationconfig/applicationconfig.go | 43 ++++++--- pkg/apis/applicationconfig/dns_alias.go | 21 ++++- pkg/apis/applicationconfig/dns_alias_test.go | 89 +++++++++++++++---- pkg/apis/applicationconfig/errors.go | 8 ++ pkg/apis/dnsalias/syncer_test.go | 26 ++---- pkg/apis/test/utils.go | 68 ++++++++++---- pkg/apis/utils/application_builder.go | 6 +- .../utils/applicationcomponent_builder.go | 2 +- radix-operator/dnsalias/handler_test.go | 26 +----- 9 files changed, 197 insertions(+), 92 deletions(-) create mode 100644 pkg/apis/applicationconfig/errors.go diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index 24e94a4f9..4204a7554 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -137,21 +137,24 @@ func (app *ApplicationConfig) ApplyConfigToApplicationNamespace() error { return fmt.Errorf("failed to get radix application. %v", err) } - // Update RA if different log.Debugf("RadixApplication %s exists in namespace %s", app.config.Name, appNamespace) - if !reflect.DeepEqual(app.config.Spec, existingRA.Spec) { - log.Debugf("RadixApplication %s in namespace %s has changed, updating now", app.config.Name, appNamespace) - // For an update, ResourceVersion of the new object must be the same with the old object - app.config.SetResourceVersion(existingRA.GetResourceVersion()) - _, err = app.radixclient.RadixV1().RadixApplications(appNamespace).Update(context.TODO(), app.config, metav1.UpdateOptions{}) - if err != nil { - return fmt.Errorf("failed to update existing radix application. %v", err) - } - log.Infof("RadixApplication %s updated in namespace %s", app.config.Name, appNamespace) - } else { + if reflect.DeepEqual(app.config.Spec, existingRA.Spec) { log.Infof("No changes to RadixApplication %s in namespace %s", app.config.Name, appNamespace) + return nil } + if err = app.ValidateApplicationCanBeApplied(); err != nil { + return err + } + // Update RA if different + log.Debugf("RadixApplication %s in namespace %s has changed, updating now", app.config.Name, appNamespace) + // For an update, ResourceVersion of the new object must be the same with the old object + app.config.SetResourceVersion(existingRA.GetResourceVersion()) + _, err = app.radixclient.RadixV1().RadixApplications(appNamespace).Update(context.TODO(), app.config, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("failed to update existing radix application. %v", err) + } + log.Infof("RadixApplication %s updated in namespace %s", app.config.Name, appNamespace) return nil } @@ -288,6 +291,24 @@ func (app *ApplicationConfig) getPortForDNSAlias(dnsAlias radixv1.DNSAlias) (int return componentPublicPort.Port, nil } +// ValidateApplicationCanBeApplied Validate that the RadixApplication can be applied +func (app *ApplicationConfig) ValidateApplicationCanBeApplied() error { + return app.validateDNSAliases() +} + +func (app *ApplicationConfig) validateDNSAliases() error { + radixDNSAliasMap, err := app.getAllRadixDNSAliasesMap() + if err != nil { + return err + } + for _, dnsAlias := range app.config.Spec.DNSAlias { + if radixDNSAlias, ok := radixDNSAliasMap[dnsAlias.Domain]; ok && radixDNSAlias.Spec.AppName != app.config.Name { + return RadixDNSAliasAlreadyUsedByAnotherApplicationError(dnsAlias.Domain) + } + } + return nil +} + // patchDifference creates a mergepatch, comparing old and new RadixEnvironments and issues the patch to radix func patchDifference(repository radixTypes.RadixEnvironmentInterface, oldRe *radixv1.RadixEnvironment, newRe *radixv1.RadixEnvironment, logger *log.Entry) error { radixEnvironment := oldRe.DeepCopy() diff --git a/pkg/apis/applicationconfig/dns_alias.go b/pkg/apis/applicationconfig/dns_alias.go index 5efe9ff44..0deb7e83f 100644 --- a/pkg/apis/applicationconfig/dns_alias.go +++ b/pkg/apis/applicationconfig/dns_alias.go @@ -1,6 +1,7 @@ package applicationconfig import ( + "context" "fmt" "strings" @@ -13,7 +14,7 @@ import ( func (app *ApplicationConfig) createOrUpdateDNSAliases() error { appName := app.registration.Name - radixDNSAliasesMap, err := app.getRadixDNSAliasesMap(appName) + radixDNSAliasesMap, err := app.getRadixDNSAliasesMapForAppName(appName) if err != nil { return err } @@ -83,13 +84,25 @@ func (app *ApplicationConfig) createRadixDNSAlias(appName string, dnsAlias radix return app.kubeutil.CreateRadixDNSAlias(&radixDNSAlias) } -func (app *ApplicationConfig) getRadixDNSAliasesMap(appName string) (map[string]*radixv1.RadixDNSAlias, error) { - dnsAliases, err := app.kubeutil.ListRadixDNSAliasWithSelector(labels.ForApplicationName(appName).String()) +func (app *ApplicationConfig) getRadixDNSAliasesMapForAppName(appName string) (map[string]*radixv1.RadixDNSAlias, error) { + radixDNSAliasList, err := app.kubeutil.ListRadixDNSAliasWithSelector(labels.ForApplicationName(appName).String()) if err != nil { return nil, err } + return getRadixDNSAliasMap(radixDNSAliasList), err +} + +func (app *ApplicationConfig) getAllRadixDNSAliasesMap() (map[string]*radixv1.RadixDNSAlias, error) { + radixDNSAliasList, err := app.kubeutil.RadixClient().RadixV1().RadixDNSAliases().List(context.Background(), metav1.ListOptions{}) + if err != nil { + return nil, err + } + return getRadixDNSAliasMap(slice.PointersOf(radixDNSAliasList.Items).([]*radixv1.RadixDNSAlias)), nil +} + +func getRadixDNSAliasMap(dnsAliases []*radixv1.RadixDNSAlias) map[string]*radixv1.RadixDNSAlias { return slice.Reduce(dnsAliases, make(map[string]*radixv1.RadixDNSAlias), func(acc map[string]*radixv1.RadixDNSAlias, dnsAlias *radixv1.RadixDNSAlias) map[string]*radixv1.RadixDNSAlias { acc[dnsAlias.Name] = dnsAlias return acc - }), err + }) } diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go index d14a88e6f..b97946a4b 100644 --- a/pkg/apis/applicationconfig/dns_alias_test.go +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -5,11 +5,12 @@ import ( "fmt" "testing" + "github.com/equinor/radix-operator/pkg/apis/applicationconfig" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + commonTest "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" - radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -237,7 +238,7 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { t.Run(ts.name, func(t *testing.T) { tu, kubeClient, kubeUtil, radixClient := setupTest() - require.NoError(t, registerExistingRadixDNSAliases(radixClient, ts.existingRadixDNSAliases), "create existing RadixDNSAlias") + require.NoError(t, commonTest.RegisterRadixDNSAliases(radixClient, ts.existingRadixDNSAliases), "create existing RadixDNSAlias") require.NoError(t, applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, ts.applicationBuilder), "register radix application") radixDNSAliases, err := radixClient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{}) @@ -303,19 +304,75 @@ func Test_DNSAliases_FileOndInvalidAppName(t *testing.T) { require.Error(t, err, "register radix application") } -func registerExistingRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]radixv1.RadixDNSAliasSpec) error { - for domain, aliasesSpec := range radixDNSAliasesMap { - _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), - &radixv1.RadixDNSAlias{ - ObjectMeta: metav1.ObjectMeta{ - Name: domain, - Labels: map[string]string{kube.RadixAppLabel: aliasesSpec.AppName}, - }, - Spec: aliasesSpec, - }, metav1.CreateOptions{}) - if err != nil { - return err - } +func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { + const ( + raAppName = "anyapp" + otherAppName = "anyapp2" + raEnv = "test" + raComponentName = "app" + raPublicPort = 8080 + someEnv = "dev" + someComponentName = "component-abc" + somePort = 9090 + domain1 = "domain1" + domain2 = "domain2" + ) + var testScenarios = []struct { + name string + applicationBuilder utils.ApplicationBuilder + existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec + expectedValidationError error + }{ + { + name: "No dns aliases", + applicationBuilder: utils.ARadixApplication(), + expectedValidationError: nil, + }, + { + name: "Added dns aliases", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: raEnv, Component: raComponentName}), + expectedValidationError: nil, + }, + { + name: "Existing dns aliases for the app", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: raEnv, Component: raComponentName}), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: raAppName, Environment: raEnv, Component: raComponentName, Port: raPublicPort}, + }, + expectedValidationError: nil, + }, + { + name: "Existing dns aliases for the app and another app", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: raEnv, Component: raComponentName}), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: raAppName, Environment: raEnv, Component: raComponentName, Port: raPublicPort}, + domain2: {AppName: otherAppName, Environment: someEnv, Component: someComponentName, Port: somePort}, + }, + expectedValidationError: nil, + }, + { + name: "Same domain exists in dns alias for another app", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: raEnv, Component: raComponentName}), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + domain1: {AppName: otherAppName, Environment: someEnv, Component: someComponentName, Port: somePort}, + }, + expectedValidationError: applicationconfig.RadixDNSAliasAlreadyUsedByAnotherApplicationError(domain1), + }, + } + + for _, ts := range testScenarios { + t.Run(ts.name, func(t *testing.T) { + _, kubeClient, kubeUtil, radixClient := setupTest() + err := commonTest.RegisterRadixDNSAliases(radixClient, ts.existingRadixDNSAliases) + require.NoError(t, err) + rr := ts.applicationBuilder.GetRegistrationBuilder().BuildRR() + ra := ts.applicationBuilder.BuildRA() + applicationConfig, err := applicationconfig.NewApplicationConfig(kubeClient, kubeUtil, radixClient, rr, ra) + require.NoError(t, err) + + actualValidationErr := applicationConfig.ValidateApplicationCanBeApplied() + + require.Equal(t, ts.expectedValidationError, actualValidationErr) + }) } - return nil } diff --git a/pkg/apis/applicationconfig/errors.go b/pkg/apis/applicationconfig/errors.go new file mode 100644 index 000000000..a9168b22f --- /dev/null +++ b/pkg/apis/applicationconfig/errors.go @@ -0,0 +1,8 @@ +package applicationconfig + +import "fmt" + +// RadixDNSAliasAlreadyUsedByAnotherApplicationError Error when RadixDNSAlias already used by another application +func RadixDNSAliasAlreadyUsedByAnotherApplicationError(domain string) error { + return fmt.Errorf("DNS alias %s already used by another application", domain) +} diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index f097b80a2..32cf83419 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -9,9 +9,8 @@ import ( "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - "github.com/equinor/radix-operator/pkg/apis/test" + commonTest "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" - radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" "github.com/equinor/radix-operator/radix-operator/config" prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" @@ -65,13 +64,12 @@ type testDNSAlias struct { } type scenario struct { - name string - expectedError string - dnsAlias testDNSAlias - dnsZone string - existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec - existingIngress map[string]testIngress - expectedIngress map[string]testIngress + name string + expectedError string + dnsAlias testDNSAlias + dnsZone string + existingIngress map[string]testIngress + expectedIngress map[string]testIngress } func (s *syncerTestSuite) Test_syncer_OnSync() { @@ -194,12 +192,12 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { s.SetupTest() radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Domain, UID: uuid.NewUUID()}, Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component, Port: ts.dnsAlias.Port}} - s.Require().NoError(registerExistingRadixDNSAlias(s.radixClient, radixDNSAlias), "create existing alias") + s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Domain, radixDNSAlias.Spec), "create existing alias") cfg := &config.ClusterConfig{DNSZone: ts.dnsZone} s.Require().NoError(registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1, cfg), "create existing ingresses") syncer := s.createSyncer(radixDNSAlias) err := syncer.OnSync() - test.AssertError(s.T(), ts.expectedError, err) + commonTest.AssertError(s.T(), ts.expectedError, err) ingresses, err := s.kubeClient.NetworkingV1().Ingresses("").List(context.Background(), metav1.ListOptions{}) s.Require().NoError(err) @@ -253,9 +251,3 @@ func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses ma } return nil } - -func registerExistingRadixDNSAlias(radixClient radixclient.Interface, radixDNSAlias *radixv1.RadixDNSAlias) error { - _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.TODO(), - radixDNSAlias, metav1.CreateOptions{}) - return err -} diff --git a/pkg/apis/test/utils.go b/pkg/apis/test/utils.go index 953259185..8952b274f 100644 --- a/pkg/apis/test/utils.go +++ b/pkg/apis/test/utils.go @@ -7,7 +7,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" log "github.com/sirupsen/logrus" @@ -45,7 +45,7 @@ func (tu *Utils) GetKubeUtil() *kube.Kube { } // ApplyRegistration Will help persist an application registration -func (tu *Utils) ApplyRegistration(registrationBuilder utils.RegistrationBuilder) (*v1.RadixRegistration, error) { +func (tu *Utils) ApplyRegistration(registrationBuilder utils.RegistrationBuilder) (*radixv1.RadixRegistration, error) { rr := registrationBuilder.BuildRR() _, err := tu.radixclient.RadixV1().RadixRegistrations().Create(context.TODO(), rr, metav1.CreateOptions{}) @@ -60,7 +60,7 @@ func (tu *Utils) ApplyRegistration(registrationBuilder utils.RegistrationBuilder } // ApplyRegistrationUpdate Will help update a registration -func (tu *Utils) ApplyRegistrationUpdate(registrationBuilder utils.RegistrationBuilder) (*v1.RadixRegistration, error) { +func (tu *Utils) ApplyRegistrationUpdate(registrationBuilder utils.RegistrationBuilder) (*radixv1.RadixRegistration, error) { rr := registrationBuilder.BuildRR() rrPrev, err := tu.radixclient.RadixV1().RadixRegistrations().Get(context.TODO(), rr.GetName(), metav1.GetOptions{}) @@ -78,9 +78,9 @@ func (tu *Utils) ApplyRegistrationUpdate(registrationBuilder utils.RegistrationB } // ApplyApplication Will help persist an application -func (tu *Utils) ApplyApplication(applicationBuilder utils.ApplicationBuilder) (*v1.RadixApplication, error) { +func (tu *Utils) ApplyApplication(applicationBuilder utils.ApplicationBuilder) (*radixv1.RadixApplication, error) { regBuilder := applicationBuilder.GetRegistrationBuilder() - var rr *v1.RadixRegistration + var rr *radixv1.RadixRegistration if regBuilder != nil { rr, _ = tu.ApplyRegistration(regBuilder) @@ -111,7 +111,7 @@ func (tu *Utils) ApplyApplication(applicationBuilder utils.ApplicationBuilder) ( } // ApplyApplicationUpdate Will help update an application -func (tu *Utils) ApplyApplicationUpdate(applicationBuilder utils.ApplicationBuilder) (*v1.RadixApplication, error) { +func (tu *Utils) ApplyApplicationUpdate(applicationBuilder utils.ApplicationBuilder) (*radixv1.RadixApplication, error) { ra := applicationBuilder.BuildRA() appNamespace := utils.GetAppNamespace(ra.GetName()) @@ -120,7 +120,7 @@ func (tu *Utils) ApplyApplicationUpdate(applicationBuilder utils.ApplicationBuil return ra, err } - var rr *v1.RadixRegistration + var rr *radixv1.RadixRegistration regBuilder := applicationBuilder.GetRegistrationBuilder() if regBuilder != nil { rr, err = tu.ApplyRegistration(regBuilder) @@ -144,7 +144,7 @@ func (tu *Utils) ApplyApplicationUpdate(applicationBuilder utils.ApplicationBuil } // ApplyDeployment Will help persist a deployment -func (tu *Utils) ApplyDeployment(deploymentBuilder utils.DeploymentBuilder) (*v1.RadixDeployment, error) { +func (tu *Utils) ApplyDeployment(deploymentBuilder utils.DeploymentBuilder) (*radixv1.RadixDeployment, error) { envs := make(map[string]struct{}) if deploymentBuilder.GetApplicationBuilder() != nil { ra, _ := tu.ApplyApplication(deploymentBuilder.GetApplicationBuilder()) @@ -172,7 +172,7 @@ func (tu *Utils) ApplyDeployment(deploymentBuilder utils.DeploymentBuilder) (*v1 } // ApplyDeploymentUpdate Will help update a deployment -func (tu *Utils) ApplyDeploymentUpdate(deploymentBuilder utils.DeploymentBuilder) (*v1.RadixDeployment, error) { +func (tu *Utils) ApplyDeploymentUpdate(deploymentBuilder utils.DeploymentBuilder) (*radixv1.RadixDeployment, error) { rd := deploymentBuilder.BuildRD() envNamespace := utils.GetEnvironmentNamespace(rd.Spec.AppName, rd.Spec.Environment) @@ -191,7 +191,7 @@ func (tu *Utils) ApplyDeploymentUpdate(deploymentBuilder utils.DeploymentBuilder } // ApplyJob Will help persist a radixjob -func (tu *Utils) ApplyJob(jobBuilder utils.JobBuilder) (*v1.RadixJob, error) { +func (tu *Utils) ApplyJob(jobBuilder utils.JobBuilder) (*radixv1.RadixJob, error) { if jobBuilder.GetApplicationBuilder() != nil { tu.ApplyApplication(jobBuilder.GetApplicationBuilder()) } @@ -208,7 +208,7 @@ func (tu *Utils) ApplyJob(jobBuilder utils.JobBuilder) (*v1.RadixJob, error) { } // ApplyJobUpdate Will help update a radixjob -func (tu *Utils) ApplyJobUpdate(jobBuilder utils.JobBuilder) (*v1.RadixJob, error) { +func (tu *Utils) ApplyJobUpdate(jobBuilder utils.JobBuilder) (*radixv1.RadixJob, error) { rj := jobBuilder.BuildRJ() appNamespace := CreateAppNamespace(tu.client, rj.Spec.AppName) @@ -228,7 +228,7 @@ func (tu *Utils) ApplyJobUpdate(jobBuilder utils.JobBuilder) (*v1.RadixJob, erro } // ApplyEnvironment Will help persist a RadixEnvironment -func (tu *Utils) ApplyEnvironment(environmentBuilder utils.EnvironmentBuilder) (*v1.RadixEnvironment, error) { +func (tu *Utils) ApplyEnvironment(environmentBuilder utils.EnvironmentBuilder) (*radixv1.RadixEnvironment, error) { re := environmentBuilder.BuildRE() log.Debugf("%s", re.GetObjectMeta().GetCreationTimestamp()) @@ -244,7 +244,7 @@ func (tu *Utils) ApplyEnvironment(environmentBuilder utils.EnvironmentBuilder) ( } // ApplyEnvironmentUpdate Will help update a RadixEnvironment -func (tu *Utils) ApplyEnvironmentUpdate(environmentBuilder utils.EnvironmentBuilder) (*v1.RadixEnvironment, error) { +func (tu *Utils) ApplyEnvironmentUpdate(environmentBuilder utils.EnvironmentBuilder) (*radixv1.RadixEnvironment, error) { re := environmentBuilder.BuildRE() rePrev, err := tu.radixclient.RadixV1().RadixEnvironments().Get(context.TODO(), re.GetName(), metav1.GetOptions{}) @@ -346,7 +346,7 @@ func IntPtr(i int) *int { return &i } -func (tu *Utils) applyRadixDeploymentEnvVarsConfigMaps(rd *v1.RadixDeployment) map[string]*corev1.ConfigMap { +func (tu *Utils) applyRadixDeploymentEnvVarsConfigMaps(rd *radixv1.RadixDeployment) map[string]*corev1.ConfigMap { envVarConfigMapsMap := map[string]*corev1.ConfigMap{} for _, deployComponent := range rd.Spec.Components { envVarConfigMapsMap[deployComponent.GetName()] = tu.ensurePopulatedEnvVarsConfigMaps(rd, &deployComponent) @@ -357,7 +357,7 @@ func (tu *Utils) applyRadixDeploymentEnvVarsConfigMaps(rd *v1.RadixDeployment) m return envVarConfigMapsMap } -func (tu *Utils) ensurePopulatedEnvVarsConfigMaps(rd *v1.RadixDeployment, deployComponent v1.RadixCommonDeployComponent) *corev1.ConfigMap { +func (tu *Utils) ensurePopulatedEnvVarsConfigMaps(rd *radixv1.RadixDeployment, deployComponent radixv1.RadixCommonDeployComponent) *corev1.ConfigMap { initialEnvVarsConfigMap, _, _ := tu.kubeUtil.GetOrCreateEnvVarsConfigMapAndMetadataMap(rd.GetNamespace(), rd.Spec.AppName, deployComponent.GetName()) desiredConfigMap := initialEnvVarsConfigMap.DeepCopy() @@ -372,7 +372,7 @@ func (tu *Utils) ensurePopulatedEnvVarsConfigMaps(rd *v1.RadixDeployment, deploy } // GetRadixAzureKeyVaultObjectTypePtr Gets pointer to RadixAzureKeyVaultObjectType -func GetRadixAzureKeyVaultObjectTypePtr(objectType v1.RadixAzureKeyVaultObjectType) *v1.RadixAzureKeyVaultObjectType { +func GetRadixAzureKeyVaultObjectTypePtr(objectType radixv1.RadixAzureKeyVaultObjectType) *radixv1.RadixAzureKeyVaultObjectType { return &objectType } @@ -380,7 +380,7 @@ func GetRadixAzureKeyVaultObjectTypePtr(objectType v1.RadixAzureKeyVaultObjectTy func GetAzureKeyVaultTypeSecrets(secrets *corev1.SecretList) *corev1.SecretList { var azureKeyVaultSecrets []corev1.Secret for _, secret := range secrets.Items { - if label, ok := secret.ObjectMeta.Labels[kube.RadixSecretRefTypeLabel]; ok && label == string(v1.RadixSecretRefTypeAzureKeyVault) { + if label, ok := secret.ObjectMeta.Labels[kube.RadixSecretRefTypeLabel]; ok && label == string(radixv1.RadixSecretRefTypeAzureKeyVault) { azureKeyVaultSecrets = append(azureKeyVaultSecrets, secret) } } @@ -399,3 +399,37 @@ func AssertError(t *testing.T, expectedError string, err error) { require.Equal(t, expectedError, err.Error()) } } + +// RegisterRadixDNSAliases Register RadixDNSAliases +func RegisterRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]radixv1.RadixDNSAliasSpec) error { + for domain, aliasesSpec := range radixDNSAliasesMap { + err := RegisterRadixDNSAliasBySpec(radixClient, domain, aliasesSpec) + if err != nil { + return err + } + } + return nil +} + +// RegisterRadixDNSAlias Register RadixDNSAlias by properties +func RegisterRadixDNSAlias(radixClient radixclient.Interface, appName, componentName, envName, domain string, port int32) error { + return RegisterRadixDNSAliasBySpec(radixClient, domain, radixv1.RadixDNSAliasSpec{ + AppName: appName, + Environment: envName, + Component: componentName, + Port: port, + }) +} + +// RegisterRadixDNSAliasBySpec Register RadixDNSAlias by its spec +func RegisterRadixDNSAliasBySpec(radixClient radixclient.Interface, domain string, aliasesSpec radixv1.RadixDNSAliasSpec) error { + _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), + &radixv1.RadixDNSAlias{ + ObjectMeta: metav1.ObjectMeta{ + Name: domain, + Labels: map[string]string{kube.RadixAppLabel: aliasesSpec.AppName}, + }, + Spec: aliasesSpec, + }, metav1.CreateOptions{}) + return err +} diff --git a/pkg/apis/utils/application_builder.go b/pkg/apis/utils/application_builder.go index e5ad75efa..d518a3f30 100644 --- a/pkg/apis/utils/application_builder.go +++ b/pkg/apis/utils/application_builder.go @@ -212,8 +212,8 @@ func (ap *ApplicationBuilderStruct) BuildRA() *radixv1.RadixApplication { build = nil } else { build = &radixv1.BuildSpec{ - Secrets: ap.buildSecrets, - UseBuildKit: ap.useBuildKit, + Secrets: ap.buildSecrets, + UseBuildKit: ap.useBuildKit, UseBuildCache: ap.useBuildCache, } } @@ -252,7 +252,7 @@ func ARadixApplication() ApplicationBuilder { WithRadixRegistration(ARadixRegistration()). WithAppName("anyapp"). WithEnvironment("test", "master"). - WithComponent(AnApplicationComponent()). + WithComponent(AnApplicationComponent().WithPort("http", 8080).WithPublicPort("http")). WithJobComponent( AnApplicationJobComponent(). WithSchedulerPort(numbers.Int32Ptr(8888)), diff --git a/pkg/apis/utils/applicationcomponent_builder.go b/pkg/apis/utils/applicationcomponent_builder.go index 64aa73a95..46e8a9ff8 100644 --- a/pkg/apis/utils/applicationcomponent_builder.go +++ b/pkg/apis/utils/applicationcomponent_builder.go @@ -212,7 +212,7 @@ func NewApplicationComponentBuilder() RadixApplicationComponentBuilder { return &radixApplicationComponentBuilder{} } -// AnApplicationComponent Constructor for component builder builder containing test data +// AnApplicationComponent Constructor for component builder containing test data func AnApplicationComponent() RadixApplicationComponentBuilder { return &radixApplicationComponentBuilder{ name: "app", diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index d421c8f6e..60b663191 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -1,21 +1,17 @@ package dnsalias_test import ( - "context" "fmt" "testing" dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" - radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - "github.com/equinor/radix-operator/pkg/apis/utils/labels" - radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + commonTest "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/radix-operator/common" "github.com/equinor/radix-operator/radix-operator/config" "github.com/equinor/radix-operator/radix-operator/dnsalias" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" "github.com/golang/mock/gomock" "github.com/stretchr/testify/suite" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type handlerTestSuite struct { @@ -59,7 +55,7 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { clusterConfig := &config.ClusterConfig{DNSZone: "test.radix.equinor.com"} - s.Require().NoError(registerExistingRadixDNSAliases(s.RadixClient, appName1, env1, component1, domain1), "create existing RadixDNSAlias") + s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, domain1, 8080), "create existing RadixDNSAlias") handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, clusterConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) expectedError := fmt.Errorf("some error") @@ -72,7 +68,7 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsNoError() { clusterConfig := &config.ClusterConfig{DNSZone: "test.radix.equinor.com"} - s.Require().NoError(registerExistingRadixDNSAliases(s.RadixClient, appName1, env1, component1, domain1), "create existing RadixDNSAlias") + s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, domain1, 8080), "create existing RadixDNSAlias") handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, clusterConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), clusterConfig, gomock.Any()).Return(s.syncer).Times(1) @@ -81,19 +77,3 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsNoError() { err := handler.Sync("", domain1, s.EventRecorder) s.Require().Nil(err) } - -func registerExistingRadixDNSAliases(radixClient radixclient.Interface, appName, envName, component, domain string) error { - _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), - &radixv1.RadixDNSAlias{ - ObjectMeta: metav1.ObjectMeta{ - Name: domain, - Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(component)), - }, - Spec: radixv1.RadixDNSAliasSpec{ - AppName: appName, - Environment: envName, - Component: component, - }, - }, metav1.CreateOptions{}) - return err -} From 38c7f8c1b0357ee12e8fa0de08961a7753eceda2 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 2 Nov 2023 16:51:24 +0100 Subject: [PATCH 028/121] Added whitelisted DNS aliases to the chart --- charts/radix-operator/templates/deployment.yaml | 2 ++ charts/radix-operator/values.yaml | 8 ++++++++ pkg/apis/defaults/environment_variables.go | 3 +++ 3 files changed, 13 insertions(+) diff --git a/charts/radix-operator/templates/deployment.yaml b/charts/radix-operator/templates/deployment.yaml index 1a5f97a27..835578100 100644 --- a/charts/radix-operator/templates/deployment.yaml +++ b/charts/radix-operator/templates/deployment.yaml @@ -158,6 +158,8 @@ spec: value: {{ .Values.seccompProfile.fileNameOnNode }} - name: RADIX_BUILDAH_IMAGE_BUILDER value: {{ .Values.buildahImageBuilder }} + - name: RADIX_DNS_ALIAS_WHITELISTED + value: {{ .Values.dnsAliasWhitelisted }} livenessProbe: httpGet: path: /healthz diff --git a/charts/radix-operator/values.yaml b/charts/radix-operator/values.yaml index 4ed7786f8..1fb7d4be7 100644 --- a/charts/radix-operator/values.yaml +++ b/charts/radix-operator/values.yaml @@ -20,6 +20,14 @@ buildahImageBuilder: xx jobScheduler: radix-job-scheduler:main-latest radixTekton: radix-tekton:main-latest useImageBuilderCache: 0 +dnsAliasWhitelisted: +- api +- canary +- console +- cost-api +- grafana +- prometheus +- webhook appAliasBaseURL: app.dev.radix.equinor.com dnsZone: dev.radix.equinor.com diff --git a/pkg/apis/defaults/environment_variables.go b/pkg/apis/defaults/environment_variables.go index b316e61e5..35f63d43e 100644 --- a/pkg/apis/defaults/environment_variables.go +++ b/pkg/apis/defaults/environment_variables.go @@ -191,4 +191,7 @@ const ( // RadixBuildahImageBuilderEnvironmentVariable The container image used for running the buildah engine RadixBuildahImageBuilderEnvironmentVariable = "RADIX_BUILDAH_IMAGE_BUILDER" + + // RadixDNSAliasWhitelistedEnvironmentVariable The list of DNS aliases, which cannot be used by Radix applications + RadixDNSAliasWhitelistedEnvironmentVariable = "RADIX_DNS_ALIAS_WHITELISTED" ) From 1a26b66e791a322dad77b6628431e3aa1a2d5b5f Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 3 Nov 2023 16:14:59 +0100 Subject: [PATCH 029/121] Added reserved DNS aliases to the chart and config --- README.md | 4 +++ charts/radix-operator/templates/_helpers.tpl | 16 ++++++++++ .../radix-operator/templates/deployment.yaml | 6 ++-- charts/radix-operator/values.yaml | 17 +++++----- pkg/apis/defaults/environment_variables.go | 7 +++-- radix-operator/config/cluster_config.go | 4 +++ radix-operator/config/config.go | 31 +++++++++++++++---- 7 files changed, 67 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index b23e30ea7..d6f3759dd 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,10 @@ The `radix-pipeline` never gets deployed to cluster, but rather is invoked by th - `master` branch should be used for creating the image used in the `qa` environment of any cluster. When a pull request is approved and merged to `master`, Github actions build will create a will create a `radix-pipeline:master-latest` image available in ACR of the subscription - `release` branch should be used for image used in the `prod` environment of any cluster. When a pull request is approved and merged to `master`, and tested ok in `qa` environment of any cluster, we should immediately merge `master` into `release` and build image used in the `prod` environment of any cluster, unless there are breaking changes which needs to be coordinated with release of our other components. When the `master` branch is merged to the `release` branch, Github actions build will create a `radix-pipeline:release-latest` image available in ACR of the subscription. +Test modification of Helm chart and its values (important option `--dry-run`!) +```bash +helm upgrade radix-operator /charts/radix-operator -n default --dry-run +``` ### Dependencies management As of 2019-10-28, radix-operator uses go modules. See [Using go modules](https://blog.golang.org/using-go-modules) for more information and guidelines. diff --git a/charts/radix-operator/templates/_helpers.tpl b/charts/radix-operator/templates/_helpers.tpl index 2ee8f9b7b..2d70af796 100644 --- a/charts/radix-operator/templates/_helpers.tpl +++ b/charts/radix-operator/templates/_helpers.tpl @@ -56,3 +56,19 @@ Create the name of the service account to use {{- define "radix-operator.serviceAccountName" -}} {{- default (include "radix-operator.fullname" .) .Values.serviceAccount.name }} {{- end }} + +{{/* +Utility function to take list to comma separated string +*/}} +{{- define "helm-toolkit.utils.joinListWithComma" -}} +{{- $local := dict "first" true -}} +{{- range $k, $v := . -}}{{- if not $local.first -}},{{- end -}}{{- $v -}}{{- $_ := set $local "first" false -}}{{- end -}} +{{- end -}} + +{{/* +Utility function to take list to comma separated dictionary +*/}} +{{- define "helm-toolkit.utils.joinMapWithComma" -}} +{{- $local := dict "first" true -}} +{{- range $k, $v := . -}}{{- if not $local.first -}},{{- end -}}{{ $k }}={{ $v }}{{- $_ := set $local "first" false -}}{{- end -}} +{{- end -}} diff --git a/charts/radix-operator/templates/deployment.yaml b/charts/radix-operator/templates/deployment.yaml index 835578100..c441d4c36 100644 --- a/charts/radix-operator/templates/deployment.yaml +++ b/charts/radix-operator/templates/deployment.yaml @@ -158,8 +158,10 @@ spec: value: {{ .Values.seccompProfile.fileNameOnNode }} - name: RADIX_BUILDAH_IMAGE_BUILDER value: {{ .Values.buildahImageBuilder }} - - name: RADIX_DNS_ALIAS_WHITELISTED - value: {{ .Values.dnsAliasWhitelisted }} + - name: RADIX_DNS_ALIAS_APP_RESERVED + value: {{ include "helm-toolkit.utils.joinMapWithComma" .Values.dnsAliasAppReserved | quote }} + - name: RADIX_DNS_ALIAS_RESERVED + value: {{ include "helm-toolkit.utils.joinListWithComma" .Values.dnsAliasReserved | quote }} livenessProbe: httpGet: path: /healthz diff --git a/charts/radix-operator/values.yaml b/charts/radix-operator/values.yaml index 1fb7d4be7..85364c62e 100644 --- a/charts/radix-operator/values.yaml +++ b/charts/radix-operator/values.yaml @@ -20,14 +20,15 @@ buildahImageBuilder: xx jobScheduler: radix-job-scheduler:main-latest radixTekton: radix-tekton:main-latest useImageBuilderCache: 0 -dnsAliasWhitelisted: -- api -- canary -- console -- cost-api -- grafana -- prometheus -- webhook +dnsAliasAppReserved: + api: radix-api + canary: radix-canary-golang + console: radix-web-console + cost-api: radix-cost-allocation-api + webhook: radix-github-webhook +dnsAliasReserved: + - grafana + - prometheus appAliasBaseURL: app.dev.radix.equinor.com dnsZone: dev.radix.equinor.com diff --git a/pkg/apis/defaults/environment_variables.go b/pkg/apis/defaults/environment_variables.go index 35f63d43e..31afada4d 100644 --- a/pkg/apis/defaults/environment_variables.go +++ b/pkg/apis/defaults/environment_variables.go @@ -192,6 +192,9 @@ const ( // RadixBuildahImageBuilderEnvironmentVariable The container image used for running the buildah engine RadixBuildahImageBuilderEnvironmentVariable = "RADIX_BUILDAH_IMAGE_BUILDER" - // RadixDNSAliasWhitelistedEnvironmentVariable The list of DNS aliases, which cannot be used by Radix applications - RadixDNSAliasWhitelistedEnvironmentVariable = "RADIX_DNS_ALIAS_WHITELISTED" + // RadixDNSAliasAppReservedEnvironmentVariable The list of DNS aliases, reserved for Radix platform Radix application + RadixDNSAliasAppReservedEnvironmentVariable = "RADIX_DNS_ALIAS_APP_RESERVED" + + // RadixDNSAliasReservedEnvironmentVariable The list of DNS aliases, reserved for Radix platform services + RadixDNSAliasReservedEnvironmentVariable = "RADIX_DNS_ALIAS_RESERVED" ) diff --git a/radix-operator/config/cluster_config.go b/radix-operator/config/cluster_config.go index cd512c219..15ec9b75a 100644 --- a/radix-operator/config/cluster_config.go +++ b/radix-operator/config/cluster_config.go @@ -5,4 +5,8 @@ type ClusterConfig struct { // DNSZone Cluster DNS zone. // Example radix.equinor.com, playground.radix.equinor.com DNSZone string + // DNSAliasAppReserved The list of DNS aliases, reserved for Radix platform Radix applications + DNSAliasAppReserved map[string]string + // DNSAliasReserved The list of DNS aliases, reserved for Radix platform services + DNSAliasReserved []string } diff --git a/radix-operator/config/config.go b/radix-operator/config/config.go index 3cea02c9f..33e146603 100644 --- a/radix-operator/config/config.go +++ b/radix-operator/config/config.go @@ -2,6 +2,7 @@ package config import ( "strconv" + "strings" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/job" @@ -36,13 +37,29 @@ func getDeploymentsHistoryLimitPerEnvironment() int { return getIntFromEnvVar(defaults.DeploymentsHistoryLimitEnvironmentVariable, 0) } -// Gets DNS zone func getDNSZone() string { - envVar, err := defaults.GetEnvVar(defaults.OperatorDNSZoneEnvironmentVariable) - if err != nil { - panic(err) + return viper.GetString(defaults.OperatorDNSZoneEnvironmentVariable) +} + +func getDNSAliasAppReserved() map[string]string { + return convertToMap(viper.GetString(defaults.RadixDNSAliasAppReservedEnvironmentVariable)) +} + +func convertToMap(keyValuePairs string) map[string]string { + pair := strings.Split(keyValuePairs, ",") + keyValues := make(map[string]string) + for _, part := range pair { + kv := strings.Split(part, "=") + if len(kv) == 2 { + keyValues[kv[0]] = kv[1] + } } - return envVar + return keyValues +} + +func getDNSAliasReserved() []string { + envVar := viper.GetString(defaults.RadixDNSAliasReservedEnvironmentVariable) + return strings.Split(envVar, ",") } func getIntFromEnvVar(envVarName string, defaultValue int) int { @@ -66,7 +83,9 @@ func NewConfig() *Config { return &Config{ LogLevel: getLogLevel(), ClusterConfig: &ClusterConfig{ - DNSZone: getDNSZone(), + DNSZone: getDNSZone(), + DNSAliasAppReserved: getDNSAliasAppReserved(), + DNSAliasReserved: getDNSAliasReserved(), }, PipelineJobConfig: &job.Config{ PipelineJobsHistoryLimit: getPipelineJobsHistoryLimit(), From 51b1786de40fb6176e19c578026cd9cc0af59c47 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 3 Nov 2023 16:51:07 +0100 Subject: [PATCH 030/121] Added unit-tests --- pkg/apis/applicationconfig/dns_alias_test.go | 10 ++++++++++ pkg/apis/applicationconfig/errors.go | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go index b97946a4b..859daee3e 100644 --- a/pkg/apis/applicationconfig/dns_alias_test.go +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -358,6 +358,16 @@ func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { }, expectedValidationError: applicationconfig.RadixDNSAliasAlreadyUsedByAnotherApplicationError(domain1), }, + { + name: "Reserved domain api for another app", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Domain: "api", Environment: raEnv, Component: raComponentName}), + expectedValidationError: applicationconfig.RadixDNSAliasIsReservedForRadixPlatformApplicationError("api"), + }, + { + name: "Reserved domain api for another app", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Domain: "api", Environment: raEnv, Component: raComponentName}), + expectedValidationError: applicationconfig.RadixDNSAliasIsReservedForRadixPlatformApplicationError("api"), + }, } for _, ts := range testScenarios { diff --git a/pkg/apis/applicationconfig/errors.go b/pkg/apis/applicationconfig/errors.go index a9168b22f..ac5ef6ce0 100644 --- a/pkg/apis/applicationconfig/errors.go +++ b/pkg/apis/applicationconfig/errors.go @@ -6,3 +6,13 @@ import "fmt" func RadixDNSAliasAlreadyUsedByAnotherApplicationError(domain string) error { return fmt.Errorf("DNS alias %s already used by another application", domain) } + +// RadixDNSAliasIsReservedForRadixPlatformApplicationError Error when RadixDNSAlias is reserved by Radix platform for a Radix application +func RadixDNSAliasIsReservedForRadixPlatformApplicationError(domain string) error { + return fmt.Errorf("DNS alias %s is reserved by Radix platform application", domain) +} + +// RadixDNSAliasIsReservedForRadixPlatformServiceError Error when RadixDNSAlias is reserved by Radix platform for a Radix service +func RadixDNSAliasIsReservedForRadixPlatformServiceError(domain string) error { + return fmt.Errorf("DNS alias %s is reserved by Radix platform service", domain) +} From 104d503c37c377a6627bf078f1bbe48fd5dbb8b7 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 6 Nov 2023 13:01:49 +0100 Subject: [PATCH 031/121] Added dnsalias reserved list check to common validation --- .../applicationconfig/applicationconfig.go | 21 --------------- pkg/apis/applicationconfig/dns_alias.go | 27 ++----------------- pkg/apis/kube/radix_dns_alias.go | 15 ++++++++++- pkg/apis/radixvalidators/errors.go | 15 +++++++++++ pkg/apis/radixvalidators/validate_ra.go | 15 ++++++++--- 5 files changed, 42 insertions(+), 51 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index 4204a7554..288eee38e 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -143,9 +143,6 @@ func (app *ApplicationConfig) ApplyConfigToApplicationNamespace() error { return nil } - if err = app.ValidateApplicationCanBeApplied(); err != nil { - return err - } // Update RA if different log.Debugf("RadixApplication %s in namespace %s has changed, updating now", app.config.Name, appNamespace) // For an update, ResourceVersion of the new object must be the same with the old object @@ -291,24 +288,6 @@ func (app *ApplicationConfig) getPortForDNSAlias(dnsAlias radixv1.DNSAlias) (int return componentPublicPort.Port, nil } -// ValidateApplicationCanBeApplied Validate that the RadixApplication can be applied -func (app *ApplicationConfig) ValidateApplicationCanBeApplied() error { - return app.validateDNSAliases() -} - -func (app *ApplicationConfig) validateDNSAliases() error { - radixDNSAliasMap, err := app.getAllRadixDNSAliasesMap() - if err != nil { - return err - } - for _, dnsAlias := range app.config.Spec.DNSAlias { - if radixDNSAlias, ok := radixDNSAliasMap[dnsAlias.Domain]; ok && radixDNSAlias.Spec.AppName != app.config.Name { - return RadixDNSAliasAlreadyUsedByAnotherApplicationError(dnsAlias.Domain) - } - } - return nil -} - // patchDifference creates a mergepatch, comparing old and new RadixEnvironments and issues the patch to radix func patchDifference(repository radixTypes.RadixEnvironmentInterface, oldRe *radixv1.RadixEnvironment, newRe *radixv1.RadixEnvironment, logger *log.Entry) error { radixEnvironment := oldRe.DeepCopy() diff --git a/pkg/apis/applicationconfig/dns_alias.go b/pkg/apis/applicationconfig/dns_alias.go index 0deb7e83f..3063576b3 100644 --- a/pkg/apis/applicationconfig/dns_alias.go +++ b/pkg/apis/applicationconfig/dns_alias.go @@ -1,12 +1,12 @@ package applicationconfig import ( - "context" "fmt" "strings" "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-common/utils/slice" + "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils/labels" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -14,7 +14,7 @@ import ( func (app *ApplicationConfig) createOrUpdateDNSAliases() error { appName := app.registration.Name - radixDNSAliasesMap, err := app.getRadixDNSAliasesMapForAppName(appName) + radixDNSAliasesMap, err := kube.GetRadixDNSAliasMapWithSelector(app.radixclient) if err != nil { return err } @@ -83,26 +83,3 @@ func (app *ApplicationConfig) createRadixDNSAlias(appName string, dnsAlias radix } return app.kubeutil.CreateRadixDNSAlias(&radixDNSAlias) } - -func (app *ApplicationConfig) getRadixDNSAliasesMapForAppName(appName string) (map[string]*radixv1.RadixDNSAlias, error) { - radixDNSAliasList, err := app.kubeutil.ListRadixDNSAliasWithSelector(labels.ForApplicationName(appName).String()) - if err != nil { - return nil, err - } - return getRadixDNSAliasMap(radixDNSAliasList), err -} - -func (app *ApplicationConfig) getAllRadixDNSAliasesMap() (map[string]*radixv1.RadixDNSAlias, error) { - radixDNSAliasList, err := app.kubeutil.RadixClient().RadixV1().RadixDNSAliases().List(context.Background(), metav1.ListOptions{}) - if err != nil { - return nil, err - } - return getRadixDNSAliasMap(slice.PointersOf(radixDNSAliasList.Items).([]*radixv1.RadixDNSAlias)), nil -} - -func getRadixDNSAliasMap(dnsAliases []*radixv1.RadixDNSAlias) map[string]*radixv1.RadixDNSAlias { - return slice.Reduce(dnsAliases, make(map[string]*radixv1.RadixDNSAlias), func(acc map[string]*radixv1.RadixDNSAlias, dnsAlias *radixv1.RadixDNSAlias) map[string]*radixv1.RadixDNSAlias { - acc[dnsAlias.Name] = dnsAlias - return acc - }) -} diff --git a/pkg/apis/kube/radix_dns_alias.go b/pkg/apis/kube/radix_dns_alias.go index 2f314e546..f636e08b7 100644 --- a/pkg/apis/kube/radix_dns_alias.go +++ b/pkg/apis/kube/radix_dns_alias.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/equinor/radix-common/utils/slice" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - "github.com/equinor/radix-operator/pkg/apis/utils/slice" + radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" ) @@ -58,6 +59,18 @@ func (kubeutil *Kube) ListRadixDNSAliasWithSelector(labelSelectorString string) return slice.PointersOf(aliasList.Items).([]*radixv1.RadixDNSAlias), nil } +// GetRadixDNSAliasMapWithSelector Gets a map of RadixDNSAliases by an optional selector +func GetRadixDNSAliasMapWithSelector(radixClient radixclient.Interface, labelSelectorString string) (map[string]*radixv1.RadixDNSAlias, error) { + radixDNSAliases, err := radixClient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{LabelSelector: labelSelectorString}) + if err != nil { + return make(map[string]*radixv1.RadixDNSAlias), err + } + return slice.Reduce(radixDNSAliases.Items, make(map[string]*radixv1.RadixDNSAlias, len(radixDNSAliases.Items)), func(acc map[string]*radixv1.RadixDNSAlias, dnsAlias radixv1.RadixDNSAlias) map[string]*radixv1.RadixDNSAlias { + acc[dnsAlias.Name] = &dnsAlias + return acc + }), nil +} + // UpdateRadixDNSAlias Update RadixDNSAlias func (kubeutil *Kube) UpdateRadixDNSAlias(radixDNSAlias *radixv1.RadixDNSAlias) error { _, err := kubeutil.radixclient.RadixV1().RadixDNSAliases().Update(context.Background(), radixDNSAlias, metav1.UpdateOptions{}) diff --git a/pkg/apis/radixvalidators/errors.go b/pkg/apis/radixvalidators/errors.go index 4529d89bb..53a0bac52 100644 --- a/pkg/apis/radixvalidators/errors.go +++ b/pkg/apis/radixvalidators/errors.go @@ -38,6 +38,21 @@ func ComponentForDNSAliasIsNotMarkedAsPublicError(component string) error { return fmt.Errorf("component %s referred to by dnsAlias is not marked as public", component) } +// RadixDNSAliasAlreadyUsedByAnotherApplicationError Error when RadixDNSAlias already used by another application +func RadixDNSAliasAlreadyUsedByAnotherApplicationError(domain string) error { + return fmt.Errorf("DNS alias %s already used by another application", domain) +} + +// RadixDNSAliasIsReservedForRadixPlatformApplicationError Error when RadixDNSAlias is reserved by Radix platform for a Radix application +func RadixDNSAliasIsReservedForRadixPlatformApplicationError(domain string) error { + return fmt.Errorf("DNS alias %s is reserved by Radix platform application", domain) +} + +// RadixDNSAliasIsReservedForRadixPlatformServiceError Error when RadixDNSAlias is reserved by Radix platform for a Radix service +func RadixDNSAliasIsReservedForRadixPlatformServiceError(domain string) error { + return fmt.Errorf("DNS alias %s is reserved by Radix platform service", domain) +} + // EnvForDNSAppAliasNotDefinedError Error when env not defined func EnvForDNSAppAliasNotDefinedError(env string) error { return fmt.Errorf("environment %s referred to by dnsAppAlias is not defined", env) diff --git a/pkg/apis/radixvalidators/validate_ra.go b/pkg/apis/radixvalidators/validate_ra.go index c767d3c49..74a198aee 100644 --- a/pkg/apis/radixvalidators/validate_ra.go +++ b/pkg/apis/radixvalidators/validate_ra.go @@ -14,6 +14,7 @@ import ( errorUtils "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/deployment" + "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/branch" @@ -62,7 +63,7 @@ func duplicatePathForAzureKeyVault(path, azureKeyVaultName, component string) er } // CanRadixApplicationBeInsertedErrors Checks if application config is valid. Returns list of errors, if present -func CanRadixApplicationBeInsertedErrors(client radixclient.Interface, app *radixv1.RadixApplication) (bool, []error) { +func CanRadixApplicationBeInsertedErrors(radixClient radixclient.Interface, app *radixv1.RadixApplication) (bool, []error) { errs := []error{} err := validateAppName(app.Name) if err != nil { @@ -105,12 +106,12 @@ func CanRadixApplicationBeInsertedErrors(client radixclient.Interface, app *radi errs = append(errs, err) } - err = validateDoesRRExist(client, app.Name) + err = validateDoesRRExist(radixClient, app.Name) if err != nil { errs = append(errs, err) } - if dnsAliasErrs := validateDNSAlias(app); len(dnsAliasErrs) > 0 { + if dnsAliasErrs := validateDNSAlias(radixClient, app); len(dnsAliasErrs) > 0 { errs = append(errs, dnsAliasErrs...) } @@ -175,8 +176,12 @@ func validateDNSAppAlias(app *radixv1.RadixApplication) []error { return validateDNSAppAliasComponentAndEnvironmentAvailable(app, alias.Component, alias.Environment) } -func validateDNSAlias(app *radixv1.RadixApplication) []error { +func validateDNSAlias(radixClient radixclient.Interface, app *radixv1.RadixApplication) []error { var errs []error + radixDNSAliasMap, err := kube.GetRadixDNSAliasMapWithSelector(radixClient, "") + if err != nil { + return []error{err} + } domainSet := make(map[string]struct{}) for _, dnsAlias := range app.Spec.DNSAlias { if _, ok := domainSet[dnsAlias.Domain]; ok { @@ -205,6 +210,8 @@ func validateDNSAlias(app *radixv1.RadixApplication) []error { } if !doesComponentHaveAPublicPort(app, dnsAlias.Component) { errs = append(errs, ComponentForDNSAliasIsNotMarkedAsPublicError(dnsAlias.Component)) + } else if radixDNSAlias, ok := radixDNSAliasMap[dnsAlias.Domain]; ok && radixDNSAlias.Spec.AppName != app.Name { + errs = append(errs, RadixDNSAliasAlreadyUsedByAnotherApplicationError(dnsAlias.Domain)) } } return errs From ccea4756c43ec3d8c86493f82177b36c20c0ba73 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 6 Nov 2023 15:58:27 +0100 Subject: [PATCH 032/121] Fixed method invocation --- pkg/apis/applicationconfig/dns_alias.go | 2 +- pkg/apis/radixvalidators/validate_ra.go | 33 ++++++++++++------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/pkg/apis/applicationconfig/dns_alias.go b/pkg/apis/applicationconfig/dns_alias.go index 3063576b3..328a05454 100644 --- a/pkg/apis/applicationconfig/dns_alias.go +++ b/pkg/apis/applicationconfig/dns_alias.go @@ -14,7 +14,7 @@ import ( func (app *ApplicationConfig) createOrUpdateDNSAliases() error { appName := app.registration.Name - radixDNSAliasesMap, err := kube.GetRadixDNSAliasMapWithSelector(app.radixclient) + radixDNSAliasesMap, err := kube.GetRadixDNSAliasMapWithSelector(app.radixclient, "") if err != nil { return err } diff --git a/pkg/apis/radixvalidators/validate_ra.go b/pkg/apis/radixvalidators/validate_ra.go index 74a198aee..c4ae8b75d 100644 --- a/pkg/apis/radixvalidators/validate_ra.go +++ b/pkg/apis/radixvalidators/validate_ra.go @@ -182,35 +182,35 @@ func validateDNSAlias(radixClient radixclient.Interface, app *radixv1.RadixAppli if err != nil { return []error{err} } - domainSet := make(map[string]struct{}) + uniqueDomainNames := make(map[string]struct{}) for _, dnsAlias := range app.Spec.DNSAlias { - if _, ok := domainSet[dnsAlias.Domain]; ok { + if _, ok := uniqueDomainNames[dnsAlias.Domain]; ok { errs = append(errs, DuplicateDomainForDNSAliasError(dnsAlias.Domain)) - } else { - if err := validateRequiredResourceName("dnsAlias domain", dnsAlias.Domain); err != nil { - errs = append(errs, err) - } + } else if err = validateRequiredResourceName("dnsAlias domain", dnsAlias.Domain); err != nil { + errs = append(errs, err) } - domainSet[dnsAlias.Domain] = struct{}{} + uniqueDomainNames[dnsAlias.Domain] = struct{}{} componentNameIsValid, environmentNameIsValid := true, true - if err := validateRequiredResourceName("dnsAlias component", dnsAlias.Component); err != nil { + if err = validateRequiredResourceName("dnsAlias component", dnsAlias.Component); err != nil { errs = append(errs, err) componentNameIsValid = false } - if err := validateRequiredResourceName("dnsAlias environment", dnsAlias.Environment); err != nil { + if err = validateRequiredResourceName("dnsAlias environment", dnsAlias.Environment); err != nil { errs = append(errs, err) environmentNameIsValid = false } if !componentNameIsValid || !environmentNameIsValid { continue } - if err := validateDNSAliasComponentAndEnvironmentAvailable(app, dnsAlias.Component, dnsAlias.Environment); err != nil { - errs = append(errs, err...) + if err = validateDNSAliasComponentAndEnvironmentAvailable(app, dnsAlias.Component, dnsAlias.Environment); err != nil { + errs = append(errs, err) continue } if !doesComponentHaveAPublicPort(app, dnsAlias.Component) { errs = append(errs, ComponentForDNSAliasIsNotMarkedAsPublicError(dnsAlias.Component)) - } else if radixDNSAlias, ok := radixDNSAliasMap[dnsAlias.Domain]; ok && radixDNSAlias.Spec.AppName != app.Name { + continue + } + if radixDNSAlias, ok := radixDNSAliasMap[dnsAlias.Domain]; ok && radixDNSAlias.Spec.AppName != app.Name { errs = append(errs, RadixDNSAliasAlreadyUsedByAnotherApplicationError(dnsAlias.Domain)) } } @@ -231,15 +231,14 @@ func validateDNSAppAliasComponentAndEnvironmentAvailable(app *radixv1.RadixAppli return errs } -func validateDNSAliasComponentAndEnvironmentAvailable(app *radixv1.RadixApplication, component string, environment string) []error { - var errs []error +func validateDNSAliasComponentAndEnvironmentAvailable(app *radixv1.RadixApplication, component string, environment string) error { if !doesEnvExist(app, environment) { - errs = append(errs, EnvForDNSAliasNotDefinedError(environment)) + return EnvForDNSAliasNotDefinedError(environment) } if !doesComponentExistInEnvironment(app, component, environment) { - errs = append(errs, ComponentForDNSAliasNotDefinedError(component)) + return ComponentForDNSAliasNotDefinedError(component) } - return errs + return nil } func validateDNSExternalAlias(app *radixv1.RadixApplication) []error { From 7f0b7ecf301087d9e2cabad911ee9d9af2539247 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 6 Nov 2023 16:34:03 +0100 Subject: [PATCH 033/121] Added validation on applying ra --- pkg/apis/applicationconfig/applicationconfig.go | 8 ++++++++ pkg/apis/applicationconfig/dns_alias.go | 2 +- pkg/apis/applicationconfig/dns_alias_test.go | 4 +++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index 288eee38e..c59dc4ffb 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -12,6 +12,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/radixvalidators" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/branch" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -127,6 +128,9 @@ func (app *ApplicationConfig) ApplyConfigToApplicationNamespace() error { if err != nil { if errors.IsNotFound(err) { log.Debugf("RadixApplication %s doesn't exist in namespace %s, creating now", app.config.Name, appNamespace) + if _, errs := radixvalidators.CanRadixApplicationBeInsertedErrors(app.radixclient, app.config); len(errs) > 0 { + return commonErrors.Concat(errs) + } _, err = app.radixclient.RadixV1().RadixApplications(appNamespace).Create(context.TODO(), app.config, metav1.CreateOptions{}) if err != nil { return fmt.Errorf("failed to create radix application. %v", err) @@ -143,6 +147,10 @@ func (app *ApplicationConfig) ApplyConfigToApplicationNamespace() error { return nil } + if _, errs := radixvalidators.CanRadixApplicationBeInsertedErrors(app.radixclient, app.config); len(errs) > 0 { + return commonErrors.Concat(errs) + } + // Update RA if different log.Debugf("RadixApplication %s in namespace %s has changed, updating now", app.config.Name, appNamespace) // For an update, ResourceVersion of the new object must be the same with the old object diff --git a/pkg/apis/applicationconfig/dns_alias.go b/pkg/apis/applicationconfig/dns_alias.go index 328a05454..003c091cc 100644 --- a/pkg/apis/applicationconfig/dns_alias.go +++ b/pkg/apis/applicationconfig/dns_alias.go @@ -14,7 +14,7 @@ import ( func (app *ApplicationConfig) createOrUpdateDNSAliases() error { appName := app.registration.Name - radixDNSAliasesMap, err := kube.GetRadixDNSAliasMapWithSelector(app.radixclient, "") + radixDNSAliasesMap, err := kube.GetRadixDNSAliasMapWithSelector(app.radixclient, labels.ForApplicationName(app.config.Name).String()) if err != nil { return err } diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go index 859daee3e..33c45712d 100644 --- a/pkg/apis/applicationconfig/dns_alias_test.go +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -376,11 +376,13 @@ func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { err := commonTest.RegisterRadixDNSAliases(radixClient, ts.existingRadixDNSAliases) require.NoError(t, err) rr := ts.applicationBuilder.GetRegistrationBuilder().BuildRR() + _, err = radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) + require.NoError(t, err) ra := ts.applicationBuilder.BuildRA() applicationConfig, err := applicationconfig.NewApplicationConfig(kubeClient, kubeUtil, radixClient, rr, ra) require.NoError(t, err) - actualValidationErr := applicationConfig.ValidateApplicationCanBeApplied() + actualValidationErr := applicationConfig.ApplyConfigToApplicationNamespace() require.Equal(t, ts.expectedValidationError, actualValidationErr) }) From 7848bac17243419458246ded19bb39cf590e83f5 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 6 Nov 2023 16:58:28 +0100 Subject: [PATCH 034/121] Added pipeline args for reserved dns aliases --- pipeline-runner/main.go | 9 ++++- pipeline-runner/model/pipelineInfo.go | 10 +++--- pipeline-runner/steps/apply_radixconfig.go | 5 +-- pipeline-runner/steps/build_test.go | 2 +- pipeline-runner/steps/deploy_test.go | 6 ++-- pipeline-runner/steps/promotion_test.go | 14 ++++---- .../applicationconfig/applicationconfig.go | 36 +++++++++---------- .../applicationconfig_test.go | 10 +++--- pkg/apis/applicationconfig/dns_alias_test.go | 19 +++++++--- pkg/apis/radixvalidators/validate_ra.go | 4 +-- pkg/apis/radixvalidators/validate_ra_test.go | 2 +- radix-operator/application/handler.go | 2 +- 12 files changed, 70 insertions(+), 49 deletions(-) diff --git a/pipeline-runner/main.go b/pipeline-runner/main.go index 2e561ebab..539154e35 100755 --- a/pipeline-runner/main.go +++ b/pipeline-runner/main.go @@ -113,12 +113,19 @@ func setPipelineArgsFromArguments(cmd *cobra.Command, pipelineArgs *model.Pipeli var debug string cmd.Flags().StringVar(&debug, "DEBUG", "false", "Debug information") cmd.Flags().StringToStringVar(&pipelineArgs.ImageTagNames, defaults.RadixImageTagNameEnvironmentVariable, make(map[string]string), "Image tag names for components (optional)") + cmd.Flags().StringToStringVar(&pipelineArgs.DNSAliasAppReserved, defaults.RadixDNSAliasAppReservedEnvironmentVariable, make(map[string]string), "The list of DNS aliases, reserved for Radix platform Radix application") + cmd.Flags().StringArrayVar(&pipelineArgs.DNSAliasReserved, defaults.RadixDNSAliasReservedEnvironmentVariable, make([]string, 0), "he list of DNS aliases, reserved for Radix platform services") err := cmd.Flags().Parse(arguments) if err != nil { return fmt.Errorf("failed to parse command arguments. Error: %v", err) } - + if pipelineArgs.DNSAliasAppReserved == nil || len(pipelineArgs.DNSAliasAppReserved) == 0 { + return fmt.Errorf("missing DNS aliases, reserved for Radix platform Radix application") + } + if len(pipelineArgs.DNSAliasReserved) == 0 { + return fmt.Errorf("missing DNS aliases, reserved for Radix platform services") + } pipelineArgs.PushImage, _ = strconv.ParseBool(pushImage) pipelineArgs.PushImage = pipelineArgs.PipelineType == string(v1.BuildDeploy) || pipelineArgs.PushImage // build and deploy require push pipelineArgs.UseCache, _ = strconv.ParseBool(useCache) diff --git a/pipeline-runner/model/pipelineInfo.go b/pipeline-runner/model/pipelineInfo.go index 083d8ca97..565bfd685 100644 --- a/pipeline-runner/model/pipelineInfo.go +++ b/pipeline-runner/model/pipelineInfo.go @@ -111,10 +111,12 @@ type PipelineArguments struct { // Used to indicate debugging session Debug bool // Image tag names for components: component-name:image-tag - ImageTagNames map[string]string - LogLevel string - AppName string - Builder Builder + ImageTagNames map[string]string + LogLevel string + AppName string + Builder Builder + DNSAliasAppReserved map[string]string + DNSAliasReserved []string } // InitPipeline Initialize pipeline with step implementations diff --git a/pipeline-runner/steps/apply_radixconfig.go b/pipeline-runner/steps/apply_radixconfig.go index f21eaf293..766d0185a 100644 --- a/pipeline-runner/steps/apply_radixconfig.go +++ b/pipeline-runner/steps/apply_radixconfig.go @@ -75,7 +75,8 @@ func (cli *ApplyConfigStepImplementation) Run(pipelineInfo *model.PipelineInfo) // Apply RA to cluster applicationConfig, err := application.NewApplicationConfig(cli.GetKubeclient(), cli.GetKubeutil(), - cli.GetRadixclient(), cli.GetRegistration(), ra) + cli.GetRadixclient(), cli.GetRegistration(), ra, + pipelineInfo.PipelineArguments.DNSAliasAppReserved, pipelineInfo.PipelineArguments.DNSAliasReserved) if err != nil { return err } @@ -198,7 +199,7 @@ func CreateRadixApplication(radixClient radixclient.Interface, ra.Name = strings.ToLower(ra.Name) } - isRAValid, errs := validate.CanRadixApplicationBeInsertedErrors(radixClient, ra) + isRAValid, errs := validate.CanRadixApplicationBeInsertedErrors(radixClient, ra, nil, nil) if !isRAValid { log.Errorf("Radix config not valid.") return nil, errorUtils.Concat(errs) diff --git a/pipeline-runner/steps/build_test.go b/pipeline-runner/steps/build_test.go index b821d9d52..3153fa1b5 100644 --- a/pipeline-runner/steps/build_test.go +++ b/pipeline-runner/steps/build_test.go @@ -73,7 +73,7 @@ func (s *buildTestSuite) Test_BranchIsNotMapped_ShouldSkip() { cli := steps.NewBuildStep(jobWaiter) cli.Init(s.kubeClient, s.radixClient, s.kubeUtil, s.promClient, rr) - applicationConfig, _ := application.NewApplicationConfig(s.kubeClient, s.kubeUtil, s.radixClient, rr, ra) + applicationConfig, _ := application.NewApplicationConfig(s.kubeClient, s.kubeUtil, s.radixClient, rr, ra, nil, nil) branchIsMapped, targetEnvs := applicationConfig.IsThereAnythingToDeploy(anyNoMappedBranch) pipelineInfo := &model.PipelineInfo{ diff --git a/pipeline-runner/steps/deploy_test.go b/pipeline-runner/steps/deploy_test.go index 1cd6f29e6..82594a8e8 100644 --- a/pipeline-runner/steps/deploy_test.go +++ b/pipeline-runner/steps/deploy_test.go @@ -75,7 +75,7 @@ func TestDeploy_BranchIsNotMapped_ShouldSkip(t *testing.T) { cli := steps.NewDeployStep(FakeNamespaceWatcher{}) cli.Init(kubeclient, radixclient, kubeUtil, &monitoring.Clientset{}, rr) - applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra) + applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) branchIsMapped, targetEnvs := applicationConfig.IsThereAnythingToDeploy(anyNoMappedBranch) pipelineInfo := &model.PipelineInfo{ @@ -181,7 +181,7 @@ func TestDeploy_PromotionSetup_ShouldCreateNamespacesForAllBranchesIfNotExists(t cli := steps.NewDeployStep(FakeNamespaceWatcher{}) cli.Init(kubeclient, radixclient, kubeUtil, &monitoring.Clientset{}, rr) - applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra) + applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) branchIsMapped, targetEnvs := applicationConfig.IsThereAnythingToDeploy("master") pipelineInfo := &model.PipelineInfo{ @@ -297,7 +297,7 @@ func TestDeploy_SetCommitID_whenSet(t *testing.T) { cli := steps.NewDeployStep(FakeNamespaceWatcher{}) cli.Init(kubeclient, radixclient, kubeUtil, &monitoring.Clientset{}, rr) - applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra) + applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) const commitID = "222ca8595c5283a9d0f17a623b9255a0d9866a2e" diff --git a/pipeline-runner/steps/promotion_test.go b/pipeline-runner/steps/promotion_test.go index 743ce5159..d90fd0cae 100644 --- a/pipeline-runner/steps/promotion_test.go +++ b/pipeline-runner/steps/promotion_test.go @@ -274,7 +274,7 @@ func TestPromote_PromoteToOtherEnvironment_NewStateIsExpected(t *testing.T) { }, } - applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra) + applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -399,7 +399,7 @@ func TestPromote_PromoteToOtherEnvironment_Resources_NoOverride(t *testing.T) { }, } - applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra) + applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -493,7 +493,7 @@ func TestPromote_PromoteToOtherEnvironment_Authentication(t *testing.T) { }, } - applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra) + applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -609,7 +609,7 @@ func TestPromote_PromoteToOtherEnvironment_Resources_WithOverride(t *testing.T) }, } - applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra) + applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -670,7 +670,7 @@ func TestPromote_PromoteToSameEnvironment_NewStateIsExpected(t *testing.T) { }, } - applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra) + applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -788,7 +788,7 @@ func TestPromote_PromoteToOtherEnvironment_Identity(t *testing.T) { }, } - applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra) + applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) pipelineInfo.SetApplicationConfig(applicationConfig) err = cli.Run(pipelineInfo) require.NoError(t, err) @@ -848,7 +848,7 @@ func TestPromote_AnnotatedBySourceDeploymentAttributes(t *testing.T) { }, } - applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra) + applicationConfig, _ := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index c59dc4ffb..588811403 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -29,26 +29,26 @@ const ConfigBranchFallback = "master" // ApplicationConfig Instance variables type ApplicationConfig struct { - kubeclient kubernetes.Interface - radixclient radixclient.Interface - kubeutil *kube.Kube - registration *radixv1.RadixRegistration - config *radixv1.RadixApplication + kubeclient kubernetes.Interface + radixclient radixclient.Interface + kubeutil *kube.Kube + registration *radixv1.RadixRegistration + config *radixv1.RadixApplication + dnsAliasAppReserved map[string]string + dnsAliasReserved []string } // NewApplicationConfig Constructor -func NewApplicationConfig( - kubeclient kubernetes.Interface, - kubeutil *kube.Kube, - radixclient radixclient.Interface, - registration *radixv1.RadixRegistration, - config *radixv1.RadixApplication) (*ApplicationConfig, error) { +func NewApplicationConfig(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, registration *radixv1.RadixRegistration, config *radixv1.RadixApplication, dnsAliasAppReserved map[string]string, dnsAliasReserved []string) (*ApplicationConfig, error) { return &ApplicationConfig{ - kubeclient, - radixclient, - kubeutil, - registration, - config}, nil + kubeclient: kubeclient, + radixclient: radixclient, + kubeutil: kubeutil, + registration: registration, + config: config, + dnsAliasAppReserved: dnsAliasAppReserved, + dnsAliasReserved: dnsAliasReserved, + }, nil } // GetRadixApplicationConfig returns the provided config @@ -128,7 +128,7 @@ func (app *ApplicationConfig) ApplyConfigToApplicationNamespace() error { if err != nil { if errors.IsNotFound(err) { log.Debugf("RadixApplication %s doesn't exist in namespace %s, creating now", app.config.Name, appNamespace) - if _, errs := radixvalidators.CanRadixApplicationBeInsertedErrors(app.radixclient, app.config); len(errs) > 0 { + if _, errs := radixvalidators.CanRadixApplicationBeInsertedErrors(app.radixclient, app.config, app.dnsAliasAppReserved, app.dnsAliasReserved); len(errs) > 0 { return commonErrors.Concat(errs) } _, err = app.radixclient.RadixV1().RadixApplications(appNamespace).Create(context.TODO(), app.config, metav1.CreateOptions{}) @@ -147,7 +147,7 @@ func (app *ApplicationConfig) ApplyConfigToApplicationNamespace() error { return nil } - if _, errs := radixvalidators.CanRadixApplicationBeInsertedErrors(app.radixclient, app.config); len(errs) > 0 { + if _, errs := radixvalidators.CanRadixApplicationBeInsertedErrors(app.radixclient, app.config, app.dnsAliasAppReserved, app.dnsAliasReserved); len(errs) > 0 { return commonErrors.Concat(errs) } diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 766b0f291..258ffd547 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -47,7 +47,7 @@ func setupTest() (*test.Utils, kubernetes.Interface, *kube.Kube, radixclient.Int func getApplication(ra *radixv1.RadixApplication) *applicationconfig.ApplicationConfig { // The other arguments are not relevant for this test - application, _ := applicationconfig.NewApplicationConfig(nil, nil, nil, nil, ra) + application, _ := applicationconfig.NewApplicationConfig(nil, nil, nil, nil, ra, nil, nil) return application } @@ -56,7 +56,7 @@ func Test_Create_Radix_Environments(t *testing.T) { radixRegistration, _ := utils.GetRadixRegistrationFromFile(sampleRegistration) radixApp, _ := utils.GetRadixApplicationFromFile(sampleApp) - app, _ := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, radixApp) + app, _ := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, radixApp, nil, nil) label := fmt.Sprintf("%s=%s", kube.RadixAppLabel, radixRegistration.Name) t.Run("It can create environments", func(t *testing.T) { @@ -117,7 +117,7 @@ func Test_Reconciles_Radix_Environments(t *testing.T) { WithEnvironment("prod", "master"). BuildRA() - app, _ := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, rr, ra) + app, _ := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, rr, ra, nil, nil) label := fmt.Sprintf("%s=%s", kube.RadixAppLabel, rr.Name) // Test @@ -690,7 +690,7 @@ func getAppConfig(client kubernetes.Interface, kubeUtil *kube.Kube, radixClient ra := applicationBuilder.BuildRA() radixRegistration, _ := radixClient.RadixV1().RadixRegistrations().Get(context.TODO(), ra.Name, metav1.GetOptions{}) - return applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra) + return applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra, nil, nil) } func applyApplicationWithSync(tu *test.Utils, client kubernetes.Interface, kubeUtil *kube.Kube, @@ -706,7 +706,7 @@ func applyApplicationWithSync(tu *test.Utils, client kubernetes.Interface, kubeU return err } - applicationConfig, err := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra) + applicationConfig, err := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra, nil, nil) if err != nil { return err } diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go index 33c45712d..bec481fdb 100644 --- a/pkg/apis/applicationconfig/dns_alias_test.go +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -317,6 +317,11 @@ func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { domain1 = "domain1" domain2 = "domain2" ) + dnsAliasAppReserved := map[string]string{ + "api": "radix-api", + "console": "radix-web-console", + } + dnsAliasReserved := []string{"grafana"} var testScenarios = []struct { name string applicationBuilder utils.ApplicationBuilder @@ -364,9 +369,14 @@ func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { expectedValidationError: applicationconfig.RadixDNSAliasIsReservedForRadixPlatformApplicationError("api"), }, { - name: "Reserved domain api for another app", - applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Domain: "api", Environment: raEnv, Component: raComponentName}), - expectedValidationError: applicationconfig.RadixDNSAliasIsReservedForRadixPlatformApplicationError("api"), + name: "Reserved domain api for another service", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Domain: "grafana", Environment: raEnv, Component: raComponentName}), + expectedValidationError: applicationconfig.RadixDNSAliasIsReservedForRadixPlatformServiceError("grafana"), + }, + { + name: "Reserved domain api for this app", + applicationBuilder: utils.ARadixApplication().WithAppName("radix-api").WithDNSAlias(radixv1.DNSAlias{Domain: "api", Environment: raEnv, Component: raComponentName}), + expectedValidationError: nil, }, } @@ -379,7 +389,8 @@ func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { _, err = radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) require.NoError(t, err) ra := ts.applicationBuilder.BuildRA() - applicationConfig, err := applicationconfig.NewApplicationConfig(kubeClient, kubeUtil, radixClient, rr, ra) + applicationConfig, err := applicationconfig.NewApplicationConfig(kubeClient, kubeUtil, radixClient, rr, ra, + dnsAliasAppReserved, dnsAliasReserved) require.NoError(t, err) actualValidationErr := applicationConfig.ApplyConfigToApplicationNamespace() diff --git a/pkg/apis/radixvalidators/validate_ra.go b/pkg/apis/radixvalidators/validate_ra.go index c4ae8b75d..0e98d72da 100644 --- a/pkg/apis/radixvalidators/validate_ra.go +++ b/pkg/apis/radixvalidators/validate_ra.go @@ -38,7 +38,7 @@ var ( // CanRadixApplicationBeInserted Checks if application config is valid. Returns a single error, if this is the case func CanRadixApplicationBeInserted(client radixclient.Interface, app *radixv1.RadixApplication) (bool, error) { - isValid, errs := CanRadixApplicationBeInsertedErrors(client, app) + isValid, errs := CanRadixApplicationBeInsertedErrors(client, app, nil, nil) if isValid { return true, nil } @@ -63,7 +63,7 @@ func duplicatePathForAzureKeyVault(path, azureKeyVaultName, component string) er } // CanRadixApplicationBeInsertedErrors Checks if application config is valid. Returns list of errors, if present -func CanRadixApplicationBeInsertedErrors(radixClient radixclient.Interface, app *radixv1.RadixApplication) (bool, []error) { +func CanRadixApplicationBeInsertedErrors(radixClient radixclient.Interface, app *radixv1.RadixApplication, dnsAliasAppReserved map[string]string, dnsAliasReserved []string) (bool, []error) { errs := []error{} err := validateAppName(app.Name) if err != nil { diff --git a/pkg/apis/radixvalidators/validate_ra_test.go b/pkg/apis/radixvalidators/validate_ra_test.go index 8b9dc3230..0da54f73a 100644 --- a/pkg/apis/radixvalidators/validate_ra_test.go +++ b/pkg/apis/radixvalidators/validate_ra_test.go @@ -669,7 +669,7 @@ func Test_invalid_ra(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - isValid, errs := radixvalidators.CanRadixApplicationBeInsertedErrors(client, validRA) + isValid, errs := radixvalidators.CanRadixApplicationBeInsertedErrors(client, validRA, nil, nil) if testcase.expectedError != nil { assert.False(t, isValid) diff --git a/radix-operator/application/handler.go b/radix-operator/application/handler.go index 0ef6e529b..87fe2d413 100644 --- a/radix-operator/application/handler.go +++ b/radix-operator/application/handler.go @@ -78,7 +78,7 @@ func (t *Handler) Sync(namespace, name string, eventRecorder record.EventRecorde syncApplication := radixApplication.DeepCopy() logger.Debugf("Sync application %s", syncApplication.Name) - applicationConfig, err := application.NewApplicationConfig(t.kubeclient, t.kubeutil, t.radixclient, radixRegistration, radixApplication) + applicationConfig, err := application.NewApplicationConfig(t.kubeclient, t.kubeutil, t.radixclient, radixRegistration, radixApplication, nil, nil) if err != nil { // Put back on queue return err From bfc246916fd0a74fb17df9fa8e26eefa453c7675 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 7 Nov 2023 14:49:18 +0100 Subject: [PATCH 035/121] Merged with master --- pipeline-runner/steps/apply_radixconfig.go | 2 +- .../applicationconfig/applicationconfig.go | 8 +- pkg/apis/radixvalidators/errors.go | 22 +++--- pkg/apis/radixvalidators/validate_ra.go | 76 ++++++++----------- pkg/apis/radixvalidators/validate_ra_test.go | 49 ++++++------ pkg/apis/radixvalidators/validate_rr.go | 13 ++-- 6 files changed, 78 insertions(+), 92 deletions(-) diff --git a/pipeline-runner/steps/apply_radixconfig.go b/pipeline-runner/steps/apply_radixconfig.go index 4dc9fe12a..eda392be4 100644 --- a/pipeline-runner/steps/apply_radixconfig.go +++ b/pipeline-runner/steps/apply_radixconfig.go @@ -199,7 +199,7 @@ func CreateRadixApplication(radixClient radixclient.Interface, ra.Name = strings.ToLower(ra.Name) } - err = validate.CanRadixApplicationBeInserted(radixClient, ra) + err = validate.CanRadixApplicationBeInserted(radixClient, ra, nil, nil) if err != nil { log.Errorf("Radix config not valid.") return nil, err diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index 588811403..127cb5b5c 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -128,8 +128,8 @@ func (app *ApplicationConfig) ApplyConfigToApplicationNamespace() error { if err != nil { if errors.IsNotFound(err) { log.Debugf("RadixApplication %s doesn't exist in namespace %s, creating now", app.config.Name, appNamespace) - if _, errs := radixvalidators.CanRadixApplicationBeInsertedErrors(app.radixclient, app.config, app.dnsAliasAppReserved, app.dnsAliasReserved); len(errs) > 0 { - return commonErrors.Concat(errs) + if err = radixvalidators.CanRadixApplicationBeInserted(app.radixclient, app.config, app.dnsAliasAppReserved, app.dnsAliasReserved); err != nil { + return err } _, err = app.radixclient.RadixV1().RadixApplications(appNamespace).Create(context.TODO(), app.config, metav1.CreateOptions{}) if err != nil { @@ -147,8 +147,8 @@ func (app *ApplicationConfig) ApplyConfigToApplicationNamespace() error { return nil } - if _, errs := radixvalidators.CanRadixApplicationBeInsertedErrors(app.radixclient, app.config, app.dnsAliasAppReserved, app.dnsAliasReserved); len(errs) > 0 { - return commonErrors.Concat(errs) + if err = radixvalidators.CanRadixApplicationBeInserted(app.radixclient, app.config, app.dnsAliasAppReserved, app.dnsAliasReserved); err != nil { + return err } // Update RA if different diff --git a/pkg/apis/radixvalidators/errors.go b/pkg/apis/radixvalidators/errors.go index 853b56fa0..3e63d515d 100644 --- a/pkg/apis/radixvalidators/errors.go +++ b/pkg/apis/radixvalidators/errors.go @@ -1,21 +1,21 @@ package radixvalidators import ( - "errors" "fmt" "strings" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/pkg/errors" ) var ( ErrMissingPrivateImageHubUsername = errors.New("missing private image hub username") - ErrEnvForDNSAppAliasNotDefined = errors.New("env for dnsapp alias not defined") - ErrComponentForDNSAppAliasNotDefined = errors.New("component for dnsapp alias not defined") + ErrEnvForDNSAppAliasNotDefined = errors.New("env for dns app alias not defined") + ErrComponentForDNSAppAliasNotDefined = errors.New("component for dns app alias not defined") ErrExternalAliasCannotBeEmpty = errors.New("external alias cannot be empty") - ErrEnvForDNSExternalAliasNotDefined = errors.New("env for dnsexternal alias not defined") - ErrComponentForDNSExternalAliasNotDefined = errors.New("component for dnsexternal alias not defined") - ErrComponentForDNSExternalAliasIsNotMarkedAsPublic = errors.New("component for dnsexternal alias is not marked as public") + ErrEnvForDNSExternalAliasNotDefined = errors.New("env for dns external alias not defined") + ErrComponentForDNSExternalAliasNotDefined = errors.New("component for dns external alias not defined") + ErrComponentForDNSExternalAliasIsNotMarkedAsPublic = errors.New("component for dns external alias is not marked as public") ErrEnvironmentReferencedByComponentDoesNotExist = errors.New("environment referenced by component does not exist") ErrInvalidPortNameLength = errors.New("invalid port name length") ErrPortSpecificationCannotBeEmptyForComponent = errors.New("port specification cannot be empty for component") @@ -25,7 +25,7 @@ var ( ErrSchedulerPortCannotBeEmptyForJob = errors.New("scheduler port cannot be empty for job") ErrPayloadPathCannotBeEmptyForJob = errors.New("payload path cannot be empty for job") ErrMemoryResourceRequirementFormat = errors.New("memory resource requirement format") - ErrCPUResourceRequirementFormat = errors.New("cpuresource requirement format") + ErrCPUResourceRequirementFormat = errors.New("cpu resource requirement format") ErrInvalidVerificationType = errors.New("invalid verification") ErrResourceRequestOverLimit = errors.New("resource request over limit") ErrInvalidResource = errors.New("invalid resource") @@ -56,7 +56,7 @@ var ( ErrInvalidUUID = errors.New("invalid") ErrInvalidEmail = errors.New("invalid email") ErrInvalidResourceName = errors.New("invalid resource name") - ErrInvalidLowerCaseAlphaNumericDotDashResourceName = errors.New("invalid lower case alpha numeric dot dash resource name") + ErrInvalidLowerCaseAlphaNumericDashResourceName = errors.New("invalid lower case alpha numeric dash resource name") ErrNoRegistrationExistsForApplication = errors.New("no registration exists for application") ErrInvalidConfigBranchName = errors.New("invalid config branch") ErrOauth = errors.New("oauth error") @@ -374,9 +374,9 @@ func InvalidResourceNameErrorWithMessage(resourceName, value string) error { return errors.WithMessagef(ErrInvalidResourceName, "%s %s can only consist of alphanumeric characters and '-'", resourceName, value) } -// InvalidLowerCaseAlphaNumericDotDashResourceNameErrorWithMessage Invalid lower case alpha-numeric, dash resource name error -func InvalidLowerCaseAlphaNumericDotDashResourceNameErrorWithMessage(resourceName, value string) error { - return errors.WithMessagef(ErrInvalidLowerCaseAlphaNumericDotDashResourceName, "%s %s can only consist of lower case alphanumeric characters and '-'", resourceName, value) +// InvalidLowerCaseAlphaNumericDashResourceNameErrorWithMessage Invalid lower case alphanumeric, dash resource name error +func InvalidLowerCaseAlphaNumericDashResourceNameErrorWithMessage(resourceName, value string) error { + return errors.WithMessagef(ErrInvalidLowerCaseAlphaNumericDashResourceName, "%s %s can only consist of lower case alphanumeric characters and '-'", resourceName, value) } // NoRegistrationExistsForApplicationErrorWithMessage No registration exists diff --git a/pkg/apis/radixvalidators/validate_ra.go b/pkg/apis/radixvalidators/validate_ra.go index 6cc4ca76d..acced8007 100644 --- a/pkg/apis/radixvalidators/validate_ra.go +++ b/pkg/apis/radixvalidators/validate_ra.go @@ -12,7 +12,6 @@ import ( "unicode" commonUtils "github.com/equinor/radix-common/utils" - errorUtils "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/deployment" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -28,10 +27,6 @@ import ( const ( maximumNumberOfEgressRules = 1000 - maxPortNameLength = 15 - minimumPortNumber = 1024 - maximumPortNumber = 65535 - cpuRegex = "^[0-9]+m$" azureClientIdResourceName = "identity.azure.clientId" ) @@ -56,7 +51,6 @@ var ( validateHPAConfigForRA, validateVolumeMountConfigForRA, ValidateNotificationsForRA, - validateDNSAlias, } ) @@ -64,9 +58,12 @@ var ( type RadixApplicationValidator func(radixApplication *radixv1.RadixApplication) error // CanRadixApplicationBeInserted Checks if application config is valid. Returns a single error, if this is the case -func CanRadixApplicationBeInserted(client radixclient.Interface, app *radixv1.RadixApplication, additionalValidators ...RadixApplicationValidator) error { +func CanRadixApplicationBeInserted(radixClient radixclient.Interface, app *radixv1.RadixApplication, dnsAliasAppReserved map[string]string, dnsAliasReserved []string, additionalValidators ...RadixApplicationValidator) error { - validators := append(requiredRadixApplicationValidators, validateDoesRRExistFactory(client)) + validators := append(requiredRadixApplicationValidators, + validateDoesRRExistFactory(radixClient), + validateDNSAliasFactory(radixClient, dnsAliasAppReserved, dnsAliasReserved), + ) validators = append(validators, additionalValidators...) return validateRadixApplication(app, validators...) @@ -115,7 +112,13 @@ func validateDoesRRExistFactory(client radixclient.Interface) RadixApplicationVa } } -func validatePrivateImageHubs(app *radixv1.RadixApplication) []error { +func validateDNSAliasFactory(client radixclient.Interface, dnsAliasAppReserved map[string]string, dnsAliasReserved []string) RadixApplicationValidator { + return func(radixApplication *radixv1.RadixApplication) error { + return validateDNSAlias(client, radixApplication, dnsAliasAppReserved, dnsAliasReserved) + } +} + +func validatePrivateImageHubs(app *radixv1.RadixApplication) error { var errs []error for server, config := range app.Spec.PrivateImageHubs { if config.Username == "" { @@ -136,31 +139,14 @@ func RAContainsOldPublic(app *radixv1.RadixApplication) bool { } func validateDNSAppAlias(app *radixv1.RadixApplication) error { - errs := []error{} - alias := app.Spec.DNSAppAlias - if alias.Component == "" && alias.Environment == "" { - return nil - } - - if !doesEnvExist(app, alias.Environment) { - errs = append(errs, EnvForDNSAppAliasNotDefinedErrorWithMessage(alias.Environment)) - } - if !doesComponentExistInEnvironment(app, alias.Component, alias.Environment) { - errs = append(errs, ComponentForDNSAppAliasNotDefinedErrorWithMessage(alias.Component)) - } - return errors.Join(errs...) + return validateDNSAppAliasComponentAndEnvironmentAvailable(app) } -func validateDNSAppAlias(app *radixv1.RadixApplication) []error { - alias := app.Spec.DNSAppAlias - return validateDNSAppAliasComponentAndEnvironmentAvailable(app, alias.Component, alias.Environment) -} - -func validateDNSAlias(radixClient radixclient.Interface, app *radixv1.RadixApplication) []error { +func validateDNSAlias(radixClient radixclient.Interface, app *radixv1.RadixApplication, dnsAliasAppReserved map[string]string, dnsAliasReserved []string) error { var errs []error radixDNSAliasMap, err := kube.GetRadixDNSAliasMapWithSelector(radixClient, "") if err != nil { - return []error{err} + return err } uniqueDomainNames := make(map[string]struct{}) for _, dnsAlias := range app.Spec.DNSAlias { @@ -194,21 +180,23 @@ func validateDNSAlias(radixClient radixclient.Interface, app *radixv1.RadixAppli errs = append(errs, RadixDNSAliasAlreadyUsedByAnotherApplicationError(dnsAlias.Domain)) } } - return errs + return errors.Join(errs...) } -func validateDNSAppAliasComponentAndEnvironmentAvailable(app *radixv1.RadixApplication, component string, environment string) []error { - var errs []error - if component == "" && environment == "" { - return errs +func validateDNSAppAliasComponentAndEnvironmentAvailable(app *radixv1.RadixApplication) error { + alias := app.Spec.DNSAppAlias + if alias.Component == "" && alias.Environment == "" { + return nil } - if !doesEnvExist(app, environment) { - errs = append(errs, EnvForDNSAppAliasNotDefinedError(environment)) + + var errs []error + if !doesEnvExist(app, alias.Environment) { + errs = append(errs, EnvForDNSAppAliasNotDefinedErrorWithMessage(alias.Environment)) } - if !doesComponentExistInEnvironment(app, component, environment) { - errs = append(errs, ComponentForDNSAppAliasNotDefinedError(component)) + if !doesComponentExistInEnvironment(app, alias.Component, alias.Environment) { + errs = append(errs, ComponentForDNSAppAliasNotDefinedErrorWithMessage(alias.Component)) } - return errs + return errors.Join(errs...) } func validateDNSAliasComponentAndEnvironmentAvailable(app *radixv1.RadixApplication, component string, environment string) error { @@ -455,7 +443,7 @@ func validateAuthentication(component *radixv1.RadixComponent, environments []ra return nil } - var errors []error + var errs []error for _, environment := range environments { environmentAuth := envAuthConfigGetter(environment.Name) if componentAuth == nil && environmentAuth == nil { @@ -463,19 +451,19 @@ func validateAuthentication(component *radixv1.RadixComponent, environments []ra } combinedAuth, err := deployment.GetAuthenticationForComponent(componentAuth, environmentAuth) if err != nil { - errors = append(errors, err) + errs = append(errs, err) } if combinedAuth == nil { continue } if err := validateClientCertificate(combinedAuth.ClientCertificate); err != nil { - errors = append(errors, err) + errs = append(errs, err) } - errors = append(errors, validateOAuth(combinedAuth.OAuth2, component.GetName(), environment.Name)...) + errs = append(errs, validateOAuth(combinedAuth.OAuth2, component.GetName(), environment.Name)...) } - return errors + return errs } func validateClientCertificate(clientCertificate *radixv1.ClientCertificate) error { diff --git a/pkg/apis/radixvalidators/validate_ra_test.go b/pkg/apis/radixvalidators/validate_ra_test.go index c5558d3ed..8c65d1883 100644 --- a/pkg/apis/radixvalidators/validate_ra_test.go +++ b/pkg/apis/radixvalidators/validate_ra_test.go @@ -7,7 +7,6 @@ import ( commonUtils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-common/utils/pointers" - "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-operator/pkg/apis/defaults" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/radixvalidators" @@ -24,7 +23,7 @@ type updateRAFunc func(rr *v1.RadixApplication) func Test_valid_ra_returns_true(t *testing.T) { _, client := validRASetup() validRA := createValidRA() - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) assert.NoError(t, err) } @@ -32,7 +31,7 @@ func Test_missing_rr(t *testing.T) { client := radixfake.NewSimpleClientset() validRA := createValidRA() - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) assert.Error(t, err) } @@ -104,7 +103,7 @@ func Test_invalid_ra(t *testing.T) { {"too long app name", radixvalidators.InvalidAppNameLengthErrorWithMessage(wayTooLongName), func(ra *v1.RadixApplication) { ra.Name = wayTooLongName }}, - {"invalid app name", radixvalidators.InvalidLowerCaseAlphaNumericDotDashResourceNameErrorWithMessage("app name", invalidResourceName), func(ra *v1.RadixApplication) { + {"invalid app name", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameErrorWithMessage("app name", invalidResourceName), func(ra *v1.RadixApplication) { ra.Name = invalidResourceName }}, {"empty name", radixvalidators.ResourceNameCannotBeEmptyErrorWithMessage("app name"), func(ra *v1.RadixApplication) { @@ -120,10 +119,10 @@ func Test_invalid_ra(t *testing.T) { }, } }}, - {"invalid component name", radixvalidators.InvalidLowerCaseAlphaNumericDotDashResourceNameErrorWithMessage("component name", invalidResourceName), func(ra *v1.RadixApplication) { + {"invalid component name", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameErrorWithMessage("component name", invalidResourceName), func(ra *v1.RadixApplication) { ra.Spec.Components[0].Name = invalidResourceName }}, - {"uppercase component name", radixvalidators.InvalidLowerCaseAlphaNumericDotDashResourceNameErrorWithMessage("component name", invalidUpperCaseResourceName), func(ra *v1.RadixApplication) { + {"uppercase component name", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameErrorWithMessage("component name", invalidUpperCaseResourceName), func(ra *v1.RadixApplication) { ra.Spec.Components[0].Name = invalidUpperCaseResourceName }}, {"duplicate component name", radixvalidators.DuplicateComponentOrJobNameErrorWithMessage([]string{validRAFirstComponentName}), func(ra *v1.RadixApplication) { @@ -138,7 +137,7 @@ func Test_invalid_ra(t *testing.T) { {"invalid port specification. Empty value", radixvalidators.PortSpecificationCannotBeEmptyForComponentErrorWithMessage(validRAFirstComponentName), func(ra *v1.RadixApplication) { ra.Spec.Components[0].Ports = []v1.ComponentPort{} }}, - {"invalid port name", radixvalidators.InvalidLowerCaseAlphaNumericDotDashResourceNameErrorWithMessage("port name", invalidResourceName), func(ra *v1.RadixApplication) { + {"invalid port name", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameErrorWithMessage("port name", invalidResourceName), func(ra *v1.RadixApplication) { ra.Spec.Components[0].Ports[0].Name = invalidResourceName }}, {"too long port name", radixvalidators.InvalidPortNameLengthErrorWithMessage(tooLongPortName), func(ra *v1.RadixApplication) { @@ -189,7 +188,7 @@ func Test_invalid_ra(t *testing.T) { {"invalid number of replicas", radixvalidators.InvalidNumberOfReplicaError(radixvalidators.MaxReplica + 1), func(ra *v1.RadixApplication) { *ra.Spec.Components[0].EnvironmentConfig[0].Replicas = radixvalidators.MaxReplica + 1 }}, - {"invalid env name", radixvalidators.InvalidLowerCaseAlphaNumericDotDashResourceNameErrorWithMessage("env name", invalidResourceName), func(ra *v1.RadixApplication) { + {"invalid env name", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameErrorWithMessage("env name", invalidResourceName), func(ra *v1.RadixApplication) { ra.Spec.Environments[0].Name = invalidResourceName }}, {"invalid branch name", radixvalidators.InvalidBranchNameErrorWithMessage(invalidBranchName), func(ra *v1.RadixApplication) { @@ -201,19 +200,19 @@ func Test_invalid_ra(t *testing.T) { {"dns app alias non existing component", radixvalidators.ComponentForDNSAppAliasNotDefinedError(nonExistingComponent), func(ra *v1.RadixApplication) { ra.Spec.DNSAppAlias.Component = nonExistingComponent }}, - {"dns app alias non existing env", radixvalidators.EnvForDNSAppAliasNotDefinedError(noExistingEnvironment), func(ra *v1.RadixApplication) { + {"dns app alias non existing env", radixvalidators.EnvForDNSAppAliasNotDefinedErrorWithMessage(noExistingEnvironment), func(ra *v1.RadixApplication) { ra.Spec.DNSAppAlias.Environment = noExistingEnvironment }}, - {"dns alias is empty", radixvalidators.ResourceNameCannotBeEmptyError("dnsAlias component"), func(ra *v1.RadixApplication) { + {"dns alias is empty", radixvalidators.ResourceNameCannotBeEmptyErrorWithMessage("dnsAlias component"), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias[0].Component = "" }}, - {"dns alias is empty", radixvalidators.ResourceNameCannotBeEmptyError("dnsAlias environment"), func(ra *v1.RadixApplication) { + {"dns alias is empty", radixvalidators.ResourceNameCannotBeEmptyErrorWithMessage("dnsAlias environment"), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias[0].Environment = "" }}, - {"dns alias is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameError("dnsAlias component", "component.abc"), func(ra *v1.RadixApplication) { + {"dns alias is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameErrorWithMessage("dnsAlias component", "component.abc"), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias[0].Component = "component.abc" }}, - {"dns alias is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameError("dnsAlias environment", "environment.abc"), func(ra *v1.RadixApplication) { + {"dns alias is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameErrorWithMessage("dnsAlias environment", "environment.abc"), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias[0].Environment = "environment.abc" }}, {"dns alias non existing component", radixvalidators.ComponentForDNSAliasNotDefinedError(nonExistingComponent), func(ra *v1.RadixApplication) { @@ -222,10 +221,10 @@ func Test_invalid_ra(t *testing.T) { {"dns alias non existing env", radixvalidators.EnvForDNSAliasNotDefinedError(noExistingEnvironment), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias[0].Environment = noExistingEnvironment }}, - {"dns alias domain is empty", radixvalidators.ResourceNameCannotBeEmptyError("dnsAlias domain"), func(ra *v1.RadixApplication) { + {"dns alias domain is empty", radixvalidators.ResourceNameCannotBeEmptyErrorWithMessage("dnsAlias domain"), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias[0].Domain = "" }}, - {"dns alias domain is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameError("dnsAlias domain", "my.domain"), func(ra *v1.RadixApplication) { + {"dns alias domain is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameErrorWithMessage("dnsAlias domain", "my.domain"), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias[0].Domain = "my.domain" }}, {"dns alias domain is invalid", radixvalidators.DuplicateDomainForDNSAliasError("my-domain"), func(ra *v1.RadixApplication) { @@ -672,7 +671,7 @@ func Test_invalid_ra(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) if testcase.expectedError != nil { assert.Error(t, err) @@ -769,7 +768,7 @@ func Test_ValidRAComponentLimitRequest_NoError(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) assert.NoError(t, err) }) @@ -852,7 +851,7 @@ func Test_ValidRAJobLimitRequest_NoError(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) assert.NoError(t, err) }) @@ -887,7 +886,7 @@ func Test_InvalidRAComponentLimitRequest_Error(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) assert.Error(t, err) }) @@ -922,7 +921,7 @@ func Test_InvalidRAJobLimitRequest_Error(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) assert.Error(t, err) }) @@ -1063,7 +1062,7 @@ func Test_PublicPort(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) if testcase.isValid { assert.NoError(t, err) @@ -1146,7 +1145,7 @@ func Test_Variables(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) if testcase.isValid { assert.NoError(t, err) @@ -1460,7 +1459,7 @@ func Test_ValidationOfVolumeMounts_Errors(t *testing.T) { validRA := createValidRA() volumes := testcase.volumeMounts() ra(validRA, volumes) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) isErrorNil := err == nil assert.Equal(t, testcase.isValid, err == nil) @@ -1555,7 +1554,7 @@ func Test_ValidHPA_NoError(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) if testcase.isValid { assert.NoError(t, err) @@ -1731,7 +1730,7 @@ func Test_EgressConfig(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) if testcase.isValid { assert.NoError(t, err) diff --git a/pkg/apis/radixvalidators/validate_rr.go b/pkg/apis/radixvalidators/validate_rr.go index 8163fa6ec..e50906c9d 100644 --- a/pkg/apis/radixvalidators/validate_rr.go +++ b/pkg/apis/radixvalidators/validate_rr.go @@ -2,16 +2,15 @@ package radixvalidators import ( "context" - errors2 "errors" "fmt" "regexp" "strings" - "github.com/equinor/radix-common/utils/errors" + commonErrors "github.com/equinor/radix-common/utils/errors" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils/branch" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" - k8serrors "k8s.io/apimachinery/pkg/api/errors" + errors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -20,7 +19,7 @@ const ( ) var ( - ErrInvalidRadixConfigFullName = errors2.New("invalid file name for radixconfig. See https://www.radix.equinor.com/references/reference-radix-config/ for more information") + ErrInvalidRadixConfigFullName = fmt.Errorf("invalid file name for radixconfig. See https://www.radix.equinor.com/references/reference-radix-config/ for more information") requiredRadixRegistrationValidators []RadixRegistrationValidator = []RadixRegistrationValidator{ validateRadixRegistrationAppName, @@ -74,7 +73,7 @@ func validateRadixRegistration(radixRegistration *v1.RadixRegistration, validato errs = append(errs, err) } } - return errors.Concat(errs) + return commonErrors.Concat(errs) } // GetRadixRegistrationBeInsertedWarnings Get warnings for inserting RadixRegistration @@ -133,7 +132,7 @@ func validateRequiredResourceName(resourceName, value string) error { isValid := re.MatchString(value) if !isValid { - return InvalidLowerCaseAlphaNumericDotDashResourceNameErrorWithMessage(resourceName, value) + return InvalidLowerCaseAlphaNumericDashResourceNameErrorWithMessage(resourceName, value) } return nil @@ -203,7 +202,7 @@ func validateSSHKey(deployKey string) error { func validateDoesRRExist(client radixclient.Interface, appName string) error { _, err := client.RadixV1().RadixRegistrations().Get(context.TODO(), appName, metav1.GetOptions{}) if err != nil { - if k8serrors.IsNotFound(err) { + if errors.IsNotFound(err) { return NoRegistrationExistsForApplicationErrorWithMessage(appName) } return err From 1a237869e639bcbdcd38a8cccfb5624f23f8751f Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 7 Nov 2023 16:43:34 +0100 Subject: [PATCH 036/121] Fixed unit-test --- pkg/apis/applicationconfig/dns_alias_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go index bec481fdb..8424598c2 100644 --- a/pkg/apis/applicationconfig/dns_alias_test.go +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -395,7 +395,11 @@ func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { actualValidationErr := applicationConfig.ApplyConfigToApplicationNamespace() - require.Equal(t, ts.expectedValidationError, actualValidationErr) + if ts.expectedValidationError == nil { + require.NoError(t, actualValidationErr) + } else { + require.EqualError(t, actualValidationErr, ts.expectedValidationError.Error(), "missing or unexpected error") + } }) } } From ce13bb583b7ecc6fc3ab73b4c1bef07a4adeb197 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 7 Nov 2023 16:56:25 +0100 Subject: [PATCH 037/121] Added validation for reserved aliases --- pkg/apis/applicationconfig/dns_alias.go | 20 ++++++++++---------- pkg/apis/applicationconfig/dns_alias_test.go | 3 +-- pkg/apis/radixvalidators/validate_ra.go | 7 +++++++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/pkg/apis/applicationconfig/dns_alias.go b/pkg/apis/applicationconfig/dns_alias.go index 003c091cc..b89898a6e 100644 --- a/pkg/apis/applicationconfig/dns_alias.go +++ b/pkg/apis/applicationconfig/dns_alias.go @@ -14,7 +14,7 @@ import ( func (app *ApplicationConfig) createOrUpdateDNSAliases() error { appName := app.registration.Name - radixDNSAliasesMap, err := kube.GetRadixDNSAliasMapWithSelector(app.radixclient, labels.ForApplicationName(app.config.Name).String()) + existingRadixDNSAliasesMap, err := kube.GetRadixDNSAliasMapWithSelector(app.radixclient, labels.ForApplicationName(app.config.Name).String()) if err != nil { return err } @@ -24,27 +24,27 @@ func (app *ApplicationConfig) createOrUpdateDNSAliases() error { if err != nil { return err } - if radixDNSAlias, ok := radixDNSAliasesMap[dnsAlias.Domain]; ok { + if existingRadixDNSAlias, ok := existingRadixDNSAliasesMap[dnsAlias.Domain]; ok { switch { - case !strings.EqualFold(appName, radixDNSAlias.Spec.AppName): - errs = append(errs, fmt.Errorf("existing DNS alias domain %s is used by the application %s", dnsAlias.Domain, radixDNSAlias.Spec.AppName)) - case strings.EqualFold(dnsAlias.Environment, radixDNSAlias.Spec.Environment) && - strings.EqualFold(dnsAlias.Component, radixDNSAlias.Spec.Component) && - port == radixDNSAlias.Spec.Port: + case !strings.EqualFold(appName, existingRadixDNSAlias.Spec.AppName): + errs = append(errs, fmt.Errorf("existing DNS alias domain %s is used by the application %s", dnsAlias.Domain, existingRadixDNSAlias.Spec.AppName)) + case strings.EqualFold(dnsAlias.Environment, existingRadixDNSAlias.Spec.Environment) && + strings.EqualFold(dnsAlias.Component, existingRadixDNSAlias.Spec.Component) && + port == existingRadixDNSAlias.Spec.Port: // No changes default: - if err = app.updateRadixDNSAlias(radixDNSAlias, dnsAlias, port); err != nil { + if err = app.updateRadixDNSAlias(existingRadixDNSAlias, dnsAlias, port); err != nil { errs = append(errs, err) } } - delete(radixDNSAliasesMap, dnsAlias.Domain) + delete(existingRadixDNSAliasesMap, dnsAlias.Domain) continue } if err = app.createRadixDNSAlias(appName, dnsAlias, port); err != nil { errs = append(errs, err) } } - for _, radixDNSAlias := range radixDNSAliasesMap { + for _, radixDNSAlias := range existingRadixDNSAliasesMap { if err = app.kubeutil.DeleteRadixDNSAlias(radixDNSAlias); err != nil { errs = append(errs, err) } diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go index 8424598c2..673f27de7 100644 --- a/pkg/apis/applicationconfig/dns_alias_test.go +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -318,8 +318,7 @@ func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { domain2 = "domain2" ) dnsAliasAppReserved := map[string]string{ - "api": "radix-api", - "console": "radix-web-console", + "api": "radix-api", } dnsAliasReserved := []string{"grafana"} var testScenarios = []struct { diff --git a/pkg/apis/radixvalidators/validate_ra.go b/pkg/apis/radixvalidators/validate_ra.go index acced8007..67d94ccb6 100644 --- a/pkg/apis/radixvalidators/validate_ra.go +++ b/pkg/apis/radixvalidators/validate_ra.go @@ -12,6 +12,7 @@ import ( "unicode" commonUtils "github.com/equinor/radix-common/utils" + "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/deployment" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -179,6 +180,12 @@ func validateDNSAlias(radixClient radixclient.Interface, app *radixv1.RadixAppli if radixDNSAlias, ok := radixDNSAliasMap[dnsAlias.Domain]; ok && radixDNSAlias.Spec.AppName != app.Name { errs = append(errs, RadixDNSAliasAlreadyUsedByAnotherApplicationError(dnsAlias.Domain)) } + if reservingAppName, aliasReserved := dnsAliasAppReserved[dnsAlias.Domain]; aliasReserved && reservingAppName != app.Name { + errs = append(errs, RadixDNSAliasIsReservedForRadixPlatformApplicationError(dnsAlias.Domain)) + } + if slice.Any(dnsAliasReserved, func(reservedAlias string) bool { return reservedAlias == dnsAlias.Domain }) { + errs = append(errs, RadixDNSAliasIsReservedForRadixPlatformServiceError(dnsAlias.Domain)) + } } return errors.Join(errs...) } From 8eaa2db519277a3eaf5e2b9986ef39492c6f2ec8 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 8 Nov 2023 11:05:46 +0100 Subject: [PATCH 038/121] Config moved to pkg --- .../apis}/config/cluster_config.go | 0 pkg/apis/config/config.go | 20 ++++++++++++ pkg/apis/dnsalias/ingress.go | 2 +- pkg/apis/dnsalias/syncer.go | 2 +- pkg/apis/dnsalias/syncer_test.go | 2 +- pkg/apis/radix/config.go | 1 + radix-operator/config/config.go | 30 +++++------------- radix-operator/dnsalias/controller_test.go | 2 +- radix-operator/dnsalias/handler.go | 2 +- radix-operator/dnsalias/handler_test.go | 2 +- .../dnsalias/internal/syncerfactory.go | 2 +- .../dnsalias/internal/syncerfactory_mock.go | 2 +- radix-operator/main.go | 31 ++++++++++--------- 13 files changed, 53 insertions(+), 45 deletions(-) rename {radix-operator => pkg/apis}/config/cluster_config.go (100%) create mode 100644 pkg/apis/config/config.go create mode 100644 pkg/apis/radix/config.go diff --git a/radix-operator/config/cluster_config.go b/pkg/apis/config/cluster_config.go similarity index 100% rename from radix-operator/config/cluster_config.go rename to pkg/apis/config/cluster_config.go diff --git a/pkg/apis/config/config.go b/pkg/apis/config/config.go new file mode 100644 index 000000000..c084dd44d --- /dev/null +++ b/pkg/apis/config/config.go @@ -0,0 +1,20 @@ +package config + +import ( + "github.com/equinor/radix-operator/pkg/apis/job" +) + +type LogLevel string + +const ( + LogLevelInfo LogLevel = "INFO" + LogLevelError LogLevel = "ERROR" + LogLevelDebug LogLevel = "DEBUG" +) + +// Config from environment variables +type Config struct { + LogLevel LogLevel + ClusterConfig *ClusterConfig + PipelineJobConfig *job.Config +} diff --git a/pkg/apis/dnsalias/ingress.go b/pkg/apis/dnsalias/ingress.go index 41c2e8991..4d8d10fc3 100644 --- a/pkg/apis/dnsalias/ingress.go +++ b/pkg/apis/dnsalias/ingress.go @@ -4,13 +4,13 @@ import ( "context" "fmt" + "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/annotations" "github.com/equinor/radix-operator/pkg/apis/utils/labels" - "github.com/equinor/radix-operator/radix-operator/config" networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index abd62f525..f53a979f2 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -3,11 +3,11 @@ package dnsalias import ( "fmt" + "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" - "github.com/equinor/radix-operator/radix-operator/config" networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/client-go/kubernetes" diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 32cf83419..894aa3a8e 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix" @@ -12,7 +13,6 @@ import ( commonTest "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" - "github.com/equinor/radix-operator/radix-operator/config" prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" diff --git a/pkg/apis/radix/config.go b/pkg/apis/radix/config.go new file mode 100644 index 000000000..a751fe77d --- /dev/null +++ b/pkg/apis/radix/config.go @@ -0,0 +1 @@ +package radix diff --git a/radix-operator/config/config.go b/radix-operator/config/config.go index 33e146603..78f531438 100644 --- a/radix-operator/config/config.go +++ b/radix-operator/config/config.go @@ -4,27 +4,20 @@ import ( "strconv" "strings" + apiconfig "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/job" "github.com/spf13/viper" ) -type LogLevel string +var logLevels = map[string]bool{string(apiconfig.LogLevelInfo): true, string(apiconfig.LogLevelDebug): true, string(apiconfig.LogLevelError): true} -const ( - LogLevelInfo LogLevel = "INFO" - LogLevelError LogLevel = "ERROR" - LogLevelDebug LogLevel = "DEBUG" -) - -var logLevels = map[string]bool{string(LogLevelInfo): true, string(LogLevelDebug): true, string(LogLevelError): true} - -func getLogLevel() string { +func getLogLevel() apiconfig.LogLevel { logLevel := viper.GetString(defaults.LogLevel) if _, ok := logLevels[logLevel]; ok { - return logLevel + return apiconfig.LogLevel(logLevel) } - return string(LogLevelInfo) + return apiconfig.LogLevelInfo } // Gets pipeline job history limit per each list, grouped by pipeline branch and job status @@ -70,19 +63,12 @@ func getIntFromEnvVar(envVarName string, defaultValue int) int { return val } -// Config from environment variables -type Config struct { - LogLevel string - ClusterConfig *ClusterConfig - PipelineJobConfig *job.Config -} - // NewConfig New instance of the Config -func NewConfig() *Config { +func NewConfig() *apiconfig.Config { viper.AutomaticEnv() - return &Config{ + return &apiconfig.Config{ LogLevel: getLogLevel(), - ClusterConfig: &ClusterConfig{ + ClusterConfig: &apiconfig.ClusterConfig{ DNSZone: getDNSZone(), DNSAliasAppReserved: getDNSAliasAppReserved(), DNSAliasReserved: getDNSAliasReserved(), diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go index 30545b92e..914c42586 100644 --- a/radix-operator/dnsalias/controller_test.go +++ b/radix-operator/dnsalias/controller_test.go @@ -5,11 +5,11 @@ import ( "testing" "github.com/equinor/radix-common/utils/pointers" + "github.com/equinor/radix-operator/pkg/apis/config" dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/radix" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/radix-operator/common" - "github.com/equinor/radix-operator/radix-operator/config" "github.com/equinor/radix-operator/radix-operator/dnsalias" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" "github.com/stretchr/testify/suite" diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go index 2a5e9304d..737b07fc0 100644 --- a/radix-operator/dnsalias/handler.go +++ b/radix-operator/dnsalias/handler.go @@ -3,11 +3,11 @@ package dnsalias import ( "fmt" + "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" - "github.com/equinor/radix-operator/radix-operator/config" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index 60b663191..9333ad392 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -4,10 +4,10 @@ import ( "fmt" "testing" + "github.com/equinor/radix-operator/pkg/apis/config" dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" commonTest "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/radix-operator/common" - "github.com/equinor/radix-operator/radix-operator/config" "github.com/equinor/radix-operator/radix-operator/dnsalias" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" "github.com/golang/mock/gomock" diff --git a/radix-operator/dnsalias/internal/syncerfactory.go b/radix-operator/dnsalias/internal/syncerfactory.go index e9aace1e9..1819bfe21 100644 --- a/radix-operator/dnsalias/internal/syncerfactory.go +++ b/radix-operator/dnsalias/internal/syncerfactory.go @@ -1,11 +1,11 @@ package internal import ( + "github.com/equinor/radix-operator/pkg/apis/config" dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" - "github.com/equinor/radix-operator/radix-operator/config" "k8s.io/client-go/kubernetes" ) diff --git a/radix-operator/dnsalias/internal/syncerfactory_mock.go b/radix-operator/dnsalias/internal/syncerfactory_mock.go index d456488db..0cd301717 100644 --- a/radix-operator/dnsalias/internal/syncerfactory_mock.go +++ b/radix-operator/dnsalias/internal/syncerfactory_mock.go @@ -7,11 +7,11 @@ package internal import ( reflect "reflect" + "github.com/equinor/radix-operator/pkg/apis/config" dnsalias "github.com/equinor/radix-operator/pkg/apis/dnsalias" kube "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" versioned "github.com/equinor/radix-operator/pkg/client/clientset/versioned" - config "github.com/equinor/radix-operator/radix-operator/config" gomock "github.com/golang/mock/gomock" kubernetes "k8s.io/client-go/kubernetes" ) diff --git a/radix-operator/main.go b/radix-operator/main.go index 0fae4615c..f1fe5cb5f 100644 --- a/radix-operator/main.go +++ b/radix-operator/main.go @@ -11,6 +11,7 @@ import ( "time" errorUtils "github.com/equinor/radix-common/utils/errors" + apiconfig "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/defaults" deploymentAPI "github.com/equinor/radix-operator/pkg/apis/deployment" jobUtil "github.com/equinor/radix-operator/pkg/apis/job" @@ -24,7 +25,7 @@ import ( "github.com/equinor/radix-operator/radix-operator/common" "github.com/equinor/radix-operator/radix-operator/config" "github.com/equinor/radix-operator/radix-operator/deployment" - dnsalias "github.com/equinor/radix-operator/radix-operator/dnsalias" + "github.com/equinor/radix-operator/radix-operator/dnsalias" "github.com/equinor/radix-operator/radix-operator/environment" "github.com/equinor/radix-operator/radix-operator/job" "github.com/equinor/radix-operator/radix-operator/registration" @@ -38,7 +39,7 @@ import ( _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/client-go/tools/record" "k8s.io/client-go/util/flowcontrol" - secretProviderClient "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned" + secretproviderclient "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned" ) const ( @@ -114,7 +115,7 @@ func getInitParams() (int, int, int, int, int, int, int, float32, error) { return registrationControllerThreads, applicationControllerThreads, environmentControllerThreads, deploymentControllerThreads, jobControllerThreads, alertControllerThreads, kubeClientRateLimitBurst, kubeClientRateLimitQPS, errCat } -func createRegistrationController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretProviderClient.Interface) *common.Controller { +func createRegistrationController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, @@ -141,7 +142,7 @@ func createRegistrationController(client kubernetes.Interface, radixClient radix recorder) } -func createApplicationController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretProviderClient.Interface) *common.Controller { +func createApplicationController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, @@ -153,7 +154,7 @@ func createApplicationController(client kubernetes.Interface, radixClient radixc handler := application.NewHandler(client, kubeUtil, radixClient, - func(syncedOk bool) {}, // Not interested in getting notifications of synced) + func(syncedOk bool) {}, // Not interested in getting notifications of synced ) const waitForChildrenToSync = true @@ -167,7 +168,7 @@ func createApplicationController(client kubernetes.Interface, radixClient radixc recorder) } -func createEnvironmentController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretProviderClient.Interface) *common.Controller { +func createEnvironmentController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, @@ -194,7 +195,7 @@ func createEnvironmentController(client kubernetes.Interface, radixClient radixc recorder) } -func createDNSAliasesController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretProviderClient.Interface, clusterConfig *config.ClusterConfig) *common.Controller { +func createDNSAliasesController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, clusterConfig *apiconfig.ClusterConfig) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, @@ -222,7 +223,7 @@ func createDNSAliasesController(client kubernetes.Interface, radixClient radixcl recorder) } -func createDeploymentController(client kubernetes.Interface, radixClient radixclient.Interface, prometheusOperatorClient monitoring.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretProviderClient.Interface) *common.Controller { +func createDeploymentController(client kubernetes.Interface, radixClient radixclient.Interface, prometheusOperatorClient monitoring.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, @@ -267,7 +268,7 @@ func createDeploymentController(client kubernetes.Interface, radixClient radixcl recorder) } -func createJobController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretProviderClient.Interface, config *jobUtil.Config) *common.Controller { +func createJobController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, config *jobUtil.Config) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, @@ -276,13 +277,13 @@ func createJobController(client kubernetes.Interface, radixClient radixclient.In radixInformerFactory, ) - handler := job.NewHandler(client, kubeUtil, radixClient, config, func(syncedOk bool) {}) // Not interested in getting notifications of synced) + handler := job.NewHandler(client, kubeUtil, radixClient, config, func(syncedOk bool) {}) // Not interested in getting notifications of synced const waitForChildrenToSync = true return job.NewController(client, radixClient, &handler, kubeInformerFactory, radixInformerFactory, waitForChildrenToSync, recorder) } -func createAlertController(client kubernetes.Interface, radixClient radixclient.Interface, prometheusOperatorClient monitoring.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretProviderClient.Interface) *common.Controller { +func createAlertController(client kubernetes.Interface, radixClient radixclient.Interface, prometheusOperatorClient monitoring.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, @@ -308,7 +309,7 @@ func createAlertController(client kubernetes.Interface, radixClient radixclient. recorder) } -func createBatchController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretProviderClient.Interface) *common.Controller { +func createBatchController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, @@ -387,11 +388,11 @@ func Healthz(writer http.ResponseWriter, _ *http.Request) { _, _ = fmt.Fprintf(writer, "%s", response) } -func setLogLevel(logLevel string) { +func setLogLevel(logLevel apiconfig.LogLevel) { switch logLevel { - case string(config.LogLevelDebug): + case apiconfig.LogLevelDebug: log.SetLevel(log.DebugLevel) - case string(config.LogLevelError): + case apiconfig.LogLevelError: log.SetLevel(log.ErrorLevel) default: log.SetLevel(log.InfoLevel) From ac5ea339d60e939df77326bd78f2de54fc4e8d75 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 8 Nov 2023 14:23:23 +0100 Subject: [PATCH 039/121] Renamed CRD plural name for radixdnsalias --- Makefile | 2 +- charts/radix-operator/templates/radix-operator-rbac.yaml | 4 ++-- charts/radix-operator/templates/radixdnsalias.yaml | 4 ++-- pkg/apis/radix/v1/radixdnsaliastypes.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 84f1357f2..560f5f52d 100644 --- a/Makefile +++ b/Makefile @@ -145,7 +145,7 @@ radixbatch-crd: temp-crds .PHONY: radixdnsalias-crd radixdnsalias-crd: temp-crds - cp $(CRD_TEMP_DIR)radix.equinor.com_radixdnsalias.yaml $(CRD_CHART_DIR)radixdnsalias.yaml + cp $(CRD_TEMP_DIR)radix.equinor.com_radixdnsaliases.yaml $(CRD_CHART_DIR)radixdnsalias.yaml yq eval '.spec.versions[0].schema.openAPIV3Schema' -ojson $(CRD_CHART_DIR)radixdnsalias.yaml > $(JSON_SCHEMA_DIR)radixdnsalias.json .PHONY: temp-crds diff --git a/charts/radix-operator/templates/radix-operator-rbac.yaml b/charts/radix-operator/templates/radix-operator-rbac.yaml index 856b36ec8..73a41ee92 100644 --- a/charts/radix-operator/templates/radix-operator-rbac.yaml +++ b/charts/radix-operator/templates/radix-operator-rbac.yaml @@ -29,8 +29,8 @@ rules: - radixalerts/status - radixbatches - radixbatches/status - - radixdnsalias - - radixdnsalias/status + - radixdnsaliases + - radixdnsaliases/status verbs: - get - list diff --git a/charts/radix-operator/templates/radixdnsalias.yaml b/charts/radix-operator/templates/radixdnsalias.yaml index 3bdbe5a6f..c835db973 100644 --- a/charts/radix-operator/templates/radixdnsalias.yaml +++ b/charts/radix-operator/templates/radixdnsalias.yaml @@ -5,13 +5,13 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.10.0 creationTimestamp: null - name: radixdnsalias.radix.equinor.com + name: radixdnsaliases.radix.equinor.com spec: group: radix.equinor.com names: kind: RadixDNSAlias listKind: RadixDNSAliasList - plural: radixdnsalias + plural: radixdnsaliases shortNames: - rda singular: radixdnsalias diff --git a/pkg/apis/radix/v1/radixdnsaliastypes.go b/pkg/apis/radix/v1/radixdnsaliastypes.go index b390de928..0b2bc4edb 100644 --- a/pkg/apis/radix/v1/radixdnsaliastypes.go +++ b/pkg/apis/radix/v1/radixdnsaliastypes.go @@ -5,7 +5,7 @@ import meta "k8s.io/apimachinery/pkg/apis/meta/v1" // +genclient // +genclient:nonNamespaced // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// +kubebuilder:resource:path=radixdnsalias,scope=Cluster,shortName=rda +// +kubebuilder:resource:path=radixdnsaliases,scope=Cluster,shortName=rda // RadixDNSAlias is a Custom Resource Definition type RadixDNSAlias struct { From 8fefc42b8c84764727ea93c5c0bb0b7f1113fcb8 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 8 Nov 2023 16:13:17 +0100 Subject: [PATCH 040/121] ClusterConfig renamed to DNSConfig --- pkg/apis/config/config.go | 2 +- .../{cluster_config.go => dns_config.go} | 4 ++-- pkg/apis/dnsalias/ingress.go | 2 +- pkg/apis/dnsalias/syncer.go | 8 ++++---- pkg/apis/dnsalias/syncer_test.go | 18 +++++++++--------- radix-operator/config/config.go | 2 +- radix-operator/dnsalias/controller_test.go | 2 +- radix-operator/dnsalias/handler.go | 16 ++++++++-------- radix-operator/dnsalias/handler_test.go | 18 +++++++++--------- .../dnsalias/internal/syncerfactory.go | 8 ++++---- .../dnsalias/internal/syncerfactory_mock.go | 8 ++++---- radix-operator/main.go | 6 +++--- 12 files changed, 47 insertions(+), 47 deletions(-) rename pkg/apis/config/{cluster_config.go => dns_config.go} (82%) diff --git a/pkg/apis/config/config.go b/pkg/apis/config/config.go index c084dd44d..6bda8fc83 100644 --- a/pkg/apis/config/config.go +++ b/pkg/apis/config/config.go @@ -15,6 +15,6 @@ const ( // Config from environment variables type Config struct { LogLevel LogLevel - ClusterConfig *ClusterConfig + DNSConfig *DNSConfig PipelineJobConfig *job.Config } diff --git a/pkg/apis/config/cluster_config.go b/pkg/apis/config/dns_config.go similarity index 82% rename from pkg/apis/config/cluster_config.go rename to pkg/apis/config/dns_config.go index 15ec9b75a..17b08ca2d 100644 --- a/pkg/apis/config/cluster_config.go +++ b/pkg/apis/config/dns_config.go @@ -1,7 +1,7 @@ package config -// ClusterConfig Config settings for the cluster -type ClusterConfig struct { +// DNSConfig Config settings for the cluster DNS +type DNSConfig struct { // DNSZone Cluster DNS zone. // Example radix.equinor.com, playground.radix.equinor.com DNSZone string diff --git a/pkg/apis/dnsalias/ingress.go b/pkg/apis/dnsalias/ingress.go index 4d8d10fc3..8acdd0835 100644 --- a/pkg/apis/dnsalias/ingress.go +++ b/pkg/apis/dnsalias/ingress.go @@ -22,7 +22,7 @@ func CreateRadixDNSAliasIngress(kubeClient kubernetes.Interface, appName, envNam } // BuildRadixDNSAliasIngress Build an Ingress for a RadixDNSAlias -func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, owner *v1.RadixDNSAlias, config *config.ClusterConfig) *networkingv1.Ingress { +func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, owner *v1.RadixDNSAlias, config *config.DNSConfig) *networkingv1.Ingress { pathTypeImplementationSpecific := networkingv1.PathTypeImplementationSpecific ingressName := GetDNSAliasIngressName(service, domain) host := GetDNSAliasHost(domain, config.DNSZone) diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index f53a979f2..a90b96516 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -25,16 +25,16 @@ type syncer struct { radixClient radixclient.Interface kubeUtil *kube.Kube radixDNSAlias *radixv1.RadixDNSAlias - clusterConfig *config.ClusterConfig + dnsConfig *config.DNSConfig } // NewSyncer is the constructor for RadixDNSAlias syncer -func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, clusterConfig *config.ClusterConfig, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { +func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *config.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { return &syncer{ kubeClient: kubeClient, radixClient: radixClient, kubeUtil: kubeUtil, - clusterConfig: clusterConfig, + dnsConfig: dnsConfig, radixDNSAlias: radixDNSAlias, } } @@ -87,5 +87,5 @@ func (s *syncer) createIngress() error { func (s *syncer) buildIngress() (*networkingv1.Ingress, error) { aliasSpec := s.radixDNSAlias.Spec domain := s.radixDNSAlias.GetName() - return BuildRadixDNSAliasIngress(aliasSpec.AppName, domain, aliasSpec.Component, aliasSpec.Port, s.radixDNSAlias, s.clusterConfig), nil + return BuildRadixDNSAliasIngress(aliasSpec.AppName, domain, aliasSpec.Component, aliasSpec.Port, s.radixDNSAlias, s.dnsConfig), nil } diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 894aa3a8e..eeb82825d 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -25,11 +25,11 @@ import ( type syncerTestSuite struct { suite.Suite - kubeClient *kubefake.Clientset - radixClient *radixfake.Clientset - kubeUtil *kube.Kube - promClient *prometheusfake.Clientset - clusterConfig *config.ClusterConfig + kubeClient *kubefake.Clientset + radixClient *radixfake.Clientset + kubeUtil *kube.Kube + promClient *prometheusfake.Clientset + dnsConfig *config.DNSConfig } func TestSyncerTestSuite(t *testing.T) { @@ -40,12 +40,12 @@ func (s *syncerTestSuite) SetupTest() { s.kubeClient = kubefake.NewSimpleClientset() s.radixClient = radixfake.NewSimpleClientset() s.promClient = prometheusfake.NewSimpleClientset() - s.clusterConfig = &config.ClusterConfig{DNSZone: "test.radix.equinor.com"} + s.dnsConfig = &config.DNSConfig{DNSZone: "test.radix.equinor.com"} s.kubeUtil, _ = kube.New(s.kubeClient, s.radixClient, secretproviderfake.NewSimpleClientset()) } func (s *syncerTestSuite) createSyncer(radixDNSAlias *radixv1.RadixDNSAlias) dnsalias.Syncer { - return dnsalias.NewSyncer(s.kubeClient, s.kubeUtil, s.radixClient, s.clusterConfig, radixDNSAlias) + return dnsalias.NewSyncer(s.kubeClient, s.kubeUtil, s.radixClient, s.dnsConfig, radixDNSAlias) } type testIngress struct { @@ -193,7 +193,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Domain, UID: uuid.NewUUID()}, Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component, Port: ts.dnsAlias.Port}} s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Domain, radixDNSAlias.Spec), "create existing alias") - cfg := &config.ClusterConfig{DNSZone: ts.dnsZone} + cfg := &config.DNSConfig{DNSZone: ts.dnsZone} s.Require().NoError(registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1, cfg), "create existing ingresses") syncer := s.createSyncer(radixDNSAlias) err := syncer.OnSync() @@ -240,7 +240,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { } } -func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses map[string]testIngress, appNameForNamespace, envNameForNamespace string, config *config.ClusterConfig) error { +func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses map[string]testIngress, appNameForNamespace, envNameForNamespace string, config *config.DNSConfig) error { for name, ing := range testIngresses { ingress := dnsalias.BuildRadixDNSAliasIngress(ing.appName, ing.domain, ing.component, ing.port, nil, config) ingress.SetName(name) // override built name with expected name for test purpose diff --git a/radix-operator/config/config.go b/radix-operator/config/config.go index 78f531438..3fbb74792 100644 --- a/radix-operator/config/config.go +++ b/radix-operator/config/config.go @@ -68,7 +68,7 @@ func NewConfig() *apiconfig.Config { viper.AutomaticEnv() return &apiconfig.Config{ LogLevel: getLogLevel(), - ClusterConfig: &apiconfig.ClusterConfig{ + DNSConfig: &apiconfig.DNSConfig{ DNSZone: getDNSZone(), DNSAliasAppReserved: getDNSAliasAppReserved(), DNSAliasReserved: getDNSAliasReserved(), diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go index 914c42586..6a51723c6 100644 --- a/radix-operator/dnsalias/controller_test.go +++ b/radix-operator/dnsalias/controller_test.go @@ -85,7 +85,7 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { s.WaitForNotSynced("Sync should not be called when updating RadixDNSAlias with no changes") // Add Ingress with owner reference to RadixDNSAlias should not trigger sync - cfg := &config.ClusterConfig{DNSZone: dnsZone} + cfg := &config.DNSConfig{DNSZone: dnsZone} ingress := dnsaliasapi.BuildRadixDNSAliasIngress(alias.Spec.AppName, alias.GetName(), alias.Spec.Component, int32(8080), alias, cfg) ingress.SetOwnerReferences([]metav1.OwnerReference{{APIVersion: radix.APIVersion, Kind: radix.KindRadixDNSAlias, Name: aliasName, Controller: pointers.Ptr(true)}}) namespace := utils.GetEnvironmentNamespace(alias.Spec.AppName, alias.Spec.Environment) diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go index 737b07fc0..23733f34a 100644 --- a/radix-operator/dnsalias/handler.go +++ b/radix-operator/dnsalias/handler.go @@ -32,7 +32,7 @@ type handler struct { radixClient radixclient.Interface syncerFactory internal.SyncerFactory hasSynced common.HasSynced - clusterConfig *config.ClusterConfig + dnsConfig *config.DNSConfig } // NewHandler creates a handler for managing RadixDNSAlias resources @@ -40,15 +40,15 @@ func NewHandler( kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, - clusterConfig *config.ClusterConfig, + dnsConfig *config.DNSConfig, hasSynced common.HasSynced, options ...HandlerConfigOption) common.Handler { h := &handler{ - kubeClient: kubeClient, - kubeUtil: kubeUtil, - radixClient: radixClient, - hasSynced: hasSynced, - clusterConfig: clusterConfig, + kubeClient: kubeClient, + kubeUtil: kubeUtil, + radixClient: radixClient, + hasSynced: hasSynced, + dnsConfig: dnsConfig, } configureDefaultSyncerFactory(h) for _, option := range options { @@ -81,7 +81,7 @@ func (h *handler) Sync(_, name string, eventRecorder record.EventRecorder) error syncingAlias := radixDNSAlias.DeepCopy() logger.Debugf("Sync RadixDNSAlias %s", name) - syncer := h.syncerFactory.CreateSyncer(h.kubeClient, h.kubeUtil, h.radixClient, h.clusterConfig, syncingAlias) + syncer := h.syncerFactory.CreateSyncer(h.kubeClient, h.kubeUtil, h.radixClient, h.dnsConfig, syncingAlias) err = syncer.OnSync() if err != nil { return err diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index 9333ad392..43ff0d8c6 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -42,11 +42,11 @@ func (s *handlerTestSuite) TearDownTest() { } func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { - clusterConfig := &config.ClusterConfig{DNSZone: "test.radix.equinor.com"} - handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, clusterConfig, + dnsConfig := &config.DNSConfig{DNSZone: "test.radix.equinor.com"} + handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) - s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), clusterConfig, gomock.Any()).Times(0) + s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any()).Times(0) s.syncer.EXPECT().OnSync().Times(0) err := handler.Sync("", domain1, s.EventRecorder) @@ -54,12 +54,12 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { } func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { - clusterConfig := &config.ClusterConfig{DNSZone: "test.radix.equinor.com"} + dnsConfig := &config.DNSConfig{DNSZone: "test.radix.equinor.com"} s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, domain1, 8080), "create existing RadixDNSAlias") - handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, clusterConfig, + handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) expectedError := fmt.Errorf("some error") - s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), clusterConfig, gomock.Any()).Return(s.syncer).Times(1) + s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any()).Return(s.syncer).Times(1) s.syncer.EXPECT().OnSync().Return(expectedError).Times(1) actualError := handler.Sync("", domain1, s.EventRecorder) @@ -67,11 +67,11 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { } func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsNoError() { - clusterConfig := &config.ClusterConfig{DNSZone: "test.radix.equinor.com"} + dnsConfig := &config.DNSConfig{DNSZone: "test.radix.equinor.com"} s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, domain1, 8080), "create existing RadixDNSAlias") - handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, clusterConfig, + handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) - s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), clusterConfig, gomock.Any()).Return(s.syncer).Times(1) + s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any()).Return(s.syncer).Times(1) s.syncer.EXPECT().OnSync().Return(nil).Times(1) err := handler.Sync("", domain1, s.EventRecorder) diff --git a/radix-operator/dnsalias/internal/syncerfactory.go b/radix-operator/dnsalias/internal/syncerfactory.go index 1819bfe21..09f90f279 100644 --- a/radix-operator/dnsalias/internal/syncerfactory.go +++ b/radix-operator/dnsalias/internal/syncerfactory.go @@ -11,7 +11,7 @@ import ( // SyncerFactory defines a factory to create a DNS alias Syncer type SyncerFactory interface { - CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, clusterConfig *config.ClusterConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer + CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *config.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer } // SyncerFactoryFunc is an adapter that can be used to convert @@ -20,11 +20,11 @@ type SyncerFactoryFunc func( kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, - clusterConfig *config.ClusterConfig, + dnsConfig *config.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias, ) dnsaliasapi.Syncer // CreateSyncer Create a DNS alias Syncer -func (f SyncerFactoryFunc) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, clusterConfig *config.ClusterConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer { - return f(kubeClient, kubeUtil, radixClient, clusterConfig, radixDNSAlias) +func (f SyncerFactoryFunc) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *config.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer { + return f(kubeClient, kubeUtil, radixClient, dnsConfig, radixDNSAlias) } diff --git a/radix-operator/dnsalias/internal/syncerfactory_mock.go b/radix-operator/dnsalias/internal/syncerfactory_mock.go index 0cd301717..188ee55d1 100644 --- a/radix-operator/dnsalias/internal/syncerfactory_mock.go +++ b/radix-operator/dnsalias/internal/syncerfactory_mock.go @@ -40,15 +40,15 @@ func (m *MockSyncerFactory) EXPECT() *MockSyncerFactoryMockRecorder { } // CreateSyncer mocks base method. -func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, clusterConfig *config.ClusterConfig, radixDNSAlias *v1.RadixDNSAlias) dnsalias.Syncer { +func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, dnsConfig *config.DNSConfig, radixDNSAlias *v1.RadixDNSAlias) dnsalias.Syncer { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateSyncer", kubeClient, kubeUtil, radixClient, clusterConfig, radixDNSAlias) + ret := m.ctrl.Call(m, "CreateSyncer", kubeClient, kubeUtil, radixClient, dnsConfig, radixDNSAlias) ret0, _ := ret[0].(dnsalias.Syncer) return ret0 } // CreateSyncer indicates an expected call of CreateSyncer. -func (mr *MockSyncerFactoryMockRecorder) CreateSyncer(kubeClient, kubeUtil, radixClient, clusterConfig, radixDNSAlias interface{}) *gomock.Call { +func (mr *MockSyncerFactoryMockRecorder) CreateSyncer(kubeClient, kubeUtil, radixClient, dnsConfig, radixDNSAlias interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSyncer", reflect.TypeOf((*MockSyncerFactory)(nil).CreateSyncer), kubeClient, kubeUtil, radixClient, clusterConfig, radixDNSAlias) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSyncer", reflect.TypeOf((*MockSyncerFactory)(nil).CreateSyncer), kubeClient, kubeUtil, radixClient, dnsConfig, radixDNSAlias) } diff --git a/radix-operator/main.go b/radix-operator/main.go index f1fe5cb5f..39ea37410 100644 --- a/radix-operator/main.go +++ b/radix-operator/main.go @@ -81,7 +81,7 @@ func main() { startController(createJobController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg.PipelineJobConfig), jobControllerThreads, stop) startController(createAlertController(client, radixClient, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), alertControllerThreads, stop) startController(createBatchController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), 1, stop) - startController(createDNSAliasesController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg.ClusterConfig), environmentControllerThreads, stop) + startController(createDNSAliasesController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg.DNSConfig), environmentControllerThreads, stop) // Start informers when all controllers are running kubeInformerFactory.Start(stop) @@ -195,7 +195,7 @@ func createEnvironmentController(client kubernetes.Interface, radixClient radixc recorder) } -func createDNSAliasesController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, clusterConfig *apiconfig.ClusterConfig) *common.Controller { +func createDNSAliasesController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, dnsConfig *apiconfig.DNSConfig) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, @@ -208,7 +208,7 @@ func createDNSAliasesController(client kubernetes.Interface, radixClient radixcl client, kubeUtil, radixClient, - clusterConfig, + dnsConfig, func(syncedOk bool) {}, // Not interested in getting notifications of synced ) From 5abdea45f116c2d31c498f1d9d79cb2bc44fd40e Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 8 Nov 2023 16:15:08 +0100 Subject: [PATCH 041/121] DNSConfig moved to dnsalias package --- pkg/apis/config/config.go | 3 ++- pkg/apis/{config => dnsalias}/dns_config.go | 2 +- pkg/apis/dnsalias/ingress.go | 3 +-- pkg/apis/dnsalias/syncer.go | 5 ++--- pkg/apis/dnsalias/syncer_test.go | 9 ++++----- radix-operator/config/config.go | 3 ++- radix-operator/dnsalias/controller_test.go | 3 +-- radix-operator/dnsalias/handler.go | 5 ++--- radix-operator/dnsalias/handler_test.go | 7 +++---- radix-operator/dnsalias/internal/syncerfactory.go | 7 +++---- radix-operator/dnsalias/internal/syncerfactory_mock.go | 3 +-- radix-operator/main.go | 3 ++- 12 files changed, 24 insertions(+), 29 deletions(-) rename pkg/apis/{config => dnsalias}/dns_config.go (96%) diff --git a/pkg/apis/config/config.go b/pkg/apis/config/config.go index 6bda8fc83..15787cf62 100644 --- a/pkg/apis/config/config.go +++ b/pkg/apis/config/config.go @@ -1,6 +1,7 @@ package config import ( + "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/job" ) @@ -15,6 +16,6 @@ const ( // Config from environment variables type Config struct { LogLevel LogLevel - DNSConfig *DNSConfig + DNSConfig *dnsalias.DNSConfig PipelineJobConfig *job.Config } diff --git a/pkg/apis/config/dns_config.go b/pkg/apis/dnsalias/dns_config.go similarity index 96% rename from pkg/apis/config/dns_config.go rename to pkg/apis/dnsalias/dns_config.go index 17b08ca2d..c3ce975ea 100644 --- a/pkg/apis/config/dns_config.go +++ b/pkg/apis/dnsalias/dns_config.go @@ -1,4 +1,4 @@ -package config +package dnsalias // DNSConfig Config settings for the cluster DNS type DNSConfig struct { diff --git a/pkg/apis/dnsalias/ingress.go b/pkg/apis/dnsalias/ingress.go index 8acdd0835..126c97b04 100644 --- a/pkg/apis/dnsalias/ingress.go +++ b/pkg/apis/dnsalias/ingress.go @@ -4,7 +4,6 @@ import ( "context" "fmt" - "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -22,7 +21,7 @@ func CreateRadixDNSAliasIngress(kubeClient kubernetes.Interface, appName, envNam } // BuildRadixDNSAliasIngress Build an Ingress for a RadixDNSAlias -func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, owner *v1.RadixDNSAlias, config *config.DNSConfig) *networkingv1.Ingress { +func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, owner *v1.RadixDNSAlias, config *DNSConfig) *networkingv1.Ingress { pathTypeImplementationSpecific := networkingv1.PathTypeImplementationSpecific ingressName := GetDNSAliasIngressName(service, domain) host := GetDNSAliasHost(domain, config.DNSZone) diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index a90b96516..618b72ecc 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -3,7 +3,6 @@ package dnsalias import ( "fmt" - "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -25,11 +24,11 @@ type syncer struct { radixClient radixclient.Interface kubeUtil *kube.Kube radixDNSAlias *radixv1.RadixDNSAlias - dnsConfig *config.DNSConfig + dnsConfig *DNSConfig } // NewSyncer is the constructor for RadixDNSAlias syncer -func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *config.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { +func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { return &syncer{ kubeClient: kubeClient, radixClient: radixClient, diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index eeb82825d..4623c86ab 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -5,7 +5,6 @@ import ( "fmt" "testing" - "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix" @@ -29,7 +28,7 @@ type syncerTestSuite struct { radixClient *radixfake.Clientset kubeUtil *kube.Kube promClient *prometheusfake.Clientset - dnsConfig *config.DNSConfig + dnsConfig *dnsalias.DNSConfig } func TestSyncerTestSuite(t *testing.T) { @@ -40,7 +39,7 @@ func (s *syncerTestSuite) SetupTest() { s.kubeClient = kubefake.NewSimpleClientset() s.radixClient = radixfake.NewSimpleClientset() s.promClient = prometheusfake.NewSimpleClientset() - s.dnsConfig = &config.DNSConfig{DNSZone: "test.radix.equinor.com"} + s.dnsConfig = &dnsalias.DNSConfig{DNSZone: "test.radix.equinor.com"} s.kubeUtil, _ = kube.New(s.kubeClient, s.radixClient, secretproviderfake.NewSimpleClientset()) } @@ -193,7 +192,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Domain, UID: uuid.NewUUID()}, Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component, Port: ts.dnsAlias.Port}} s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Domain, radixDNSAlias.Spec), "create existing alias") - cfg := &config.DNSConfig{DNSZone: ts.dnsZone} + cfg := &dnsalias.DNSConfig{DNSZone: ts.dnsZone} s.Require().NoError(registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1, cfg), "create existing ingresses") syncer := s.createSyncer(radixDNSAlias) err := syncer.OnSync() @@ -240,7 +239,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { } } -func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses map[string]testIngress, appNameForNamespace, envNameForNamespace string, config *config.DNSConfig) error { +func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses map[string]testIngress, appNameForNamespace, envNameForNamespace string, config *dnsalias.DNSConfig) error { for name, ing := range testIngresses { ingress := dnsalias.BuildRadixDNSAliasIngress(ing.appName, ing.domain, ing.component, ing.port, nil, config) ingress.SetName(name) // override built name with expected name for test purpose diff --git a/radix-operator/config/config.go b/radix-operator/config/config.go index 3fbb74792..b5c8a11ba 100644 --- a/radix-operator/config/config.go +++ b/radix-operator/config/config.go @@ -6,6 +6,7 @@ import ( apiconfig "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/job" "github.com/spf13/viper" ) @@ -68,7 +69,7 @@ func NewConfig() *apiconfig.Config { viper.AutomaticEnv() return &apiconfig.Config{ LogLevel: getLogLevel(), - DNSConfig: &apiconfig.DNSConfig{ + DNSConfig: &dnsalias.DNSConfig{ DNSZone: getDNSZone(), DNSAliasAppReserved: getDNSAliasAppReserved(), DNSAliasReserved: getDNSAliasReserved(), diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go index 6a51723c6..56757c292 100644 --- a/radix-operator/dnsalias/controller_test.go +++ b/radix-operator/dnsalias/controller_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/equinor/radix-common/utils/pointers" - "github.com/equinor/radix-operator/pkg/apis/config" dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/radix" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -85,7 +84,7 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { s.WaitForNotSynced("Sync should not be called when updating RadixDNSAlias with no changes") // Add Ingress with owner reference to RadixDNSAlias should not trigger sync - cfg := &config.DNSConfig{DNSZone: dnsZone} + cfg := &dnsaliasapi.DNSConfig{DNSZone: dnsZone} ingress := dnsaliasapi.BuildRadixDNSAliasIngress(alias.Spec.AppName, alias.GetName(), alias.Spec.Component, int32(8080), alias, cfg) ingress.SetOwnerReferences([]metav1.OwnerReference{{APIVersion: radix.APIVersion, Kind: radix.KindRadixDNSAlias, Name: aliasName, Controller: pointers.Ptr(true)}}) namespace := utils.GetEnvironmentNamespace(alias.Spec.AppName, alias.Spec.Environment) diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go index 23733f34a..b12623cc8 100644 --- a/radix-operator/dnsalias/handler.go +++ b/radix-operator/dnsalias/handler.go @@ -3,7 +3,6 @@ package dnsalias import ( "fmt" - "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -32,7 +31,7 @@ type handler struct { radixClient radixclient.Interface syncerFactory internal.SyncerFactory hasSynced common.HasSynced - dnsConfig *config.DNSConfig + dnsConfig *dnsalias.DNSConfig } // NewHandler creates a handler for managing RadixDNSAlias resources @@ -40,7 +39,7 @@ func NewHandler( kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, - dnsConfig *config.DNSConfig, + dnsConfig *dnsalias.DNSConfig, hasSynced common.HasSynced, options ...HandlerConfigOption) common.Handler { h := &handler{ diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index 43ff0d8c6..f4739feee 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -4,7 +4,6 @@ import ( "fmt" "testing" - "github.com/equinor/radix-operator/pkg/apis/config" dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" commonTest "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/radix-operator/common" @@ -42,7 +41,7 @@ func (s *handlerTestSuite) TearDownTest() { } func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { - dnsConfig := &config.DNSConfig{DNSZone: "test.radix.equinor.com"} + dnsConfig := &dnsaliasapi.DNSConfig{DNSZone: "test.radix.equinor.com"} handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) @@ -54,7 +53,7 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { } func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { - dnsConfig := &config.DNSConfig{DNSZone: "test.radix.equinor.com"} + dnsConfig := &dnsaliasapi.DNSConfig{DNSZone: "test.radix.equinor.com"} s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, domain1, 8080), "create existing RadixDNSAlias") handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) @@ -67,7 +66,7 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { } func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsNoError() { - dnsConfig := &config.DNSConfig{DNSZone: "test.radix.equinor.com"} + dnsConfig := &dnsaliasapi.DNSConfig{DNSZone: "test.radix.equinor.com"} s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, domain1, 8080), "create existing RadixDNSAlias") handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) diff --git a/radix-operator/dnsalias/internal/syncerfactory.go b/radix-operator/dnsalias/internal/syncerfactory.go index 09f90f279..153e028f1 100644 --- a/radix-operator/dnsalias/internal/syncerfactory.go +++ b/radix-operator/dnsalias/internal/syncerfactory.go @@ -1,7 +1,6 @@ package internal import ( - "github.com/equinor/radix-operator/pkg/apis/config" dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -11,7 +10,7 @@ import ( // SyncerFactory defines a factory to create a DNS alias Syncer type SyncerFactory interface { - CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *config.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer + CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsaliasapi.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer } // SyncerFactoryFunc is an adapter that can be used to convert @@ -20,11 +19,11 @@ type SyncerFactoryFunc func( kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, - dnsConfig *config.DNSConfig, + dnsConfig *dnsaliasapi.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias, ) dnsaliasapi.Syncer // CreateSyncer Create a DNS alias Syncer -func (f SyncerFactoryFunc) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *config.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer { +func (f SyncerFactoryFunc) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsaliasapi.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer { return f(kubeClient, kubeUtil, radixClient, dnsConfig, radixDNSAlias) } diff --git a/radix-operator/dnsalias/internal/syncerfactory_mock.go b/radix-operator/dnsalias/internal/syncerfactory_mock.go index 188ee55d1..4adbc93d1 100644 --- a/radix-operator/dnsalias/internal/syncerfactory_mock.go +++ b/radix-operator/dnsalias/internal/syncerfactory_mock.go @@ -7,7 +7,6 @@ package internal import ( reflect "reflect" - "github.com/equinor/radix-operator/pkg/apis/config" dnsalias "github.com/equinor/radix-operator/pkg/apis/dnsalias" kube "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -40,7 +39,7 @@ func (m *MockSyncerFactory) EXPECT() *MockSyncerFactoryMockRecorder { } // CreateSyncer mocks base method. -func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, dnsConfig *config.DNSConfig, radixDNSAlias *v1.RadixDNSAlias) dnsalias.Syncer { +func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, dnsConfig *dnsalias.DNSConfig, radixDNSAlias *v1.RadixDNSAlias) dnsalias.Syncer { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateSyncer", kubeClient, kubeUtil, radixClient, dnsConfig, radixDNSAlias) ret0, _ := ret[0].(dnsalias.Syncer) diff --git a/radix-operator/main.go b/radix-operator/main.go index 39ea37410..927af0cc5 100644 --- a/radix-operator/main.go +++ b/radix-operator/main.go @@ -14,6 +14,7 @@ import ( apiconfig "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/defaults" deploymentAPI "github.com/equinor/radix-operator/pkg/apis/deployment" + dnsalias2 "github.com/equinor/radix-operator/pkg/apis/dnsalias" jobUtil "github.com/equinor/radix-operator/pkg/apis/job" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -195,7 +196,7 @@ func createEnvironmentController(client kubernetes.Interface, radixClient radixc recorder) } -func createDNSAliasesController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, dnsConfig *apiconfig.DNSConfig) *common.Controller { +func createDNSAliasesController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, dnsConfig *dnsalias2.DNSConfig) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, From 5dc2042861d4778806992ad96f93519cff5f7200 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 8 Nov 2023 16:42:07 +0100 Subject: [PATCH 042/121] Merged --- pipeline-runner/steps/build_test.go | 18 +++++++++--------- .../applicationconfig/applicationconfig.go | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pipeline-runner/steps/build_test.go b/pipeline-runner/steps/build_test.go index de1cc861d..f2bf43fa3 100644 --- a/pipeline-runner/steps/build_test.go +++ b/pipeline-runner/steps/build_test.go @@ -86,7 +86,7 @@ func (s *buildTestSuite) Test_BranchIsNotMapped_ShouldSkip() { cli.Init(s.kubeClient, s.radixClient, s.kubeUtil, s.promClient, rr) applicationConfig := application.NewApplicationConfig(s.kubeClient, s.kubeUtil, s.radixClient, rr, ra, nil, nil) - branchIsMapped, targetEnvs := applicationConfig.IsThereAnythingToDeploy(anyNoMappedBranch) + targetEnvs := applicationConfig.GetTargetEnvironments(anyNoMappedBranch) pipelineInfo := &model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ @@ -1611,18 +1611,18 @@ func (s *buildTestSuite) createBuildSecret(appName string, data map[string][]byt func (s *buildTestSuite) getRadixApplicationHash(ra *radixv1.RadixApplication) string { if ra == nil { - hash, _ := hash.ToHashString(hash.SHA256, "0nXSg9l6EUepshGFmolpgV3elB0m8Mv7") - return hash + appHash, _ := hash.ToHashString(hash.SHA256, "0nXSg9l6EUepshGFmolpgV3elB0m8Mv7") + return appHash } - hash, _ := hash.ToHashString(hash.SHA256, ra.Spec) - return hash + appHash, _ := hash.ToHashString(hash.SHA256, ra.Spec) + return appHash } func (s *buildTestSuite) getBuildSecretHash(secret *corev1.Secret) string { if secret == nil { - hash, _ := hash.ToHashString(hash.SHA256, "34Wd68DsJRUzrHp2f63o3U5hUD6zl8Tj") - return hash + secretHash, _ := hash.ToHashString(hash.SHA256, "34Wd68DsJRUzrHp2f63o3U5hUD6zl8Tj") + return secretHash } - hash, _ := hash.ToHashString(hash.SHA256, secret.Data) - return hash + secretHash, _ := hash.ToHashString(hash.SHA256, secret.Data) + return secretHash } diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index a0c162fd6..ce8a267b0 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -252,7 +252,7 @@ func (app *ApplicationConfig) getPortForDNSAlias(dnsAlias radixv1.DNSAlias) (int // TODO test return 0, fmt.Errorf("component %s does not exist in the application %s", dnsAlias.Component, app.config.GetName()) } - if !component.GetEnabledForAnyEnvironment([]string{dnsAlias.Environment}) { + if !component.GetEnabledForEnvironment(dnsAlias.Environment) { // TODO test return 0, fmt.Errorf("component %s is not enabled for the environment %s in the application %s", dnsAlias.Component, dnsAlias.Environment, app.config.GetName()) } @@ -283,7 +283,7 @@ func patchDifference(repository radixTypes.RadixEnvironmentInterface, oldRe *rad return fmt.Errorf("failed to marshal new RadixEnvironment object: %v", err) } - patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldReJSON, radixEnvironmentJSON, v1.RadixEnvironment{}) + patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldReJSON, radixEnvironmentJSON, radixv1.RadixEnvironment{}) if err != nil { return fmt.Errorf("failed to create patch document for RadixEnvironment object: %v", err) } From edf9b834f969ee9d3263a6c33d5ef115f5fee030 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 8 Nov 2023 16:50:33 +0100 Subject: [PATCH 043/121] Merged --- .../applicationconfig/applicationconfig_test.go | 13 +++++-------- pkg/apis/applicationconfig/dns_alias_test.go | 3 +-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 0e5d52d20..68534ee04 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -1,4 +1,4 @@ -package applicationconfig +package applicationconfig_test import ( "context" @@ -619,7 +619,7 @@ func rrAsOwnerReference(rr *radixv1.RadixRegistration) []metav1.OwnerReference { } } -func applyRadixAppWithPrivateImageHub(privateImageHubs radixv1.PrivateImageHubEntries) (kubernetes.Interface, *applicationconfig.ApplicationConfig, error) { +func applyRadixAppWithPrivateImageHub(privateImageHubs radixv1.PrivateImageHubEntries) (kubernetes.Interface, *applicationconfig.ApplicationConfig) { tu, client, kubeUtil, radixClient := setupTest() appBuilder := utils.ARadixApplication(). WithAppName("any-app"). @@ -630,10 +630,10 @@ func applyRadixAppWithPrivateImageHub(privateImageHubs radixv1.PrivateImageHubEn err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, appBuilder) if err != nil { - return nil, nil, err + return nil, nil } appConfig := getAppConfig(client, kubeUtil, radixClient, appBuilder) - return client, appConfig, err + return client, appConfig } func getAppConfig(client kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, applicationBuilder utils.ApplicationBuilder) *applicationconfig.ApplicationConfig { @@ -656,10 +656,7 @@ func applyApplicationWithSync(tu *test.Utils, client kubernetes.Interface, kubeU return err } - applicationConfig, err := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra, nil, nil) - if err != nil { - return err - } + applicationConfig := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra, nil, nil) err = applicationConfig.OnSync() if err != nil { diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go index 673f27de7..6a71f4909 100644 --- a/pkg/apis/applicationconfig/dns_alias_test.go +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -388,9 +388,8 @@ func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { _, err = radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) require.NoError(t, err) ra := ts.applicationBuilder.BuildRA() - applicationConfig, err := applicationconfig.NewApplicationConfig(kubeClient, kubeUtil, radixClient, rr, ra, + applicationConfig := applicationconfig.NewApplicationConfig(kubeClient, kubeUtil, radixClient, rr, ra, dnsAliasAppReserved, dnsAliasReserved) - require.NoError(t, err) actualValidationErr := applicationConfig.ApplyConfigToApplicationNamespace() From 02ee052fa68aeaf07e8ceeca6e307cf7810c2c9e Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 9 Nov 2023 13:43:42 +0100 Subject: [PATCH 044/121] Full config used as an argument of pipelinejob handler --- pkg/apis/config/config.go | 13 +-- .../dnsalias/config.go} | 0 .../{job => config/pipelinejob}/config.go | 2 +- pkg/apis/dnsalias/ingress.go | 3 +- pkg/apis/dnsalias/syncer.go | 5 +- pkg/apis/dnsalias/syncer_test.go | 9 ++- pkg/apis/job/job.go | 10 +-- pkg/apis/job/job_history.go | 4 +- pkg/apis/job/job_test.go | 80 ++++++++++++------- pkg/apis/job/kubejob.go | 12 +-- radix-operator/config/config.go | 8 +- radix-operator/dnsalias/controller_test.go | 3 +- radix-operator/dnsalias/handler.go | 5 +- radix-operator/dnsalias/handler_test.go | 7 +- .../dnsalias/internal/syncerfactory.go | 7 +- .../dnsalias/internal/syncerfactory_mock.go | 3 +- radix-operator/job/controller_test.go | 22 +++-- radix-operator/job/handler.go | 5 +- radix-operator/main.go | 9 ++- 19 files changed, 125 insertions(+), 82 deletions(-) rename pkg/apis/{dnsalias/dns_config.go => config/dnsalias/config.go} (100%) rename pkg/apis/{job => config/pipelinejob}/config.go (94%) diff --git a/pkg/apis/config/config.go b/pkg/apis/config/config.go index 15787cf62..5bda72a92 100644 --- a/pkg/apis/config/config.go +++ b/pkg/apis/config/config.go @@ -1,21 +1,22 @@ package config import ( - "github.com/equinor/radix-operator/pkg/apis/dnsalias" - "github.com/equinor/radix-operator/pkg/apis/job" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/config/pipelinejob" ) type LogLevel string const ( - LogLevelInfo LogLevel = "INFO" - LogLevelError LogLevel = "ERROR" - LogLevelDebug LogLevel = "DEBUG" + LogLevelError LogLevel = "ERROR" + LogLevelInfo LogLevel = "INFO" + LogLevelWarning LogLevel = "WARNING" + LogLevelDebug LogLevel = "DEBUG" ) // Config from environment variables type Config struct { LogLevel LogLevel DNSConfig *dnsalias.DNSConfig - PipelineJobConfig *job.Config + PipelineJobConfig *pipelinejob.Config } diff --git a/pkg/apis/dnsalias/dns_config.go b/pkg/apis/config/dnsalias/config.go similarity index 100% rename from pkg/apis/dnsalias/dns_config.go rename to pkg/apis/config/dnsalias/config.go diff --git a/pkg/apis/job/config.go b/pkg/apis/config/pipelinejob/config.go similarity index 94% rename from pkg/apis/job/config.go rename to pkg/apis/config/pipelinejob/config.go index f9321770b..d73f3f810 100644 --- a/pkg/apis/job/config.go +++ b/pkg/apis/config/pipelinejob/config.go @@ -1,4 +1,4 @@ -package job +package pipelinejob import "k8s.io/apimachinery/pkg/api/resource" diff --git a/pkg/apis/dnsalias/ingress.go b/pkg/apis/dnsalias/ingress.go index 126c97b04..cf53da82b 100644 --- a/pkg/apis/dnsalias/ingress.go +++ b/pkg/apis/dnsalias/ingress.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -21,7 +22,7 @@ func CreateRadixDNSAliasIngress(kubeClient kubernetes.Interface, appName, envNam } // BuildRadixDNSAliasIngress Build an Ingress for a RadixDNSAlias -func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, owner *v1.RadixDNSAlias, config *DNSConfig) *networkingv1.Ingress { +func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, owner *v1.RadixDNSAlias, config *dnsalias.DNSConfig) *networkingv1.Ingress { pathTypeImplementationSpecific := networkingv1.PathTypeImplementationSpecific ingressName := GetDNSAliasIngressName(service, domain) host := GetDNSAliasHost(domain, config.DNSZone) diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 618b72ecc..603b13897 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -3,6 +3,7 @@ package dnsalias import ( "fmt" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -24,11 +25,11 @@ type syncer struct { radixClient radixclient.Interface kubeUtil *kube.Kube radixDNSAlias *radixv1.RadixDNSAlias - dnsConfig *DNSConfig + dnsConfig *dnsalias.DNSConfig } // NewSyncer is the constructor for RadixDNSAlias syncer -func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { +func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { return &syncer{ kubeClient: kubeClient, radixClient: radixClient, diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 4623c86ab..a86bde51b 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix" @@ -28,7 +29,7 @@ type syncerTestSuite struct { radixClient *radixfake.Clientset kubeUtil *kube.Kube promClient *prometheusfake.Clientset - dnsConfig *dnsalias.DNSConfig + dnsConfig *dnsalias2.DNSConfig } func TestSyncerTestSuite(t *testing.T) { @@ -39,7 +40,7 @@ func (s *syncerTestSuite) SetupTest() { s.kubeClient = kubefake.NewSimpleClientset() s.radixClient = radixfake.NewSimpleClientset() s.promClient = prometheusfake.NewSimpleClientset() - s.dnsConfig = &dnsalias.DNSConfig{DNSZone: "test.radix.equinor.com"} + s.dnsConfig = &dnsalias2.DNSConfig{DNSZone: "test.radix.equinor.com"} s.kubeUtil, _ = kube.New(s.kubeClient, s.radixClient, secretproviderfake.NewSimpleClientset()) } @@ -192,7 +193,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Domain, UID: uuid.NewUUID()}, Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component, Port: ts.dnsAlias.Port}} s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Domain, radixDNSAlias.Spec), "create existing alias") - cfg := &dnsalias.DNSConfig{DNSZone: ts.dnsZone} + cfg := &dnsalias2.DNSConfig{DNSZone: ts.dnsZone} s.Require().NoError(registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1, cfg), "create existing ingresses") syncer := s.createSyncer(radixDNSAlias) err := syncer.OnSync() @@ -239,7 +240,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { } } -func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses map[string]testIngress, appNameForNamespace, envNameForNamespace string, config *dnsalias.DNSConfig) error { +func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses map[string]testIngress, appNameForNamespace, envNameForNamespace string, config *dnsalias2.DNSConfig) error { for name, ing := range testIngresses { ingress := dnsalias.BuildRadixDNSAliasIngress(ing.appName, ing.domain, ing.component, ing.port, nil, config) ingress.SetName(name) // override built name with expected name for test purpose diff --git a/pkg/apis/job/job.go b/pkg/apis/job/job.go index db24a33a1..19ef7f6f3 100644 --- a/pkg/apis/job/job.go +++ b/pkg/apis/job/job.go @@ -8,9 +8,7 @@ import ( "strings" "time" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/selection" - + apiconfig "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/metrics" "github.com/equinor/radix-operator/pkg/apis/pipeline" @@ -23,6 +21,8 @@ import ( corev1 "k8s.io/api/core/v1" k8sErrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" "k8s.io/client-go/kubernetes" "k8s.io/client-go/util/retry" ) @@ -34,11 +34,11 @@ type Job struct { kubeutil *kube.Kube radixJob *v1.RadixJob originalRadixJobCondition v1.RadixJobCondition - config *Config + config *apiconfig.Config } // NewJob Constructor -func NewJob(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, radixJob *v1.RadixJob, config *Config) Job { +func NewJob(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, radixJob *v1.RadixJob, config *apiconfig.Config) Job { originalRadixJobStatus := radixJob.Status.Condition return Job{ diff --git a/pkg/apis/job/job_history.go b/pkg/apis/job/job_history.go index e5f669e20..b0ce9284f 100644 --- a/pkg/apis/job/job_history.go +++ b/pkg/apis/job/job_history.go @@ -32,7 +32,7 @@ func (job *Job) maintainHistoryLimit() { return } deletingJobs, radixJobsForConditions := job.groupSortedRadixJobs(radixJobs, radixJobsWithRDs) - jobHistoryLimit := job.config.PipelineJobsHistoryLimit + jobHistoryLimit := job.config.PipelineJobConfig.PipelineJobsHistoryLimit log.Infof("Delete history RadixJob for limit %d", jobHistoryLimit) jobsByConditionAndBranch := job.getJobsToGarbageCollectByJobConditionAndBranch(radixJobsForConditions, jobHistoryLimit) @@ -47,7 +47,7 @@ func (job *Job) garbageCollectRadixJobs(radixJobs []v1.RadixJob) { } for _, rj := range radixJobs { if strings.EqualFold(rj.GetName(), job.radixJob.GetName()) { - continue //do not remove current job + continue // do not remove current job } log.Infof("- delete RadixJob %s from %s", rj.GetName(), rj.GetNamespace()) err := job.radixclient.RadixV1().RadixJobs(rj.GetNamespace()).Delete(context.TODO(), rj.GetName(), metav1.DeleteOptions{}) diff --git a/pkg/apis/job/job_test.go b/pkg/apis/job/job_test.go index b4cbb6c99..bdac376f2 100644 --- a/pkg/apis/job/job_test.go +++ b/pkg/apis/job/job_test.go @@ -9,6 +9,9 @@ import ( "time" "github.com/equinor/radix-common/utils/pointers" + "github.com/equinor/radix-operator/pkg/apis/config" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/config/pipelinejob" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -114,7 +117,7 @@ func (s *RadixJobTestSuiteBase) teardownTest() { os.Unsetenv(defaults.OperatorTenantIdEnvironmentVariable) } -func (s *RadixJobTestSuiteBase) applyJobWithSync(jobBuilder utils.JobBuilder, config *Config) (*radixv1.RadixJob, error) { +func (s *RadixJobTestSuiteBase) applyJobWithSync(jobBuilder utils.JobBuilder, config *config.Config) (*radixv1.RadixJob, error) { rj, err := s.testUtils.ApplyJob(jobBuilder) if err != nil { return nil, err @@ -128,7 +131,7 @@ func (s *RadixJobTestSuiteBase) applyJobWithSync(jobBuilder utils.JobBuilder, co return s.radixClient.RadixV1().RadixJobs(rj.GetNamespace()).Get(context.TODO(), rj.Name, metav1.GetOptions{}) } -func (s *RadixJobTestSuiteBase) runSync(rj *radixv1.RadixJob, config *Config) error { +func (s *RadixJobTestSuiteBase) runSync(rj *radixv1.RadixJob, config *config.Config) error { job := NewJob(s.kubeClient, s.kubeUtils, s.radixClient, rj, config) return job.OnSync() } @@ -847,7 +850,7 @@ func (s *RadixJobTestSuite) assertExistRadixJobsWithNames(radixJobList *radixv1. } } -func (s *RadixJobTestSuite) applyJobWithSyncFor(raBuilder utils.ApplicationBuilder, appName string, rdJob radixDeploymentJob, config *Config) error { +func (s *RadixJobTestSuite) applyJobWithSyncFor(raBuilder utils.ApplicationBuilder, appName string, rdJob radixDeploymentJob, config *config.Config) error { _, err := s.applyJobWithSync(utils.ARadixBuildDeployJob(). WithRadixApplication(raBuilder). WithAppName(appName). @@ -901,9 +904,14 @@ func (s *RadixJobTestSuite) assertStatusEqual(expectedStatus, actualStatus radix } func (s *RadixJobTestSuite) TestObjectSynced_UseBuildKid_HasResourcesArgs() { + dnsConfig := dnsalias.DNSConfig{ + DNSZone: "dev.radix.equinor.com", + DNSAliasAppReserved: map[string]string{"api": "radix-api"}, + DNSAliasReserved: []string{"grafana"}, + } scenarios := []struct { name string - config *Config + config *config.Config expectedAppBuilderResourcesRequestsCPU string expectedAppBuilderResourcesRequestsMemory string expectedAppBuilderResourcesLimitsMemory string @@ -911,12 +919,14 @@ func (s *RadixJobTestSuite) TestObjectSynced_UseBuildKid_HasResourcesArgs() { }{ { name: "Configured AppBuilderResources", - config: &Config{ - PipelineJobsHistoryLimit: 3, - AppBuilderResourcesRequestsCPU: pointers.Ptr(resource.MustParse("123m")), - AppBuilderResourcesRequestsMemory: pointers.Ptr(resource.MustParse("1234Mi")), - AppBuilderResourcesLimitsMemory: pointers.Ptr(resource.MustParse("2345Mi")), - }, + config: &config.Config{ + DNSConfig: &dnsConfig, + PipelineJobConfig: &pipelinejob.Config{ + PipelineJobsHistoryLimit: 3, + AppBuilderResourcesRequestsCPU: pointers.Ptr(resource.MustParse("123m")), + AppBuilderResourcesRequestsMemory: pointers.Ptr(resource.MustParse("1234Mi")), + AppBuilderResourcesLimitsMemory: pointers.Ptr(resource.MustParse("2345Mi")), + }}, expectedError: "", expectedAppBuilderResourcesRequestsCPU: "123m", expectedAppBuilderResourcesRequestsMemory: "1234Mi", @@ -924,26 +934,32 @@ func (s *RadixJobTestSuite) TestObjectSynced_UseBuildKid_HasResourcesArgs() { }, { name: "Missing config for ResourcesRequestsCPU", - config: &Config{ - AppBuilderResourcesRequestsMemory: pointers.Ptr(resource.MustParse("1234Mi")), - AppBuilderResourcesLimitsMemory: pointers.Ptr(resource.MustParse("2345Mi")), - }, + config: &config.Config{ + DNSConfig: &dnsConfig, + PipelineJobConfig: &pipelinejob.Config{ + AppBuilderResourcesRequestsMemory: pointers.Ptr(resource.MustParse("1234Mi")), + AppBuilderResourcesLimitsMemory: pointers.Ptr(resource.MustParse("2345Mi")), + }}, expectedError: "invalid or missing app builder resources", }, { name: "Missing config for ResourcesRequestsMemory", - config: &Config{ - AppBuilderResourcesRequestsCPU: pointers.Ptr(resource.MustParse("123m")), - AppBuilderResourcesLimitsMemory: pointers.Ptr(resource.MustParse("2345Mi")), - }, + config: &config.Config{ + DNSConfig: &dnsConfig, + PipelineJobConfig: &pipelinejob.Config{ + AppBuilderResourcesRequestsCPU: pointers.Ptr(resource.MustParse("123m")), + AppBuilderResourcesLimitsMemory: pointers.Ptr(resource.MustParse("2345Mi")), + }}, expectedError: "invalid or missing app builder resources", }, { name: "Missing config for ResourcesLimitsMemory", - config: &Config{ - AppBuilderResourcesRequestsCPU: pointers.Ptr(resource.MustParse("123m")), - AppBuilderResourcesRequestsMemory: pointers.Ptr(resource.MustParse("1234Mi")), - }, + config: &config.Config{ + DNSConfig: &dnsConfig, + PipelineJobConfig: &pipelinejob.Config{ + AppBuilderResourcesRequestsCPU: pointers.Ptr(resource.MustParse("123m")), + AppBuilderResourcesRequestsMemory: pointers.Ptr(resource.MustParse("1234Mi")), + }}, expectedError: "invalid or missing app builder resources", }, } @@ -986,11 +1002,17 @@ func getJobContainerArgument(container corev1.Container, variableName string) st return "" } -func getConfigWithPipelineJobsHistoryLimit(historyLimit int) *Config { - return &Config{ - PipelineJobsHistoryLimit: historyLimit, - AppBuilderResourcesRequestsCPU: pointers.Ptr(resource.MustParse("100m")), - AppBuilderResourcesRequestsMemory: pointers.Ptr(resource.MustParse("1000Mi")), - AppBuilderResourcesLimitsMemory: pointers.Ptr(resource.MustParse("2000Mi")), - } +func getConfigWithPipelineJobsHistoryLimit(historyLimit int) *config.Config { + return &config.Config{ + DNSConfig: &dnsalias.DNSConfig{ + DNSZone: "dev.radix.equinor.com", + DNSAliasAppReserved: map[string]string{"api": "radix-api"}, + DNSAliasReserved: []string{"grafana"}, + }, + PipelineJobConfig: &pipelinejob.Config{ + PipelineJobsHistoryLimit: historyLimit, + AppBuilderResourcesRequestsCPU: pointers.Ptr(resource.MustParse("100m")), + AppBuilderResourcesRequestsMemory: pointers.Ptr(resource.MustParse("1000Mi")), + AppBuilderResourcesLimitsMemory: pointers.Ptr(resource.MustParse("2000Mi")), + }} } diff --git a/pkg/apis/job/kubejob.go b/pkg/apis/job/kubejob.go index e82031033..d96ad50d1 100644 --- a/pkg/apis/job/kubejob.go +++ b/pkg/apis/job/kubejob.go @@ -137,9 +137,9 @@ func (job *Job) getPipelineJobArguments(appName, jobName string, jobSpec v1.Radi return nil, err } - if job.config.AppBuilderResourcesRequestsMemory == nil || job.config.AppBuilderResourcesRequestsMemory.IsZero() || - job.config.AppBuilderResourcesRequestsCPU == nil || job.config.AppBuilderResourcesRequestsCPU.IsZero() || - job.config.AppBuilderResourcesLimitsMemory == nil || job.config.AppBuilderResourcesLimitsMemory.IsZero() { + if job.config.PipelineJobConfig.AppBuilderResourcesRequestsMemory == nil || job.config.PipelineJobConfig.AppBuilderResourcesRequestsMemory.IsZero() || + job.config.PipelineJobConfig.AppBuilderResourcesRequestsCPU == nil || job.config.PipelineJobConfig.AppBuilderResourcesRequestsCPU.IsZero() || + job.config.PipelineJobConfig.AppBuilderResourcesLimitsMemory == nil || job.config.PipelineJobConfig.AppBuilderResourcesLimitsMemory.IsZero() { return nil, fmt.Errorf("invalid or missing app builder resources") } @@ -148,9 +148,9 @@ func (job *Job) getPipelineJobArguments(appName, jobName string, jobSpec v1.Radi fmt.Sprintf("--%s=%s", defaults.RadixAppEnvironmentVariable, appName), fmt.Sprintf("--%s=%s", defaults.RadixPipelineJobEnvironmentVariable, jobName), fmt.Sprintf("--%s=%s", defaults.RadixPipelineTypeEnvironmentVariable, pipeline.Type), - fmt.Sprintf("--%s=%s", defaults.OperatorAppBuilderResourcesRequestsMemoryEnvironmentVariable, job.config.AppBuilderResourcesRequestsMemory.String()), - fmt.Sprintf("--%s=%s", defaults.OperatorAppBuilderResourcesRequestsCPUEnvironmentVariable, job.config.AppBuilderResourcesRequestsCPU.String()), - fmt.Sprintf("--%s=%s", defaults.OperatorAppBuilderResourcesLimitsMemoryEnvironmentVariable, job.config.AppBuilderResourcesLimitsMemory.String()), + fmt.Sprintf("--%s=%s", defaults.OperatorAppBuilderResourcesRequestsMemoryEnvironmentVariable, job.config.PipelineJobConfig.AppBuilderResourcesRequestsMemory.String()), + fmt.Sprintf("--%s=%s", defaults.OperatorAppBuilderResourcesRequestsCPUEnvironmentVariable, job.config.PipelineJobConfig.AppBuilderResourcesRequestsCPU.String()), + fmt.Sprintf("--%s=%s", defaults.OperatorAppBuilderResourcesLimitsMemoryEnvironmentVariable, job.config.PipelineJobConfig.AppBuilderResourcesLimitsMemory.String()), // Pass tekton and builder images fmt.Sprintf("--%s=%s", defaults.RadixTektonPipelineImageEnvironmentVariable, os.Getenv(defaults.RadixTektonPipelineImageEnvironmentVariable)), diff --git a/radix-operator/config/config.go b/radix-operator/config/config.go index b5c8a11ba..a3b8556fb 100644 --- a/radix-operator/config/config.go +++ b/radix-operator/config/config.go @@ -5,13 +5,13 @@ import ( "strings" apiconfig "github.com/equinor/radix-operator/pkg/apis/config" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/config/pipelinejob" "github.com/equinor/radix-operator/pkg/apis/defaults" - "github.com/equinor/radix-operator/pkg/apis/dnsalias" - "github.com/equinor/radix-operator/pkg/apis/job" "github.com/spf13/viper" ) -var logLevels = map[string]bool{string(apiconfig.LogLevelInfo): true, string(apiconfig.LogLevelDebug): true, string(apiconfig.LogLevelError): true} +var logLevels = map[string]bool{string(apiconfig.LogLevelInfo): true, string(apiconfig.LogLevelWarning): true, string(apiconfig.LogLevelDebug): true, string(apiconfig.LogLevelError): true} func getLogLevel() apiconfig.LogLevel { logLevel := viper.GetString(defaults.LogLevel) @@ -74,7 +74,7 @@ func NewConfig() *apiconfig.Config { DNSAliasAppReserved: getDNSAliasAppReserved(), DNSAliasReserved: getDNSAliasReserved(), }, - PipelineJobConfig: &job.Config{ + PipelineJobConfig: &pipelinejob.Config{ PipelineJobsHistoryLimit: getPipelineJobsHistoryLimit(), DeploymentsHistoryLimitPerEnvironment: getDeploymentsHistoryLimitPerEnvironment(), AppBuilderResourcesLimitsMemory: defaults.GetResourcesLimitsMemoryForAppBuilderNamespace(), diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go index 56757c292..89d6262f3 100644 --- a/radix-operator/dnsalias/controller_test.go +++ b/radix-operator/dnsalias/controller_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/equinor/radix-common/utils/pointers" + dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/radix" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -84,7 +85,7 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { s.WaitForNotSynced("Sync should not be called when updating RadixDNSAlias with no changes") // Add Ingress with owner reference to RadixDNSAlias should not trigger sync - cfg := &dnsaliasapi.DNSConfig{DNSZone: dnsZone} + cfg := &dnsalias2.DNSConfig{DNSZone: dnsZone} ingress := dnsaliasapi.BuildRadixDNSAliasIngress(alias.Spec.AppName, alias.GetName(), alias.Spec.Component, int32(8080), alias, cfg) ingress.SetOwnerReferences([]metav1.OwnerReference{{APIVersion: radix.APIVersion, Kind: radix.KindRadixDNSAlias, Name: aliasName, Controller: pointers.Ptr(true)}}) namespace := utils.GetEnvironmentNamespace(alias.Spec.AppName, alias.Spec.Environment) diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go index b12623cc8..50080e5c9 100644 --- a/radix-operator/dnsalias/handler.go +++ b/radix-operator/dnsalias/handler.go @@ -3,6 +3,7 @@ package dnsalias import ( "fmt" + dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -31,7 +32,7 @@ type handler struct { radixClient radixclient.Interface syncerFactory internal.SyncerFactory hasSynced common.HasSynced - dnsConfig *dnsalias.DNSConfig + dnsConfig *dnsalias2.DNSConfig } // NewHandler creates a handler for managing RadixDNSAlias resources @@ -39,7 +40,7 @@ func NewHandler( kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, - dnsConfig *dnsalias.DNSConfig, + dnsConfig *dnsalias2.DNSConfig, hasSynced common.HasSynced, options ...HandlerConfigOption) common.Handler { h := &handler{ diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index f4739feee..c79501123 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" commonTest "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/radix-operator/common" @@ -41,7 +42,7 @@ func (s *handlerTestSuite) TearDownTest() { } func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { - dnsConfig := &dnsaliasapi.DNSConfig{DNSZone: "test.radix.equinor.com"} + dnsConfig := &dnsalias2.DNSConfig{DNSZone: "test.radix.equinor.com"} handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) @@ -53,7 +54,7 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { } func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { - dnsConfig := &dnsaliasapi.DNSConfig{DNSZone: "test.radix.equinor.com"} + dnsConfig := &dnsalias2.DNSConfig{DNSZone: "test.radix.equinor.com"} s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, domain1, 8080), "create existing RadixDNSAlias") handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) @@ -66,7 +67,7 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { } func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsNoError() { - dnsConfig := &dnsaliasapi.DNSConfig{DNSZone: "test.radix.equinor.com"} + dnsConfig := &dnsalias2.DNSConfig{DNSZone: "test.radix.equinor.com"} s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, domain1, 8080), "create existing RadixDNSAlias") handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) diff --git a/radix-operator/dnsalias/internal/syncerfactory.go b/radix-operator/dnsalias/internal/syncerfactory.go index 153e028f1..e04abc719 100644 --- a/radix-operator/dnsalias/internal/syncerfactory.go +++ b/radix-operator/dnsalias/internal/syncerfactory.go @@ -1,6 +1,7 @@ package internal import ( + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -10,7 +11,7 @@ import ( // SyncerFactory defines a factory to create a DNS alias Syncer type SyncerFactory interface { - CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsaliasapi.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer + CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer } // SyncerFactoryFunc is an adapter that can be used to convert @@ -19,11 +20,11 @@ type SyncerFactoryFunc func( kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, - dnsConfig *dnsaliasapi.DNSConfig, + dnsConfig *dnsalias.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias, ) dnsaliasapi.Syncer // CreateSyncer Create a DNS alias Syncer -func (f SyncerFactoryFunc) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsaliasapi.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer { +func (f SyncerFactoryFunc) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer { return f(kubeClient, kubeUtil, radixClient, dnsConfig, radixDNSAlias) } diff --git a/radix-operator/dnsalias/internal/syncerfactory_mock.go b/radix-operator/dnsalias/internal/syncerfactory_mock.go index 4adbc93d1..8bea9f74a 100644 --- a/radix-operator/dnsalias/internal/syncerfactory_mock.go +++ b/radix-operator/dnsalias/internal/syncerfactory_mock.go @@ -7,6 +7,7 @@ package internal import ( reflect "reflect" + dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" dnsalias "github.com/equinor/radix-operator/pkg/apis/dnsalias" kube "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -39,7 +40,7 @@ func (m *MockSyncerFactory) EXPECT() *MockSyncerFactoryMockRecorder { } // CreateSyncer mocks base method. -func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, dnsConfig *dnsalias.DNSConfig, radixDNSAlias *v1.RadixDNSAlias) dnsalias.Syncer { +func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, dnsConfig *dnsalias2.DNSConfig, radixDNSAlias *v1.RadixDNSAlias) dnsalias.Syncer { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateSyncer", kubeClient, kubeUtil, radixClient, dnsConfig, radixDNSAlias) ret0, _ := ret[0].(dnsalias.Syncer) diff --git a/radix-operator/job/controller_test.go b/radix-operator/job/controller_test.go index 4a530db70..f5aeed806 100644 --- a/radix-operator/job/controller_test.go +++ b/radix-operator/job/controller_test.go @@ -6,6 +6,9 @@ import ( "testing" "github.com/equinor/radix-common/utils/pointers" + "github.com/equinor/radix-operator/pkg/apis/config" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/config/pipelinejob" "github.com/equinor/radix-operator/pkg/apis/defaults" jobs "github.com/equinor/radix-operator/pkg/apis/job" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -68,18 +71,25 @@ func (s *jobTestSuite) Test_Controller_Calls_Handler() { kubeInformerFactory := kubeinformers.NewSharedInformerFactory(s.kubeUtil.KubeClient(), 0) radixInformerFactory := informers.NewSharedInformerFactory(s.kubeUtil.RadixClient(), 0) - pipelineJobConfig := &jobs.Config{ - PipelineJobsHistoryLimit: 3, - AppBuilderResourcesRequestsCPU: pointers.Ptr(resource.MustParse("100m")), - AppBuilderResourcesRequestsMemory: pointers.Ptr(resource.MustParse("1000Mi")), - AppBuilderResourcesLimitsMemory: pointers.Ptr(resource.MustParse("2000Mi")), + cfg := &config.Config{ + DNSConfig: &dnsalias.DNSConfig{ + DNSZone: "dev.radix.equinor.com", + DNSAliasAppReserved: map[string]string{"api": "radix-api"}, + DNSAliasReserved: []string{"grafana"}, + }, + PipelineJobConfig: &pipelinejob.Config{ + PipelineJobsHistoryLimit: 3, + AppBuilderResourcesRequestsCPU: pointers.Ptr(resource.MustParse("100m")), + AppBuilderResourcesRequestsMemory: pointers.Ptr(resource.MustParse("1000Mi")), + AppBuilderResourcesLimitsMemory: pointers.Ptr(resource.MustParse("2000Mi")), + }, } jobHandler := NewHandler( s.kubeUtil.KubeClient(), s.kubeUtil, s.kubeUtil.RadixClient(), - pipelineJobConfig, + cfg, func(syncedOk bool) { synced <- syncedOk }, diff --git a/radix-operator/job/handler.go b/radix-operator/job/handler.go index 7c19cdd31..293791860 100644 --- a/radix-operator/job/handler.go +++ b/radix-operator/job/handler.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + apiconfig "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/job" "github.com/equinor/radix-operator/pkg/apis/kube" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -31,11 +32,11 @@ type Handler struct { radixclient radixclient.Interface kubeutil *kube.Kube hasSynced common.HasSynced - config *job.Config + config *apiconfig.Config } // NewHandler Constructor -func NewHandler(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, config *job.Config, hasSynced common.HasSynced) Handler { +func NewHandler(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, config *apiconfig.Config, hasSynced common.HasSynced) Handler { handler := Handler{ kubeclient: kubeclient, diff --git a/radix-operator/main.go b/radix-operator/main.go index 927af0cc5..15c7599ad 100644 --- a/radix-operator/main.go +++ b/radix-operator/main.go @@ -12,10 +12,9 @@ import ( errorUtils "github.com/equinor/radix-common/utils/errors" apiconfig "github.com/equinor/radix-operator/pkg/apis/config" + dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" deploymentAPI "github.com/equinor/radix-operator/pkg/apis/deployment" - dnsalias2 "github.com/equinor/radix-operator/pkg/apis/dnsalias" - jobUtil "github.com/equinor/radix-operator/pkg/apis/job" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -79,7 +78,7 @@ func main() { startController(createApplicationController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), applicationControllerThreads, stop) startController(createEnvironmentController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), environmentControllerThreads, stop) startController(createDeploymentController(client, radixClient, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), deploymentControllerThreads, stop) - startController(createJobController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg.PipelineJobConfig), jobControllerThreads, stop) + startController(createJobController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg), jobControllerThreads, stop) startController(createAlertController(client, radixClient, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), alertControllerThreads, stop) startController(createBatchController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), 1, stop) startController(createDNSAliasesController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg.DNSConfig), environmentControllerThreads, stop) @@ -269,7 +268,7 @@ func createDeploymentController(client kubernetes.Interface, radixClient radixcl recorder) } -func createJobController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, config *jobUtil.Config) *common.Controller { +func createJobController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, config *apiconfig.Config) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, @@ -393,6 +392,8 @@ func setLogLevel(logLevel apiconfig.LogLevel) { switch logLevel { case apiconfig.LogLevelDebug: log.SetLevel(log.DebugLevel) + case apiconfig.LogLevelWarning: + log.SetLevel(log.WarnLevel) case apiconfig.LogLevelError: log.SetLevel(log.ErrorLevel) default: From eacdb936093593d43680758da31122a61215f8c6 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 9 Nov 2023 15:53:18 +0100 Subject: [PATCH 045/121] Added reserved dns aliases validation to pipeline jobs --- charts/radix-operator/templates/_helpers.tpl | 13 +++-- .../radix-operator/templates/deployment.yaml | 8 +-- charts/radix-operator/values.yaml | 4 +- pipeline-runner/main.go | 11 ++-- pipeline-runner/model/pipelineInfo.go | 17 +++--- pipeline-runner/model/pipelineInfo_test.go | 27 +++++++-- pipeline-runner/pipelines/app_test.go | 11 +++- pipeline-runner/steps/apply_radixconfig.go | 10 ++-- pipeline-runner/steps/build_test.go | 56 +++++++++++++------ pipeline-runner/steps/deploy_test.go | 33 ++++++----- pipeline-runner/steps/promotion_test.go | 22 +++++--- .../applicationconfig/applicationconfig.go | 33 ++++++----- .../applicationconfig_test.go | 19 +++++-- pkg/apis/applicationconfig/dns_alias_test.go | 11 ++-- pkg/apis/config/dnsalias/config.go | 11 ++-- pkg/apis/defaults/environment_variables.go | 8 +-- pkg/apis/dnsalias/syncer_test.go | 4 +- pkg/apis/job/job_test.go | 22 ++++++-- pkg/apis/job/kubejob.go | 6 ++ pkg/apis/radixvalidators/validate_ra.go | 15 ++--- pkg/apis/radixvalidators/validate_ra_test.go | 33 +++++++---- radix-operator/application/handler.go | 11 ++-- radix-operator/config/config.go | 10 ++-- radix-operator/dnsalias/controller_test.go | 2 +- radix-operator/dnsalias/handler_test.go | 6 +- radix-operator/job/controller_test.go | 6 +- radix-operator/main.go | 9 +-- 27 files changed, 259 insertions(+), 159 deletions(-) diff --git a/charts/radix-operator/templates/_helpers.tpl b/charts/radix-operator/templates/_helpers.tpl index 2d70af796..1923b748d 100644 --- a/charts/radix-operator/templates/_helpers.tpl +++ b/charts/radix-operator/templates/_helpers.tpl @@ -58,17 +58,18 @@ Create the name of the service account to use {{- end }} {{/* -Utility function to take list to comma separated string +Utility function to take list to comma separated dictionary */}} -{{- define "helm-toolkit.utils.joinListWithComma" -}} +{{- define "helm-toolkit.utils.joinMapWithComma" -}} {{- $local := dict "first" true -}} -{{- range $k, $v := . -}}{{- if not $local.first -}},{{- end -}}{{- $v -}}{{- $_ := set $local "first" false -}}{{- end -}} +{{- range $k, $v := . -}}{{- if not $local.first -}},{{- end -}}{{ $k }}={{ $v }}{{- $_ := set $local "first" false -}}{{- end -}} {{- end -}} {{/* -Utility function to take list to comma separated dictionary +Utility function to take list to comma separated string */}} -{{- define "helm-toolkit.utils.joinMapWithComma" -}} +{{- define "helm-toolkit.utils.joinListWithComma" -}} {{- $local := dict "first" true -}} -{{- range $k, $v := . -}}{{- if not $local.first -}},{{- end -}}{{ $k }}={{ $v }}{{- $_ := set $local "first" false -}}{{- end -}} +{{- range $k, $v := . -}}{{- if not $local.first -}},{{- end -}}{{- $v -}}{{- $_ := set $local "first" false -}}{{- end -}} {{- end -}} + diff --git a/charts/radix-operator/templates/deployment.yaml b/charts/radix-operator/templates/deployment.yaml index c441d4c36..761ca2372 100644 --- a/charts/radix-operator/templates/deployment.yaml +++ b/charts/radix-operator/templates/deployment.yaml @@ -158,10 +158,10 @@ spec: value: {{ .Values.seccompProfile.fileNameOnNode }} - name: RADIX_BUILDAH_IMAGE_BUILDER value: {{ .Values.buildahImageBuilder }} - - name: RADIX_DNS_ALIAS_APP_RESERVED - value: {{ include "helm-toolkit.utils.joinMapWithComma" .Values.dnsAliasAppReserved | quote }} - - name: RADIX_DNS_ALIAS_RESERVED - value: {{ include "helm-toolkit.utils.joinListWithComma" .Values.dnsAliasReserved | quote }} + - name: RADIX_RESERVED_APP_DNS_ALIASES + value: {{ include "helm-toolkit.utils.joinMapWithComma" .Values.reservedAppDNSAlias | quote }} + - name: RADIX_RESERVED_DNS_ALIASES + value: {{ include "helm-toolkit.utils.joinListWithComma" .Values.reservedDNSAlias | quote }} livenessProbe: httpGet: path: /healthz diff --git a/charts/radix-operator/values.yaml b/charts/radix-operator/values.yaml index 85364c62e..a16993cf6 100644 --- a/charts/radix-operator/values.yaml +++ b/charts/radix-operator/values.yaml @@ -20,13 +20,13 @@ buildahImageBuilder: xx jobScheduler: radix-job-scheduler:main-latest radixTekton: radix-tekton:main-latest useImageBuilderCache: 0 -dnsAliasAppReserved: +reservedAppDNSAlias: api: radix-api canary: radix-canary-golang console: radix-web-console cost-api: radix-cost-allocation-api webhook: radix-github-webhook -dnsAliasReserved: +reservedDNSAlias: - grafana - prometheus diff --git a/pipeline-runner/main.go b/pipeline-runner/main.go index 539154e35..a2f847972 100755 --- a/pipeline-runner/main.go +++ b/pipeline-runner/main.go @@ -7,6 +7,7 @@ import ( "github.com/equinor/radix-operator/pipeline-runner/model" pipe "github.com/equinor/radix-operator/pipeline-runner/pipelines" + dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/pipeline" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -23,7 +24,7 @@ import ( // - a secret radix-snyk-service-account with access token to SNYK service account func main() { - pipelineArgs := &model.PipelineArguments{} + pipelineArgs := &model.PipelineArguments{DNSConfig: &dnsaliasconfig.DNSConfig{ReservedAppDNSAliases: make(map[string]string)}} cmd := &cobra.Command{ Use: "run", @@ -113,17 +114,17 @@ func setPipelineArgsFromArguments(cmd *cobra.Command, pipelineArgs *model.Pipeli var debug string cmd.Flags().StringVar(&debug, "DEBUG", "false", "Debug information") cmd.Flags().StringToStringVar(&pipelineArgs.ImageTagNames, defaults.RadixImageTagNameEnvironmentVariable, make(map[string]string), "Image tag names for components (optional)") - cmd.Flags().StringToStringVar(&pipelineArgs.DNSAliasAppReserved, defaults.RadixDNSAliasAppReservedEnvironmentVariable, make(map[string]string), "The list of DNS aliases, reserved for Radix platform Radix application") - cmd.Flags().StringArrayVar(&pipelineArgs.DNSAliasReserved, defaults.RadixDNSAliasReservedEnvironmentVariable, make([]string, 0), "he list of DNS aliases, reserved for Radix platform services") + cmd.Flags().StringToStringVar(&pipelineArgs.DNSConfig.ReservedAppDNSAliases, defaults.RadixReservedAppDNSAliasesEnvironmentVariable, make(map[string]string), "The list of DNS aliases, reserved for Radix platform Radix application") + cmd.Flags().StringArrayVar(&pipelineArgs.DNSConfig.ReservedDNSAlias, defaults.RadixReservedDNSAliasesEnvironmentVariable, make([]string, 0), "The list of DNS aliases, reserved for Radix platform services") err := cmd.Flags().Parse(arguments) if err != nil { return fmt.Errorf("failed to parse command arguments. Error: %v", err) } - if pipelineArgs.DNSAliasAppReserved == nil || len(pipelineArgs.DNSAliasAppReserved) == 0 { + if len(pipelineArgs.DNSConfig.ReservedAppDNSAliases) == 0 { return fmt.Errorf("missing DNS aliases, reserved for Radix platform Radix application") } - if len(pipelineArgs.DNSAliasReserved) == 0 { + if len(pipelineArgs.DNSConfig.ReservedDNSAlias) == 0 { return fmt.Errorf("missing DNS aliases, reserved for Radix platform services") } pipelineArgs.PushImage, _ = strconv.ParseBool(pushImage) diff --git a/pipeline-runner/model/pipelineInfo.go b/pipeline-runner/model/pipelineInfo.go index 4fdf6ca6b..5c952bb7d 100644 --- a/pipeline-runner/model/pipelineInfo.go +++ b/pipeline-runner/model/pipelineInfo.go @@ -6,14 +6,14 @@ import ( "time" "github.com/equinor/radix-common/utils/slice" - "github.com/equinor/radix-operator/pkg/apis/defaults" - "github.com/equinor/radix-operator/pkg/apis/utils/conditions" - application "github.com/equinor/radix-operator/pkg/apis/applicationconfig" + dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/pipeline" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/securitycontext" "github.com/equinor/radix-operator/pkg/apis/utils" + "github.com/equinor/radix-operator/pkg/apis/utils/conditions" corev1 "k8s.io/api/core/v1" ) @@ -102,12 +102,11 @@ type PipelineArguments struct { // Used to indicate debugging session Debug bool // Image tag names for components: component-name:image-tag - ImageTagNames map[string]string - LogLevel string - AppName string - Builder Builder - DNSAliasAppReserved map[string]string - DNSAliasReserved []string + ImageTagNames map[string]string + LogLevel string + AppName string + Builder Builder + DNSConfig *dnsaliasconfig.DNSConfig } // InitPipeline Initialize pipeline with step implementations diff --git a/pipeline-runner/model/pipelineInfo_test.go b/pipeline-runner/model/pipelineInfo_test.go index 004e994bc..f017a4c20 100644 --- a/pipeline-runner/model/pipelineInfo_test.go +++ b/pipeline-runner/model/pipelineInfo_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/equinor/radix-operator/pipeline-runner/model" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/pipeline" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/stretchr/testify/assert" @@ -21,7 +22,7 @@ var ( func Test_DefaultPipeType(t *testing.T) { pipelineType, _ := pipeline.GetPipelineFromName("") - p, _ := model.InitPipeline(pipelineType, &model.PipelineArguments{}, prepareTektonPipelineStep, applyConfigStep, buildStep, runTektonPipelineStep, deployStep) + p, _ := model.InitPipeline(pipelineType, getPipelineArguments(), prepareTektonPipelineStep, applyConfigStep, buildStep, runTektonPipelineStep, deployStep) assert.Equal(t, v1.BuildDeploy, p.Definition.Type) assert.Equal(t, 5, len(p.Steps)) @@ -34,7 +35,7 @@ func Test_DefaultPipeType(t *testing.T) { func Test_BuildDeployPipeType(t *testing.T) { pipelineType, _ := pipeline.GetPipelineFromName(string(v1.BuildDeploy)) - p, _ := model.InitPipeline(pipelineType, &model.PipelineArguments{}, prepareTektonPipelineStep, applyConfigStep, buildStep, runTektonPipelineStep, deployStep) + p, _ := model.InitPipeline(pipelineType, getPipelineArguments(), prepareTektonPipelineStep, applyConfigStep, buildStep, runTektonPipelineStep, deployStep) assert.Equal(t, v1.BuildDeploy, p.Definition.Type) assert.Equal(t, 5, len(p.Steps)) @@ -48,7 +49,7 @@ func Test_BuildDeployPipeType(t *testing.T) { func Test_BuildAndDefaultNoPushOnlyPipeline(t *testing.T) { pipelineType, _ := pipeline.GetPipelineFromName(string(v1.Build)) - p, _ := model.InitPipeline(pipelineType, &model.PipelineArguments{}, prepareTektonPipelineStep, applyConfigStep, buildStep, runTektonPipelineStep, deployStep) + p, _ := model.InitPipeline(pipelineType, getPipelineArguments(), prepareTektonPipelineStep, applyConfigStep, buildStep, runTektonPipelineStep, deployStep) assert.Equal(t, v1.Build, p.Definition.Type) assert.False(t, p.PipelineArguments.PushImage) assert.Equal(t, 4, len(p.Steps)) @@ -73,6 +74,7 @@ func Test_GetImageTagNamesFromArgs(t *testing.T) { pipelineArguments: model.PipelineArguments{ ToEnvironment: "env1", ImageTagNames: map[string]string{}, + DNSConfig: getDNSAliasConfig(), }, expectedToEnvironment: "env1", expectedImageTagNames: map[string]string{}, @@ -82,6 +84,7 @@ func Test_GetImageTagNamesFromArgs(t *testing.T) { pipelineArguments: model.PipelineArguments{ ToEnvironment: "env1", ImageTagNames: map[string]string{"component1": "tag1", "component2": "tag22"}, + DNSConfig: getDNSAliasConfig(), }, expectedToEnvironment: "env1", expectedImageTagNames: map[string]string{"component1": "tag1", "component2": "tag22"}, @@ -104,6 +107,7 @@ func Test_BuildOnlyPipeline(t *testing.T) { pipelineArgs := &model.PipelineArguments{ PushImage: false, + DNSConfig: getDNSAliasConfig(), } p, _ := model.InitPipeline(pipelineType, pipelineArgs, prepareTektonPipelineStep, applyConfigStep, buildStep, runTektonPipelineStep, deployStep) @@ -121,6 +125,7 @@ func Test_BuildAndPushOnlyPipeline(t *testing.T) { pipelineArgs := &model.PipelineArguments{ PushImage: true, + DNSConfig: getDNSAliasConfig(), } p, _ := model.InitPipeline(pipelineType, pipelineArgs, prepareTektonPipelineStep, applyConfigStep, buildStep, runTektonPipelineStep, deployStep) @@ -146,12 +151,12 @@ func Test_DeployOnlyPipeline(t *testing.T) { scenarios := []scenario{ { name: "only target environment", - pipelineArguments: model.PipelineArguments{ToEnvironment: "target"}, + pipelineArguments: model.PipelineArguments{ToEnvironment: "target", DNSConfig: getDNSAliasConfig()}, expectedToEnvironment: "target", }, { name: "target environment with image tags", - pipelineArguments: model.PipelineArguments{ToEnvironment: "target", ImageTagNames: map[string]string{"component1": "tag1", "component2": "tag22"}}, + pipelineArguments: model.PipelineArguments{ToEnvironment: "target", ImageTagNames: map[string]string{"component1": "tag1", "component2": "tag22"}, DNSConfig: getDNSAliasConfig()}, expectedToEnvironment: "target", expectedImageTagNames: map[string]string{"component1": "tag1", "component2": "tag22"}, }, @@ -177,3 +182,15 @@ func Test_NonExistingPipelineType(t *testing.T) { _, err := pipeline.GetPipelineFromName("non existing pipeline") assert.NotNil(t, err) } + +func getPipelineArguments() *model.PipelineArguments { + return &model.PipelineArguments{DNSConfig: getDNSAliasConfig()} +} + +func getDNSAliasConfig() *dnsalias.DNSConfig { + return &dnsalias.DNSConfig{ + DNSZone: "dev.radix.equinor.com", + ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, + ReservedDNSAlias: []string{"grafana"}, + } +} diff --git a/pipeline-runner/pipelines/app_test.go b/pipeline-runner/pipelines/app_test.go index 4792cce94..e1b1ed66c 100644 --- a/pipeline-runner/pipelines/app_test.go +++ b/pipeline-runner/pipelines/app_test.go @@ -5,6 +5,7 @@ import ( "github.com/equinor/radix-operator/pipeline-runner/model" "github.com/equinor/radix-operator/pipeline-runner/pipelines" + dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/pipeline" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" commonTest "github.com/equinor/radix-operator/pkg/apis/test" @@ -30,6 +31,14 @@ func TestPrepare_NoRegistration_NotValid(t *testing.T) { pipelineDefinition, _ := pipeline.GetPipelineFromName(string(v1.BuildDeploy)) cli := pipelines.NewRunner(kubeclient, radixclient, &monitoring.Clientset{}, secretproviderclient, pipelineDefinition, "any-app") - err := cli.PrepareRun(&model.PipelineArguments{}) + err := cli.PrepareRun(&model.PipelineArguments{DNSConfig: getDNSAliasConfig()}) assert.Error(t, err) } + +func getDNSAliasConfig() *dnsaliasconfig.DNSConfig { + return &dnsaliasconfig.DNSConfig{ + DNSZone: "dev.radix.equinor.com", + ReservedAppDNSAliases: dnsaliasconfig.AppReservedDNSAlias{"api": "radix-api"}, + ReservedDNSAlias: []string{"grafana"}, + } +} diff --git a/pipeline-runner/steps/apply_radixconfig.go b/pipeline-runner/steps/apply_radixconfig.go index 84baecd7f..19ba40feb 100644 --- a/pipeline-runner/steps/apply_radixconfig.go +++ b/pipeline-runner/steps/apply_radixconfig.go @@ -13,6 +13,7 @@ import ( "github.com/equinor/radix-operator/pipeline-runner/model" pipelineDefaults "github.com/equinor/radix-operator/pipeline-runner/model/defaults" application "github.com/equinor/radix-operator/pkg/apis/applicationconfig" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/pipeline" @@ -81,7 +82,7 @@ func (cli *ApplyConfigStepImplementation) Run(pipelineInfo *model.PipelineInfo) if !ok { return fmt.Errorf("failed load RadixApplication from ConfigMap") } - ra, err := CreateRadixApplication(cli.GetRadixclient(), configFileContent) + ra, err := CreateRadixApplication(cli.GetRadixclient(), pipelineInfo.PipelineArguments.DNSConfig, configFileContent) if err != nil { return err } @@ -89,7 +90,7 @@ func (cli *ApplyConfigStepImplementation) Run(pipelineInfo *model.PipelineInfo) // Apply RA to cluster applicationConfig := application.NewApplicationConfig(cli.GetKubeclient(), cli.GetKubeutil(), cli.GetRadixclient(), cli.GetRegistration(), ra, - pipelineInfo.PipelineArguments.DNSAliasAppReserved, pipelineInfo.PipelineArguments.DNSAliasReserved) + pipelineInfo.PipelineArguments.DNSConfig) err = applicationConfig.ApplyConfigToApplicationNamespace() if err != nil { @@ -515,8 +516,7 @@ func (cli *ApplyConfigStepImplementation) getHashAndTags(namespace string, pipel } // CreateRadixApplication Create RadixApplication from radixconfig.yaml content -func CreateRadixApplication(radixClient radixclient.Interface, - configFileContent string) (*radixv1.RadixApplication, error) { +func CreateRadixApplication(radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, configFileContent string) (*radixv1.RadixApplication, error) { ra := &radixv1.RadixApplication{} // Important: Must use sigs.k8s.io/yaml decoder to correctly unmarshal Kubernetes objects. @@ -537,7 +537,7 @@ func CreateRadixApplication(radixClient radixclient.Interface, ra.Name = strings.ToLower(ra.Name) } - err = validate.CanRadixApplicationBeInserted(radixClient, ra, nil, nil) + err = validate.CanRadixApplicationBeInserted(radixClient, ra, dnsConfig) if err != nil { log.Errorf("Radix config not valid.") return nil, err diff --git a/pipeline-runner/steps/build_test.go b/pipeline-runner/steps/build_test.go index f2bf43fa3..e76fee6fc 100644 --- a/pipeline-runner/steps/build_test.go +++ b/pipeline-runner/steps/build_test.go @@ -15,6 +15,7 @@ import ( pipelineDefaults "github.com/equinor/radix-operator/pipeline-runner/model/defaults" "github.com/equinor/radix-operator/pipeline-runner/steps" application "github.com/equinor/radix-operator/pkg/apis/applicationconfig" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -85,15 +86,16 @@ func (s *buildTestSuite) Test_BranchIsNotMapped_ShouldSkip() { cli := steps.NewBuildStep(jobWaiter) cli.Init(s.kubeClient, s.radixClient, s.kubeUtil, s.promClient, rr) - applicationConfig := application.NewApplicationConfig(s.kubeClient, s.kubeUtil, s.radixClient, rr, ra, nil, nil) + applicationConfig := application.NewApplicationConfig(s.kubeClient, s.kubeUtil, s.radixClient, rr, ra, getDNSAliasConfig()) targetEnvs := applicationConfig.GetTargetEnvironments(anyNoMappedBranch) pipelineInfo := &model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - JobName: anyJobName, - ImageTag: anyImageTag, - Branch: anyNoMappedBranch, - CommitID: anyCommitID, + JobName: anyJobName, + ImageTag: anyImageTag, + Branch: anyNoMappedBranch, + CommitID: anyCommitID, + DNSConfig: getDNSAliasConfig(), }, TargetEnvironments: targetEnvs, } @@ -105,6 +107,14 @@ func (s *buildTestSuite) Test_BranchIsNotMapped_ShouldSkip() { s.Empty(radixJobList.Items) } +func getDNSAliasConfig() *dnsalias.DNSConfig { + return &dnsalias.DNSConfig{ + DNSZone: "dev.radix.equinor.com", + ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, + ReservedDNSAlias: []string{"grafana"}, + } +} + func (s *buildTestSuite) Test_BuildDeploy_JobSpecAndDeploymentConsistent() { appName, envName, rjName, compName, cloneURL, buildBranch := "anyapp", "dev", "anyrj", "c1", "git@github.com:anyorg/anyrepo", "anybranch" prepareConfigMapName := "preparecm" @@ -136,6 +146,7 @@ func (s *buildTestSuite) Test_BuildDeploy_JobSpecAndDeploymentConsistent() { RadixZone: "radixzone", Clustername: "clustername", SubscriptionId: "subscriptionid", + DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, GitConfigMapName: gitConfigMapName, @@ -269,6 +280,7 @@ func (s *buildTestSuite) Test_BuildJobSpec_MultipleComponents() { ContainerRegistry: "registry", Clustertype: "clustertype", Clustername: "clustername", + DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -408,6 +420,7 @@ func (s *buildTestSuite) Test_BuildJobSpec_MultipleComponents_IgnoreDisabled() { ContainerRegistry: "registry", Clustertype: "clustertype", Clustername: "clustername", + DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -552,12 +565,13 @@ func (s *buildTestSuite) Test_BuildChangedComponents() { pipeline := model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ PipelineType: "build-deploy", - Branch: buildBranch, JobName: rjName, + Branch: buildBranch, ImageTag: "imgtag", - ContainerRegistry: "registry", Clustertype: "clustertype", Clustername: "clustername", + ContainerRegistry: "registry", + DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -676,6 +690,7 @@ func (s *buildTestSuite) Test_DetectComponentsToBuild() { ContainerRegistry: "registry", Clustertype: "clustertype", Clustername: "clustername", + DNSConfig: getDNSAliasConfig(), } imageNameFunc := func(s string) string { return fmt.Sprintf("%s/%s-%s:%s", piplineArgs.ContainerRegistry, appName, s, piplineArgs.ImageTag) @@ -1104,6 +1119,7 @@ func (s *buildTestSuite) Test_BuildJobSpec_ImageTagNames() { ToEnvironment: envName, JobName: rjName, ImageTagNames: map[string]string{"comp1": "comp1customtag", "job1": "job1customtag"}, + DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -1160,6 +1176,7 @@ func (s *buildTestSuite) Test_BuildJobSpec_PushImage() { Branch: "main", JobName: rjName, PushImage: true, + DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -1197,9 +1214,10 @@ func (s *buildTestSuite) Test_BuildJobSpec_UseCache() { s.Require().NoError(s.createPreparePipelineConfigMapResponse(prepareConfigMapName, appName, ra, nil)) pipeline := model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - Branch: "main", - JobName: rjName, - UseCache: true, + Branch: "main", + JobName: rjName, + UseCache: true, + DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -1237,8 +1255,9 @@ func (s *buildTestSuite) Test_BuildJobSpec_WithDockerfileName() { s.Require().NoError(s.createPreparePipelineConfigMapResponse(prepareConfigMapName, appName, ra, nil)) pipeline := model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - Branch: "main", - JobName: rjName, + Branch: "main", + JobName: rjName, + DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -1276,8 +1295,9 @@ func (s *buildTestSuite) Test_BuildJobSpec_WithSourceFolder() { s.Require().NoError(s.createPreparePipelineConfigMapResponse(prepareConfigMapName, appName, ra, nil)) pipeline := model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - Branch: "main", - JobName: rjName, + Branch: "main", + JobName: rjName, + DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -1317,8 +1337,9 @@ func (s *buildTestSuite) Test_BuildJobSpec_WithBuildSecrets() { s.Require().NoError(s.createBuildSecret(appName, map[string][]byte{"SECRET1": nil, "SECRET2": nil})) pipeline := model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - Branch: "main", - JobName: rjName, + Branch: "main", + JobName: rjName, + DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -1380,6 +1401,7 @@ func (s *buildTestSuite) Test_BuildJobSpec_BuildKit() { Clustertype: "anyclustertype", Clustername: "anyclustername", Builder: model.Builder{ResourcesLimitsMemory: "100M", ResourcesRequestsCPU: "50m", ResourcesRequestsMemory: "50M"}, + DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -1444,6 +1466,7 @@ func (s *buildTestSuite) Test_BuildJobSpec_BuildKit_PushImage() { Clustername: "anyclustername", PushImage: true, Builder: model.Builder{ResourcesLimitsMemory: "100M", ResourcesRequestsCPU: "50m", ResourcesRequestsMemory: "50M"}, + DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -1514,6 +1537,7 @@ func (s *buildTestSuite) Test_BuildJobSpec_BuildKit_WithBuildSecrets() { Clustertype: "anyclustertype", Clustername: "anyclustername", Builder: model.Builder{ResourcesLimitsMemory: "100M", ResourcesRequestsCPU: "50m", ResourcesRequestsMemory: "50M"}, + DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } diff --git a/pipeline-runner/steps/deploy_test.go b/pipeline-runner/steps/deploy_test.go index 0d45d7bde..2a7c9ee69 100644 --- a/pipeline-runner/steps/deploy_test.go +++ b/pipeline-runner/steps/deploy_test.go @@ -75,15 +75,16 @@ func TestDeploy_BranchIsNotMapped_ShouldSkip(t *testing.T) { cli := steps.NewDeployStep(FakeNamespaceWatcher{}) cli.Init(kubeclient, radixclient, kubeUtil, &monitoring.Clientset{}, rr) - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) targetEnvs := applicationConfig.GetTargetEnvironments(anyNoMappedBranch) pipelineInfo := &model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - JobName: anyJobName, - ImageTag: anyImageTag, - Branch: anyNoMappedBranch, - CommitID: anyCommitID, + JobName: anyJobName, + ImageTag: anyImageTag, + Branch: anyNoMappedBranch, + CommitID: anyCommitID, + DNSConfig: getDNSAliasConfig(), }, TargetEnvironments: targetEnvs, } @@ -180,15 +181,16 @@ func TestDeploy_PromotionSetup_ShouldCreateNamespacesForAllBranchesIfNotExists(t cli := steps.NewDeployStep(FakeNamespaceWatcher{}) cli.Init(kubeclient, radixclient, kubeUtil, &monitoring.Clientset{}, rr) - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) targetEnvs := applicationConfig.GetTargetEnvironments("master") pipelineInfo := &model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - JobName: anyJobName, - ImageTag: anyImageTag, - Branch: "master", - CommitID: anyCommitID, + JobName: anyJobName, + ImageTag: anyImageTag, + Branch: "master", + CommitID: anyCommitID, + DNSConfig: getDNSAliasConfig(), }, TargetEnvironments: targetEnvs, GitCommitHash: anyCommitID, @@ -295,16 +297,17 @@ func TestDeploy_SetCommitID_whenSet(t *testing.T) { cli := steps.NewDeployStep(FakeNamespaceWatcher{}) cli.Init(kubeclient, radixclient, kubeUtil, &monitoring.Clientset{}, rr) - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) const commitID = "222ca8595c5283a9d0f17a623b9255a0d9866a2e" pipelineInfo := &model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - JobName: anyJobName, - ImageTag: anyImageTag, - Branch: "master", - CommitID: anyCommitID, + JobName: anyJobName, + ImageTag: anyImageTag, + Branch: "master", + CommitID: anyCommitID, + DNSConfig: getDNSAliasConfig(), }, TargetEnvironments: []string{"master"}, GitCommitHash: commitID, diff --git a/pipeline-runner/steps/promotion_test.go b/pipeline-runner/steps/promotion_test.go index d1ad12778..d0b9421aa 100644 --- a/pipeline-runner/steps/promotion_test.go +++ b/pipeline-runner/steps/promotion_test.go @@ -127,6 +127,7 @@ func TestPromote_ErrorScenarios_ErrorIsReturned(t *testing.T) { JobName: scenario.jobName, ImageTag: scenario.imageTag, CommitID: anyCommitID, + DNSConfig: getDNSAliasConfig(), }, } @@ -271,10 +272,11 @@ func TestPromote_PromoteToOtherEnvironment_NewStateIsExpected(t *testing.T) { JobName: anyPromoteJobName, ImageTag: anyImageTag, CommitID: anyCommitID, + DNSConfig: getDNSAliasConfig(), }, } - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -396,10 +398,11 @@ func TestPromote_PromoteToOtherEnvironment_Resources_NoOverride(t *testing.T) { JobName: anyPromoteJobName, ImageTag: anyImageTag, CommitID: anyCommitID, + DNSConfig: getDNSAliasConfig(), }, } - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -490,10 +493,11 @@ func TestPromote_PromoteToOtherEnvironment_Authentication(t *testing.T) { JobName: anyPromoteJobName, ImageTag: anyImageTag, CommitID: anyCommitID, + DNSConfig: getDNSAliasConfig(), }, } - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -606,10 +610,11 @@ func TestPromote_PromoteToOtherEnvironment_Resources_WithOverride(t *testing.T) JobName: anyPromoteJobName, ImageTag: anyImageTag, CommitID: anyCommitID, + DNSConfig: getDNSAliasConfig(), }, } - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -667,10 +672,11 @@ func TestPromote_PromoteToSameEnvironment_NewStateIsExpected(t *testing.T) { JobName: anyPromoteJobName, ImageTag: anyImageTag, CommitID: anyCommitID, + DNSConfig: getDNSAliasConfig(), }, } - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -785,10 +791,11 @@ func TestPromote_PromoteToOtherEnvironment_Identity(t *testing.T) { JobName: anyPromoteJobName, ImageTag: anyImageTag, CommitID: anyCommitID, + DNSConfig: getDNSAliasConfig(), }, } - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) pipelineInfo.SetApplicationConfig(applicationConfig) err = cli.Run(pipelineInfo) require.NoError(t, err) @@ -846,10 +853,11 @@ func TestPromote_AnnotatedBySourceDeploymentAttributes(t *testing.T) { JobName: anyPromoteJobName, ImageTag: anyImageTag, CommitID: anyCommitID, + DNSConfig: getDNSAliasConfig(), }, } - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil, nil) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index ce8a267b0..68a5790e1 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -9,6 +9,7 @@ import ( commonErrors "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-common/utils/slice" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -29,25 +30,23 @@ const ConfigBranchFallback = "master" // ApplicationConfig Instance variables type ApplicationConfig struct { - kubeclient kubernetes.Interface - radixclient radixclient.Interface - kubeutil *kube.Kube - registration *radixv1.RadixRegistration - config *radixv1.RadixApplication - dnsAliasAppReserved map[string]string - dnsAliasReserved []string + kubeclient kubernetes.Interface + radixclient radixclient.Interface + kubeutil *kube.Kube + registration *radixv1.RadixRegistration + config *radixv1.RadixApplication + dnsAliasConfig *dnsalias.DNSConfig } // NewApplicationConfig Constructor -func NewApplicationConfig(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, registration *radixv1.RadixRegistration, config *radixv1.RadixApplication, dnsAliasAppReserved map[string]string, dnsAliasReserved []string) *ApplicationConfig { +func NewApplicationConfig(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, registration *radixv1.RadixRegistration, config *radixv1.RadixApplication, dnsAliasConfig *dnsalias.DNSConfig) *ApplicationConfig { return &ApplicationConfig{ - kubeclient: kubeclient, - radixclient: radixclient, - kubeutil: kubeutil, - registration: registration, - config: config, - dnsAliasAppReserved: dnsAliasAppReserved, - dnsAliasReserved: dnsAliasReserved, + kubeclient: kubeclient, + radixclient: radixclient, + kubeutil: kubeutil, + registration: registration, + config: config, + dnsAliasConfig: dnsAliasConfig, } } @@ -125,7 +124,7 @@ func (app *ApplicationConfig) ApplyConfigToApplicationNamespace() error { if err != nil { if errors.IsNotFound(err) { log.Debugf("RadixApplication %s doesn't exist in namespace %s, creating now", app.config.Name, appNamespace) - if err = radixvalidators.CanRadixApplicationBeInserted(app.radixclient, app.config, app.dnsAliasAppReserved, app.dnsAliasReserved); err != nil { + if err = radixvalidators.CanRadixApplicationBeInserted(app.radixclient, app.config, app.dnsAliasConfig); err != nil { return err } _, err = app.radixclient.RadixV1().RadixApplications(appNamespace).Create(context.TODO(), app.config, metav1.CreateOptions{}) @@ -144,7 +143,7 @@ func (app *ApplicationConfig) ApplyConfigToApplicationNamespace() error { return nil } - if err = radixvalidators.CanRadixApplicationBeInserted(app.radixclient, app.config, app.dnsAliasAppReserved, app.dnsAliasReserved); err != nil { + if err = radixvalidators.CanRadixApplicationBeInserted(app.radixclient, app.config, app.dnsAliasConfig); err != nil { return err } diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 68534ee04..b550d9a44 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/equinor/radix-operator/pkg/apis/applicationconfig" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix" @@ -47,7 +48,7 @@ func setupTest() (*test.Utils, kubernetes.Interface, *kube.Kube, radixclient.Int func getApplication(ra *radixv1.RadixApplication) *applicationconfig.ApplicationConfig { // The other arguments are not relevant for this test - application := applicationconfig.NewApplicationConfig(nil, nil, nil, nil, ra, nil, nil) + application := applicationconfig.NewApplicationConfig(nil, nil, nil, nil, ra, nil) return application } @@ -56,7 +57,7 @@ func Test_Create_Radix_Environments(t *testing.T) { radixRegistration, _ := utils.GetRadixRegistrationFromFile(sampleRegistration) radixApp, _ := utils.GetRadixApplicationFromFile(sampleApp) - app := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, radixApp, nil, nil) + app := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, radixApp, nil) label := fmt.Sprintf("%s=%s", kube.RadixAppLabel, radixRegistration.Name) t.Run("It can create environments", func(t *testing.T) { @@ -117,7 +118,7 @@ func Test_Reconciles_Radix_Environments(t *testing.T) { WithEnvironment("prod", "master"). BuildRA() - app := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, rr, ra, nil, nil) + app := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, rr, ra, getDNSAliasConfig()) label := fmt.Sprintf("%s=%s", kube.RadixAppLabel, rr.Name) // Test @@ -640,7 +641,7 @@ func getAppConfig(client kubernetes.Interface, kubeUtil *kube.Kube, radixClient ra := applicationBuilder.BuildRA() radixRegistration, _ := radixClient.RadixV1().RadixRegistrations().Get(context.TODO(), ra.Name, metav1.GetOptions{}) - return applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra, nil, nil) + return applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra, getDNSAliasConfig()) } func applyApplicationWithSync(tu *test.Utils, client kubernetes.Interface, kubeUtil *kube.Kube, @@ -656,7 +657,7 @@ func applyApplicationWithSync(tu *test.Utils, client kubernetes.Interface, kubeU return err } - applicationConfig := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra, nil, nil) + applicationConfig := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra, getDNSAliasConfig()) err = applicationConfig.OnSync() if err != nil { @@ -707,3 +708,11 @@ func getRoleBindingByName(name string, roleBindings *rbacv1.RoleBindingList) *rb func roleBindingByNameExists(name string, roleBindings *rbacv1.RoleBindingList) bool { return getRoleBindingByName(name, roleBindings) != nil } + +func getDNSAliasConfig() *dnsalias.DNSConfig { + return &dnsalias.DNSConfig{ + DNSZone: "dev.radix.equinor.com", + ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, + ReservedDNSAlias: []string{"grafana"}, + } +} diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go index 6a71f4909..2ad428174 100644 --- a/pkg/apis/applicationconfig/dns_alias_test.go +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/equinor/radix-operator/pkg/apis/applicationconfig" + dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -317,10 +318,11 @@ func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { domain1 = "domain1" domain2 = "domain2" ) - dnsAliasAppReserved := map[string]string{ - "api": "radix-api", + dnsConfig := &dnsaliasconfig.DNSConfig{ + DNSZone: "dev.radix.equinor.com", + ReservedAppDNSAliases: dnsaliasconfig.AppReservedDNSAlias{"api": "radix-api"}, + ReservedDNSAlias: []string{"grafana"}, } - dnsAliasReserved := []string{"grafana"} var testScenarios = []struct { name string applicationBuilder utils.ApplicationBuilder @@ -388,8 +390,7 @@ func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { _, err = radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) require.NoError(t, err) ra := ts.applicationBuilder.BuildRA() - applicationConfig := applicationconfig.NewApplicationConfig(kubeClient, kubeUtil, radixClient, rr, ra, - dnsAliasAppReserved, dnsAliasReserved) + applicationConfig := applicationconfig.NewApplicationConfig(kubeClient, kubeUtil, radixClient, rr, ra, dnsConfig) actualValidationErr := applicationConfig.ApplyConfigToApplicationNamespace() diff --git a/pkg/apis/config/dnsalias/config.go b/pkg/apis/config/dnsalias/config.go index c3ce975ea..176eb2465 100644 --- a/pkg/apis/config/dnsalias/config.go +++ b/pkg/apis/config/dnsalias/config.go @@ -5,8 +5,11 @@ type DNSConfig struct { // DNSZone Cluster DNS zone. // Example radix.equinor.com, playground.radix.equinor.com DNSZone string - // DNSAliasAppReserved The list of DNS aliases, reserved for Radix platform Radix applications - DNSAliasAppReserved map[string]string - // DNSAliasReserved The list of DNS aliases, reserved for Radix platform services - DNSAliasReserved []string + // ReservedAppDNSAliases The list of DNS aliases, reserved for Radix platform Radix applications + ReservedAppDNSAliases map[string]string + // ReservedDNSAlias The list of DNS aliases, reserved for Radix platform services + ReservedDNSAlias []string } + +// AppReservedDNSAlias DNS aliases, reserved for Radix application +type AppReservedDNSAlias map[string]string // map[dnsAlias]appName diff --git a/pkg/apis/defaults/environment_variables.go b/pkg/apis/defaults/environment_variables.go index 31afada4d..39f1f7759 100644 --- a/pkg/apis/defaults/environment_variables.go +++ b/pkg/apis/defaults/environment_variables.go @@ -192,9 +192,9 @@ const ( // RadixBuildahImageBuilderEnvironmentVariable The container image used for running the buildah engine RadixBuildahImageBuilderEnvironmentVariable = "RADIX_BUILDAH_IMAGE_BUILDER" - // RadixDNSAliasAppReservedEnvironmentVariable The list of DNS aliases, reserved for Radix platform Radix application - RadixDNSAliasAppReservedEnvironmentVariable = "RADIX_DNS_ALIAS_APP_RESERVED" + // RadixReservedAppDNSAliasesEnvironmentVariable The list of DNS aliases, reserved for Radix platform Radix application + RadixReservedAppDNSAliasesEnvironmentVariable = "RADIX_RESERVED_APP_DNS_ALIASES" - // RadixDNSAliasReservedEnvironmentVariable The list of DNS aliases, reserved for Radix platform services - RadixDNSAliasReservedEnvironmentVariable = "RADIX_DNS_ALIAS_RESERVED" + // RadixReservedDNSAliasesEnvironmentVariable The list of DNS aliases, reserved for Radix platform services + RadixReservedDNSAliasesEnvironmentVariable = "RADIX_RESERVED_DNS_ALIASES" ) diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index a86bde51b..4d24bb0b9 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -40,7 +40,7 @@ func (s *syncerTestSuite) SetupTest() { s.kubeClient = kubefake.NewSimpleClientset() s.radixClient = radixfake.NewSimpleClientset() s.promClient = prometheusfake.NewSimpleClientset() - s.dnsConfig = &dnsalias2.DNSConfig{DNSZone: "test.radix.equinor.com"} + s.dnsConfig = &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} s.kubeUtil, _ = kube.New(s.kubeClient, s.radixClient, secretproviderfake.NewSimpleClientset()) } @@ -84,7 +84,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { domain2 = "domain2" port8080 = 8080 port9090 = 9090 - dnsZone1 = "test.radix.equinor.com" + dnsZone1 = "dev.radix.equinor.com" ) scenarios := []scenario{ diff --git a/pkg/apis/job/job_test.go b/pkg/apis/job/job_test.go index bdac376f2..509dc11d5 100644 --- a/pkg/apis/job/job_test.go +++ b/pkg/apis/job/job_test.go @@ -219,6 +219,8 @@ func (s *RadixJobTestSuite) TestObjectSynced_PipelineJobCreated() { fmt.Sprintf("--RADIX_CONTAINER_REGISTRY=%s", s.config.registry), fmt.Sprintf("--RADIX_APP_CONTAINER_REGISTRY=%s", s.config.appRegistry), fmt.Sprintf("--AZURE_SUBSCRIPTION_ID=%s", s.config.subscriptionID), + fmt.Sprint("--RADIX_RESERVED_APP_DNS_ALIASES=api=radix-api"), + fmt.Sprint("--RADIX_RESERVED_DNS_ALIASES=grafana"), fmt.Sprintf("--IMAGE_TAG=%s", imageTag), fmt.Sprintf("--BRANCH=%s", branch), fmt.Sprintf("--COMMIT_ID=%s", commitID), @@ -905,9 +907,9 @@ func (s *RadixJobTestSuite) assertStatusEqual(expectedStatus, actualStatus radix func (s *RadixJobTestSuite) TestObjectSynced_UseBuildKid_HasResourcesArgs() { dnsConfig := dnsalias.DNSConfig{ - DNSZone: "dev.radix.equinor.com", - DNSAliasAppReserved: map[string]string{"api": "radix-api"}, - DNSAliasReserved: []string{"grafana"}, + DNSZone: "dev.radix.equinor.com", + ReservedAppDNSAliases: map[string]string{"api": "radix-api"}, + ReservedDNSAlias: []string{"grafana"}, } scenarios := []struct { name string @@ -1005,9 +1007,9 @@ func getJobContainerArgument(container corev1.Container, variableName string) st func getConfigWithPipelineJobsHistoryLimit(historyLimit int) *config.Config { return &config.Config{ DNSConfig: &dnsalias.DNSConfig{ - DNSZone: "dev.radix.equinor.com", - DNSAliasAppReserved: map[string]string{"api": "radix-api"}, - DNSAliasReserved: []string{"grafana"}, + DNSZone: "dev.radix.equinor.com", + ReservedAppDNSAliases: map[string]string{"api": "radix-api"}, + ReservedDNSAlias: []string{"grafana"}, }, PipelineJobConfig: &pipelinejob.Config{ PipelineJobsHistoryLimit: historyLimit, @@ -1016,3 +1018,11 @@ func getConfigWithPipelineJobsHistoryLimit(historyLimit int) *config.Config { AppBuilderResourcesLimitsMemory: pointers.Ptr(resource.MustParse("2000Mi")), }} } + +func getDNSAliasConfig() *dnsalias.DNSConfig { + return &dnsalias.DNSConfig{ + DNSZone: "dev.radix.equinor.com", + ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, + ReservedDNSAlias: []string{"grafana"}, + } +} diff --git a/pkg/apis/job/kubejob.go b/pkg/apis/job/kubejob.go index d96ad50d1..ba98d40b2 100644 --- a/pkg/apis/job/kubejob.go +++ b/pkg/apis/job/kubejob.go @@ -166,6 +166,12 @@ func (job *Job) getPipelineJobArguments(appName, jobName string, jobSpec v1.Radi fmt.Sprintf("--%s=%s", defaults.AppContainerRegistryEnvironmentVariable, appContainerRegistry), fmt.Sprintf("--%s=%s", defaults.AzureSubscriptionIdEnvironmentVariable, subscriptionId), } + for dnsAlias, appName := range job.config.DNSConfig.ReservedAppDNSAliases { + args = append(args, fmt.Sprintf("--%s=%s=%s", defaults.RadixReservedAppDNSAliasesEnvironmentVariable, dnsAlias, appName)) + } + for _, reservedDNSAlias := range job.config.DNSConfig.ReservedDNSAlias { + args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixReservedDNSAliasesEnvironmentVariable, reservedDNSAlias)) + } radixConfigFullName := jobSpec.RadixConfigFullName if len(radixConfigFullName) == 0 { diff --git a/pkg/apis/radixvalidators/validate_ra.go b/pkg/apis/radixvalidators/validate_ra.go index 67d94ccb6..f3ba089fc 100644 --- a/pkg/apis/radixvalidators/validate_ra.go +++ b/pkg/apis/radixvalidators/validate_ra.go @@ -13,6 +13,7 @@ import ( commonUtils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-common/utils/slice" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/deployment" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -59,11 +60,11 @@ var ( type RadixApplicationValidator func(radixApplication *radixv1.RadixApplication) error // CanRadixApplicationBeInserted Checks if application config is valid. Returns a single error, if this is the case -func CanRadixApplicationBeInserted(radixClient radixclient.Interface, app *radixv1.RadixApplication, dnsAliasAppReserved map[string]string, dnsAliasReserved []string, additionalValidators ...RadixApplicationValidator) error { +func CanRadixApplicationBeInserted(radixClient radixclient.Interface, app *radixv1.RadixApplication, dnsAliasConfig *dnsalias.DNSConfig, additionalValidators ...RadixApplicationValidator) error { validators := append(requiredRadixApplicationValidators, validateDoesRRExistFactory(radixClient), - validateDNSAliasFactory(radixClient, dnsAliasAppReserved, dnsAliasReserved), + validateDNSAliasFactory(radixClient, dnsAliasConfig), ) validators = append(validators, additionalValidators...) @@ -113,9 +114,9 @@ func validateDoesRRExistFactory(client radixclient.Interface) RadixApplicationVa } } -func validateDNSAliasFactory(client radixclient.Interface, dnsAliasAppReserved map[string]string, dnsAliasReserved []string) RadixApplicationValidator { +func validateDNSAliasFactory(client radixclient.Interface, dnsAliasConfig *dnsalias.DNSConfig) RadixApplicationValidator { return func(radixApplication *radixv1.RadixApplication) error { - return validateDNSAlias(client, radixApplication, dnsAliasAppReserved, dnsAliasReserved) + return validateDNSAlias(client, radixApplication, dnsAliasConfig) } } @@ -143,7 +144,7 @@ func validateDNSAppAlias(app *radixv1.RadixApplication) error { return validateDNSAppAliasComponentAndEnvironmentAvailable(app) } -func validateDNSAlias(radixClient radixclient.Interface, app *radixv1.RadixApplication, dnsAliasAppReserved map[string]string, dnsAliasReserved []string) error { +func validateDNSAlias(radixClient radixclient.Interface, app *radixv1.RadixApplication, dnsAliasConfig *dnsalias.DNSConfig) error { var errs []error radixDNSAliasMap, err := kube.GetRadixDNSAliasMapWithSelector(radixClient, "") if err != nil { @@ -180,10 +181,10 @@ func validateDNSAlias(radixClient radixclient.Interface, app *radixv1.RadixAppli if radixDNSAlias, ok := radixDNSAliasMap[dnsAlias.Domain]; ok && radixDNSAlias.Spec.AppName != app.Name { errs = append(errs, RadixDNSAliasAlreadyUsedByAnotherApplicationError(dnsAlias.Domain)) } - if reservingAppName, aliasReserved := dnsAliasAppReserved[dnsAlias.Domain]; aliasReserved && reservingAppName != app.Name { + if reservingAppName, aliasReserved := dnsAliasConfig.ReservedAppDNSAliases[dnsAlias.Domain]; aliasReserved && reservingAppName != app.Name { errs = append(errs, RadixDNSAliasIsReservedForRadixPlatformApplicationError(dnsAlias.Domain)) } - if slice.Any(dnsAliasReserved, func(reservedAlias string) bool { return reservedAlias == dnsAlias.Domain }) { + if slice.Any(dnsAliasConfig.ReservedDNSAlias, func(reservedAlias string) bool { return reservedAlias == dnsAlias.Domain }) { errs = append(errs, RadixDNSAliasIsReservedForRadixPlatformServiceError(dnsAlias.Domain)) } } diff --git a/pkg/apis/radixvalidators/validate_ra_test.go b/pkg/apis/radixvalidators/validate_ra_test.go index 8c65d1883..b732937d5 100644 --- a/pkg/apis/radixvalidators/validate_ra_test.go +++ b/pkg/apis/radixvalidators/validate_ra_test.go @@ -7,6 +7,7 @@ import ( commonUtils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-common/utils/pointers" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/radixvalidators" @@ -23,7 +24,7 @@ type updateRAFunc func(rr *v1.RadixApplication) func Test_valid_ra_returns_true(t *testing.T) { _, client := validRASetup() validRA := createValidRA() - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, getDNSAliasConfig()) assert.NoError(t, err) } @@ -31,7 +32,7 @@ func Test_missing_rr(t *testing.T) { client := radixfake.NewSimpleClientset() validRA := createValidRA() - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, getDNSAliasConfig()) assert.Error(t, err) } @@ -671,7 +672,7 @@ func Test_invalid_ra(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, getDNSAliasConfig()) if testcase.expectedError != nil { assert.Error(t, err) @@ -768,7 +769,7 @@ func Test_ValidRAComponentLimitRequest_NoError(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, getDNSAliasConfig()) assert.NoError(t, err) }) @@ -851,7 +852,7 @@ func Test_ValidRAJobLimitRequest_NoError(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, getDNSAliasConfig()) assert.NoError(t, err) }) @@ -886,7 +887,7 @@ func Test_InvalidRAComponentLimitRequest_Error(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, getDNSAliasConfig()) assert.Error(t, err) }) @@ -921,7 +922,7 @@ func Test_InvalidRAJobLimitRequest_Error(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, getDNSAliasConfig()) assert.Error(t, err) }) @@ -1062,7 +1063,7 @@ func Test_PublicPort(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, getDNSAliasConfig()) if testcase.isValid { assert.NoError(t, err) @@ -1145,7 +1146,7 @@ func Test_Variables(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, getDNSAliasConfig()) if testcase.isValid { assert.NoError(t, err) @@ -1459,7 +1460,7 @@ func Test_ValidationOfVolumeMounts_Errors(t *testing.T) { validRA := createValidRA() volumes := testcase.volumeMounts() ra(validRA, volumes) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, getDNSAliasConfig()) isErrorNil := err == nil assert.Equal(t, testcase.isValid, err == nil) @@ -1554,7 +1555,7 @@ func Test_ValidHPA_NoError(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, getDNSAliasConfig()) if testcase.isValid { assert.NoError(t, err) @@ -1730,7 +1731,7 @@ func Test_EgressConfig(t *testing.T) { t.Run(testcase.name, func(t *testing.T) { validRA := createValidRA() testcase.updateRA(validRA) - err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, nil, nil) + err := radixvalidators.CanRadixApplicationBeInserted(client, validRA, getDNSAliasConfig()) if testcase.isValid { assert.NoError(t, err) @@ -1886,3 +1887,11 @@ func validRASetup() (kubernetes.Interface, radixclient.Interface) { return kubeclient, client } + +func getDNSAliasConfig() *dnsalias.DNSConfig { + return &dnsalias.DNSConfig{ + DNSZone: "dev.radix.equinor.com", + ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, + ReservedDNSAlias: []string{"grafana"}, + } +} diff --git a/radix-operator/application/handler.go b/radix-operator/application/handler.go index fb59ddeea..329371a90 100644 --- a/radix-operator/application/handler.go +++ b/radix-operator/application/handler.go @@ -5,6 +5,7 @@ import ( "fmt" application "github.com/equinor/radix-operator/pkg/apis/applicationconfig" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" @@ -31,20 +32,18 @@ type Handler struct { radixclient radixclient.Interface kubeutil *kube.Kube hasSynced common.HasSynced + dnsConfig *dnsalias.DNSConfig } // NewHandler Constructor -func NewHandler( - kubeclient kubernetes.Interface, - kubeutil *kube.Kube, - radixclient radixclient.Interface, - hasSynced common.HasSynced) Handler { +func NewHandler(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, hasSynced common.HasSynced) Handler { handler := Handler{ kubeclient: kubeclient, radixclient: radixclient, kubeutil: kubeutil, hasSynced: hasSynced, + dnsConfig: dnsConfig, } return handler @@ -78,7 +77,7 @@ func (t *Handler) Sync(namespace, name string, eventRecorder record.EventRecorde syncApplication := radixApplication.DeepCopy() logger.Debugf("Sync application %s", syncApplication.Name) - applicationConfig := application.NewApplicationConfig(t.kubeclient, t.kubeutil, t.radixclient, radixRegistration, radixApplication, nil, nil) + applicationConfig := application.NewApplicationConfig(t.kubeclient, t.kubeutil, t.radixclient, radixRegistration, radixApplication, t.dnsConfig) err = applicationConfig.OnSync() if err != nil { // Put back on queue diff --git a/radix-operator/config/config.go b/radix-operator/config/config.go index a3b8556fb..c1cca6687 100644 --- a/radix-operator/config/config.go +++ b/radix-operator/config/config.go @@ -36,7 +36,7 @@ func getDNSZone() string { } func getDNSAliasAppReserved() map[string]string { - return convertToMap(viper.GetString(defaults.RadixDNSAliasAppReservedEnvironmentVariable)) + return convertToMap(viper.GetString(defaults.RadixReservedAppDNSAliasesEnvironmentVariable)) } func convertToMap(keyValuePairs string) map[string]string { @@ -52,7 +52,7 @@ func convertToMap(keyValuePairs string) map[string]string { } func getDNSAliasReserved() []string { - envVar := viper.GetString(defaults.RadixDNSAliasReservedEnvironmentVariable) + envVar := viper.GetString(defaults.RadixReservedDNSAliasesEnvironmentVariable) return strings.Split(envVar, ",") } @@ -70,9 +70,9 @@ func NewConfig() *apiconfig.Config { return &apiconfig.Config{ LogLevel: getLogLevel(), DNSConfig: &dnsalias.DNSConfig{ - DNSZone: getDNSZone(), - DNSAliasAppReserved: getDNSAliasAppReserved(), - DNSAliasReserved: getDNSAliasReserved(), + DNSZone: getDNSZone(), + ReservedAppDNSAliases: getDNSAliasAppReserved(), + ReservedDNSAlias: getDNSAliasReserved(), }, PipelineJobConfig: &pipelinejob.Config{ PipelineJobsHistoryLimit: getPipelineJobsHistoryLimit(), diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go index 89d6262f3..719075542 100644 --- a/radix-operator/dnsalias/controller_test.go +++ b/radix-operator/dnsalias/controller_test.go @@ -47,7 +47,7 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { envName2 = "env2" componentName1 = "server1" componentName2 = "server2" - dnsZone = "test.radix.equinor.com" + dnsZone = "dev.radix.equinor.com" ) alias := internal.BuildRadixDNSAlias(appName1, componentName1, envName1, aliasName) diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index c79501123..17653742a 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -42,7 +42,7 @@ func (s *handlerTestSuite) TearDownTest() { } func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { - dnsConfig := &dnsalias2.DNSConfig{DNSZone: "test.radix.equinor.com"} + dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) @@ -54,7 +54,7 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { } func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { - dnsConfig := &dnsalias2.DNSConfig{DNSZone: "test.radix.equinor.com"} + dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, domain1, 8080), "create existing RadixDNSAlias") handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) @@ -67,7 +67,7 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { } func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsNoError() { - dnsConfig := &dnsalias2.DNSConfig{DNSZone: "test.radix.equinor.com"} + dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, domain1, 8080), "create existing RadixDNSAlias") handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) diff --git a/radix-operator/job/controller_test.go b/radix-operator/job/controller_test.go index f5aeed806..a90313daf 100644 --- a/radix-operator/job/controller_test.go +++ b/radix-operator/job/controller_test.go @@ -73,9 +73,9 @@ func (s *jobTestSuite) Test_Controller_Calls_Handler() { cfg := &config.Config{ DNSConfig: &dnsalias.DNSConfig{ - DNSZone: "dev.radix.equinor.com", - DNSAliasAppReserved: map[string]string{"api": "radix-api"}, - DNSAliasReserved: []string{"grafana"}, + DNSZone: "dev.radix.equinor.com", + ReservedAppDNSAliases: map[string]string{"api": "radix-api"}, + ReservedDNSAlias: []string{"grafana"}, }, PipelineJobConfig: &pipelinejob.Config{ PipelineJobsHistoryLimit: 3, diff --git a/radix-operator/main.go b/radix-operator/main.go index 15c7599ad..186e6bb1f 100644 --- a/radix-operator/main.go +++ b/radix-operator/main.go @@ -12,7 +12,7 @@ import ( errorUtils "github.com/equinor/radix-common/utils/errors" apiconfig "github.com/equinor/radix-operator/pkg/apis/config" - dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" deploymentAPI "github.com/equinor/radix-operator/pkg/apis/deployment" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -75,7 +75,7 @@ func main() { radixInformerFactory := radixinformers.NewSharedInformerFactory(radixClient, resyncPeriod) startController(createRegistrationController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), registrationControllerThreads, stop) - startController(createApplicationController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), applicationControllerThreads, stop) + startController(createApplicationController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg.DNSConfig), applicationControllerThreads, stop) startController(createEnvironmentController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), environmentControllerThreads, stop) startController(createDeploymentController(client, radixClient, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), deploymentControllerThreads, stop) startController(createJobController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg), jobControllerThreads, stop) @@ -142,7 +142,7 @@ func createRegistrationController(client kubernetes.Interface, radixClient radix recorder) } -func createApplicationController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface) *common.Controller { +func createApplicationController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, dnsConfig *dnsaliasconfig.DNSConfig) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, @@ -154,6 +154,7 @@ func createApplicationController(client kubernetes.Interface, radixClient radixc handler := application.NewHandler(client, kubeUtil, radixClient, + dnsConfig, func(syncedOk bool) {}, // Not interested in getting notifications of synced ) @@ -195,7 +196,7 @@ func createEnvironmentController(client kubernetes.Interface, radixClient radixc recorder) } -func createDNSAliasesController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, dnsConfig *dnsalias2.DNSConfig) *common.Controller { +func createDNSAliasesController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, dnsConfig *dnsaliasconfig.DNSConfig) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, From cbc308789d543a279a30fcfb7f4de60e81661a48 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 9 Nov 2023 16:08:12 +0100 Subject: [PATCH 046/121] Fixed test --- pkg/apis/job/job_test.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/pkg/apis/job/job_test.go b/pkg/apis/job/job_test.go index 509dc11d5..af9449c4a 100644 --- a/pkg/apis/job/job_test.go +++ b/pkg/apis/job/job_test.go @@ -219,8 +219,8 @@ func (s *RadixJobTestSuite) TestObjectSynced_PipelineJobCreated() { fmt.Sprintf("--RADIX_CONTAINER_REGISTRY=%s", s.config.registry), fmt.Sprintf("--RADIX_APP_CONTAINER_REGISTRY=%s", s.config.appRegistry), fmt.Sprintf("--AZURE_SUBSCRIPTION_ID=%s", s.config.subscriptionID), - fmt.Sprint("--RADIX_RESERVED_APP_DNS_ALIASES=api=radix-api"), - fmt.Sprint("--RADIX_RESERVED_DNS_ALIASES=grafana"), + "--RADIX_RESERVED_APP_DNS_ALIASES=api=radix-api", + "--RADIX_RESERVED_DNS_ALIASES=grafana", fmt.Sprintf("--IMAGE_TAG=%s", imageTag), fmt.Sprintf("--BRANCH=%s", branch), fmt.Sprintf("--COMMIT_ID=%s", commitID), @@ -1018,11 +1018,3 @@ func getConfigWithPipelineJobsHistoryLimit(historyLimit int) *config.Config { AppBuilderResourcesLimitsMemory: pointers.Ptr(resource.MustParse("2000Mi")), }} } - -func getDNSAliasConfig() *dnsalias.DNSConfig { - return &dnsalias.DNSConfig{ - DNSZone: "dev.radix.equinor.com", - ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, - ReservedDNSAlias: []string{"grafana"}, - } -} From 9e4d82baba1d90c3857a5287a7efc608180f7292 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 10 Nov 2023 10:43:17 +0100 Subject: [PATCH 047/121] Adding RDA role and binding to tekton --- pkg/apis/application/application.go | 2 +- pkg/apis/application/limitrange.go | 2 +- pkg/apis/application/rolebinding.go | 87 ++++++++++++++++++++++----- pkg/apis/application/roles.go | 51 ++++++++-------- pkg/apis/defaults/roles.go | 11 +++- pkg/apis/deployment/deploymentrbac.go | 3 +- pkg/apis/radix/register.go | 4 ++ 7 files changed, 116 insertions(+), 44 deletions(-) diff --git a/pkg/apis/application/application.go b/pkg/apis/application/application.go index acec6b2da..2287473ff 100644 --- a/pkg/apis/application/application.go +++ b/pkg/apis/application/application.go @@ -113,7 +113,7 @@ func (app Application) OnSync() error { return nil } -func (app *Application) updateRadixRegistrationStatus(rr *v1.RadixRegistration, changeStatusFunc func(currStatus *v1.RadixRegistrationStatus)) error { +func (app Application) updateRadixRegistrationStatus(rr *v1.RadixRegistration, changeStatusFunc func(currStatus *v1.RadixRegistrationStatus)) error { rrInterface := app.radixclient.RadixV1().RadixRegistrations() return retry.RetryOnConflict(retry.DefaultRetry, func() error { currentRR, err := rrInterface.Get(context.TODO(), rr.GetName(), metav1.GetOptions{}) diff --git a/pkg/apis/application/limitrange.go b/pkg/apis/application/limitrange.go index a4f910173..db8b5aedf 100644 --- a/pkg/apis/application/limitrange.go +++ b/pkg/apis/application/limitrange.go @@ -9,7 +9,7 @@ const ( limitRangeName = "mem-cpu-limit-range-app" ) -func (app *Application) createLimitRangeOnAppNamespace(namespace string) error { +func (app Application) createLimitRangeOnAppNamespace(namespace string) error { defaultMemoryLimit := defaults.GetDefaultMemoryLimitForAppNamespace() defaultCPURequest := defaults.GetDefaultCPURequestForAppNamespace() defaultMemoryRequest := defaults.GetDefaultMemoryRequestForAppNamespace() diff --git a/pkg/apis/application/rolebinding.go b/pkg/apis/application/rolebinding.go index 49539b4ca..8ffeee6c8 100644 --- a/pkg/apis/application/rolebinding.go +++ b/pkg/apis/application/rolebinding.go @@ -93,7 +93,7 @@ func (app Application) applyRbacOnPipelineRunner() error { return err } - err = app.givePipelineAccessToRR(serviceAccount, "radix-pipeline-rr") + err = app.givePipelineAccessToRR(serviceAccount, defaults.RadixPipelineRRRoleNamePrefix) if err != nil { return err } @@ -107,8 +107,10 @@ func (app Application) applyRbacOnRadixTekton() error { return err } - err = app.givePipelineAccessToRR(serviceAccount, "radix-tekton-rr") - if err != nil { + if err = app.givePipelineAccessToRR(serviceAccount, defaults.RadixTektonRRRoleNamePrefix); err != nil { + return err + } + if err = app.givePipelineAccessToRadixDNSAliases(serviceAccount, defaults.RadixTektonRadixDNSAliasRoleNamePrefix); err != nil { return err } @@ -118,15 +120,33 @@ func (app Application) applyRbacOnRadixTekton() error { func (app Application) givePipelineAccessToRR(serviceAccount *corev1.ServiceAccount, clusterRoleNamePrefix string) error { k := app.kubeutil - clusterrole := app.rrPipelineClusterRole(clusterRoleNamePrefix) - clusterrolebinding := app.rrClusterRoleBinding(serviceAccount, clusterrole) + clusterRole := app.rrPipelineClusterRole(clusterRoleNamePrefix) + clusterRoleBinding := app.rrClusterRoleBinding(serviceAccount, clusterRole) - err := k.ApplyClusterRole(clusterrole) + err := k.ApplyClusterRole(clusterRole) if err != nil { return err } - err = k.ApplyClusterRoleBinding(clusterrolebinding) + err = k.ApplyClusterRoleBinding(clusterRoleBinding) + if err != nil { + return err + } + return nil +} + +func (app Application) givePipelineAccessToRadixDNSAliases(serviceAccount *corev1.ServiceAccount, clusterRoleNamePrefix string) error { + k := app.kubeutil + + clusterRole := app.radixDNSAliasPipelineClusterRole(clusterRoleNamePrefix) + clusterRoleBinding := app.radixDNSAliasClusterRoleBinding(serviceAccount, clusterRole) + + err := k.ApplyClusterRole(clusterRole) + if err != nil { + return err + } + + err = k.ApplyClusterRoleBinding(clusterRoleBinding) if err != nil { return err } @@ -177,7 +197,7 @@ func (app Application) pipelineRoleBinding(serviceAccount *corev1.ServiceAccount }, Subjects: []auth.Subject{ { - Kind: "ServiceAccount", + Kind: k8s.KindServiceAccount, Name: serviceAccount.Name, Namespace: serviceAccount.Namespace, }, @@ -209,7 +229,7 @@ func (app Application) radixTektonRoleBinding(serviceAccount *corev1.ServiceAcco }, Subjects: []auth.Subject{ { - Kind: "ServiceAccount", + Kind: k8s.KindServiceAccount, Name: serviceAccount.Name, Namespace: serviceAccount.Namespace, }, @@ -221,17 +241,17 @@ func (app Application) radixTektonRoleBinding(serviceAccount *corev1.ServiceAcco func (app Application) rrClusterRoleBinding(serviceAccount *corev1.ServiceAccount, clusterrole *auth.ClusterRole) *auth.ClusterRoleBinding { registration := app.registration appName := registration.Name - clusterroleBindingName := clusterrole.Name + clusterRoleBindingName := clusterrole.Name ownerReference := app.getOwnerReference() - logger.Debugf("Create clusterrolebinding config %s", clusterroleBindingName) + logger.Debugf("Create clusterrolebinding config %s", clusterRoleBindingName) - clusterrolebinding := &auth.ClusterRoleBinding{ + clusterRoleBinding := &auth.ClusterRoleBinding{ TypeMeta: metav1.TypeMeta{ APIVersion: k8s.RbacApiVersion, Kind: k8s.KindClusterRoleBinding, }, ObjectMeta: metav1.ObjectMeta{ - Name: clusterroleBindingName, + Name: clusterRoleBindingName, Labels: map[string]string{ kube.RadixAppLabel: appName, }, @@ -244,13 +264,50 @@ func (app Application) rrClusterRoleBinding(serviceAccount *corev1.ServiceAccoun }, Subjects: []auth.Subject{ { - Kind: "ServiceAccount", + Kind: k8s.KindServiceAccount, Name: serviceAccount.Name, Namespace: serviceAccount.Namespace, }, }, } - return clusterrolebinding + return clusterRoleBinding +} + +func (app Application) radixDNSAliasClusterRoleBinding(serviceAccount *corev1.ServiceAccount, clusterrole *auth.ClusterRole) *auth.ClusterRoleBinding { + // TODO + return nil + /* registration := app.registration + appName := registration.Name + clusterRoleBindingName := clusterrole.Name + ownerReference := app.getOwnerReference() + logger.Debugf("Create clusterrolebinding config %s", clusterRoleBindingName) + + clusterRoleBinding := &auth.ClusterRoleBinding{ + TypeMeta: metav1.TypeMeta{ + APIVersion: k8s.RbacApiVersion, + Kind: k8s.KindClusterRoleBinding, + }, + ObjectMeta: metav1.ObjectMeta{ + Name: clusterRoleBindingName, + Labels: map[string]string{ + kube.RadixAppLabel: appName, + }, + OwnerReferences: ownerReference, + }, + RoleRef: auth.RoleRef{ + APIGroup: k8s.RbacApiGroup, + Kind: k8s.KindClusterRole, + Name: clusterrole.Name, + }, + Subjects: []auth.Subject{ + { + Kind: k8s.KindServiceAccount, + Name: serviceAccount.Name, + Namespace: serviceAccount.Namespace, + }, + }, + } + return clusterRoleBinding*/ } func (app Application) rrClusterroleBinding(clusterrole *auth.ClusterRole, subjects []auth.Subject) *auth.ClusterRoleBinding { diff --git a/pkg/apis/application/roles.go b/pkg/apis/application/roles.go index 526247c87..ab380006c 100644 --- a/pkg/apis/application/roles.go +++ b/pkg/apis/application/roles.go @@ -11,42 +11,43 @@ import ( ) func (app Application) rrPipelineClusterRole(roleNamePrefix string) *auth.ClusterRole { - registration := app.registration - appName := registration.Name - clusterroleName := fmt.Sprintf("%s-%s", roleNamePrefix, appName) - return app.rrClusterRole(clusterroleName, []string{"get"}) + clusterRoleName := fmt.Sprintf("%s-%s", roleNamePrefix, app.registration.Name) + return app.rrClusterRole(clusterRoleName, []string{"get"}) } -func (app Application) rrClusterRole(clusterroleName string, verbs []string) *auth.ClusterRole { - registration := app.registration - appName := registration.Name - - ownerRef := app.getOwnerReference() +func (app Application) rrClusterRole(clusterRoleName string, verbs []string) *auth.ClusterRole { + appName := app.registration.Name + return app.buildClusterRole(clusterRoleName, auth.PolicyRule{APIGroups: []string{radix.GroupName}, + Resources: []string{radix.ResourceRadixRegistrations}, + ResourceNames: []string{appName}, + Verbs: verbs, + }) +} - logger.Debugf("Creating clusterrole config %s", clusterroleName) +func (app Application) radixDNSAliasPipelineClusterRole(roleNamePrefix string) *auth.ClusterRole { + clusterRoleName := fmt.Sprintf("%s-%s", roleNamePrefix, app.registration.Name) + return app.buildClusterRole(clusterRoleName, auth.PolicyRule{APIGroups: []string{radix.GroupName}, + Resources: []string{radix.ResourceRadixDNSAliases}, + Verbs: []string{"list"}, + }) +} - clusterrole := &auth.ClusterRole{ +func (app Application) buildClusterRole(clusterRoleName string, rules ...auth.PolicyRule) *auth.ClusterRole { + logger.Debugf("Creating clusterrole config %s", clusterRoleName) + clusterRole := &auth.ClusterRole{ TypeMeta: metav1.TypeMeta{ APIVersion: k8s.RbacApiVersion, Kind: k8s.KindClusterRole, }, ObjectMeta: metav1.ObjectMeta{ - Name: clusterroleName, + Name: clusterRoleName, Labels: map[string]string{ - kube.RadixAppLabel: appName, - }, - OwnerReferences: ownerRef, - }, - Rules: []auth.PolicyRule{ - { - APIGroups: []string{radix.GroupName}, - Resources: []string{"radixregistrations"}, - ResourceNames: []string{appName}, - Verbs: verbs, + kube.RadixAppLabel: app.registration.Name, }, + OwnerReferences: app.getOwnerReference(), }, + Rules: rules, } - logger.Debugf("Done - creating clusterrole config %s", clusterroleName) - - return clusterrole + logger.Debugf("Done - creating clusterrole config %s", clusterRoleName) + return clusterRole } diff --git a/pkg/apis/defaults/roles.go b/pkg/apis/defaults/roles.go index 054f8c303..bf33a3f33 100644 --- a/pkg/apis/defaults/roles.go +++ b/pkg/apis/defaults/roles.go @@ -43,9 +43,18 @@ const ( // RadixTektonAppRoleName Role of user to apply radixconfig to configmap and process Tekton objects RadixTektonAppRoleName = "radix-tekton-app" - // RadixTektonEnvRoleName Role of user to get app environment data for prepare pipeline job + // RadixTektonEnvRoleName Role to get app environment data for prepare pipeline job RadixTektonEnvRoleName = "radix-tekton-env" + // RadixPipelineRRRoleNamePrefix Role of to get RadixRegistrations for pipeline job + RadixPipelineRRRoleNamePrefix = "radix-pipeline-rr" + + // RadixTektonRRRoleNamePrefix Role of to get RadixRegistrations for prepare pipeline job + RadixTektonRRRoleNamePrefix = "radix-tekton-rr" + + // RadixTektonRadixDNSAliasRoleNamePrefix Role of to get RadixDNSAliases for prepare pipeline job + RadixTektonRadixDNSAliasRoleNamePrefix = "radix-tekton-rda" + // PlatformUserRoleName Name of platform user cluster role PlatformUserRoleName = "radix-platform-user" diff --git a/pkg/apis/deployment/deploymentrbac.go b/pkg/apis/deployment/deploymentrbac.go index af13b0a88..b80c718cd 100644 --- a/pkg/apis/deployment/deploymentrbac.go +++ b/pkg/apis/deployment/deploymentrbac.go @@ -2,6 +2,7 @@ package deployment import ( "fmt" + "github.com/equinor/radix-operator/pkg/apis/application" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/defaults/k8s" @@ -79,7 +80,7 @@ func configureRbacForRadixJobComponents(deploy *Deployment) ConfigureDeploymentR } subjects := []auth.Subject{ { - Kind: "ServiceAccount", + Kind: k8s.KindServiceAccount, Name: serviceAccount.Name, Namespace: serviceAccount.Namespace, }} diff --git a/pkg/apis/radix/register.go b/pkg/apis/radix/register.go index 2913f560a..07d964010 100644 --- a/pkg/apis/radix/register.go +++ b/pkg/apis/radix/register.go @@ -23,4 +23,8 @@ const ( KindRadixAlert = "RadixAlert" // KindRadixDNSAlias RadixDNSAlias object Kind KindRadixDNSAlias = "RadixDNSAlias" + // ResourceRadixRegistrations RadixRegistrations API resource + ResourceRadixRegistrations = "radixregistrations" + // ResourceRadixDNSAliases RadixDNSAliases API resource + ResourceRadixDNSAliases = "radixdnsaliases" ) From 6569f597a01d9e9b95e1e05fb8ca7b56899211ae Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 10 Nov 2023 16:44:49 +0100 Subject: [PATCH 048/121] Added RDA role and binding to tekton --- pkg/apis/application/rolebinding.go | 95 +++++------------------------ 1 file changed, 15 insertions(+), 80 deletions(-) diff --git a/pkg/apis/application/rolebinding.go b/pkg/apis/application/rolebinding.go index 8ffeee6c8..84873f688 100644 --- a/pkg/apis/application/rolebinding.go +++ b/pkg/apis/application/rolebinding.go @@ -106,72 +106,44 @@ func (app Application) applyRbacOnRadixTekton() error { if err != nil { return err } - if err = app.givePipelineAccessToRR(serviceAccount, defaults.RadixTektonRRRoleNamePrefix); err != nil { return err } if err = app.givePipelineAccessToRadixDNSAliases(serviceAccount, defaults.RadixTektonRadixDNSAliasRoleNamePrefix); err != nil { return err } - return app.giveRadixTektonAccessToAppNamespace(serviceAccount) } func (app Application) givePipelineAccessToRR(serviceAccount *corev1.ServiceAccount, clusterRoleNamePrefix string) error { - k := app.kubeutil - clusterRole := app.rrPipelineClusterRole(clusterRoleNamePrefix) - clusterRoleBinding := app.rrClusterRoleBinding(serviceAccount, clusterRole) - - err := k.ApplyClusterRole(clusterRole) - if err != nil { - return err - } - - err = k.ApplyClusterRoleBinding(clusterRoleBinding) - if err != nil { - return err - } - return nil + clusterRoleBinding := app.clusterRoleBinding(serviceAccount, clusterRole) + return app.applyClusterRoleAndBinding(clusterRole, clusterRoleBinding) } func (app Application) givePipelineAccessToRadixDNSAliases(serviceAccount *corev1.ServiceAccount, clusterRoleNamePrefix string) error { - k := app.kubeutil - clusterRole := app.radixDNSAliasPipelineClusterRole(clusterRoleNamePrefix) - clusterRoleBinding := app.radixDNSAliasClusterRoleBinding(serviceAccount, clusterRole) + clusterRoleBinding := app.clusterRoleBinding(serviceAccount, clusterRole) + return app.applyClusterRoleAndBinding(clusterRole, clusterRoleBinding) +} - err := k.ApplyClusterRole(clusterRole) - if err != nil { +func (app Application) applyClusterRoleAndBinding(clusterRole *auth.ClusterRole, clusterRoleBinding *auth.ClusterRoleBinding) error { + if err := app.kubeutil.ApplyClusterRole(clusterRole); err != nil { return err } - - err = k.ApplyClusterRoleBinding(clusterRoleBinding) - if err != nil { - return err - } - return nil + return app.kubeutil.ApplyClusterRoleBinding(clusterRoleBinding) } func (app Application) givePipelineAccessToAppNamespace(serviceAccount *corev1.ServiceAccount) error { - k := app.kubeutil - registration := app.registration - - namespace := utils.GetAppNamespace(registration.Name) + namespace := utils.GetAppNamespace(app.registration.Name) rolebinding := app.pipelineRoleBinding(serviceAccount) - - return k.ApplyRoleBinding(namespace, rolebinding) + return app.kubeutil.ApplyRoleBinding(namespace, rolebinding) } func (app Application) giveRadixTektonAccessToAppNamespace(serviceAccount *corev1.ServiceAccount) error { - k := app.kubeutil - registration := app.registration - - namespace := utils.GetAppNamespace(registration.Name) - - // Create role binding + namespace := utils.GetAppNamespace(app.registration.Name) roleBinding := app.radixTektonRoleBinding(serviceAccount) - return k.ApplyRoleBinding(namespace, roleBinding) + return app.kubeutil.ApplyRoleBinding(namespace, roleBinding) } func (app Application) pipelineRoleBinding(serviceAccount *corev1.ServiceAccount) *auth.RoleBinding { @@ -238,10 +210,10 @@ func (app Application) radixTektonRoleBinding(serviceAccount *corev1.ServiceAcco return rolebinding } -func (app Application) rrClusterRoleBinding(serviceAccount *corev1.ServiceAccount, clusterrole *auth.ClusterRole) *auth.ClusterRoleBinding { +func (app Application) clusterRoleBinding(serviceAccount *corev1.ServiceAccount, clusterRole *auth.ClusterRole) *auth.ClusterRoleBinding { registration := app.registration appName := registration.Name - clusterRoleBindingName := clusterrole.Name + clusterRoleBindingName := clusterRole.Name ownerReference := app.getOwnerReference() logger.Debugf("Create clusterrolebinding config %s", clusterRoleBindingName) @@ -260,7 +232,7 @@ func (app Application) rrClusterRoleBinding(serviceAccount *corev1.ServiceAccoun RoleRef: auth.RoleRef{ APIGroup: k8s.RbacApiGroup, Kind: k8s.KindClusterRole, - Name: clusterrole.Name, + Name: clusterRole.Name, }, Subjects: []auth.Subject{ { @@ -273,43 +245,6 @@ func (app Application) rrClusterRoleBinding(serviceAccount *corev1.ServiceAccoun return clusterRoleBinding } -func (app Application) radixDNSAliasClusterRoleBinding(serviceAccount *corev1.ServiceAccount, clusterrole *auth.ClusterRole) *auth.ClusterRoleBinding { - // TODO - return nil - /* registration := app.registration - appName := registration.Name - clusterRoleBindingName := clusterrole.Name - ownerReference := app.getOwnerReference() - logger.Debugf("Create clusterrolebinding config %s", clusterRoleBindingName) - - clusterRoleBinding := &auth.ClusterRoleBinding{ - TypeMeta: metav1.TypeMeta{ - APIVersion: k8s.RbacApiVersion, - Kind: k8s.KindClusterRoleBinding, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: clusterRoleBindingName, - Labels: map[string]string{ - kube.RadixAppLabel: appName, - }, - OwnerReferences: ownerReference, - }, - RoleRef: auth.RoleRef{ - APIGroup: k8s.RbacApiGroup, - Kind: k8s.KindClusterRole, - Name: clusterrole.Name, - }, - Subjects: []auth.Subject{ - { - Kind: k8s.KindServiceAccount, - Name: serviceAccount.Name, - Namespace: serviceAccount.Namespace, - }, - }, - } - return clusterRoleBinding*/ -} - func (app Application) rrClusterroleBinding(clusterrole *auth.ClusterRole, subjects []auth.Subject) *auth.ClusterRoleBinding { registration := app.registration appName := registration.Name From 2c556ad3debcf5182ab373fb79d0e251c83c2110 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 13 Nov 2023 09:02:02 +0100 Subject: [PATCH 049/121] Extracted a method for tekton use --- pkg/apis/applicationconfig/applicationconfig.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index 68a5790e1..18f212b41 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -107,8 +107,13 @@ func IsConfigBranch(branch string, rr *radixv1.RadixRegistration) bool { // GetTargetEnvironments Checks if given branch requires deployment to environments func (app *ApplicationConfig) GetTargetEnvironments(branchToBuild string) []string { + return GetRadixApplicationTargetEnvironments(app.config, branchToBuild) +} + +// GetRadixApplicationTargetEnvironments Gets environments to be built for a branch +func GetRadixApplicationTargetEnvironments(radixApplication *radixv1.RadixApplication, branchToBuild string) []string { var targetEnvs []string - for _, env := range app.config.Spec.Environments { + for _, env := range radixApplication.Spec.Environments { if env.Build.From != "" && branch.MatchesPattern(env.Build.From, branchToBuild) { targetEnvs = append(targetEnvs, env.Name) } From c49a32b2c383802fc9482b5680c3a1b182ed7678 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 13 Nov 2023 13:24:19 +0100 Subject: [PATCH 050/121] Renamed property --- pipeline-runner/main.go | 4 ++-- pipeline-runner/model/pipelineInfo_test.go | 2 +- pipeline-runner/pipelines/app_test.go | 2 +- pipeline-runner/steps/build_test.go | 2 +- pkg/apis/applicationconfig/applicationconfig_test.go | 2 +- pkg/apis/applicationconfig/dns_alias_test.go | 2 +- pkg/apis/config/dnsalias/config.go | 4 ++-- pkg/apis/job/job_test.go | 4 ++-- pkg/apis/job/kubejob.go | 2 +- pkg/apis/radixvalidators/validate_ra.go | 2 +- pkg/apis/radixvalidators/validate_ra_test.go | 2 +- radix-operator/config/config.go | 2 +- radix-operator/job/controller_test.go | 2 +- 13 files changed, 16 insertions(+), 16 deletions(-) diff --git a/pipeline-runner/main.go b/pipeline-runner/main.go index a2f847972..2358f5441 100755 --- a/pipeline-runner/main.go +++ b/pipeline-runner/main.go @@ -115,7 +115,7 @@ func setPipelineArgsFromArguments(cmd *cobra.Command, pipelineArgs *model.Pipeli cmd.Flags().StringVar(&debug, "DEBUG", "false", "Debug information") cmd.Flags().StringToStringVar(&pipelineArgs.ImageTagNames, defaults.RadixImageTagNameEnvironmentVariable, make(map[string]string), "Image tag names for components (optional)") cmd.Flags().StringToStringVar(&pipelineArgs.DNSConfig.ReservedAppDNSAliases, defaults.RadixReservedAppDNSAliasesEnvironmentVariable, make(map[string]string), "The list of DNS aliases, reserved for Radix platform Radix application") - cmd.Flags().StringArrayVar(&pipelineArgs.DNSConfig.ReservedDNSAlias, defaults.RadixReservedDNSAliasesEnvironmentVariable, make([]string, 0), "The list of DNS aliases, reserved for Radix platform services") + cmd.Flags().StringArrayVar(&pipelineArgs.DNSConfig.ReservedDNSAliases, defaults.RadixReservedDNSAliasesEnvironmentVariable, make([]string, 0), "The list of DNS aliases, reserved for Radix platform services") err := cmd.Flags().Parse(arguments) if err != nil { @@ -124,7 +124,7 @@ func setPipelineArgsFromArguments(cmd *cobra.Command, pipelineArgs *model.Pipeli if len(pipelineArgs.DNSConfig.ReservedAppDNSAliases) == 0 { return fmt.Errorf("missing DNS aliases, reserved for Radix platform Radix application") } - if len(pipelineArgs.DNSConfig.ReservedDNSAlias) == 0 { + if len(pipelineArgs.DNSConfig.ReservedDNSAliases) == 0 { return fmt.Errorf("missing DNS aliases, reserved for Radix platform services") } pipelineArgs.PushImage, _ = strconv.ParseBool(pushImage) diff --git a/pipeline-runner/model/pipelineInfo_test.go b/pipeline-runner/model/pipelineInfo_test.go index f017a4c20..8367f19d6 100644 --- a/pipeline-runner/model/pipelineInfo_test.go +++ b/pipeline-runner/model/pipelineInfo_test.go @@ -191,6 +191,6 @@ func getDNSAliasConfig() *dnsalias.DNSConfig { return &dnsalias.DNSConfig{ DNSZone: "dev.radix.equinor.com", ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, - ReservedDNSAlias: []string{"grafana"}, + ReservedDNSAliases: []string{"grafana"}, } } diff --git a/pipeline-runner/pipelines/app_test.go b/pipeline-runner/pipelines/app_test.go index e1b1ed66c..9db4780ea 100644 --- a/pipeline-runner/pipelines/app_test.go +++ b/pipeline-runner/pipelines/app_test.go @@ -39,6 +39,6 @@ func getDNSAliasConfig() *dnsaliasconfig.DNSConfig { return &dnsaliasconfig.DNSConfig{ DNSZone: "dev.radix.equinor.com", ReservedAppDNSAliases: dnsaliasconfig.AppReservedDNSAlias{"api": "radix-api"}, - ReservedDNSAlias: []string{"grafana"}, + ReservedDNSAliases: []string{"grafana"}, } } diff --git a/pipeline-runner/steps/build_test.go b/pipeline-runner/steps/build_test.go index e76fee6fc..d0c1eb5e3 100644 --- a/pipeline-runner/steps/build_test.go +++ b/pipeline-runner/steps/build_test.go @@ -111,7 +111,7 @@ func getDNSAliasConfig() *dnsalias.DNSConfig { return &dnsalias.DNSConfig{ DNSZone: "dev.radix.equinor.com", ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, - ReservedDNSAlias: []string{"grafana"}, + ReservedDNSAliases: []string{"grafana"}, } } diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index b550d9a44..1635528f4 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -713,6 +713,6 @@ func getDNSAliasConfig() *dnsalias.DNSConfig { return &dnsalias.DNSConfig{ DNSZone: "dev.radix.equinor.com", ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, - ReservedDNSAlias: []string{"grafana"}, + ReservedDNSAliases: []string{"grafana"}, } } diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go index 2ad428174..c20b1745a 100644 --- a/pkg/apis/applicationconfig/dns_alias_test.go +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -321,7 +321,7 @@ func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { dnsConfig := &dnsaliasconfig.DNSConfig{ DNSZone: "dev.radix.equinor.com", ReservedAppDNSAliases: dnsaliasconfig.AppReservedDNSAlias{"api": "radix-api"}, - ReservedDNSAlias: []string{"grafana"}, + ReservedDNSAliases: []string{"grafana"}, } var testScenarios = []struct { name string diff --git a/pkg/apis/config/dnsalias/config.go b/pkg/apis/config/dnsalias/config.go index 176eb2465..d1e7c7936 100644 --- a/pkg/apis/config/dnsalias/config.go +++ b/pkg/apis/config/dnsalias/config.go @@ -7,8 +7,8 @@ type DNSConfig struct { DNSZone string // ReservedAppDNSAliases The list of DNS aliases, reserved for Radix platform Radix applications ReservedAppDNSAliases map[string]string - // ReservedDNSAlias The list of DNS aliases, reserved for Radix platform services - ReservedDNSAlias []string + // ReservedDNSAliases The list of DNS aliases, reserved for Radix platform services + ReservedDNSAliases []string } // AppReservedDNSAlias DNS aliases, reserved for Radix application diff --git a/pkg/apis/job/job_test.go b/pkg/apis/job/job_test.go index af9449c4a..145b8fc1b 100644 --- a/pkg/apis/job/job_test.go +++ b/pkg/apis/job/job_test.go @@ -909,7 +909,7 @@ func (s *RadixJobTestSuite) TestObjectSynced_UseBuildKid_HasResourcesArgs() { dnsConfig := dnsalias.DNSConfig{ DNSZone: "dev.radix.equinor.com", ReservedAppDNSAliases: map[string]string{"api": "radix-api"}, - ReservedDNSAlias: []string{"grafana"}, + ReservedDNSAliases: []string{"grafana"}, } scenarios := []struct { name string @@ -1009,7 +1009,7 @@ func getConfigWithPipelineJobsHistoryLimit(historyLimit int) *config.Config { DNSConfig: &dnsalias.DNSConfig{ DNSZone: "dev.radix.equinor.com", ReservedAppDNSAliases: map[string]string{"api": "radix-api"}, - ReservedDNSAlias: []string{"grafana"}, + ReservedDNSAliases: []string{"grafana"}, }, PipelineJobConfig: &pipelinejob.Config{ PipelineJobsHistoryLimit: historyLimit, diff --git a/pkg/apis/job/kubejob.go b/pkg/apis/job/kubejob.go index ba98d40b2..42823fbf6 100644 --- a/pkg/apis/job/kubejob.go +++ b/pkg/apis/job/kubejob.go @@ -169,7 +169,7 @@ func (job *Job) getPipelineJobArguments(appName, jobName string, jobSpec v1.Radi for dnsAlias, appName := range job.config.DNSConfig.ReservedAppDNSAliases { args = append(args, fmt.Sprintf("--%s=%s=%s", defaults.RadixReservedAppDNSAliasesEnvironmentVariable, dnsAlias, appName)) } - for _, reservedDNSAlias := range job.config.DNSConfig.ReservedDNSAlias { + for _, reservedDNSAlias := range job.config.DNSConfig.ReservedDNSAliases { args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixReservedDNSAliasesEnvironmentVariable, reservedDNSAlias)) } diff --git a/pkg/apis/radixvalidators/validate_ra.go b/pkg/apis/radixvalidators/validate_ra.go index f3ba089fc..12b56db59 100644 --- a/pkg/apis/radixvalidators/validate_ra.go +++ b/pkg/apis/radixvalidators/validate_ra.go @@ -184,7 +184,7 @@ func validateDNSAlias(radixClient radixclient.Interface, app *radixv1.RadixAppli if reservingAppName, aliasReserved := dnsAliasConfig.ReservedAppDNSAliases[dnsAlias.Domain]; aliasReserved && reservingAppName != app.Name { errs = append(errs, RadixDNSAliasIsReservedForRadixPlatformApplicationError(dnsAlias.Domain)) } - if slice.Any(dnsAliasConfig.ReservedDNSAlias, func(reservedAlias string) bool { return reservedAlias == dnsAlias.Domain }) { + if slice.Any(dnsAliasConfig.ReservedDNSAliases, func(reservedAlias string) bool { return reservedAlias == dnsAlias.Domain }) { errs = append(errs, RadixDNSAliasIsReservedForRadixPlatformServiceError(dnsAlias.Domain)) } } diff --git a/pkg/apis/radixvalidators/validate_ra_test.go b/pkg/apis/radixvalidators/validate_ra_test.go index b732937d5..ede971143 100644 --- a/pkg/apis/radixvalidators/validate_ra_test.go +++ b/pkg/apis/radixvalidators/validate_ra_test.go @@ -1892,6 +1892,6 @@ func getDNSAliasConfig() *dnsalias.DNSConfig { return &dnsalias.DNSConfig{ DNSZone: "dev.radix.equinor.com", ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, - ReservedDNSAlias: []string{"grafana"}, + ReservedDNSAliases: []string{"grafana"}, } } diff --git a/radix-operator/config/config.go b/radix-operator/config/config.go index c1cca6687..019407197 100644 --- a/radix-operator/config/config.go +++ b/radix-operator/config/config.go @@ -72,7 +72,7 @@ func NewConfig() *apiconfig.Config { DNSConfig: &dnsalias.DNSConfig{ DNSZone: getDNSZone(), ReservedAppDNSAliases: getDNSAliasAppReserved(), - ReservedDNSAlias: getDNSAliasReserved(), + ReservedDNSAliases: getDNSAliasReserved(), }, PipelineJobConfig: &pipelinejob.Config{ PipelineJobsHistoryLimit: getPipelineJobsHistoryLimit(), diff --git a/radix-operator/job/controller_test.go b/radix-operator/job/controller_test.go index a90313daf..8fa91e9c0 100644 --- a/radix-operator/job/controller_test.go +++ b/radix-operator/job/controller_test.go @@ -75,7 +75,7 @@ func (s *jobTestSuite) Test_Controller_Calls_Handler() { DNSConfig: &dnsalias.DNSConfig{ DNSZone: "dev.radix.equinor.com", ReservedAppDNSAliases: map[string]string{"api": "radix-api"}, - ReservedDNSAlias: []string{"grafana"}, + ReservedDNSAliases: []string{"grafana"}, }, PipelineJobConfig: &pipelinejob.Config{ PipelineJobsHistoryLimit: 3, From d369c3651dc002a6e69d19a8acffb572dac1cc10 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 14 Nov 2023 09:57:43 +0100 Subject: [PATCH 051/121] Merged --- pipeline-runner/steps/deploy_test.go | 2 +- pkg/apis/applicationconfig/applicationconfig.go | 2 +- .../applicationconfig/applicationconfig_test.go | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pipeline-runner/steps/deploy_test.go b/pipeline-runner/steps/deploy_test.go index cc81f3ab5..eff8dfc9a 100644 --- a/pipeline-runner/steps/deploy_test.go +++ b/pipeline-runner/steps/deploy_test.go @@ -180,7 +180,7 @@ func TestDeploy_PromotionSetup_ShouldCreateNamespacesForAllBranchesIfNotExists(t cli := steps.NewDeployStep(FakeNamespaceWatcher{}) cli.Init(kubeclient, radixclient, kubeUtil, &monitoring.Clientset{}, rr) - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) targetEnvs := application.GetTargetEnvironments("master", ra) pipelineInfo := &model.PipelineInfo{ diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index d0cfc3876..d94b66491 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -106,7 +106,7 @@ func IsConfigBranch(branch string, rr *radixv1.RadixRegistration) bool { } // GetTargetEnvironments Checks if given branch requires deployment to environments -func GetTargetEnvironments(branchToBuild string, ra *v1.RadixApplication) []string { +func GetTargetEnvironments(branchToBuild string, ra *radixv1.RadixApplication) []string { var targetEnvs []string for _, env := range ra.Spec.Environments { if env.Build.From != "" && branch.MatchesPattern(env.Build.From, branchToBuild) { diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 4950ebd2c..7b9329bb5 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -1,4 +1,4 @@ -package applicationconfig +package applicationconfig_test import ( "context" @@ -139,7 +139,7 @@ func TestIsThereAnythingToDeploy_multipleEnvsToOneBranch_ListsBoth(t *testing.T) WithEnvironment("prod", "master"). BuildRA() - targetEnvs := GetTargetEnvironments(branch, ra) + targetEnvs := applicationconfig.GetTargetEnvironments(branch, ra) assert.ElementsMatch(t, []string{"prod", "qa"}, targetEnvs) } @@ -151,7 +151,7 @@ func TestIsThereAnythingToDeploy_multipleEnvsToOneBranchOtherBranchIsChanged_Lis WithEnvironment("prod", "master"). BuildRA() - targetEnvs := GetTargetEnvironments(branch, ra) + targetEnvs := applicationconfig.GetTargetEnvironments(branch, ra) assert.Equal(t, 0, len(targetEnvs)) } @@ -163,7 +163,7 @@ func TestIsThereAnythingToDeploy_oneEnvToOneBranch_ListsBothButOnlyOneShouldBeBu WithEnvironment("prod", "master"). BuildRA() - targetEnvs := GetTargetEnvironments(branch, ra) + targetEnvs := applicationconfig.GetTargetEnvironments(branch, ra) assert.ElementsMatch(t, []string{"qa"}, targetEnvs) } @@ -175,7 +175,7 @@ func TestIsThereAnythingToDeploy_twoEnvNoBranch(t *testing.T) { WithEnvironmentNoBranch("prod"). BuildRA() - targetEnvs := GetTargetEnvironments(branch, ra) + targetEnvs := applicationconfig.GetTargetEnvironments(branch, ra) assert.Equal(t, 0, len(targetEnvs)) } @@ -185,7 +185,7 @@ func TestIsThereAnythingToDeploy_NoEnv(t *testing.T) { ra := utils.NewRadixApplicationBuilder(). BuildRA() - targetEnvs := GetTargetEnvironments(branch, ra) + targetEnvs := applicationconfig.GetTargetEnvironments(branch, ra) assert.Equal(t, 0, len(targetEnvs)) } @@ -197,7 +197,7 @@ func TestIsThereAnythingToDeploy_promotionScheme_ListsBothButOnlyOneShouldBeBuil WithEnvironment("prod", ""). BuildRA() - targetEnvs := GetTargetEnvironments(branch, ra) + targetEnvs := applicationconfig.GetTargetEnvironments(branch, ra) assert.ElementsMatch(t, []string{"qa"}, targetEnvs) } @@ -209,7 +209,7 @@ func TestIsThereAnythingToDeploy_wildcardMatch_ListsBothButOnlyOneShouldBeBuilt( WithEnvironment("prod", "master"). BuildRA() - targetEnvs := GetTargetEnvironments(branch, ra) + targetEnvs := applicationconfig.GetTargetEnvironments(branch, ra) assert.ElementsMatch(t, []string{"feature"}, targetEnvs) } From 9287fe28661cbf3da2fe91e44338790a86ea2ffc Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 14 Nov 2023 14:13:51 +0100 Subject: [PATCH 052/121] Added reserved DNS alias arguments to pipeline and tekton jobs --- .vscode/launch.json | 16 ++++++++++++---- go.mod | 2 +- go.sum | 2 ++ pipeline-runner/main.go | 2 +- pipeline-runner/steps/prepare_pipelines.go | 10 ++++++++++ pkg/apis/job/kubejob.go | 10 ++++------ radix-operator/config/config.go | 18 +++--------------- 7 files changed, 33 insertions(+), 27 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 1ce4d21b3..69619860e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -29,7 +29,9 @@ "--RADIX_FILE_NAME=/workspace/radixconfig.yaml", "--TO_ENVIRONMENT=qa", "--IMAGE_TAG_NAME=server=1.23-alpine-slim", - "--IMAGE_TAG_NAME=server2=1.22.1-alpine-perl" + "--IMAGE_TAG_NAME=server2=1.22.1-alpine-perl", + "--RADIX_RESERVED_APP_DNS_ALIASES=api=radix-api,canary=radix-canary-golang,console=radix-web-console,cost-api=radix-cost-allocation-api,webhook=radix-github-webhook", + "--RADIX_RESERVED_DNS_ALIASES=grafana,prometheus" ] }, { @@ -49,7 +51,9 @@ "--TO_ENVIRONMENT=prod", "--DEPLOYMENT_NAME=qa-etxkt-ac6rxchq", "--DEBUG=true", - "--RADIX_CONTAINER_REGISTRY=radixdev.azurecr.io" + "--RADIX_CONTAINER_REGISTRY=radixdev.azurecr.io", + "--RADIX_RESERVED_APP_DNS_ALIASES=api=radix-api,canary=radix-canary-golang,console=radix-web-console,cost-api=radix-cost-allocation-api,webhook=radix-github-webhook", + "--RADIX_RESERVED_DNS_ALIASES=grafana,prometheus" ] }, { @@ -70,7 +74,9 @@ "--RADIX_CLUSTER_TYPE=development", "--RADIX_ZONE=dev", "--RADIX_CLUSTERNAME=weekly-44", - "--RADIX_CONTAINER_REGISTRY=radixdev.azurecr.io" + "--RADIX_CONTAINER_REGISTRY=radixdev.azurecr.io", + "--RADIX_RESERVED_APP_DNS_ALIASES=api=radix-api,canary=radix-canary-golang,console=radix-web-console,cost-api=radix-cost-allocation-api,webhook=radix-github-webhook", + "--RADIX_RESERVED_DNS_ALIASES=grafana,prometheus" ] }, { @@ -126,7 +132,9 @@ "RADIX_DEPLOYMENTS_PER_ENVIRONMENT_HISTORY_LIMIT": "10", "RADIX_PIPELINE_JOBS_HISTORY_LIMIT": "5", "SECCOMP_PROFILE_FILENAME": "allow-buildah.json", - "RADIX_BUILDAH_IMAGE_BUILDER": "quay.io/buildah/stable:v1.31" + "RADIX_BUILDAH_IMAGE_BUILDER": "quay.io/buildah/stable:v1.31", + "RADIX_RESERVED_APP_DNS_ALIASES": "api=radix-api,canary=radix-canary-golang,console=radix-web-console,cost-api=radix-cost-allocation-api,webhook=radix-github-webhook", + "RADIX_RESERVED_DNS_ALIASES": "grafana,prometheus" }, "args": ["--useOutClusterClient=false"] }, diff --git a/go.mod b/go.mod index d69150403..70822af18 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( dario.cat/mergo v1.0.0 - github.com/equinor/radix-common v1.5.0 + github.com/equinor/radix-common v1.6.1-0.20231114095949-d7354edaf04c github.com/golang/mock v1.6.0 github.com/google/uuid v1.3.0 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 491c66727..13cddc4d0 100644 --- a/go.sum +++ b/go.sum @@ -74,6 +74,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/equinor/radix-common v1.5.0 h1:z5hQHlKG2x16/NnV4b9ynf9n5ZageYUewE4MANdA96Y= github.com/equinor/radix-common v1.5.0/go.mod h1:UZ69U56VFtTxABi5JjGdaqn9Df5ilfTTqzUQ0riofVM= +github.com/equinor/radix-common v1.6.1-0.20231114095949-d7354edaf04c h1:lX3lWLliPowJHMs3yp327ExdlkJvvpqU5ErRxJyV7Zg= +github.com/equinor/radix-common v1.6.1-0.20231114095949-d7354edaf04c/go.mod h1:9hHvudaiqmoIjCqKlsW14jMj8qU/b/wMXUwkffd9MUw= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= diff --git a/pipeline-runner/main.go b/pipeline-runner/main.go index 2358f5441..fe1876ce1 100755 --- a/pipeline-runner/main.go +++ b/pipeline-runner/main.go @@ -115,7 +115,7 @@ func setPipelineArgsFromArguments(cmd *cobra.Command, pipelineArgs *model.Pipeli cmd.Flags().StringVar(&debug, "DEBUG", "false", "Debug information") cmd.Flags().StringToStringVar(&pipelineArgs.ImageTagNames, defaults.RadixImageTagNameEnvironmentVariable, make(map[string]string), "Image tag names for components (optional)") cmd.Flags().StringToStringVar(&pipelineArgs.DNSConfig.ReservedAppDNSAliases, defaults.RadixReservedAppDNSAliasesEnvironmentVariable, make(map[string]string), "The list of DNS aliases, reserved for Radix platform Radix application") - cmd.Flags().StringArrayVar(&pipelineArgs.DNSConfig.ReservedDNSAliases, defaults.RadixReservedDNSAliasesEnvironmentVariable, make([]string, 0), "The list of DNS aliases, reserved for Radix platform services") + cmd.Flags().StringSliceVar(&pipelineArgs.DNSConfig.ReservedDNSAliases, defaults.RadixReservedDNSAliasesEnvironmentVariable, make([]string, 0), "The list of DNS aliases, reserved for Radix platform services") err := cmd.Flags().Parse(arguments) if err != nil { diff --git a/pipeline-runner/steps/prepare_pipelines.go b/pipeline-runner/steps/prepare_pipelines.go index 9e681f71e..99ad84afd 100644 --- a/pipeline-runner/steps/prepare_pipelines.go +++ b/pipeline-runner/steps/prepare_pipelines.go @@ -3,7 +3,9 @@ package steps import ( "context" "fmt" + "strings" + "github.com/equinor/radix-common/utils/maps" internaltekton "github.com/equinor/radix-operator/pipeline-runner/internal/tekton" internalwait "github.com/equinor/radix-operator/pipeline-runner/internal/wait" "github.com/equinor/radix-operator/pipeline-runner/model" @@ -175,6 +177,14 @@ func (cli *PreparePipelinesStepImplementation) getPreparePipelinesJobConfig(pipe Name: defaults.RadixGithubWebhookCommitId, Value: getWebhookCommitID(pipelineInfo), }, + { + Name: defaults.RadixReservedAppDNSAliasesEnvironmentVariable, + Value: maps.ToString(pipelineInfo.PipelineArguments.DNSConfig.ReservedAppDNSAliases), + }, + { + Name: defaults.RadixReservedDNSAliasesEnvironmentVariable, + Value: strings.Join(pipelineInfo.PipelineArguments.DNSConfig.ReservedDNSAliases, ","), + }, } sshURL := registration.Spec.CloneURL initContainers := cli.getInitContainerCloningRepo(pipelineInfo, configBranch, sshURL) diff --git a/pkg/apis/job/kubejob.go b/pkg/apis/job/kubejob.go index 42823fbf6..047643d3b 100644 --- a/pkg/apis/job/kubejob.go +++ b/pkg/apis/job/kubejob.go @@ -4,7 +4,9 @@ import ( "context" "fmt" "os" + "strings" + "github.com/equinor/radix-common/utils/maps" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" pipelineJob "github.com/equinor/radix-operator/pkg/apis/pipeline" @@ -165,12 +167,8 @@ func (job *Job) getPipelineJobArguments(appName, jobName string, jobSpec v1.Radi fmt.Sprintf("--%s=%s", defaults.ContainerRegistryEnvironmentVariable, containerRegistry), fmt.Sprintf("--%s=%s", defaults.AppContainerRegistryEnvironmentVariable, appContainerRegistry), fmt.Sprintf("--%s=%s", defaults.AzureSubscriptionIdEnvironmentVariable, subscriptionId), - } - for dnsAlias, appName := range job.config.DNSConfig.ReservedAppDNSAliases { - args = append(args, fmt.Sprintf("--%s=%s=%s", defaults.RadixReservedAppDNSAliasesEnvironmentVariable, dnsAlias, appName)) - } - for _, reservedDNSAlias := range job.config.DNSConfig.ReservedDNSAliases { - args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixReservedDNSAliasesEnvironmentVariable, reservedDNSAlias)) + fmt.Sprintf("--%s=%s", defaults.RadixReservedAppDNSAliasesEnvironmentVariable, maps.ToString(job.config.DNSConfig.ReservedAppDNSAliases)), + fmt.Sprintf("--%s=%s", defaults.RadixReservedDNSAliasesEnvironmentVariable, strings.Join(job.config.DNSConfig.ReservedDNSAliases, ",")), } radixConfigFullName := jobSpec.RadixConfigFullName diff --git a/radix-operator/config/config.go b/radix-operator/config/config.go index 019407197..bc76624f5 100644 --- a/radix-operator/config/config.go +++ b/radix-operator/config/config.go @@ -4,6 +4,7 @@ import ( "strconv" "strings" + "github.com/equinor/radix-common/utils/maps" apiconfig "github.com/equinor/radix-operator/pkg/apis/config" "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/config/pipelinejob" @@ -36,24 +37,11 @@ func getDNSZone() string { } func getDNSAliasAppReserved() map[string]string { - return convertToMap(viper.GetString(defaults.RadixReservedAppDNSAliasesEnvironmentVariable)) -} - -func convertToMap(keyValuePairs string) map[string]string { - pair := strings.Split(keyValuePairs, ",") - keyValues := make(map[string]string) - for _, part := range pair { - kv := strings.Split(part, "=") - if len(kv) == 2 { - keyValues[kv[0]] = kv[1] - } - } - return keyValues + return maps.FromString(viper.GetString(defaults.RadixReservedAppDNSAliasesEnvironmentVariable)) } func getDNSAliasReserved() []string { - envVar := viper.GetString(defaults.RadixReservedDNSAliasesEnvironmentVariable) - return strings.Split(envVar, ",") + return strings.Split(viper.GetString(defaults.RadixReservedDNSAliasesEnvironmentVariable), ",") } func getIntFromEnvVar(envVarName string, defaultValue int) int { From 19a5ffd130d82f0f901faf117669c53462fab38c Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 15 Nov 2023 04:59:35 +0100 Subject: [PATCH 053/121] Added reserved DNS alias roles --- pkg/apis/application/rolebinding.go | 24 +++++++++---------- pkg/apis/application/roles.go | 9 ++----- .../applicationconfig_test.go | 6 ----- pkg/apis/defaults/roles.go | 3 +++ radix-operator/dnsalias/controller.go | 24 ------------------- 5 files changed, 17 insertions(+), 49 deletions(-) diff --git a/pkg/apis/application/rolebinding.go b/pkg/apis/application/rolebinding.go index 84873f688..f0cde5d76 100644 --- a/pkg/apis/application/rolebinding.go +++ b/pkg/apis/application/rolebinding.go @@ -45,7 +45,7 @@ func (app Application) applyRbacRadixRegistration() error { // Admin RBAC clusterRoleName := fmt.Sprintf("radix-platform-user-rr-%s", appName) - adminClusterRole := app.rrClusterRole(clusterRoleName, []string{"get", "list", "watch", "update", "patch", "delete"}) + adminClusterRole := app.buildRRClusterRole(clusterRoleName, []string{"get", "list", "watch", "update", "patch", "delete"}) appAdminSubjects, err := getAppAdminSubjects(rr) if err != nil { return err @@ -54,7 +54,7 @@ func (app Application) applyRbacRadixRegistration() error { // Reader RBAC clusterRoleReaderName := fmt.Sprintf("radix-platform-user-rr-reader-%s", appName) - readerClusterRole := app.rrClusterRole(clusterRoleReaderName, []string{"get", "list", "watch"}) + readerClusterRole := app.buildRRClusterRole(clusterRoleReaderName, []string{"get", "list", "watch"}) appReaderSubjects := kube.GetRoleBindingGroups(rr.Spec.ReaderAdGroups) readerClusterRoleBinding := app.rrClusterroleBinding(readerClusterRole, appReaderSubjects) @@ -92,12 +92,12 @@ func (app Application) applyRbacOnPipelineRunner() error { logger.Errorf("Failed to apply service account needed by pipeline. %v", err) return err } - - err = app.givePipelineAccessToRR(serviceAccount, defaults.RadixPipelineRRRoleNamePrefix) - if err != nil { + if err = app.givePipelineAccessToRR(serviceAccount, defaults.RadixPipelineRRRoleNamePrefix); err != nil { + return err + } + if err = app.giveAccessToRadixDNSAliases(serviceAccount, defaults.RadixPipelineRadixDNSAliasRoleNamePrefix); err != nil { return err } - return app.givePipelineAccessToAppNamespace(serviceAccount) } @@ -109,20 +109,21 @@ func (app Application) applyRbacOnRadixTekton() error { if err = app.givePipelineAccessToRR(serviceAccount, defaults.RadixTektonRRRoleNamePrefix); err != nil { return err } - if err = app.givePipelineAccessToRadixDNSAliases(serviceAccount, defaults.RadixTektonRadixDNSAliasRoleNamePrefix); err != nil { + if err = app.giveAccessToRadixDNSAliases(serviceAccount, defaults.RadixTektonRadixDNSAliasRoleNamePrefix); err != nil { return err } return app.giveRadixTektonAccessToAppNamespace(serviceAccount) } func (app Application) givePipelineAccessToRR(serviceAccount *corev1.ServiceAccount, clusterRoleNamePrefix string) error { - clusterRole := app.rrPipelineClusterRole(clusterRoleNamePrefix) + clusterRoleName := fmt.Sprintf("%s-%s", clusterRoleNamePrefix, app.registration.Name) + clusterRole := app.buildRRClusterRole(clusterRoleName, []string{"get"}) clusterRoleBinding := app.clusterRoleBinding(serviceAccount, clusterRole) return app.applyClusterRoleAndBinding(clusterRole, clusterRoleBinding) } -func (app Application) givePipelineAccessToRadixDNSAliases(serviceAccount *corev1.ServiceAccount, clusterRoleNamePrefix string) error { - clusterRole := app.radixDNSAliasPipelineClusterRole(clusterRoleNamePrefix) +func (app Application) giveAccessToRadixDNSAliases(serviceAccount *corev1.ServiceAccount, clusterRoleNamePrefix string) error { + clusterRole := app.buildRadixDNSAliasClusterRole(clusterRoleNamePrefix) clusterRoleBinding := app.clusterRoleBinding(serviceAccount, clusterRole) return app.applyClusterRoleAndBinding(clusterRole, clusterRoleBinding) } @@ -211,8 +212,7 @@ func (app Application) radixTektonRoleBinding(serviceAccount *corev1.ServiceAcco } func (app Application) clusterRoleBinding(serviceAccount *corev1.ServiceAccount, clusterRole *auth.ClusterRole) *auth.ClusterRoleBinding { - registration := app.registration - appName := registration.Name + appName := app.registration.Name clusterRoleBindingName := clusterRole.Name ownerReference := app.getOwnerReference() logger.Debugf("Create clusterrolebinding config %s", clusterRoleBindingName) diff --git a/pkg/apis/application/roles.go b/pkg/apis/application/roles.go index ab380006c..1a0f35d47 100644 --- a/pkg/apis/application/roles.go +++ b/pkg/apis/application/roles.go @@ -10,12 +10,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func (app Application) rrPipelineClusterRole(roleNamePrefix string) *auth.ClusterRole { - clusterRoleName := fmt.Sprintf("%s-%s", roleNamePrefix, app.registration.Name) - return app.rrClusterRole(clusterRoleName, []string{"get"}) -} - -func (app Application) rrClusterRole(clusterRoleName string, verbs []string) *auth.ClusterRole { +func (app Application) buildRRClusterRole(clusterRoleName string, verbs []string) *auth.ClusterRole { appName := app.registration.Name return app.buildClusterRole(clusterRoleName, auth.PolicyRule{APIGroups: []string{radix.GroupName}, Resources: []string{radix.ResourceRadixRegistrations}, @@ -24,7 +19,7 @@ func (app Application) rrClusterRole(clusterRoleName string, verbs []string) *au }) } -func (app Application) radixDNSAliasPipelineClusterRole(roleNamePrefix string) *auth.ClusterRole { +func (app Application) buildRadixDNSAliasClusterRole(roleNamePrefix string) *auth.ClusterRole { clusterRoleName := fmt.Sprintf("%s-%s", roleNamePrefix, app.registration.Name) return app.buildClusterRole(clusterRoleName, auth.PolicyRule{APIGroups: []string{radix.GroupName}, Resources: []string{radix.ResourceRadixDNSAliases}, diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 7b9329bb5..9979fbc94 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -46,12 +46,6 @@ func setupTest() (*test.Utils, kubernetes.Interface, *kube.Kube, radixclient.Int return &handlerTestUtils, kubeClient, kubeUtil, radixClient } -func getApplication(ra *radixv1.RadixApplication) *applicationconfig.ApplicationConfig { - // The other arguments are not relevant for this test - application := applicationconfig.NewApplicationConfig(nil, nil, nil, nil, ra, nil) - return application -} - func Test_Create_Radix_Environments(t *testing.T) { _, client, kubeUtil, radixClient := setupTest() diff --git a/pkg/apis/defaults/roles.go b/pkg/apis/defaults/roles.go index bf33a3f33..cecb0c8a7 100644 --- a/pkg/apis/defaults/roles.go +++ b/pkg/apis/defaults/roles.go @@ -49,6 +49,9 @@ const ( // RadixPipelineRRRoleNamePrefix Role of to get RadixRegistrations for pipeline job RadixPipelineRRRoleNamePrefix = "radix-pipeline-rr" + // RadixPipelineRadixDNSAliasRoleNamePrefix Role of to get RadixDNSAliases for pipeline job + RadixPipelineRadixDNSAliasRoleNamePrefix = "radix-pipeline-rda" + // RadixTektonRRRoleNamePrefix Role of to get RadixRegistrations for prepare pipeline job RadixTektonRRRoleNamePrefix = "radix-tekton-rr" diff --git a/radix-operator/dnsalias/controller.go b/radix-operator/dnsalias/controller.go index bfdf30211..7d1023ae8 100644 --- a/radix-operator/dnsalias/controller.go +++ b/radix-operator/dnsalias/controller.go @@ -121,27 +121,3 @@ func deepEqual(old, new *v1.RadixDNSAlias) bool { func getOwner(radixClient radixclient.Interface, _, name string) (interface{}, error) { return radixClient.RadixV1().RadixDNSAliases().Get(context.Background(), name, metav1.GetOptions{}) } - -// func getAddedOrDroppedDNSAliasDomains(oldRa *v1.RadixApplication, newRa *v1.RadixApplication) []string { -// var dnsAliasDomains []string -// dnsAliasDomains = append(dnsAliasDomains, getMissingDNSAliasDomains(oldRa.Spec.DNSAlias, newRa.Spec.DNSAlias)...) -// dnsAliasDomains = append(dnsAliasDomains, getMissingDNSAliasDomains(newRa.Spec.DNSAlias, oldRa.Spec.DNSAlias)...) -// return dnsAliasDomains -// } -// -// // getMissingDNSAliasDomains returns dnsAlias domains that exists in source list but not in target list -// func getMissingDNSAliasDomains(source []v1.DNSAlias, target []v1.DNSAlias) []string { -// droppedDomains := make([]string, 0) -// for _, oldDNSAlias := range source { -// dropped := true -// for _, newDnsAlias := range target { -// if oldDNSAlias.Domain == newDnsAlias.Domain { -// dropped = false -// } -// } -// if dropped { -// droppedDomains = append(droppedDomains, oldDNSAlias.Domain) -// } -// } -// return droppedDomains -// } From a015dc7ef1ac6d94ceb70579b9ab4c22162d090c Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 15 Nov 2023 16:57:37 +0100 Subject: [PATCH 054/121] Removed reconcile from RDA --- .../templates/radixdnsalias.yaml | 6 ----- go.mod | 2 +- go.sum | 2 ++ json-schema/radixdnsalias.json | 9 ------- pkg/apis/deployment/ingress.go | 27 +++++++++++++------ pkg/apis/dnsalias/status.go | 4 +-- pkg/apis/ingress/ingress.go | 1 + pkg/apis/kube/kube.go | 1 + pkg/apis/radix/v1/radixdnsaliastypes.go | 2 +- pkg/apis/radix/v1/zz_generated.deepcopy.go | 3 +-- .../dnsalias/internal/syncerfactory_mock.go | 4 +-- 11 files changed, 30 insertions(+), 31 deletions(-) create mode 100644 pkg/apis/ingress/ingress.go diff --git a/charts/radix-operator/templates/radixdnsalias.yaml b/charts/radix-operator/templates/radixdnsalias.yaml index c835db973..658dad5bd 100644 --- a/charts/radix-operator/templates/radixdnsalias.yaml +++ b/charts/radix-operator/templates/radixdnsalias.yaml @@ -70,12 +70,6 @@ spec: type: object status: description: RadixDNSAliasStatus is the status for an RadixDNSAlias - properties: - reconciled: - format: date-time - type: string - required: - - reconciled type: object required: - spec diff --git a/go.mod b/go.mod index 70822af18..d4a73a789 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( dario.cat/mergo v1.0.0 - github.com/equinor/radix-common v1.6.1-0.20231114095949-d7354edaf04c + github.com/equinor/radix-common v1.6.1 github.com/golang/mock v1.6.0 github.com/google/uuid v1.3.0 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 13cddc4d0..87cc12ba4 100644 --- a/go.sum +++ b/go.sum @@ -76,6 +76,8 @@ github.com/equinor/radix-common v1.5.0 h1:z5hQHlKG2x16/NnV4b9ynf9n5ZageYUewE4MAN github.com/equinor/radix-common v1.5.0/go.mod h1:UZ69U56VFtTxABi5JjGdaqn9Df5ilfTTqzUQ0riofVM= github.com/equinor/radix-common v1.6.1-0.20231114095949-d7354edaf04c h1:lX3lWLliPowJHMs3yp327ExdlkJvvpqU5ErRxJyV7Zg= github.com/equinor/radix-common v1.6.1-0.20231114095949-d7354edaf04c/go.mod h1:9hHvudaiqmoIjCqKlsW14jMj8qU/b/wMXUwkffd9MUw= +github.com/equinor/radix-common v1.6.1 h1:gTGvSVSgd4DUQh4y05okzzfxlRqKJEjYbfEwSPJXRnM= +github.com/equinor/radix-common v1.6.1/go.mod h1:9hHvudaiqmoIjCqKlsW14jMj8qU/b/wMXUwkffd9MUw= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= diff --git a/json-schema/radixdnsalias.json b/json-schema/radixdnsalias.json index 2db076223..424bc6641 100644 --- a/json-schema/radixdnsalias.json +++ b/json-schema/radixdnsalias.json @@ -54,15 +54,6 @@ }, "status": { "description": "RadixDNSAliasStatus is the status for an RadixDNSAlias", - "properties": { - "reconciled": { - "format": "date-time", - "type": "string" - } - }, - "required": [ - "reconciled" - ], "type": "object" } }, diff --git a/pkg/apis/deployment/ingress.go b/pkg/apis/deployment/ingress.go index 0dcbe833c..96ac3ff82 100644 --- a/pkg/apis/deployment/ingress.go +++ b/pkg/apis/deployment/ingress.go @@ -27,6 +27,16 @@ type AnnotationConfiguration struct { Annotations map[string]string } +type dnsAliasType int + +const ( + dnsDefaultAlias = iota + dnsActiveClusterAlias + dnsAlias + dnsAppAlias + dnsExternalAlias +) + func (deploy *Deployment) createOrUpdateIngress(deployComponent radixv1.RadixCommonDeployComponent) error { namespace := deploy.radixDeployment.Namespace clustername, err := deploy.kubeutil.GetClusterName() @@ -228,7 +238,7 @@ func (deploy *Deployment) getAppAliasIngressConfig(appName string, ownerReferenc hostname := fmt.Sprintf("%s.%s", appName, appAlias) ingressSpec := getIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) - return deploy.getIngressConfig(appName, component, getAppAliasIngressName(appName), ownerReference, true, false, false, ingressSpec, namespace) + return deploy.getIngressConfig(appName, component, getAppAliasIngressName(appName), ownerReference, dnsAppAlias, ingressSpec, namespace) } func getAppAliasIngressName(appName string) string { @@ -249,7 +259,7 @@ func (deploy *Deployment) getActiveClusterAliasIngressConfig( ingressSpec := getIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) ingressName := getActiveClusterIngressName(component.GetName()) - return deploy.getIngressConfig(appName, component, ingressName, ownerReference, false, false, true, ingressSpec, namespace) + return deploy.getIngressConfig(appName, component, ingressName, ownerReference, dnsActiveClusterAlias, ingressSpec, namespace) } func getActiveClusterIngressName(componentName string) string { @@ -270,7 +280,7 @@ func (deploy *Deployment) getDefaultIngressConfig( hostname := getHostName(component.GetName(), namespace, clustername, dnsZone) ingressSpec := getIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) - return deploy.getIngressConfig(appName, component, getDefaultIngressName(component.GetName()), ownerReference, false, false, false, ingressSpec, namespace) + return deploy.getIngressConfig(appName, component, getDefaultIngressName(component.GetName()), ownerReference, dnsDefaultAlias, ingressSpec, namespace) } func getDefaultIngressName(componentName string) string { @@ -286,7 +296,7 @@ func (deploy *Deployment) getExternalAliasIngressConfig( publicPortNumber int32, ) (*networkingv1.Ingress, error) { ingressSpec := getIngressSpec(externalAlias, component.GetName(), externalAlias, publicPortNumber) - return deploy.getIngressConfig(appName, component, externalAlias, ownerReference, false, true, false, ingressSpec, namespace) + return deploy.getIngressConfig(appName, component, externalAlias, ownerReference, dnsExternalAlias, ingressSpec, namespace) } func getActiveClusterHostName(componentName, namespace string) string { @@ -325,7 +335,7 @@ func (deploy *Deployment) getIngressConfig( component radixv1.RadixCommonDeployComponent, ingressName string, ownerReference []metav1.OwnerReference, - isAlias, isExternalAlias, isActiveClusterAlias bool, + aliasType dnsAliasType, ingressSpec networkingv1.IngressSpec, namespace string, ) (*networkingv1.Ingress, error) { @@ -346,9 +356,10 @@ func (deploy *Deployment) getIngressConfig( Labels: map[string]string{ kube.RadixAppLabel: appName, kube.RadixComponentLabel: component.GetName(), - kube.RadixAppAliasLabel: strconv.FormatBool(isAlias), - kube.RadixExternalAliasLabel: strconv.FormatBool(isExternalAlias), - kube.RadixActiveClusterAliasLabel: strconv.FormatBool(isActiveClusterAlias), + kube.RadixAliasLabel: strconv.FormatBool(aliasType == dnsAlias), + kube.RadixAppAliasLabel: strconv.FormatBool(aliasType == dnsAppAlias), + kube.RadixExternalAliasLabel: strconv.FormatBool(aliasType == dnsExternalAlias), + kube.RadixActiveClusterAliasLabel: strconv.FormatBool(aliasType == dnsActiveClusterAlias), }, OwnerReferences: ownerReference, }, diff --git a/pkg/apis/dnsalias/status.go b/pkg/apis/dnsalias/status.go index e125e3986..085a042c9 100644 --- a/pkg/apis/dnsalias/status.go +++ b/pkg/apis/dnsalias/status.go @@ -30,9 +30,9 @@ func (s *syncer) restoreStatus() error { } func (s *syncer) syncStatus() error { - syncCompleteTime := metav1.Now() + // syncCompleteTime := metav1.Now() err := s.updateStatus(func(currStatus *radixv1.RadixDNSAliasStatus) { - currStatus.Reconciled = syncCompleteTime + // currStatus.Reconciled = &syncCompleteTime }) if err != nil { return fmt.Errorf("failed to sync status: %v", err) diff --git a/pkg/apis/ingress/ingress.go b/pkg/apis/ingress/ingress.go new file mode 100644 index 000000000..e894973a1 --- /dev/null +++ b/pkg/apis/ingress/ingress.go @@ -0,0 +1 @@ +package ingress diff --git a/pkg/apis/kube/kube.go b/pkg/apis/kube/kube.go index 5faf9c795..c653429d4 100644 --- a/pkg/apis/kube/kube.go +++ b/pkg/apis/kube/kube.go @@ -53,6 +53,7 @@ const ( RadixJobTypeRunPipelines = "run-pipelines" RadixJobTypeJobSchedule = "job-scheduler" RadixJobTypeBatchSchedule = "batch-scheduler" + RadixAliasLabel = "radix-alias" RadixAppAliasLabel = "radix-app-alias" RadixExternalAliasLabel = "radix-app-external-alias" RadixActiveClusterAliasLabel = "radix-app-active-cluster-alias" diff --git a/pkg/apis/radix/v1/radixdnsaliastypes.go b/pkg/apis/radix/v1/radixdnsaliastypes.go index 0b2bc4edb..7ee504a61 100644 --- a/pkg/apis/radix/v1/radixdnsaliastypes.go +++ b/pkg/apis/radix/v1/radixdnsaliastypes.go @@ -52,5 +52,5 @@ type RadixDNSAliasSpec struct { // RadixDNSAliasStatus is the status for an RadixDNSAlias type RadixDNSAliasStatus struct { - Reconciled meta.Time `json:"reconciled" yaml:"reconciled"` + // Reconciled *meta.Time `json:"reconciled" yaml:"reconciled"` } diff --git a/pkg/apis/radix/v1/zz_generated.deepcopy.go b/pkg/apis/radix/v1/zz_generated.deepcopy.go index 1f1ca8b8f..f5a9c80ae 100644 --- a/pkg/apis/radix/v1/zz_generated.deepcopy.go +++ b/pkg/apis/radix/v1/zz_generated.deepcopy.go @@ -1247,7 +1247,7 @@ func (in *RadixDNSAlias) DeepCopyInto(out *RadixDNSAlias) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec - in.Status.DeepCopyInto(&out.Status) + out.Status = in.Status return } @@ -1321,7 +1321,6 @@ func (in *RadixDNSAliasSpec) DeepCopy() *RadixDNSAliasSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RadixDNSAliasStatus) DeepCopyInto(out *RadixDNSAliasStatus) { *out = *in - in.Reconciled.DeepCopyInto(&out.Reconciled) return } diff --git a/radix-operator/dnsalias/internal/syncerfactory_mock.go b/radix-operator/dnsalias/internal/syncerfactory_mock.go index 8bea9f74a..90cadce5b 100644 --- a/radix-operator/dnsalias/internal/syncerfactory_mock.go +++ b/radix-operator/dnsalias/internal/syncerfactory_mock.go @@ -7,7 +7,7 @@ package internal import ( reflect "reflect" - dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" dnsalias "github.com/equinor/radix-operator/pkg/apis/dnsalias" kube "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -40,7 +40,7 @@ func (m *MockSyncerFactory) EXPECT() *MockSyncerFactoryMockRecorder { } // CreateSyncer mocks base method. -func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, dnsConfig *dnsalias2.DNSConfig, radixDNSAlias *v1.RadixDNSAlias) dnsalias.Syncer { +func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, dnsConfig *dnsaliasconfig.DNSConfig, radixDNSAlias *v1.RadixDNSAlias) dnsalias.Syncer { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateSyncer", kubeClient, kubeUtil, radixClient, dnsConfig, radixDNSAlias) ret0, _ := ret[0].(dnsalias.Syncer) From b47091349419b4e2a03eb2ba0598c86eab0c5e1c Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 16 Nov 2023 13:54:48 +0100 Subject: [PATCH 055/121] Domain in DNSAlias renamed to Alias. DNS aliases added to RadixDeployComponent --- .../templates/radixapplication.yaml | 16 +- json-schema/radixapplication.json | 12 +- pipeline-runner/steps/promotion_test.go | 22 ++- pkg/apis/applicationconfig/dns_alias.go | 8 +- pkg/apis/applicationconfig/dns_alias_test.go | 154 +++++++++--------- pkg/apis/applicationconfig/errors.go | 12 +- pkg/apis/deployment/ingress.go | 11 -- .../deployment/ingressannotationprovider.go | 7 +- .../ingressannotationprovider_test.go | 7 +- pkg/apis/deployment/radixcomponent.go | 25 ++- pkg/apis/deployment/radixcomponent_test.go | 37 +++++ pkg/apis/dnsalias/ingress.go | 20 +-- pkg/apis/dnsalias/syncer.go | 8 +- pkg/apis/dnsalias/syncer_test.go | 72 ++++---- pkg/apis/radix/v1/radixapptypes.go | 6 +- pkg/apis/radix/v1/radixdeploytypes.go | 10 ++ pkg/apis/radix/v1/zz_generated.deepcopy.go | 5 + pkg/apis/radixvalidators/errors.go | 24 +-- .../radixvalidators/testdata/radixconfig.yaml | 2 +- pkg/apis/radixvalidators/validate_ra.go | 22 +-- pkg/apis/radixvalidators/validate_ra_test.go | 12 +- pkg/apis/test/utils.go | 12 +- pkg/apis/utils/application_builder.go | 8 +- radix-operator/deployment/handler.go | 5 +- radix-operator/deployment/handler_test.go | 3 +- radix-operator/dnsalias/controller_test.go | 2 +- radix-operator/dnsalias/handler.go | 30 +++- radix-operator/dnsalias/handler_test.go | 12 +- .../dnsalias/internal/radix_dns_alias.go | 12 +- .../dnsalias/internal/syncerfactory_mock.go | 8 +- radix-operator/ingress/ingress.go | 12 ++ radix-operator/main.go | 39 +++-- radix-operator/main_test.go | 4 +- 33 files changed, 377 insertions(+), 262 deletions(-) create mode 100644 radix-operator/ingress/ingress.go diff --git a/charts/radix-operator/templates/radixapplication.yaml b/charts/radix-operator/templates/radixapplication.yaml index 69efb725d..04c7e3646 100644 --- a/charts/radix-operator/templates/radixapplication.yaml +++ b/charts/radix-operator/templates/radixapplication.yaml @@ -1086,16 +1086,16 @@ spec: description: DNSAlias defines mapping between an DNS alias and a component and environment. properties: - component: - description: Name of the component that shall receive the incoming - requests. + alias: + description: Alias name, e.g. my-app, which will prefix full + internal alias my-app.radix.equinor.com maxLength: 63 minLength: 1 pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string - domain: - description: Domain name, e.g. my-app, which will prefix full - internal alias my-app.radix.equinor.com + component: + description: Name of the component that shall receive the incoming + requests. maxLength: 63 minLength: 1 pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ @@ -1107,13 +1107,13 @@ spec: pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string required: + - alias - component - - domain - environment type: object type: array x-kubernetes-list-map-keys: - - domain + - alias x-kubernetes-list-type: map dnsAppAlias: description: 'Configure a component and environment to be linked to diff --git a/json-schema/radixapplication.json b/json-schema/radixapplication.json index ad7ed56d3..10630f60f 100644 --- a/json-schema/radixapplication.json +++ b/json-schema/radixapplication.json @@ -1092,15 +1092,15 @@ "items": { "description": "DNSAlias defines mapping between an DNS alias and a component and environment.", "properties": { - "component": { - "description": "Name of the component that shall receive the incoming requests.", + "alias": { + "description": "Alias name, e.g. my-app, which will prefix full internal alias my-app.radix.equinor.com", "maxLength": 63, "minLength": 1, "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", "type": "string" }, - "domain": { - "description": "Domain name, e.g. my-app, which will prefix full internal alias my-app.radix.equinor.com", + "component": { + "description": "Name of the component that shall receive the incoming requests.", "maxLength": 63, "minLength": 1, "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", @@ -1115,15 +1115,15 @@ } }, "required": [ + "alias", "component", - "domain", "environment" ], "type": "object" }, "type": "array", "x-kubernetes-list-map-keys": [ - "domain" + "alias" ], "x-kubernetes-list-type": "map" }, diff --git a/pipeline-runner/steps/promotion_test.go b/pipeline-runner/steps/promotion_test.go index d0b9421aa..df080e528 100644 --- a/pipeline-runner/steps/promotion_test.go +++ b/pipeline-runner/steps/promotion_test.go @@ -148,7 +148,9 @@ func TestPromote_PromoteToOtherEnvironment_NewStateIsExpected(t *testing.T) { anyPromoteJobName := "any-promote-job" anyProdEnvironment := "prod" anyDevEnvironment := "dev" - anyDNSAlias := "a-dns-alias" + anyDNSAlias1 := "a-dns-alias1" + anyDNSAlias2 := "a-dns-alias2" + anyExternalDNSAlias := "an-external-dns-alias" prodNode := v1.RadixNode{Gpu: "prod-gpu", GpuCount: "2"} // Setup @@ -156,6 +158,17 @@ func TestPromote_PromoteToOtherEnvironment_NewStateIsExpected(t *testing.T) { secretType := v1.RadixAzureKeyVaultObjectTypeSecret keyType := v1.RadixAzureKeyVaultObjectTypeKey + componentName1 := "app" + dnsAlias1 := v1.DNSAlias{ + Alias: anyDNSAlias1, + Environment: anyProdEnvironment, + Component: componentName1, + } + dnsAlias2 := v1.DNSAlias{ + Alias: anyDNSAlias2, + Environment: anyProdEnvironment, + Component: componentName1, + } _, err := commonTestUtils.ApplyDeployment( utils.NewDeploymentBuilder(). WithComponent( @@ -179,7 +192,8 @@ func TestPromote_PromoteToOtherEnvironment_NewStateIsExpected(t *testing.T) { WithEnvironment(anyDevEnvironment, "master"). WithEnvironment(anyProdEnvironment, ""). WithDNSAppAlias(anyProdEnvironment, "app"). - WithDNSExternalAlias(anyDNSAlias, anyProdEnvironment, "app"). + WithDNSExternalAlias(anyExternalDNSAlias, anyProdEnvironment, "app"). + WithDNSAlias(dnsAlias1, dnsAlias2). WithComponents( utils.AnApplicationComponent(). WithName("app"). @@ -295,7 +309,9 @@ func TestPromote_PromoteToOtherEnvironment_NewStateIsExpected(t *testing.T) { assert.Equal(t, "5678", rds.Items[0].Spec.Components[0].EnvironmentVariables["DB_PORT"]) assert.Equal(t, "mysql", rds.Items[0].Spec.Components[0].EnvironmentVariables["DB_TYPE"]) assert.Equal(t, "my-db-prod", rds.Items[0].Spec.Components[0].EnvironmentVariables["DB_NAME"]) - assert.Equal(t, anyDNSAlias, rds.Items[0].Spec.Components[0].DNSExternalAlias[0]) + assert.Equal(t, anyExternalDNSAlias, rds.Items[0].Spec.Components[0].DNSExternalAlias[0]) + assert.Contains(t, rds.Items[0].Spec.Components[0].DNSAlias, anyDNSAlias1) + assert.Contains(t, rds.Items[0].Spec.Components[0].DNSAlias, anyDNSAlias2) assert.True(t, rds.Items[0].Spec.Components[0].DNSAppAlias) assert.Len(t, rds.Items[0].Spec.Components[0].Secrets, 1) assert.Equal(t, "DEPLOYAPPSECRET", rds.Items[0].Spec.Components[0].Secrets[0]) diff --git a/pkg/apis/applicationconfig/dns_alias.go b/pkg/apis/applicationconfig/dns_alias.go index b89898a6e..53d6d6e4b 100644 --- a/pkg/apis/applicationconfig/dns_alias.go +++ b/pkg/apis/applicationconfig/dns_alias.go @@ -24,10 +24,10 @@ func (app *ApplicationConfig) createOrUpdateDNSAliases() error { if err != nil { return err } - if existingRadixDNSAlias, ok := existingRadixDNSAliasesMap[dnsAlias.Domain]; ok { + if existingRadixDNSAlias, ok := existingRadixDNSAliasesMap[dnsAlias.Alias]; ok { switch { case !strings.EqualFold(appName, existingRadixDNSAlias.Spec.AppName): - errs = append(errs, fmt.Errorf("existing DNS alias domain %s is used by the application %s", dnsAlias.Domain, existingRadixDNSAlias.Spec.AppName)) + errs = append(errs, fmt.Errorf("existing DNS alias %s is used by the application %s", dnsAlias.Alias, existingRadixDNSAlias.Spec.AppName)) case strings.EqualFold(dnsAlias.Environment, existingRadixDNSAlias.Spec.Environment) && strings.EqualFold(dnsAlias.Component, existingRadixDNSAlias.Spec.Component) && port == existingRadixDNSAlias.Spec.Port: @@ -37,7 +37,7 @@ func (app *ApplicationConfig) createOrUpdateDNSAliases() error { errs = append(errs, err) } } - delete(existingRadixDNSAliasesMap, dnsAlias.Domain) + delete(existingRadixDNSAliasesMap, dnsAlias.Alias) continue } if err = app.createRadixDNSAlias(appName, dnsAlias, port); err != nil { @@ -70,7 +70,7 @@ func (app *ApplicationConfig) updateRadixDNSAlias(radixDNSAlias *radixv1.RadixDN func (app *ApplicationConfig) createRadixDNSAlias(appName string, dnsAlias radixv1.DNSAlias, port int32) error { radixDNSAlias := radixv1.RadixDNSAlias{ ObjectMeta: metav1.ObjectMeta{ - Name: dnsAlias.Domain, + Name: dnsAlias.Alias, Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(dnsAlias.Component)), OwnerReferences: []metav1.OwnerReference{getOwnerReferenceOfApplication(app.config)}, }, diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go index c20b1745a..2e4d5664a 100644 --- a/pkg/apis/applicationconfig/dns_alias_test.go +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -30,10 +30,10 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { portA = "port-a" port8080 = 8080 port9090 = 9090 - domain1 = "domain1" - domain2 = "domain2" - domain3 = "domain3" - domain4 = "domain4" + alias1 = "alias1" + alias2 = "alias2" + alias3 = "alias3" + alias4 = "alias4" ) var testScenarios = []struct { name string @@ -50,133 +50,133 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { { name: "one alias", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). + WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, }, { name: "aliases for multiple components", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). WithDNSAlias( - radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, - radixv1.DNSAlias{Domain: domain2, Environment: env1, Component: component2}, + radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Alias: alias2, Environment: env1, Component: component2}, ). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, }, }, { name: "aliases for multiple environments", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). WithDNSAlias( - radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, - radixv1.DNSAlias{Domain: domain2, Environment: env2, Component: component1}, + radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Alias: alias2, Environment: env2, Component: component1}, ). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain2: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias2: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, }, }, { name: "multiple aliases for one component and environment", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). WithDNSAlias( - radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, - radixv1.DNSAlias{Domain: domain2, Environment: env1, Component: component1}, + radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Alias: alias2, Environment: env1, Component: component1}, ). WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain2: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias2: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, }, { name: "aliases for multiple components in different environments", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). WithDNSAlias( - radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, - radixv1.DNSAlias{Domain: domain2, Environment: env2, Component: component2}, + radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Alias: alias2, Environment: env2, Component: component2}, ). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain2: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias2: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, }, }, { name: "one alias, exist other aliases, two expected aliases", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). + WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain2: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, + alias2: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, }, expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain2: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias2: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, }, { name: "change env and component for existing aliases", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). - WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env2, Component: component2}). + WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env2, Component: component2}). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, + alias1: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, }, }, { name: "change port for existing aliases", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). - WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). + WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port9090).WithPublicPort(portA), ), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port9090}, + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port9090}, }, }, { name: "swap env and component for existing aliases-s", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). WithDNSAlias( - radixv1.DNSAlias{Domain: domain1, Environment: env2, Component: component2}, - radixv1.DNSAlias{Domain: domain2, Environment: env1, Component: component1}, + radixv1.DNSAlias{Alias: alias1, Environment: env2, Component: component2}, + radixv1.DNSAlias{Alias: alias2, Environment: env1, Component: component1}, ). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain2: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias2: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, }, expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, - domain2: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias1: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, + alias2: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, }, { @@ -184,7 +184,7 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{}, }, @@ -192,45 +192,45 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { name: "remove multiple aliases, keep other", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). WithDNSAlias( - radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}, - radixv1.DNSAlias{Domain: domain3, Environment: env2, Component: component1}, + radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}, + radixv1.DNSAlias{Alias: alias3, Environment: env2, Component: component1}, ). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, - domain3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, - domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, + alias3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, + alias4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, }, expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, - domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, + alias4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, }, }, { name: "create new, remove some, change other aliases", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). WithDNSAlias( - radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component2}, - radixv1.DNSAlias{Domain: domain3, Environment: env2, Component: component1}, + radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component2}, + radixv1.DNSAlias{Alias: alias3, Environment: env2, Component: component1}, ). WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, - domain2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, - domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, + alias2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, + alias4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, }, expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, - domain3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, - domain4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, + alias1: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, + alias3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, + alias4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, }, }, } @@ -284,7 +284,7 @@ func Test_DNSAliases_FileOndInvalidAppName(t *testing.T) { appName2 = "any-app2" env1 = "env1" component1 = "server1" - domain1 = "domain1" + alias1 = "alias1" branch1 = "branch1" portA = "port-a" port8080 = 8080 @@ -293,13 +293,13 @@ func Test_DNSAliases_FileOndInvalidAppName(t *testing.T) { _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), &radixv1.RadixDNSAlias{ - ObjectMeta: metav1.ObjectMeta{Name: domain1, Labels: map[string]string{kube.RadixAppLabel: appName1}}, + ObjectMeta: metav1.ObjectMeta{Name: alias1, Labels: map[string]string{kube.RadixAppLabel: appName1}}, Spec: radixv1.RadixDNSAliasSpec{AppName: appName2, Environment: env1, Component: component1}, }, metav1.CreateOptions{}) require.NoError(t, err, "create existing RadixDNSAlias") applicationBuilder := utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: env1, Component: component1}). + WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)) err = applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, applicationBuilder) require.Error(t, err, "register radix application") @@ -315,8 +315,8 @@ func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { someEnv = "dev" someComponentName = "component-abc" somePort = 9090 - domain1 = "domain1" - domain2 = "domain2" + alias1 = "alias1" + alias2 = "alias2" ) dnsConfig := &dnsaliasconfig.DNSConfig{ DNSZone: "dev.radix.equinor.com", @@ -336,47 +336,47 @@ func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { }, { name: "Added dns aliases", - applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: raEnv, Component: raComponentName}), + applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: raEnv, Component: raComponentName}), expectedValidationError: nil, }, { name: "Existing dns aliases for the app", - applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: raEnv, Component: raComponentName}), + applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: raEnv, Component: raComponentName}), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: raAppName, Environment: raEnv, Component: raComponentName, Port: raPublicPort}, + alias1: {AppName: raAppName, Environment: raEnv, Component: raComponentName, Port: raPublicPort}, }, expectedValidationError: nil, }, { name: "Existing dns aliases for the app and another app", - applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: raEnv, Component: raComponentName}), + applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: raEnv, Component: raComponentName}), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: raAppName, Environment: raEnv, Component: raComponentName, Port: raPublicPort}, - domain2: {AppName: otherAppName, Environment: someEnv, Component: someComponentName, Port: somePort}, + alias1: {AppName: raAppName, Environment: raEnv, Component: raComponentName, Port: raPublicPort}, + alias2: {AppName: otherAppName, Environment: someEnv, Component: someComponentName, Port: somePort}, }, expectedValidationError: nil, }, { - name: "Same domain exists in dns alias for another app", - applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Domain: domain1, Environment: raEnv, Component: raComponentName}), + name: "Same alias exists in dns alias for another app", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: raEnv, Component: raComponentName}), existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - domain1: {AppName: otherAppName, Environment: someEnv, Component: someComponentName, Port: somePort}, + alias1: {AppName: otherAppName, Environment: someEnv, Component: someComponentName, Port: somePort}, }, - expectedValidationError: applicationconfig.RadixDNSAliasAlreadyUsedByAnotherApplicationError(domain1), + expectedValidationError: applicationconfig.RadixDNSAliasAlreadyUsedByAnotherApplicationError(alias1), }, { - name: "Reserved domain api for another app", - applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Domain: "api", Environment: raEnv, Component: raComponentName}), + name: "Reserved alias api for another app", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Alias: "api", Environment: raEnv, Component: raComponentName}), expectedValidationError: applicationconfig.RadixDNSAliasIsReservedForRadixPlatformApplicationError("api"), }, { - name: "Reserved domain api for another service", - applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Domain: "grafana", Environment: raEnv, Component: raComponentName}), + name: "Reserved alias api for another service", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Alias: "grafana", Environment: raEnv, Component: raComponentName}), expectedValidationError: applicationconfig.RadixDNSAliasIsReservedForRadixPlatformServiceError("grafana"), }, { - name: "Reserved domain api for this app", - applicationBuilder: utils.ARadixApplication().WithAppName("radix-api").WithDNSAlias(radixv1.DNSAlias{Domain: "api", Environment: raEnv, Component: raComponentName}), + name: "Reserved alias api for this app", + applicationBuilder: utils.ARadixApplication().WithAppName("radix-api").WithDNSAlias(radixv1.DNSAlias{Alias: "api", Environment: raEnv, Component: raComponentName}), expectedValidationError: nil, }, } diff --git a/pkg/apis/applicationconfig/errors.go b/pkg/apis/applicationconfig/errors.go index ac5ef6ce0..24284efec 100644 --- a/pkg/apis/applicationconfig/errors.go +++ b/pkg/apis/applicationconfig/errors.go @@ -3,16 +3,16 @@ package applicationconfig import "fmt" // RadixDNSAliasAlreadyUsedByAnotherApplicationError Error when RadixDNSAlias already used by another application -func RadixDNSAliasAlreadyUsedByAnotherApplicationError(domain string) error { - return fmt.Errorf("DNS alias %s already used by another application", domain) +func RadixDNSAliasAlreadyUsedByAnotherApplicationError(alias string) error { + return fmt.Errorf("DNS alias %s already used by another application", alias) } // RadixDNSAliasIsReservedForRadixPlatformApplicationError Error when RadixDNSAlias is reserved by Radix platform for a Radix application -func RadixDNSAliasIsReservedForRadixPlatformApplicationError(domain string) error { - return fmt.Errorf("DNS alias %s is reserved by Radix platform application", domain) +func RadixDNSAliasIsReservedForRadixPlatformApplicationError(alias string) error { + return fmt.Errorf("DNS alias %s is reserved by Radix platform application", alias) } // RadixDNSAliasIsReservedForRadixPlatformServiceError Error when RadixDNSAlias is reserved by Radix platform for a Radix service -func RadixDNSAliasIsReservedForRadixPlatformServiceError(domain string) error { - return fmt.Errorf("DNS alias %s is reserved by Radix platform service", domain) +func RadixDNSAliasIsReservedForRadixPlatformServiceError(alias string) error { + return fmt.Errorf("DNS alias %s is reserved by Radix platform service", alias) } diff --git a/pkg/apis/deployment/ingress.go b/pkg/apis/deployment/ingress.go index 96ac3ff82..a3ff58b7b 100644 --- a/pkg/apis/deployment/ingress.go +++ b/pkg/apis/deployment/ingress.go @@ -16,17 +16,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// IngressConfiguration Holds all ingress annotation configurations -type IngressConfiguration struct { - AnnotationConfigurations []AnnotationConfiguration `yaml:"configuration"` -} - -// AnnotationConfiguration Holds annotations for a single configuration -type AnnotationConfiguration struct { - Name string - Annotations map[string]string -} - type dnsAliasType int const ( diff --git a/pkg/apis/deployment/ingressannotationprovider.go b/pkg/apis/deployment/ingressannotationprovider.go index 37f90dec3..799ec98aa 100644 --- a/pkg/apis/deployment/ingressannotationprovider.go +++ b/pkg/apis/deployment/ingressannotationprovider.go @@ -8,6 +8,7 @@ import ( v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" oauthutil "github.com/equinor/radix-operator/pkg/apis/utils/oauth" + "github.com/equinor/radix-operator/radix-operator/ingress" ) type IngressAnnotationProvider interface { @@ -24,12 +25,12 @@ func (forceSslRedirectAnnotationProvider) GetAnnotations(component v1.RadixCommo return map[string]string{"nginx.ingress.kubernetes.io/force-ssl-redirect": "true"}, nil } -func NewIngressConfigurationAnnotationProvider(config IngressConfiguration) IngressAnnotationProvider { +func NewIngressConfigurationAnnotationProvider(config ingress.IngressConfiguration) IngressAnnotationProvider { return &ingressConfigurationAnnotationProvider{config: config} } type ingressConfigurationAnnotationProvider struct { - config IngressConfiguration + config ingress.IngressConfiguration } func (provider *ingressConfigurationAnnotationProvider) GetAnnotations(component v1.RadixCommonDeployComponent, namespace string) (map[string]string, error) { @@ -45,7 +46,7 @@ func (provider *ingressConfigurationAnnotationProvider) GetAnnotations(component return allAnnotations, nil } -func (provider *ingressConfigurationAnnotationProvider) getAnnotationsFromConfiguration(name string, config IngressConfiguration) map[string]string { +func (provider *ingressConfigurationAnnotationProvider) getAnnotationsFromConfiguration(name string, config ingress.IngressConfiguration) map[string]string { for _, ingressConfig := range config.AnnotationConfigurations { if strings.EqualFold(ingressConfig.Name, name) { return ingressConfig.Annotations diff --git a/pkg/apis/deployment/ingressannotationprovider_test.go b/pkg/apis/deployment/ingressannotationprovider_test.go index bd9696fef..a532760e0 100644 --- a/pkg/apis/deployment/ingressannotationprovider_test.go +++ b/pkg/apis/deployment/ingressannotationprovider_test.go @@ -8,6 +8,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" + "github.com/equinor/radix-operator/radix-operator/ingress" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" @@ -19,7 +20,7 @@ func Test_NewForceSslRedirectAnnotationProvider(t *testing.T) { } func Test_NewIngressConfigurationAnnotationProvider(t *testing.T) { - cfg := IngressConfiguration{[]AnnotationConfiguration{{Name: "test"}}} + cfg := ingress.IngressConfiguration{[]ingress.AnnotationConfiguration{{Name: "test"}}} sut := NewIngressConfigurationAnnotationProvider(cfg) assert.IsType(t, &ingressConfigurationAnnotationProvider{}, sut) sutReal := sut.(*ingressConfigurationAnnotationProvider) @@ -50,8 +51,8 @@ func Test_ForceSslRedirectAnnotations(t *testing.T) { } func Test_IngressConfigurationAnnotations(t *testing.T) { - config := IngressConfiguration{ - AnnotationConfigurations: []AnnotationConfiguration{ + config := ingress.IngressConfiguration{ + AnnotationConfigurations: []ingress.AnnotationConfiguration{ {Name: "ewma", Annotations: map[string]string{"ewma1": "x", "ewma2": "y"}}, {Name: "socket", Annotations: map[string]string{"socket1": "x", "socket2": "y", "socket3": "z"}}, {Name: "round-robin", Annotations: map[string]string{"round-robin1": "1"}}, diff --git a/pkg/apis/deployment/radixcomponent.go b/pkg/apis/deployment/radixcomponent.go index 91b4737b9..587f51b00 100644 --- a/pkg/apis/deployment/radixcomponent.go +++ b/pkg/apis/deployment/radixcomponent.go @@ -3,6 +3,7 @@ package deployment import ( "dario.cat/mergo" mergoutils "github.com/equinor/radix-common/utils/mergo" + "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/pipeline" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" ) @@ -57,7 +58,8 @@ func GetRadixComponentsForEnv(radixApplication *v1.RadixApplication, env string, deployComponent.Resources = getRadixCommonComponentResources(&radixComponent, environmentSpecificConfig) deployComponent.EnvironmentVariables = getRadixCommonComponentEnvVars(&radixComponent, environmentSpecificConfig, defaultEnvVars) deployComponent.AlwaysPullImageOnDeploy = getRadixComponentAlwaysPullImageOnDeployFlag(&radixComponent, environmentSpecificConfig) - deployComponent.DNSExternalAlias = GetExternalDNSAliasForComponentEnvironment(radixApplication, componentName, env) + deployComponent.DNSAlias = getDNSAliasForComponentEnvironment(radixApplication, componentName, env) + deployComponent.DNSExternalAlias = getExternalDNSAliasForComponentEnvironment(radixApplication, componentName, env) deployComponent.SecretRefs = getRadixCommonComponentRadixSecretRefs(&radixComponent, environmentSpecificConfig) deployComponent.PublicPort = getRadixComponentPort(&radixComponent) deployComponent.Authentication = auth @@ -141,17 +143,22 @@ func getRadixComponentPort(radixComponent *v1.RadixComponent) string { return radixComponent.PublicPort } -// GetExternalDNSAliasForComponentEnvironment Gets external DNS alias -func GetExternalDNSAliasForComponentEnvironment(radixApplication *v1.RadixApplication, component, env string) []string { - dnsExternalAlias := make([]string, 0) +func getDNSAliasForComponentEnvironment(radixApplication *v1.RadixApplication, component, env string) []string { + return slice.Reduce(radixApplication.Spec.DNSAlias, make([]string, 0), func(acc []string, dnsAlias v1.DNSAlias) []string { + if dnsAlias.Component == component && dnsAlias.Environment == env { + acc = append(acc, dnsAlias.Alias) + } + return acc + }) +} - for _, externalAlias := range radixApplication.Spec.DNSExternalAlias { +func getExternalDNSAliasForComponentEnvironment(radixApplication *v1.RadixApplication, component, env string) []string { + return slice.Reduce(radixApplication.Spec.DNSExternalAlias, make([]string, 0), func(acc []string, externalAlias v1.ExternalAlias) []string { if externalAlias.Component == component && externalAlias.Environment == env { - dnsExternalAlias = append(dnsExternalAlias, externalAlias.Alias) + acc = append(acc, externalAlias.Alias) } - } - - return dnsExternalAlias + return acc + }) } func GetCascadeBoolean(first *bool, second *bool, fallback bool) bool { diff --git a/pkg/apis/deployment/radixcomponent_test.go b/pkg/apis/deployment/radixcomponent_test.go index 4ea10d24d..03c3e5fde 100644 --- a/pkg/apis/deployment/radixcomponent_test.go +++ b/pkg/apis/deployment/radixcomponent_test.go @@ -275,6 +275,43 @@ func TestGetRadixComponentsForEnv_ListOfExternalAliasesForComponent_GetListOfAli assert.Equal(t, 0, len(deployComponent[0].DNSExternalAlias)) } +func TestGetRadixComponentsForEnv_ListOfDNSAliasesForComponent_GetListOfAliases(t *testing.T) { + componentImages := make(pipeline.DeployComponentImages) + componentImages["app"] = pipeline.DeployComponentImage{ImagePath: anyImagePath} + envVarsMap := make(radixv1.EnvVarsMap) + envVarsMap[defaults.RadixCommitHashEnvironmentVariable] = "anycommit" + envVarsMap[defaults.RadixGitTagsEnvironmentVariable] = "anytag" + + ra := utils.ARadixApplication(). + WithEnvironment("prod", "release"). + WithEnvironment("dev", "master"). + WithComponents( + utils.NewApplicationComponentBuilder(). + WithName("componentA"), + utils.NewApplicationComponentBuilder(). + WithName("componentB")). + WithDNSAlias( + radixv1.DNSAlias{Alias: "alias1", Component: "componentA", Environment: "prod"}, + radixv1.DNSAlias{Alias: "alias2", Component: "componentA", Environment: "prod"}, + radixv1.DNSAlias{Alias: "alias3", Component: "componentA", Environment: "dev"}, + ).BuildRA() + + prodDeployComponent, _ := GetRadixComponentsForEnv(ra, "prod", componentImages, envVarsMap) + assert.Equal(t, 2, len(prodDeployComponent)) + assert.Equal(t, 2, len(prodDeployComponent[0].DNSAlias)) + require.Len(t, prodDeployComponent[0].DNSAlias, 2) + assert.Equal(t, "alias1", prodDeployComponent[0].DNSAlias[0]) + assert.Equal(t, "componentA", prodDeployComponent[0].GetName()) + assert.Equal(t, "alias2", prodDeployComponent[0].DNSAlias[1]) + + devDeployComponent, _ := GetRadixComponentsForEnv(ra, "dev", componentImages, envVarsMap) + assert.Equal(t, 2, len(devDeployComponent)) + assert.Equal(t, 1, len(devDeployComponent[0].DNSAlias)) + require.Len(t, devDeployComponent[0].DNSAlias, 1) + assert.Equal(t, "alias3", devDeployComponent[0].DNSAlias[0]) + assert.Equal(t, "componentA", devDeployComponent[0].GetName()) +} + func TestGetRadixComponentsForEnv_CommonEnvironmentVariables_No_Override(t *testing.T) { componentImages := make(pipeline.DeployComponentImages) componentImages["app"] = pipeline.DeployComponentImage{ImagePath: anyImagePath} diff --git a/pkg/apis/dnsalias/ingress.go b/pkg/apis/dnsalias/ingress.go index cf53da82b..8002b1554 100644 --- a/pkg/apis/dnsalias/ingress.go +++ b/pkg/apis/dnsalias/ingress.go @@ -22,15 +22,15 @@ func CreateRadixDNSAliasIngress(kubeClient kubernetes.Interface, appName, envNam } // BuildRadixDNSAliasIngress Build an Ingress for a RadixDNSAlias -func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, owner *v1.RadixDNSAlias, config *dnsalias.DNSConfig) *networkingv1.Ingress { +func BuildRadixDNSAliasIngress(appName, alias, service string, port int32, owner *v1.RadixDNSAlias, config *dnsalias.DNSConfig) *networkingv1.Ingress { pathTypeImplementationSpecific := networkingv1.PathTypeImplementationSpecific - ingressName := GetDNSAliasIngressName(service, domain) - host := GetDNSAliasHost(domain, config.DNSZone) + ingressName := GetDNSAliasIngressName(service, alias) + host := GetDNSAliasHost(alias, config.DNSZone) ingress := networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{ Name: ingressName, Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(service)), - Annotations: annotations.ForManagedByRadixDNSAliasIngress(domain), + Annotations: annotations.ForManagedByRadixDNSAliasIngress(alias), }, Spec: networkingv1.IngressSpec{ TLS: []networkingv1.IngressTLS{ @@ -60,12 +60,12 @@ func BuildRadixDNSAliasIngress(appName, domain, service string, port int32, owne } // GetDNSAliasIngressName Gets name of the ingress for the custom DNS alias -func GetDNSAliasIngressName(service string, domain string) string { - return fmt.Sprintf("%s.%s.custom-domain", service, domain) +func GetDNSAliasIngressName(service string, alias string) string { + return fmt.Sprintf("%s.%s.custom-alias", service, alias) } -// GetDNSAliasHost Gets DNS alias domain host. -// Example for the domain "my-app" and the cluster "Playground": my-app.playground.radix.equinor.com -func GetDNSAliasHost(domain string, dnsZone string) string { - return fmt.Sprintf("%s.%s", domain, dnsZone) +// GetDNSAliasHost Gets DNS alias host. +// Example for the alias "my-app" and the cluster "Playground": my-app.playground.radix.equinor.com +func GetDNSAliasHost(alias string, dnsZone string) string { + return fmt.Sprintf("%s.%s", alias, dnsZone) } diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 603b13897..117ca8fbb 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -53,9 +53,9 @@ func (s *syncer) OnSync() error { func (s *syncer) syncAlias() error { aliasSpec := s.radixDNSAlias.Spec - domainName := s.radixDNSAlias.GetName() + aliasName := s.radixDNSAlias.GetName() envNamespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) - ingressName := GetDNSAliasIngressName(aliasSpec.Component, domainName) + ingressName := GetDNSAliasIngressName(aliasSpec.Component, aliasName) existingIngress, err := s.kubeUtil.GetIngress(envNamespace, ingressName) if err != nil { if errors.IsNotFound(err) { @@ -86,6 +86,6 @@ func (s *syncer) createIngress() error { func (s *syncer) buildIngress() (*networkingv1.Ingress, error) { aliasSpec := s.radixDNSAlias.Spec - domain := s.radixDNSAlias.GetName() - return BuildRadixDNSAliasIngress(aliasSpec.AppName, domain, aliasSpec.Component, aliasSpec.Port, s.radixDNSAlias, s.dnsConfig), nil + alias := s.radixDNSAlias.GetName() + return BuildRadixDNSAliasIngress(aliasSpec.AppName, alias, aliasSpec.Component, aliasSpec.Port, s.radixDNSAlias, s.dnsConfig), nil } diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 4d24bb0b9..9c7a3e3b3 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -51,13 +51,13 @@ func (s *syncerTestSuite) createSyncer(radixDNSAlias *radixv1.RadixDNSAlias) dns type testIngress struct { appName string envName string - domain string + alias string host string component string port int32 } type testDNSAlias struct { - Domain string + Alias string Environment string Component string Port int32 @@ -80,8 +80,8 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { envName2 = "env2" component1 = "component1" component2 = "component2" - domain1 = "domain1" - domain2 = "domain2" + alias1 = "alias1" + alias2 = "alias2" port8080 = 8080 port9090 = 9090 dnsZone1 = "dev.radix.equinor.com" @@ -90,109 +90,109 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { scenarios := []scenario{ { name: "created an ingress", - dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, dnsZone: dnsZone1, expectedIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, }, }, { name: "created additional ingress for another component", - dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, dnsZone: dnsZone1, existingIngress: map[string]testIngress{ - "component2.domain2.custom-domain": {appName: appName1, envName: envName1, domain: domain2, host: dnsalias.GetDNSAliasHost(domain2, dnsZone1), component: component2, port: port8080}, + "component2.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: port8080}, }, expectedIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, - "component2.domain2.custom-domain": {appName: appName1, envName: envName1, domain: domain2, host: dnsalias.GetDNSAliasHost(domain2, dnsZone1), component: component2, port: port8080}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + "component2.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: port8080}, }, }, { name: "changed port changes port in existing ingress", - dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port9090}, + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port9090}, dnsZone: dnsZone1, existingIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, }, expectedIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port9090}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port9090}, }, }, { - name: "created additional ingress on another domain for the same component", - dnsAlias: testDNSAlias{Domain: domain2, Environment: envName1, Component: component1, Port: port8080}, + name: "created additional ingress on another alias for the same component", + dnsAlias: testDNSAlias{Alias: alias2, Environment: envName1, Component: component1, Port: port8080}, dnsZone: dnsZone1, existingIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, }, expectedIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, - "component1.domain2.custom-domain": {appName: appName1, envName: envName1, domain: domain2, host: dnsalias.GetDNSAliasHost(domain2, dnsZone1), component: component1, port: port8080}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + "component1.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, }, }, { name: "manually changed appName repaired", - dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, dnsZone: dnsZone1, existingIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName2, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component2, port: port8080}, + "component1.alias1.custom-alias": {appName: appName2, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, }, expectedIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, }, }, { name: "manually changed envName repaired", - dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, dnsZone: dnsZone1, existingIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName2, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component2, port: port8080}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName2, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, }, expectedIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, }, }, { name: "manually changed component repaired", - dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, dnsZone: dnsZone1, existingIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component2, port: port8080}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, }, expectedIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, }, }, { name: "manually changed port repaired", - dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, dnsZone: dnsZone1, existingIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port9090}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port9090}, }, expectedIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, }, }, { name: "manually changed host repaired", - dnsAlias: testDNSAlias{Domain: domain1, Environment: envName1, Component: component1, Port: port8080}, + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, dnsZone: dnsZone1, existingIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: "/manually/edited/host", component: component1, port: port8080}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: "/manually/edited/host", component: component1, port: port8080}, }, expectedIngress: map[string]testIngress{ - "component1.domain1.custom-domain": {appName: appName1, envName: envName1, domain: domain1, host: dnsalias.GetDNSAliasHost(domain1, dnsZone1), component: component1, port: port8080}, + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, }, }, } for _, ts := range scenarios { s.T().Run(ts.name, func(t *testing.T) { s.SetupTest() - radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Domain, UID: uuid.NewUUID()}, + radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Alias, UID: uuid.NewUUID()}, Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component, Port: ts.dnsAlias.Port}} - s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Domain, radixDNSAlias.Spec), "create existing alias") + s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Alias, radixDNSAlias.Spec), "create existing alias") cfg := &dnsalias2.DNSConfig{DNSZone: ts.dnsZone} s.Require().NoError(registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1, cfg), "create existing ingresses") syncer := s.createSyncer(radixDNSAlias) @@ -242,7 +242,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses map[string]testIngress, appNameForNamespace, envNameForNamespace string, config *dnsalias2.DNSConfig) error { for name, ing := range testIngresses { - ingress := dnsalias.BuildRadixDNSAliasIngress(ing.appName, ing.domain, ing.component, ing.port, nil, config) + ingress := dnsalias.BuildRadixDNSAliasIngress(ing.appName, ing.alias, ing.component, ing.port, nil, config) ingress.SetName(name) // override built name with expected name for test purpose _, err := dnsalias.CreateRadixDNSAliasIngress(kubeClient, appNameForNamespace, envNameForNamespace, ingress) if err != nil { diff --git a/pkg/apis/radix/v1/radixapptypes.go b/pkg/apis/radix/v1/radixapptypes.go index 83a5b0bab..2b72eb1b7 100644 --- a/pkg/apis/radix/v1/radixapptypes.go +++ b/pkg/apis/radix/v1/radixapptypes.go @@ -97,7 +97,7 @@ type RadixApplicationSpec struct { // List of DNS names and which component and environment incoming requests shall be routed to. // More info: https://www.radix.equinor.com/references/reference-radix-config/#dnsalias // +listType=map - // +listMapKey=domain + // +listMapKey=alias // +optional DNSAlias []DNSAlias `json:"dnsAlias,omitempty"` @@ -252,11 +252,11 @@ type ExternalAlias struct { // DNSAlias defines mapping between an DNS alias and a component and environment. type DNSAlias struct { - // Domain name, e.g. my-app, which will prefix full internal alias my-app.radix.equinor.com + // Alias name, e.g. my-app, which will prefix full internal alias my-app.radix.equinor.com // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Pattern=`^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$` - Domain string `json:"domain"` + Alias string `json:"alias"` // Name of the environment for the component. // +kubebuilder:validation:MinLength=1 diff --git a/pkg/apis/radix/v1/radixdeploytypes.go b/pkg/apis/radix/v1/radixdeploytypes.go index 3482b7a6e..86e5e9991 100644 --- a/pkg/apis/radix/v1/radixdeploytypes.go +++ b/pkg/apis/radix/v1/radixdeploytypes.go @@ -97,6 +97,7 @@ type RadixDeployComponent struct { SecretRefs RadixSecretRefs `json:"secretRefs,omitempty" yaml:"secretRefs,omitempty"` IngressConfiguration []string `json:"ingressConfiguration,omitempty" yaml:"ingressConfiguration,omitempty"` DNSAppAlias bool `json:"dnsAppAlias,omitempty" yaml:"dnsAppAlias,omitempty"` + DNSAlias []string `json:"dnsAlias,omitempty" yaml:"dnsAlias,omitempty"` DNSExternalAlias []string `json:"dnsExternalAlias,omitempty" yaml:"dnsExternalAlias,omitempty"` Monitoring bool `json:"monitoring" yaml:"monitoring"` MonitoringConfig MonitoringConfig `json:"monitoringConfig,omitempty" yaml:"monitoringConfig,omitempty"` @@ -177,6 +178,10 @@ func (deployComponent *RadixDeployComponent) GetDNSExternalAlias() []string { return deployComponent.DNSExternalAlias } +func (deployComponent *RadixDeployComponent) GetDNSAlias() []string { + return deployComponent.DNSAlias +} + func (deployComponent *RadixDeployComponent) IsDNSAppAlias() bool { return deployComponent.DNSAppAlias } @@ -282,6 +287,10 @@ func (deployJobComponent *RadixDeployJobComponent) GetDNSExternalAlias() []strin return nil } +func (deployJobComponent *RadixDeployJobComponent) GetDNSAlias() []string { + return nil +} + func (deployJobComponent *RadixDeployJobComponent) IsDNSAppAlias() bool { return false } @@ -379,6 +388,7 @@ type RadixCommonDeployComponent interface { GetHorizontalScaling() *RadixHorizontalScaling GetPublicPort() string IsPublic() bool + GetDNSAlias() []string GetDNSExternalAlias() []string IsDNSAppAlias() bool GetIngressConfiguration() []string diff --git a/pkg/apis/radix/v1/zz_generated.deepcopy.go b/pkg/apis/radix/v1/zz_generated.deepcopy.go index f5a9c80ae..78008448b 100644 --- a/pkg/apis/radix/v1/zz_generated.deepcopy.go +++ b/pkg/apis/radix/v1/zz_generated.deepcopy.go @@ -1365,6 +1365,11 @@ func (in *RadixDeployComponent) DeepCopyInto(out *RadixDeployComponent) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.DNSAlias != nil { + in, out := &in.DNSAlias, &out.DNSAlias + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.DNSExternalAlias != nil { in, out := &in.DNSExternalAlias, &out.DNSExternalAlias *out = make([]string, len(*in)) diff --git a/pkg/apis/radixvalidators/errors.go b/pkg/apis/radixvalidators/errors.go index 3e63d515d..92a0e13d6 100644 --- a/pkg/apis/radixvalidators/errors.go +++ b/pkg/apis/radixvalidators/errors.go @@ -100,14 +100,14 @@ var ( ErrMissingAzureIdentity = errors.New("missing identity") ) -// DomainForDNSAliasNotDefinedError Error when domain is not valid -func DomainForDNSAliasNotDefinedError() error { - return fmt.Errorf("invalid or missing domain for dnsAlias") +// AliasForDNSAliasNotDefinedError Error when alias is not valid +func AliasForDNSAliasNotDefinedError() error { + return fmt.Errorf("invalid or missing alias for dnsAlias") } -// DuplicateDomainForDNSAliasError Error when domains are duplicate -func DuplicateDomainForDNSAliasError(domain string) error { - return fmt.Errorf("duplicate domains %s in dnsAlias-es are not allowed", domain) +// DuplicateAliasForDNSAliasError Error when aliases are duplicate +func DuplicateAliasForDNSAliasError(alias string) error { + return fmt.Errorf("duplicate aliases %s in dnsAliases are not allowed", alias) } // EnvForDNSAliasNotDefinedError Error when env not defined @@ -126,18 +126,18 @@ func ComponentForDNSAliasIsNotMarkedAsPublicError(component string) error { } // RadixDNSAliasAlreadyUsedByAnotherApplicationError Error when RadixDNSAlias already used by another application -func RadixDNSAliasAlreadyUsedByAnotherApplicationError(domain string) error { - return fmt.Errorf("DNS alias %s already used by another application", domain) +func RadixDNSAliasAlreadyUsedByAnotherApplicationError(alias string) error { + return fmt.Errorf("DNS alias %s already used by another application", alias) } // RadixDNSAliasIsReservedForRadixPlatformApplicationError Error when RadixDNSAlias is reserved by Radix platform for a Radix application -func RadixDNSAliasIsReservedForRadixPlatformApplicationError(domain string) error { - return fmt.Errorf("DNS alias %s is reserved by Radix platform application", domain) +func RadixDNSAliasIsReservedForRadixPlatformApplicationError(alias string) error { + return fmt.Errorf("DNS alias %s is reserved by Radix platform application", alias) } // RadixDNSAliasIsReservedForRadixPlatformServiceError Error when RadixDNSAlias is reserved by Radix platform for a Radix service -func RadixDNSAliasIsReservedForRadixPlatformServiceError(domain string) error { - return fmt.Errorf("DNS alias %s is reserved by Radix platform service", domain) +func RadixDNSAliasIsReservedForRadixPlatformServiceError(alias string) error { + return fmt.Errorf("DNS alias %s is reserved by Radix platform service", alias) } // MissingPrivateImageHubUsernameErrorWithMessage Error when username for private image hubs is not defined diff --git a/pkg/apis/radixvalidators/testdata/radixconfig.yaml b/pkg/apis/radixvalidators/testdata/radixconfig.yaml index da6de23ca..df7fd18f1 100644 --- a/pkg/apis/radixvalidators/testdata/radixconfig.yaml +++ b/pkg/apis/radixvalidators/testdata/radixconfig.yaml @@ -150,4 +150,4 @@ spec: dnsAlias: - environment: prod component: app2 - domain: my-domain \ No newline at end of file + alias: my-alias \ No newline at end of file diff --git a/pkg/apis/radixvalidators/validate_ra.go b/pkg/apis/radixvalidators/validate_ra.go index 12b56db59..d0c9186f5 100644 --- a/pkg/apis/radixvalidators/validate_ra.go +++ b/pkg/apis/radixvalidators/validate_ra.go @@ -150,14 +150,14 @@ func validateDNSAlias(radixClient radixclient.Interface, app *radixv1.RadixAppli if err != nil { return err } - uniqueDomainNames := make(map[string]struct{}) + uniqueAliasNames := make(map[string]struct{}) for _, dnsAlias := range app.Spec.DNSAlias { - if _, ok := uniqueDomainNames[dnsAlias.Domain]; ok { - errs = append(errs, DuplicateDomainForDNSAliasError(dnsAlias.Domain)) - } else if err = validateRequiredResourceName("dnsAlias domain", dnsAlias.Domain); err != nil { + if _, ok := uniqueAliasNames[dnsAlias.Alias]; ok { + errs = append(errs, DuplicateAliasForDNSAliasError(dnsAlias.Alias)) + } else if err = validateRequiredResourceName("dnsAlias alias", dnsAlias.Alias); err != nil { errs = append(errs, err) } - uniqueDomainNames[dnsAlias.Domain] = struct{}{} + uniqueAliasNames[dnsAlias.Alias] = struct{}{} componentNameIsValid, environmentNameIsValid := true, true if err = validateRequiredResourceName("dnsAlias component", dnsAlias.Component); err != nil { errs = append(errs, err) @@ -178,14 +178,14 @@ func validateDNSAlias(radixClient radixclient.Interface, app *radixv1.RadixAppli errs = append(errs, ComponentForDNSAliasIsNotMarkedAsPublicError(dnsAlias.Component)) continue } - if radixDNSAlias, ok := radixDNSAliasMap[dnsAlias.Domain]; ok && radixDNSAlias.Spec.AppName != app.Name { - errs = append(errs, RadixDNSAliasAlreadyUsedByAnotherApplicationError(dnsAlias.Domain)) + if radixDNSAlias, ok := radixDNSAliasMap[dnsAlias.Alias]; ok && radixDNSAlias.Spec.AppName != app.Name { + errs = append(errs, RadixDNSAliasAlreadyUsedByAnotherApplicationError(dnsAlias.Alias)) } - if reservingAppName, aliasReserved := dnsAliasConfig.ReservedAppDNSAliases[dnsAlias.Domain]; aliasReserved && reservingAppName != app.Name { - errs = append(errs, RadixDNSAliasIsReservedForRadixPlatformApplicationError(dnsAlias.Domain)) + if reservingAppName, aliasReserved := dnsAliasConfig.ReservedAppDNSAliases[dnsAlias.Alias]; aliasReserved && reservingAppName != app.Name { + errs = append(errs, RadixDNSAliasIsReservedForRadixPlatformApplicationError(dnsAlias.Alias)) } - if slice.Any(dnsAliasConfig.ReservedDNSAliases, func(reservedAlias string) bool { return reservedAlias == dnsAlias.Domain }) { - errs = append(errs, RadixDNSAliasIsReservedForRadixPlatformServiceError(dnsAlias.Domain)) + if slice.Any(dnsAliasConfig.ReservedDNSAliases, func(reservedAlias string) bool { return reservedAlias == dnsAlias.Alias }) { + errs = append(errs, RadixDNSAliasIsReservedForRadixPlatformServiceError(dnsAlias.Alias)) } } return errors.Join(errs...) diff --git a/pkg/apis/radixvalidators/validate_ra_test.go b/pkg/apis/radixvalidators/validate_ra_test.go index ede971143..a7c236189 100644 --- a/pkg/apis/radixvalidators/validate_ra_test.go +++ b/pkg/apis/radixvalidators/validate_ra_test.go @@ -222,20 +222,20 @@ func Test_invalid_ra(t *testing.T) { {"dns alias non existing env", radixvalidators.EnvForDNSAliasNotDefinedError(noExistingEnvironment), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias[0].Environment = noExistingEnvironment }}, - {"dns alias domain is empty", radixvalidators.ResourceNameCannotBeEmptyErrorWithMessage("dnsAlias domain"), func(ra *v1.RadixApplication) { - ra.Spec.DNSAlias[0].Domain = "" + {"dns alias alias is empty", radixvalidators.ResourceNameCannotBeEmptyErrorWithMessage("dnsAlias alias"), func(ra *v1.RadixApplication) { + ra.Spec.DNSAlias[0].Alias = "" }}, - {"dns alias domain is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameErrorWithMessage("dnsAlias domain", "my.domain"), func(ra *v1.RadixApplication) { - ra.Spec.DNSAlias[0].Domain = "my.domain" + {"dns alias alias is invalid", radixvalidators.InvalidLowerCaseAlphaNumericDashResourceNameErrorWithMessage("dnsAlias alias", "my.alias"), func(ra *v1.RadixApplication) { + ra.Spec.DNSAlias[0].Alias = "my.alias" }}, - {"dns alias domain is invalid", radixvalidators.DuplicateDomainForDNSAliasError("my-domain"), func(ra *v1.RadixApplication) { + {"dns alias alias is invalid", radixvalidators.DuplicateAliasForDNSAliasError("my-alias"), func(ra *v1.RadixApplication) { ra.Spec.DNSAlias = append(ra.Spec.DNSAlias, ra.Spec.DNSAlias[0]) }}, {"dns alias with no public port", radixvalidators.ComponentForDNSAliasIsNotMarkedAsPublicError(validRAComponentNameApp2), func(ra *v1.RadixApplication) { ra.Spec.Components[3].PublicPort = "" ra.Spec.Components[3].Public = false ra.Spec.DNSAlias[0] = v1.DNSAlias{ - Domain: "my-domain", + Alias: "my-alias", Component: ra.Spec.Components[3].Name, Environment: ra.Spec.Environments[0].Name, } diff --git a/pkg/apis/test/utils.go b/pkg/apis/test/utils.go index 8952b274f..f72be8f9d 100644 --- a/pkg/apis/test/utils.go +++ b/pkg/apis/test/utils.go @@ -402,8 +402,8 @@ func AssertError(t *testing.T, expectedError string, err error) { // RegisterRadixDNSAliases Register RadixDNSAliases func RegisterRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]radixv1.RadixDNSAliasSpec) error { - for domain, aliasesSpec := range radixDNSAliasesMap { - err := RegisterRadixDNSAliasBySpec(radixClient, domain, aliasesSpec) + for alias, aliasesSpec := range radixDNSAliasesMap { + err := RegisterRadixDNSAliasBySpec(radixClient, alias, aliasesSpec) if err != nil { return err } @@ -412,8 +412,8 @@ func RegisterRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesM } // RegisterRadixDNSAlias Register RadixDNSAlias by properties -func RegisterRadixDNSAlias(radixClient radixclient.Interface, appName, componentName, envName, domain string, port int32) error { - return RegisterRadixDNSAliasBySpec(radixClient, domain, radixv1.RadixDNSAliasSpec{ +func RegisterRadixDNSAlias(radixClient radixclient.Interface, appName, componentName, envName, alias string, port int32) error { + return RegisterRadixDNSAliasBySpec(radixClient, alias, radixv1.RadixDNSAliasSpec{ AppName: appName, Environment: envName, Component: componentName, @@ -422,11 +422,11 @@ func RegisterRadixDNSAlias(radixClient radixclient.Interface, appName, component } // RegisterRadixDNSAliasBySpec Register RadixDNSAlias by its spec -func RegisterRadixDNSAliasBySpec(radixClient radixclient.Interface, domain string, aliasesSpec radixv1.RadixDNSAliasSpec) error { +func RegisterRadixDNSAliasBySpec(radixClient radixclient.Interface, alias string, aliasesSpec radixv1.RadixDNSAliasSpec) error { _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), &radixv1.RadixDNSAlias{ ObjectMeta: metav1.ObjectMeta{ - Name: domain, + Name: alias, Labels: map[string]string{kube.RadixAppLabel: aliasesSpec.AppName}, }, Spec: aliasesSpec, diff --git a/pkg/apis/utils/application_builder.go b/pkg/apis/utils/application_builder.go index d518a3f30..57d08f3a6 100644 --- a/pkg/apis/utils/application_builder.go +++ b/pkg/apis/utils/application_builder.go @@ -120,14 +120,14 @@ func (ap *ApplicationBuilderStruct) WithDNSAppAlias(env, component string) Appli return ap } -// WithDNSAlias Sets domain for env and component to be the DNS alias like "my-domain.radix.equinor.com" or "my-domain..radix.equinor.com" +// WithDNSAlias Sets alias for env and component to be the DNS alias like "my-alias.radix.equinor.com" or "my-alias..radix.equinor.com" func (ap *ApplicationBuilderStruct) WithDNSAlias(dnsAliases ...radixv1.DNSAlias) ApplicationBuilder { var dnsAliasesToAppend []radixv1.DNSAlias for _, dnsAlias := range dnsAliases { foundExistingAlias := false for i := 0; i < len(ap.dnsAliases); i++ { - if strings.EqualFold(dnsAlias.Domain, ap.dnsAliases[i].Domain) { - ap.dnsAliases[i].Domain = dnsAlias.Domain + if strings.EqualFold(dnsAlias.Alias, ap.dnsAliases[i].Alias) { + ap.dnsAliases[i].Alias = dnsAlias.Alias ap.dnsAliases[i].Environment = dnsAlias.Environment ap.dnsAliases[i].Component = dnsAlias.Component foundExistingAlias = true @@ -138,7 +138,7 @@ func (ap *ApplicationBuilderStruct) WithDNSAlias(dnsAliases ...radixv1.DNSAlias) continue } dnsAliasesToAppend = append(dnsAliasesToAppend, radixv1.DNSAlias{ - Domain: dnsAlias.Domain, + Alias: dnsAlias.Alias, Environment: dnsAlias.Environment, Component: dnsAlias.Component, }) diff --git a/radix-operator/deployment/handler.go b/radix-operator/deployment/handler.go index 3f9d30ceb..c38df30dc 100644 --- a/radix-operator/deployment/handler.go +++ b/radix-operator/deployment/handler.go @@ -11,6 +11,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/kube" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" + "github.com/equinor/radix-operator/radix-operator/ingress" monitoring "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned" log "github.com/sirupsen/logrus" @@ -81,7 +82,7 @@ func WithOAuth2ProxyDockerImage(image string) HandlerConfigOption { } // WithIngressConfiguration sets the list of custom ingress confiigurations -func WithIngressConfiguration(config deployment.IngressConfiguration) HandlerConfigOption { +func WithIngressConfiguration(config ingress.IngressConfiguration) HandlerConfigOption { return func(h *Handler) { h.ingressConfiguration = config } @@ -106,7 +107,7 @@ type Handler struct { deploymentHistoryLimit int oauth2DefaultConfig defaults.OAuth2Config oauth2ProxyDockerImage string - ingressConfiguration deployment.IngressConfiguration + ingressConfiguration ingress.IngressConfiguration deploymentSyncerFactory deployment.DeploymentSyncerFactory } diff --git a/radix-operator/deployment/handler_test.go b/radix-operator/deployment/handler_test.go index bd97cc60f..28bc1ed6d 100644 --- a/radix-operator/deployment/handler_test.go +++ b/radix-operator/deployment/handler_test.go @@ -5,6 +5,7 @@ import ( "strconv" "testing" + "github.com/equinor/radix-operator/radix-operator/ingress" secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake" "github.com/equinor/radix-operator/pkg/apis/defaults" @@ -129,7 +130,7 @@ func (s *handlerSuite) Test_Sync() { syncer.EXPECT().OnSync().Times(1) factory := deployment.NewMockDeploymentSyncerFactory(ctrl) oauthConfig := defaults.NewOAuth2Config() - ingressConfig := deployment.IngressConfiguration{AnnotationConfigurations: []deployment.AnnotationConfiguration{{Name: "test"}}} + ingressConfig := ingress.IngressConfiguration{AnnotationConfigurations: []ingress.AnnotationConfiguration{{Name: "test"}}} expectedIngressAnnotations := []deployment.IngressAnnotationProvider{ deployment.NewForceSslRedirectAnnotationProvider(), deployment.NewIngressConfigurationAnnotationProvider(ingressConfig), diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go index 719075542..68fc9c6c1 100644 --- a/radix-operator/dnsalias/controller_test.go +++ b/radix-operator/dnsalias/controller_test.go @@ -42,7 +42,7 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { const ( appName1 = "any-app1" appName2 = "any-app2" - aliasName = "alias-domain-1" + aliasName = "alias-alias-1" envName1 = "env1" envName2 = "env2" componentName1 = "server1" diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go index 50080e5c9..c37665c8d 100644 --- a/radix-operator/dnsalias/handler.go +++ b/radix-operator/dnsalias/handler.go @@ -4,11 +4,13 @@ import ( "fmt" dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" + "github.com/equinor/radix-operator/radix-operator/ingress" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -27,12 +29,14 @@ const ( // Handler Handler for radix dns aliases type handler struct { - kubeClient kubernetes.Interface - kubeUtil *kube.Kube - radixClient radixclient.Interface - syncerFactory internal.SyncerFactory - hasSynced common.HasSynced - dnsConfig *dnsalias2.DNSConfig + kubeClient kubernetes.Interface + kubeUtil *kube.Kube + radixClient radixclient.Interface + syncerFactory internal.SyncerFactory + hasSynced common.HasSynced + dnsConfig *dnsalias2.DNSConfig + ingressConfiguration ingress.IngressConfiguration + oauth2DefaultConfig defaults.OAuth2Config } // NewHandler creates a handler for managing RadixDNSAlias resources @@ -67,6 +71,20 @@ func WithSyncerFactory(factory internal.SyncerFactory) HandlerConfigOption { } } +// WithIngressConfiguration sets the list of custom ingress confiigurations +func WithIngressConfiguration(config ingress.IngressConfiguration) HandlerConfigOption { + return func(h *handler) { + h.ingressConfiguration = config + } +} + +// WithOAuth2DefaultConfig configures default OAuth2 settings +func WithOAuth2DefaultConfig(oauth2Config defaults.OAuth2Config) HandlerConfigOption { + return func(h *handler) { + h.oauth2DefaultConfig = oauth2Config + } +} + // Sync is called by kubernetes after the Controller Enqueues a work-item func (h *handler) Sync(_, name string, eventRecorder record.EventRecorder) error { radixDNSAlias, err := h.kubeUtil.GetRadixDNSAlias(name) diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index 17653742a..c4de5c60d 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -24,7 +24,7 @@ const ( appName1 = "appName1" env1 = "env1" component1 = "component1" - domain1 = "domain1" + alias1 = "alias1" ) func (s *handlerTestSuite) SetupTest() { @@ -49,31 +49,31 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any()).Times(0) s.syncer.EXPECT().OnSync().Times(0) - err := handler.Sync("", domain1, s.EventRecorder) + err := handler.Sync("", alias1, s.EventRecorder) s.Require().NoError(err) } func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} - s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, domain1, 8080), "create existing RadixDNSAlias") + s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1, 8080), "create existing RadixDNSAlias") handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) expectedError := fmt.Errorf("some error") s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any()).Return(s.syncer).Times(1) s.syncer.EXPECT().OnSync().Return(expectedError).Times(1) - actualError := handler.Sync("", domain1, s.EventRecorder) + actualError := handler.Sync("", alias1, s.EventRecorder) s.Equal(expectedError, actualError) } func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsNoError() { dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} - s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, domain1, 8080), "create existing RadixDNSAlias") + s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1, 8080), "create existing RadixDNSAlias") handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any()).Return(s.syncer).Times(1) s.syncer.EXPECT().OnSync().Return(nil).Times(1) - err := handler.Sync("", domain1, s.EventRecorder) + err := handler.Sync("", alias1, s.EventRecorder) s.Require().Nil(err) } diff --git a/radix-operator/dnsalias/internal/radix_dns_alias.go b/radix-operator/dnsalias/internal/radix_dns_alias.go index 4d76450ef..ef49741ea 100644 --- a/radix-operator/dnsalias/internal/radix_dns_alias.go +++ b/radix-operator/dnsalias/internal/radix_dns_alias.go @@ -9,10 +9,10 @@ import ( ) // BuildRadixDNSAlias Build a RadixDNSAlias -func BuildRadixDNSAlias(appName, componentName, envName, domain string) *radixv1.RadixDNSAlias { +func BuildRadixDNSAlias(appName, componentName, envName, alias string) *radixv1.RadixDNSAlias { return &radixv1.RadixDNSAlias{ ObjectMeta: metav1.ObjectMeta{ - Name: domain, + Name: alias, Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(componentName)), }, Spec: radixv1.RadixDNSAliasSpec{ @@ -22,8 +22,8 @@ func BuildRadixDNSAlias(appName, componentName, envName, domain string) *radixv1 }} } -// GetDNSAliasHost Gets DNS alias domain host. -// Example for the domain "my-app" and the cluster "Playground": my-app.playground.radix.equinor.com -func GetDNSAliasHost(domain string, dnsZone string) string { - return fmt.Sprintf("%s.%s", domain, dnsZone) +// GetDNSAliasHost Gets DNS alias host. +// Example for the alias "my-app" and the cluster "Playground": my-app.playground.radix.equinor.com +func GetDNSAliasHost(alias string, dnsZone string) string { + return fmt.Sprintf("%s.%s", alias, dnsZone) } diff --git a/radix-operator/dnsalias/internal/syncerfactory_mock.go b/radix-operator/dnsalias/internal/syncerfactory_mock.go index 90cadce5b..e5616b5f2 100644 --- a/radix-operator/dnsalias/internal/syncerfactory_mock.go +++ b/radix-operator/dnsalias/internal/syncerfactory_mock.go @@ -7,8 +7,8 @@ package internal import ( reflect "reflect" - dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" - dnsalias "github.com/equinor/radix-operator/pkg/apis/dnsalias" + dnsalias "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + dnsalias0 "github.com/equinor/radix-operator/pkg/apis/dnsalias" kube "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" versioned "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -40,10 +40,10 @@ func (m *MockSyncerFactory) EXPECT() *MockSyncerFactoryMockRecorder { } // CreateSyncer mocks base method. -func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, dnsConfig *dnsaliasconfig.DNSConfig, radixDNSAlias *v1.RadixDNSAlias) dnsalias.Syncer { +func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, dnsConfig *dnsalias.DNSConfig, radixDNSAlias *v1.RadixDNSAlias) dnsalias0.Syncer { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateSyncer", kubeClient, kubeUtil, radixClient, dnsConfig, radixDNSAlias) - ret0, _ := ret[0].(dnsalias.Syncer) + ret0, _ := ret[0].(dnsalias0.Syncer) return ret0 } diff --git a/radix-operator/ingress/ingress.go b/radix-operator/ingress/ingress.go new file mode 100644 index 000000000..ff5db8dea --- /dev/null +++ b/radix-operator/ingress/ingress.go @@ -0,0 +1,12 @@ +package ingress + +// IngressConfiguration Holds all ingress annotation configurations +type IngressConfiguration struct { + AnnotationConfigurations []AnnotationConfiguration `yaml:"configuration"` +} + +// AnnotationConfiguration Holds annotations for a single configuration +type AnnotationConfiguration struct { + Name string + Annotations map[string]string +} diff --git a/radix-operator/main.go b/radix-operator/main.go index 186e6bb1f..2e615f2a4 100644 --- a/radix-operator/main.go +++ b/radix-operator/main.go @@ -14,7 +14,6 @@ import ( apiconfig "github.com/equinor/radix-operator/pkg/apis/config" dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" - deploymentAPI "github.com/equinor/radix-operator/pkg/apis/deployment" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -27,6 +26,7 @@ import ( "github.com/equinor/radix-operator/radix-operator/deployment" "github.com/equinor/radix-operator/radix-operator/dnsalias" "github.com/equinor/radix-operator/radix-operator/environment" + "github.com/equinor/radix-operator/radix-operator/ingress" "github.com/equinor/radix-operator/radix-operator/job" "github.com/equinor/radix-operator/radix-operator/registration" monitoring "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned" @@ -73,15 +73,16 @@ func main() { kubeInformerFactory := kubeinformers.NewSharedInformerFactory(client, resyncPeriod) radixInformerFactory := radixinformers.NewSharedInformerFactory(radixClient, resyncPeriod) + oauthDefaultConfig := getOAuthDefaultConfig() startController(createRegistrationController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), registrationControllerThreads, stop) startController(createApplicationController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg.DNSConfig), applicationControllerThreads, stop) startController(createEnvironmentController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), environmentControllerThreads, stop) - startController(createDeploymentController(client, radixClient, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), deploymentControllerThreads, stop) + startController(createDeploymentController(client, radixClient, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, oauthDefaultConfig), deploymentControllerThreads, stop) startController(createJobController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg), jobControllerThreads, stop) startController(createAlertController(client, radixClient, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), alertControllerThreads, stop) startController(createBatchController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), 1, stop) - startController(createDNSAliasesController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg.DNSConfig), environmentControllerThreads, stop) + startController(createDNSAliasesController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, oauthDefaultConfig, cfg.DNSConfig), environmentControllerThreads, stop) // Start informers when all controllers are running kubeInformerFactory.Start(stop) @@ -93,6 +94,13 @@ func main() { <-sigTerm } +func getOAuthDefaultConfig() defaults.OAuth2Config { + return defaults.NewOAuth2Config( + defaults.WithOAuth2Defaults(), + defaults.WithOIDCIssuerURL(os.Getenv(defaults.RadixOAuthProxyDefaultOIDCIssuerURLEnvironmentVariable)), + ) +} + func startController(controller *common.Controller, threadiness int, stop <-chan struct{}) { go func() { if err := controller.Run(threadiness, stop); err != nil { @@ -196,7 +204,10 @@ func createEnvironmentController(client kubernetes.Interface, radixClient radixc recorder) } -func createDNSAliasesController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, dnsConfig *dnsaliasconfig.DNSConfig) *common.Controller { +func createDNSAliasesController(client kubernetes.Interface, radixClient radixclient.Interface, + kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, + recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, + oauthDefaultConfig defaults.OAuth2Config, dnsConfig *dnsaliasconfig.DNSConfig) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, @@ -205,12 +216,19 @@ func createDNSAliasesController(client kubernetes.Interface, radixClient radixcl radixInformerFactory, ) + ingressConfiguration, err := loadIngressConfigFromMap(kubeUtil) + if err != nil { + panic(fmt.Errorf("failed to load ingress configuration: %v", err)) + } + handler := dnsalias.NewHandler( client, kubeUtil, radixClient, dnsConfig, func(syncedOk bool) {}, // Not interested in getting notifications of synced + dnsalias.WithIngressConfiguration(ingressConfiguration), + dnsalias.WithOAuth2DefaultConfig(oauthDefaultConfig), ) const waitForChildrenToSync = true @@ -224,7 +242,10 @@ func createDNSAliasesController(client kubernetes.Interface, radixClient radixcl recorder) } -func createDeploymentController(client kubernetes.Interface, radixClient radixclient.Interface, prometheusOperatorClient monitoring.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface) *common.Controller { +func createDeploymentController(client kubernetes.Interface, radixClient radixclient.Interface, prometheusOperatorClient monitoring.Interface, + kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, + recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, + oauthDefaultConfig defaults.OAuth2Config) *common.Controller { kubeUtil, _ := kube.NewWithListers( client, radixClient, @@ -233,10 +254,6 @@ func createDeploymentController(client kubernetes.Interface, radixClient radixcl radixInformerFactory, ) - oauthDefaultConfig := defaults.NewOAuth2Config( - defaults.WithOAuth2Defaults(), - defaults.WithOIDCIssuerURL(os.Getenv(defaults.RadixOAuthProxyDefaultOIDCIssuerURLEnvironmentVariable)), - ) ingressConfiguration, err := loadIngressConfigFromMap(kubeUtil) if err != nil { panic(fmt.Errorf("failed to load ingress configuration: %v", err)) @@ -336,8 +353,8 @@ func createBatchController(client kubernetes.Interface, radixClient radixclient. recorder) } -func loadIngressConfigFromMap(kubeutil *kube.Kube) (deploymentAPI.IngressConfiguration, error) { - ingressConfig := deploymentAPI.IngressConfiguration{} +func loadIngressConfigFromMap(kubeutil *kube.Kube) (ingress.IngressConfiguration, error) { + ingressConfig := ingress.IngressConfiguration{} configMap, err := kubeutil.GetConfigMap(metav1.NamespaceDefault, ingressConfigurationMap) if err != nil { return ingressConfig, err diff --git a/radix-operator/main_test.go b/radix-operator/main_test.go index 528819387..a1be21664 100644 --- a/radix-operator/main_test.go +++ b/radix-operator/main_test.go @@ -3,8 +3,8 @@ package main import ( "testing" - deploymentAPI "github.com/equinor/radix-operator/pkg/apis/deployment" "github.com/equinor/radix-operator/pkg/apis/kube" + "github.com/equinor/radix-operator/radix-operator/ingress" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -27,7 +27,7 @@ configuration: Data: map[string]string{"ingressConfiguration": ingressConfig}, } kubeutil, _ := kube.New(kubefake.NewSimpleClientset(&ingressCm), nil, nil) - expected := []deploymentAPI.AnnotationConfiguration{ + expected := []ingress.AnnotationConfiguration{ {Name: "foo", Annotations: map[string]string{"foo1": "x"}}, {Name: "bar", Annotations: map[string]string{"bar1": "x", "bar2": "y"}}, } From 65fa7ef235381464de5f7413afbc0bd2c0a2e06f Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 16 Nov 2023 14:08:20 +0100 Subject: [PATCH 056/121] Ingress interfaces moved to pkg --- pkg/apis/deployment/ingressannotationprovider.go | 2 +- .../deployment/ingressannotationprovider_test.go | 2 +- pkg/apis/ingress/ingress.go | 11 +++++++++++ radix-operator/deployment/handler.go | 2 +- radix-operator/deployment/handler_test.go | 2 +- radix-operator/dnsalias/handler.go | 2 +- radix-operator/ingress/ingress.go | 12 ------------ radix-operator/main.go | 2 +- radix-operator/main_test.go | 2 +- 9 files changed, 18 insertions(+), 19 deletions(-) delete mode 100644 radix-operator/ingress/ingress.go diff --git a/pkg/apis/deployment/ingressannotationprovider.go b/pkg/apis/deployment/ingressannotationprovider.go index 799ec98aa..2634ff58f 100644 --- a/pkg/apis/deployment/ingressannotationprovider.go +++ b/pkg/apis/deployment/ingressannotationprovider.go @@ -5,10 +5,10 @@ import ( "strings" "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/ingress" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" oauthutil "github.com/equinor/radix-operator/pkg/apis/utils/oauth" - "github.com/equinor/radix-operator/radix-operator/ingress" ) type IngressAnnotationProvider interface { diff --git a/pkg/apis/deployment/ingressannotationprovider_test.go b/pkg/apis/deployment/ingressannotationprovider_test.go index a532760e0..cd95d0839 100644 --- a/pkg/apis/deployment/ingressannotationprovider_test.go +++ b/pkg/apis/deployment/ingressannotationprovider_test.go @@ -6,9 +6,9 @@ import ( maputils "github.com/equinor/radix-common/utils/maps" "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/ingress" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" - "github.com/equinor/radix-operator/radix-operator/ingress" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" diff --git a/pkg/apis/ingress/ingress.go b/pkg/apis/ingress/ingress.go index e894973a1..ff5db8dea 100644 --- a/pkg/apis/ingress/ingress.go +++ b/pkg/apis/ingress/ingress.go @@ -1 +1,12 @@ package ingress + +// IngressConfiguration Holds all ingress annotation configurations +type IngressConfiguration struct { + AnnotationConfigurations []AnnotationConfiguration `yaml:"configuration"` +} + +// AnnotationConfiguration Holds annotations for a single configuration +type AnnotationConfiguration struct { + Name string + Annotations map[string]string +} diff --git a/radix-operator/deployment/handler.go b/radix-operator/deployment/handler.go index c38df30dc..a7d351577 100644 --- a/radix-operator/deployment/handler.go +++ b/radix-operator/deployment/handler.go @@ -8,10 +8,10 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/deployment" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" - "github.com/equinor/radix-operator/radix-operator/ingress" monitoring "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned" log "github.com/sirupsen/logrus" diff --git a/radix-operator/deployment/handler_test.go b/radix-operator/deployment/handler_test.go index 28bc1ed6d..c959d90c2 100644 --- a/radix-operator/deployment/handler_test.go +++ b/radix-operator/deployment/handler_test.go @@ -5,7 +5,7 @@ import ( "strconv" "testing" - "github.com/equinor/radix-operator/radix-operator/ingress" + "github.com/equinor/radix-operator/pkg/apis/ingress" secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake" "github.com/equinor/radix-operator/pkg/apis/defaults" diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go index c37665c8d..2ffc0aa9d 100644 --- a/radix-operator/dnsalias/handler.go +++ b/radix-operator/dnsalias/handler.go @@ -6,11 +6,11 @@ import ( dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" - "github.com/equinor/radix-operator/radix-operator/ingress" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" diff --git a/radix-operator/ingress/ingress.go b/radix-operator/ingress/ingress.go deleted file mode 100644 index ff5db8dea..000000000 --- a/radix-operator/ingress/ingress.go +++ /dev/null @@ -1,12 +0,0 @@ -package ingress - -// IngressConfiguration Holds all ingress annotation configurations -type IngressConfiguration struct { - AnnotationConfigurations []AnnotationConfiguration `yaml:"configuration"` -} - -// AnnotationConfiguration Holds annotations for a single configuration -type AnnotationConfiguration struct { - Name string - Annotations map[string]string -} diff --git a/radix-operator/main.go b/radix-operator/main.go index 2e615f2a4..a49f2870a 100644 --- a/radix-operator/main.go +++ b/radix-operator/main.go @@ -14,6 +14,7 @@ import ( apiconfig "github.com/equinor/radix-operator/pkg/apis/config" dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -26,7 +27,6 @@ import ( "github.com/equinor/radix-operator/radix-operator/deployment" "github.com/equinor/radix-operator/radix-operator/dnsalias" "github.com/equinor/radix-operator/radix-operator/environment" - "github.com/equinor/radix-operator/radix-operator/ingress" "github.com/equinor/radix-operator/radix-operator/job" "github.com/equinor/radix-operator/radix-operator/registration" monitoring "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned" diff --git a/radix-operator/main_test.go b/radix-operator/main_test.go index a1be21664..14325be8c 100644 --- a/radix-operator/main_test.go +++ b/radix-operator/main_test.go @@ -3,8 +3,8 @@ package main import ( "testing" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" - "github.com/equinor/radix-operator/radix-operator/ingress" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" From 9eb2f54b40cf6ce906e5fe61989433106440f356 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 16 Nov 2023 14:16:44 +0100 Subject: [PATCH 057/121] Fixed linter failure --- pkg/apis/deployment/ingressannotationprovider_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/apis/deployment/ingressannotationprovider_test.go b/pkg/apis/deployment/ingressannotationprovider_test.go index cd95d0839..30227677b 100644 --- a/pkg/apis/deployment/ingressannotationprovider_test.go +++ b/pkg/apis/deployment/ingressannotationprovider_test.go @@ -20,7 +20,7 @@ func Test_NewForceSslRedirectAnnotationProvider(t *testing.T) { } func Test_NewIngressConfigurationAnnotationProvider(t *testing.T) { - cfg := ingress.IngressConfiguration{[]ingress.AnnotationConfiguration{{Name: "test"}}} + cfg := ingress.IngressConfiguration{AnnotationConfigurations: []ingress.AnnotationConfiguration{{Name: "test"}}} sut := NewIngressConfigurationAnnotationProvider(cfg) assert.IsType(t, &ingressConfigurationAnnotationProvider{}, sut) sutReal := sut.(*ingressConfigurationAnnotationProvider) From 23e4524b1ac1f07e60f976d5d0596a66f8a00021 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 16 Nov 2023 16:28:25 +0100 Subject: [PATCH 058/121] Extracted kubeUtil for all controllers --- radix-operator/main.go | 193 +++++++++++++++-------------------------- 1 file changed, 71 insertions(+), 122 deletions(-) diff --git a/radix-operator/main.go b/radix-operator/main.go index a49f2870a..e3b9c44eb 100644 --- a/radix-operator/main.go +++ b/radix-operator/main.go @@ -73,16 +73,27 @@ func main() { kubeInformerFactory := kubeinformers.NewSharedInformerFactory(client, resyncPeriod) radixInformerFactory := radixinformers.NewSharedInformerFactory(radixClient, resyncPeriod) + kubeUtil, _ := kube.NewWithListers( + client, + radixClient, + secretProviderClient, + kubeInformerFactory, + radixInformerFactory, + ) oauthDefaultConfig := getOAuthDefaultConfig() + ingressConfiguration, err := loadIngressConfigFromMap(kubeUtil) + if err != nil { + panic(fmt.Errorf("failed to load ingress configuration: %v", err)) + } - startController(createRegistrationController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), registrationControllerThreads, stop) - startController(createApplicationController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg.DNSConfig), applicationControllerThreads, stop) - startController(createEnvironmentController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), environmentControllerThreads, stop) - startController(createDeploymentController(client, radixClient, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, oauthDefaultConfig), deploymentControllerThreads, stop) - startController(createJobController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, cfg), jobControllerThreads, stop) - startController(createAlertController(client, radixClient, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), alertControllerThreads, stop) - startController(createBatchController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), 1, stop) - startController(createDNSAliasesController(client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient, oauthDefaultConfig, cfg.DNSConfig), environmentControllerThreads, stop) + startController(createRegistrationController(kubeUtil, kubeInformerFactory, radixInformerFactory, eventRecorder), registrationControllerThreads, stop) + startController(createApplicationController(kubeUtil, kubeInformerFactory, radixInformerFactory, eventRecorder, cfg.DNSConfig), applicationControllerThreads, stop) + startController(createEnvironmentController(kubeUtil, kubeInformerFactory, radixInformerFactory, eventRecorder), environmentControllerThreads, stop) + startController(createDeploymentController(kubeUtil, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder, oauthDefaultConfig, ingressConfiguration), deploymentControllerThreads, stop) + startController(createJobController(kubeUtil, kubeInformerFactory, radixInformerFactory, eventRecorder, cfg), jobControllerThreads, stop) + startController(createAlertController(kubeUtil, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder), alertControllerThreads, stop) + startController(createBatchController(kubeUtil, client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), 1, stop) + startController(createDNSAliasesController(kubeUtil, kubeInformerFactory, radixInformerFactory, eventRecorder, oauthDefaultConfig, ingressConfiguration, cfg.DNSConfig), environmentControllerThreads, stop) // Start informers when all controllers are running kubeInformerFactory.Start(stop) @@ -123,26 +134,18 @@ func getInitParams() (int, int, int, int, int, int, int, float32, error) { return registrationControllerThreads, applicationControllerThreads, environmentControllerThreads, deploymentControllerThreads, jobControllerThreads, alertControllerThreads, kubeClientRateLimitBurst, kubeClientRateLimitQPS, errCat } -func createRegistrationController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface) *common.Controller { - kubeUtil, _ := kube.NewWithListers( - client, - radixClient, - secretProviderClient, - kubeInformerFactory, - radixInformerFactory, - ) - +func createRegistrationController(kubeUtil *kube.Kube, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder) *common.Controller { handler := registration.NewHandler( - client, + kubeUtil.KubeClient(), kubeUtil, - radixClient, + kubeUtil.RadixClient(), func(syncedOk bool) {}, // Not interested in getting notifications of synced ) const waitForChildrenToSync = true return registration.NewController( - client, - radixClient, + kubeUtil.KubeClient(), + kubeUtil.RadixClient(), &handler, kubeInformerFactory, radixInformerFactory, @@ -150,26 +153,19 @@ func createRegistrationController(client kubernetes.Interface, radixClient radix recorder) } -func createApplicationController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, dnsConfig *dnsaliasconfig.DNSConfig) *common.Controller { - kubeUtil, _ := kube.NewWithListers( - client, - radixClient, - secretProviderClient, - kubeInformerFactory, - radixInformerFactory, - ) - - handler := application.NewHandler(client, +func createApplicationController(kubeUtil *kube.Kube, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, dnsConfig *dnsaliasconfig.DNSConfig) *common.Controller { + handler := application.NewHandler( + kubeUtil.KubeClient(), kubeUtil, - radixClient, + kubeUtil.RadixClient(), dnsConfig, func(syncedOk bool) {}, // Not interested in getting notifications of synced ) const waitForChildrenToSync = true return application.NewController( - client, - radixClient, + kubeUtil.KubeClient(), + kubeUtil.RadixClient(), &handler, kubeInformerFactory, radixInformerFactory, @@ -177,26 +173,18 @@ func createApplicationController(client kubernetes.Interface, radixClient radixc recorder) } -func createEnvironmentController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface) *common.Controller { - kubeUtil, _ := kube.NewWithListers( - client, - radixClient, - secretProviderClient, - kubeInformerFactory, - radixInformerFactory, - ) - +func createEnvironmentController(kubeUtil *kube.Kube, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder) *common.Controller { handler := environment.NewHandler( - client, + kubeUtil.KubeClient(), kubeUtil, - radixClient, + kubeUtil.RadixClient(), func(syncedOk bool) {}, // Not interested in getting notifications of synced ) const waitForChildrenToSync = true return environment.NewController( - client, - radixClient, + kubeUtil.KubeClient(), + kubeUtil.RadixClient(), &handler, kubeInformerFactory, radixInformerFactory, @@ -204,27 +192,15 @@ func createEnvironmentController(client kubernetes.Interface, radixClient radixc recorder) } -func createDNSAliasesController(client kubernetes.Interface, radixClient radixclient.Interface, +func createDNSAliasesController(kubeUtil *kube.Kube, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, - recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, - oauthDefaultConfig defaults.OAuth2Config, dnsConfig *dnsaliasconfig.DNSConfig) *common.Controller { - kubeUtil, _ := kube.NewWithListers( - client, - radixClient, - secretProviderClient, - kubeInformerFactory, - radixInformerFactory, - ) - - ingressConfiguration, err := loadIngressConfigFromMap(kubeUtil) - if err != nil { - panic(fmt.Errorf("failed to load ingress configuration: %v", err)) - } + recorder record.EventRecorder, oauthDefaultConfig defaults.OAuth2Config, ingressConfiguration ingress.IngressConfiguration, + dnsConfig *dnsaliasconfig.DNSConfig) *common.Controller { handler := dnsalias.NewHandler( - client, + kubeUtil.KubeClient(), kubeUtil, - radixClient, + kubeUtil.RadixClient(), dnsConfig, func(syncedOk bool) {}, // Not interested in getting notifications of synced dnsalias.WithIngressConfiguration(ingressConfiguration), @@ -233,8 +209,8 @@ func createDNSAliasesController(client kubernetes.Interface, radixClient radixcl const waitForChildrenToSync = true return dnsalias.NewController( - client, - radixClient, + kubeUtil.KubeClient(), + kubeUtil.RadixClient(), handler, kubeInformerFactory, radixInformerFactory, @@ -242,30 +218,18 @@ func createDNSAliasesController(client kubernetes.Interface, radixClient radixcl recorder) } -func createDeploymentController(client kubernetes.Interface, radixClient radixclient.Interface, prometheusOperatorClient monitoring.Interface, +func createDeploymentController(kubeUtil *kube.Kube, prometheusOperatorClient monitoring.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, - recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, - oauthDefaultConfig defaults.OAuth2Config) *common.Controller { - kubeUtil, _ := kube.NewWithListers( - client, - radixClient, - secretProviderClient, - kubeInformerFactory, - radixInformerFactory, - ) - - ingressConfiguration, err := loadIngressConfigFromMap(kubeUtil) - if err != nil { - panic(fmt.Errorf("failed to load ingress configuration: %v", err)) - } + recorder record.EventRecorder, oauthDefaultConfig defaults.OAuth2Config, ingressConfiguration ingress.IngressConfiguration) *common.Controller { oauth2DockerImage := os.Getenv(defaults.RadixOAuthProxyImageEnvironmentVariable) if oauth2DockerImage == "" { panic(fmt.Errorf("failed to read OAuth2 Docker image from environment variable %s", defaults.RadixOAuthProxyImageEnvironmentVariable)) } - handler := deployment.NewHandler(client, + handler := deployment.NewHandler( + kubeUtil.KubeClient(), kubeUtil, - radixClient, + kubeUtil.RadixClient(), prometheusOperatorClient, deployment.WithTenantIdFromEnvVar(defaults.OperatorTenantIdEnvironmentVariable), deployment.WithKubernetesApiPortFromEnvVar(defaults.KubernetesApiPortEnvironmentVariable), @@ -277,8 +241,8 @@ func createDeploymentController(client kubernetes.Interface, radixClient radixcl const waitForChildrenToSync = true return deployment.NewController( - client, - radixClient, + kubeUtil.KubeClient(), + kubeUtil.RadixClient(), handler, kubeInformerFactory, radixInformerFactory, @@ -286,40 +250,33 @@ func createDeploymentController(client kubernetes.Interface, radixClient radixcl recorder) } -func createJobController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface, config *apiconfig.Config) *common.Controller { - kubeUtil, _ := kube.NewWithListers( - client, - radixClient, - secretProviderClient, - kubeInformerFactory, - radixInformerFactory, - ) - - handler := job.NewHandler(client, kubeUtil, radixClient, config, func(syncedOk bool) {}) // Not interested in getting notifications of synced +func createJobController(kubeUtil *kube.Kube, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, config *apiconfig.Config) *common.Controller { + handler := job.NewHandler( + kubeUtil.KubeClient(), + kubeUtil, + kubeUtil.RadixClient(), + config, + func(syncedOk bool) {}) // Not interested in getting notifications of synced const waitForChildrenToSync = true - return job.NewController(client, radixClient, &handler, kubeInformerFactory, radixInformerFactory, waitForChildrenToSync, recorder) + return job.NewController( + kubeUtil.KubeClient(), + kubeUtil.RadixClient(), + &handler, kubeInformerFactory, radixInformerFactory, waitForChildrenToSync, recorder) } -func createAlertController(client kubernetes.Interface, radixClient radixclient.Interface, prometheusOperatorClient monitoring.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface) *common.Controller { - kubeUtil, _ := kube.NewWithListers( - client, - radixClient, - secretProviderClient, - kubeInformerFactory, - radixInformerFactory, - ) - - handler := alert.NewHandler(client, +func createAlertController(kubeUtil *kube.Kube, prometheusOperatorClient monitoring.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder) *common.Controller { + handler := alert.NewHandler( + kubeUtil.KubeClient(), kubeUtil, - radixClient, + kubeUtil.RadixClient(), prometheusOperatorClient, ) const waitForChildrenToSync = true return alert.NewController( - client, - radixClient, + kubeUtil.KubeClient(), + kubeUtil.RadixClient(), handler, kubeInformerFactory, radixInformerFactory, @@ -327,25 +284,17 @@ func createAlertController(client kubernetes.Interface, radixClient radixclient. recorder) } -func createBatchController(client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface) *common.Controller { - kubeUtil, _ := kube.NewWithListers( - client, - radixClient, - secretProviderClient, - kubeInformerFactory, - radixInformerFactory, - ) - +func createBatchController(kubeUtil *kube.Kube, client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface) *common.Controller { handler := batch.NewHandler( - client, + kubeUtil.KubeClient(), kubeUtil, - radixClient, + kubeUtil.RadixClient(), ) const waitForChildrenToSync = true return batch.NewController( - client, - radixClient, + kubeUtil.KubeClient(), + kubeUtil.RadixClient(), handler, kubeInformerFactory, radixInformerFactory, From 94da1b24b85fd8c5c644d5275029f0a926700585 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 17 Nov 2023 15:49:56 +0100 Subject: [PATCH 059/121] Extracted ingress logic from deployment package --- Makefile | 2 +- pkg/apis/defaults/oauth2.go | 8 + pkg/apis/deployment/deployment.go | 5 +- pkg/apis/deployment/deployment_test.go | 11 +- pkg/apis/deployment/deploymentfactory.go | 7 +- pkg/apis/deployment/deploymentfactory_mock.go | 3 +- pkg/apis/deployment/ingress.go | 143 +++--------------- .../ingressannotationprovider_mock.go | 50 ------ .../deployment/oauthproxyresourcemanager.go | 27 ++-- .../oauthproxyresourcemanager_test.go | 37 ++--- pkg/apis/deployment/secrets.go | 14 +- pkg/apis/deployment/secrets_test.go | 32 ---- pkg/apis/deployment/volumemount.go | 2 +- pkg/apis/ingress/ingress.go | 113 ++++++++++++++ .../ingressannotationprovider.go | 60 ++++---- .../ingress/ingressannotationprovider_mock.go | 50 ++++++ .../ingressannotationprovider_test.go | 86 +++++------ pkg/apis/ingress/secret.go | 15 ++ pkg/apis/ingress/secret_test.go | 40 +++++ pkg/apis/kube/namespaces.go | 6 +- radix-operator/deployment/handler.go | 12 +- radix-operator/deployment/handler_test.go | 12 +- 22 files changed, 383 insertions(+), 352 deletions(-) delete mode 100644 pkg/apis/deployment/ingressannotationprovider_mock.go rename pkg/apis/{deployment => ingress}/ingressannotationprovider.go (57%) create mode 100644 pkg/apis/ingress/ingressannotationprovider_mock.go rename pkg/apis/{deployment => ingress}/ingressannotationprovider_test.go (61%) create mode 100644 pkg/apis/ingress/secret.go create mode 100644 pkg/apis/ingress/secret_test.go diff --git a/Makefile b/Makefile index fe16d160b..164e748db 100644 --- a/Makefile +++ b/Makefile @@ -91,7 +91,7 @@ mocks: mockgen -source ./pkg/apis/deployment/deploymentfactory.go -destination ./pkg/apis/deployment/deploymentfactory_mock.go -package deployment mockgen -source ./pkg/apis/deployment/deployment.go -destination ./pkg/apis/deployment/deployment_mock.go -package deployment mockgen -source ./pkg/apis/deployment/auxiliaryresourcemanager.go -destination ./pkg/apis/deployment/auxiliaryresourcemanager_mock.go -package deployment - mockgen -source ./pkg/apis/deployment/ingressannotationprovider.go -destination ./pkg/apis/deployment/ingressannotationprovider_mock.go -package deployment + mockgen -source ./pkg/apis/ingress/ingressannotationprovider.go -destination ./pkg/apis/ingress/ingressannotationprovider_mock.go -package ingress mockgen -source ./pkg/apis/alert/alert.go -destination ./pkg/apis/alert/alert_mock.go -package alert mockgen -source ./pkg/apis/alert/alertfactory.go -destination ./pkg/apis/alert/alertfactory_mock.go -package alert mockgen -source ./pkg/apis/batch/syncer.go -destination ./pkg/apis/batch/syncer_mock.go -package batch diff --git a/pkg/apis/defaults/oauth2.go b/pkg/apis/defaults/oauth2.go index 6bd955089..5464b4a9e 100644 --- a/pkg/apis/defaults/oauth2.go +++ b/pkg/apis/defaults/oauth2.go @@ -7,6 +7,14 @@ import ( v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" ) +const ( + OAuthProxyPortName = "http" + OAuthProxyPortNumber int32 = 4180 + AuthUrlAnnotation = "nginx.ingress.kubernetes.io/auth-url" + AuthSigninAnnotation = "nginx.ingress.kubernetes.io/auth-signin" + AuthResponseHeadersAnnotation = "nginx.ingress.kubernetes.io/auth-response-headers" +) + // OAuth2Config is implemented by any value that has as MergeWith method // The MergeWith method takes an OAuth2 object as input and merges it with an existing OAuth2 object // The result of the merge is returned to the caller. The source object must not be modified diff --git a/pkg/apis/deployment/deployment.go b/pkg/apis/deployment/deployment.go index 26bf083e9..7c79f61b7 100644 --- a/pkg/apis/deployment/deployment.go +++ b/pkg/apis/deployment/deployment.go @@ -11,6 +11,7 @@ import ( "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/metrics" "github.com/equinor/radix-operator/pkg/apis/pipeline" @@ -47,7 +48,7 @@ type Deployment struct { registration *v1.RadixRegistration radixDeployment *v1.RadixDeployment auxResourceManagers []AuxiliaryResourceManager - ingressAnnotationProviders []IngressAnnotationProvider + ingressAnnotationProviders []ingress.AnnotationProvider tenantId string kubernetesApiPort int32 deploymentHistoryLimit int @@ -57,7 +58,7 @@ type Deployment struct { var _ DeploymentSyncerFactory = DeploymentSyncerFactoryFunc(NewDeploymentSyncer) // NewDeploymentSyncer Constructor -func NewDeploymentSyncer(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, prometheusperatorclient monitoring.Interface, registration *v1.RadixRegistration, radixDeployment *v1.RadixDeployment, tenantId string, kubernetesApiPort int32, deploymentHistoryLimit int, ingressAnnotationProviders []IngressAnnotationProvider, auxResourceManagers []AuxiliaryResourceManager) DeploymentSyncer { +func NewDeploymentSyncer(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient radixclient.Interface, prometheusperatorclient monitoring.Interface, registration *v1.RadixRegistration, radixDeployment *v1.RadixDeployment, tenantId string, kubernetesApiPort int32, deploymentHistoryLimit int, ingressAnnotationProviders []ingress.AnnotationProvider, auxResourceManagers []AuxiliaryResourceManager) DeploymentSyncer { return &Deployment{ kubeclient: kubeclient, radixclient: radixclient, diff --git a/pkg/apis/deployment/deployment_test.go b/pkg/apis/deployment/deployment_test.go index 4b3a9b9bb..fc7f0eb9b 100644 --- a/pkg/apis/deployment/deployment_test.go +++ b/pkg/apis/deployment/deployment_test.go @@ -16,6 +16,7 @@ import ( "github.com/equinor/radix-common/utils/pointers" "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/pipeline" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -3765,9 +3766,9 @@ func Test_IngressAnnotations_Called(t *testing.T) { radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}) ctrl := gomock.NewController(t) defer ctrl.Finish() - annotations1 := NewMockIngressAnnotationProvider(ctrl) + annotations1 := ingress.NewMockAnnotationProvider(ctrl) annotations1.EXPECT().GetAnnotations(&rd.Spec.Components[0], rd.Namespace).Times(3).Return(map[string]string{"foo": "x"}, nil) - annotations2 := NewMockIngressAnnotationProvider(ctrl) + annotations2 := ingress.NewMockAnnotationProvider(ctrl) annotations2.EXPECT().GetAnnotations(&rd.Spec.Components[0], rd.Namespace).Times(3).Return(map[string]string{"bar": "y", "baz": "z"}, nil) syncer := Deployment{ @@ -3777,7 +3778,7 @@ func Test_IngressAnnotations_Called(t *testing.T) { kubeutil: kubeUtil, registration: rr, radixDeployment: rd, - ingressAnnotationProviders: []IngressAnnotationProvider{annotations1, annotations2}, + ingressAnnotationProviders: []ingress.AnnotationProvider{annotations1, annotations2}, } err := syncer.OnSync() @@ -3800,7 +3801,7 @@ func Test_IngressAnnotations_ReturnError(t *testing.T) { radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}) ctrl := gomock.NewController(t) defer ctrl.Finish() - annotations1 := NewMockIngressAnnotationProvider(ctrl) + annotations1 := ingress.NewMockAnnotationProvider(ctrl) annotations1.EXPECT().GetAnnotations(&rd.Spec.Components[0], "app-dev").Times(1).Return(nil, errors.New("any error")) syncer := Deployment{ @@ -3810,7 +3811,7 @@ func Test_IngressAnnotations_ReturnError(t *testing.T) { kubeutil: kubeUtil, registration: rr, radixDeployment: rd, - ingressAnnotationProviders: []IngressAnnotationProvider{annotations1}, + ingressAnnotationProviders: []ingress.AnnotationProvider{annotations1}, } err := syncer.OnSync() diff --git a/pkg/apis/deployment/deploymentfactory.go b/pkg/apis/deployment/deploymentfactory.go index eafbf9922..530afb568 100644 --- a/pkg/apis/deployment/deploymentfactory.go +++ b/pkg/apis/deployment/deploymentfactory.go @@ -1,6 +1,7 @@ package deployment import ( + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -20,7 +21,7 @@ type DeploymentSyncerFactoryFunc func( tenantId string, kubernetesApiPort int32, deploymentHistoryLimit int, - ingressAnnotationProviders []IngressAnnotationProvider, + ingressAnnotationProviders []ingress.AnnotationProvider, auxResourceManagers []AuxiliaryResourceManager, ) DeploymentSyncer @@ -34,7 +35,7 @@ func (f DeploymentSyncerFactoryFunc) CreateDeploymentSyncer( tenantId string, kubernetesApiPort int32, deploymentHistoryLimit int, - ingressAnnotationProviders []IngressAnnotationProvider, + ingressAnnotationProviders []ingress.AnnotationProvider, auxResourceManagers []AuxiliaryResourceManager, ) DeploymentSyncer { return f(kubeclient, kubeutil, radixclient, prometheusperatorclient, registration, radixDeployment, tenantId, kubernetesApiPort, deploymentHistoryLimit, ingressAnnotationProviders, auxResourceManagers) @@ -52,7 +53,7 @@ type DeploymentSyncerFactory interface { tenantId string, kubernetesApiPort int32, deploymentHistoryLimit int, - ingressAnnotationProviders []IngressAnnotationProvider, + ingressAnnotationProviders []ingress.AnnotationProvider, auxResourceManagers []AuxiliaryResourceManager, ) DeploymentSyncer } diff --git a/pkg/apis/deployment/deploymentfactory_mock.go b/pkg/apis/deployment/deploymentfactory_mock.go index 6df848f1e..564325392 100644 --- a/pkg/apis/deployment/deploymentfactory_mock.go +++ b/pkg/apis/deployment/deploymentfactory_mock.go @@ -7,6 +7,7 @@ package deployment import ( reflect "reflect" + ingress "github.com/equinor/radix-operator/pkg/apis/ingress" kube "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" versioned "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -39,7 +40,7 @@ func (m *MockDeploymentSyncerFactory) EXPECT() *MockDeploymentSyncerFactoryMockR } // CreateDeploymentSyncer mocks base method. -func (m *MockDeploymentSyncerFactory) CreateDeploymentSyncer(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient versioned.Interface, prometheusperatorclient versioned0.Interface, registration *v1.RadixRegistration, radixDeployment *v1.RadixDeployment, tenantId string, kubernetesApiPort int32, deploymentHistoryLimit int, ingressAnnotationProviders []IngressAnnotationProvider, auxResourceManagers []AuxiliaryResourceManager) DeploymentSyncer { +func (m *MockDeploymentSyncerFactory) CreateDeploymentSyncer(kubeclient kubernetes.Interface, kubeutil *kube.Kube, radixclient versioned.Interface, prometheusperatorclient versioned0.Interface, registration *v1.RadixRegistration, radixDeployment *v1.RadixDeployment, tenantId string, kubernetesApiPort int32, deploymentHistoryLimit int, ingressAnnotationProviders []ingress.AnnotationProvider, auxResourceManagers []AuxiliaryResourceManager) DeploymentSyncer { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateDeploymentSyncer", kubeclient, kubeutil, radixclient, prometheusperatorclient, registration, radixDeployment, tenantId, kubernetesApiPort, deploymentHistoryLimit, ingressAnnotationProviders, auxResourceManagers) ret0, _ := ret[0].(DeploymentSyncer) diff --git a/pkg/apis/deployment/ingress.go b/pkg/apis/deployment/ingress.go index a3ff58b7b..0bd6b29a0 100644 --- a/pkg/apis/deployment/ingress.go +++ b/pkg/apis/deployment/ingress.go @@ -4,28 +4,16 @@ import ( "context" "fmt" "os" - "strconv" "strings" - radixmaps "github.com/equinor/radix-common/utils/maps" "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - "github.com/equinor/radix-operator/pkg/apis/utils" networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -type dnsAliasType int - -const ( - dnsDefaultAlias = iota - dnsActiveClusterAlias - dnsAlias - dnsAppAlias - dnsExternalAlias -) - func (deploy *Deployment) createOrUpdateIngress(deployComponent radixv1.RadixCommonDeployComponent) error { namespace := deploy.radixDeployment.Namespace clustername, err := deploy.kubeutil.GetClusterName() @@ -113,12 +101,12 @@ func (deploy *Deployment) createOrUpdateIngress(deployComponent radixv1.RadixCom } } - ingress, err := deploy.getDefaultIngressConfig(deploy.radixDeployment.Spec.AppName, ownerReference, deployComponent, clustername, namespace, publicPortNumber) + ing, err := deploy.getDefaultIngressConfig(deploy.radixDeployment.Spec.AppName, ownerReference, deployComponent, clustername, namespace, publicPortNumber) if err != nil { return err } - return deploy.kubeutil.ApplyIngress(namespace, ingress) + return deploy.kubeutil.ApplyIngress(namespace, ing) } func isActiveCluster(clustername string) bool { @@ -132,15 +120,15 @@ func (deploy *Deployment) garbageCollectIngressesNoLongerInSpec() error { return err } - for _, ingress := range ingresses { - componentName, ok := RadixComponentNameFromComponentLabel(ingress) + for _, ing := range ingresses { + componentName, ok := RadixComponentNameFromComponentLabel(ing) if !ok { continue } // Ingresses should only exist for items in component list. if !componentName.ExistInDeploymentSpecComponentList(deploy.radixDeployment) { - err = deploy.kubeclient.NetworkingV1().Ingresses(deploy.radixDeployment.GetNamespace()).Delete(context.TODO(), ingress.Name, metav1.DeleteOptions{}) + err = deploy.kubeclient.NetworkingV1().Ingresses(deploy.radixDeployment.GetNamespace()).Delete(context.TODO(), ing.Name, metav1.DeleteOptions{}) if err != nil { return err } @@ -195,11 +183,11 @@ func (deploy *Deployment) garbageCollectIngressForComponentAndExternalAlias(comp return err } - for _, ingress := range ingresses { + for _, ing := range ingresses { garbageCollectIngress := true if !all { - externalAliasForIngress := ingress.Name + externalAliasForIngress := ing.Name for _, externalAlias := range component.GetDNSExternalAlias() { if externalAlias == externalAliasForIngress { garbageCollectIngress = false @@ -208,7 +196,7 @@ func (deploy *Deployment) garbageCollectIngressForComponentAndExternalAlias(comp } if garbageCollectIngress { - err = deploy.kubeclient.NetworkingV1().Ingresses(deploy.radixDeployment.GetNamespace()).Delete(context.TODO(), ingress.Name, metav1.DeleteOptions{}) + err = deploy.kubeclient.NetworkingV1().Ingresses(deploy.radixDeployment.GetNamespace()).Delete(context.TODO(), ing.Name, metav1.DeleteOptions{}) if err != nil { return err } @@ -225,9 +213,9 @@ func (deploy *Deployment) getAppAliasIngressConfig(appName string, ownerReferenc } hostname := fmt.Sprintf("%s.%s", appName, appAlias) - ingressSpec := getIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) + ingressSpec := ingress.GetIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) - return deploy.getIngressConfig(appName, component, getAppAliasIngressName(appName), ownerReference, dnsAppAlias, ingressSpec, namespace) + return ingress.GetIngressConfig(namespace, appName, component, getAppAliasIngressName(appName), ingressSpec, deploy.ingressAnnotationProviders, ingress.DNSAppAlias, ownerReference) } func getAppAliasIngressName(appName string) string { @@ -245,10 +233,10 @@ func (deploy *Deployment) getActiveClusterAliasIngressConfig( if hostname == "" { return nil, nil } - ingressSpec := getIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) + ingressSpec := ingress.GetIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) ingressName := getActiveClusterIngressName(component.GetName()) - return deploy.getIngressConfig(appName, component, ingressName, ownerReference, dnsActiveClusterAlias, ingressSpec, namespace) + return ingress.GetIngressConfig(namespace, appName, component, ingressName, ingressSpec, deploy.ingressAnnotationProviders, ingress.DNSActiveClusterAlias, ownerReference) } func getActiveClusterIngressName(componentName string) string { @@ -267,9 +255,9 @@ func (deploy *Deployment) getDefaultIngressConfig( return nil, nil } hostname := getHostName(component.GetName(), namespace, clustername, dnsZone) - ingressSpec := getIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) + ingressSpec := ingress.GetIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) - return deploy.getIngressConfig(appName, component, getDefaultIngressName(component.GetName()), ownerReference, dnsDefaultAlias, ingressSpec, namespace) + return ingress.GetIngressConfig(namespace, appName, component, getDefaultIngressName(component.GetName()), ingressSpec, deploy.ingressAnnotationProviders, ingress.DNSDefaultAlias, ownerReference) } func getDefaultIngressName(componentName string) string { @@ -284,8 +272,8 @@ func (deploy *Deployment) getExternalAliasIngressConfig( namespace string, publicPortNumber int32, ) (*networkingv1.Ingress, error) { - ingressSpec := getIngressSpec(externalAlias, component.GetName(), externalAlias, publicPortNumber) - return deploy.getIngressConfig(appName, component, externalAlias, ownerReference, dnsExternalAlias, ingressSpec, namespace) + ingressSpec := ingress.GetIngressSpec(externalAlias, component.GetName(), externalAlias, publicPortNumber) + return ingress.GetIngressConfig(namespace, appName, component, externalAlias, ingressSpec, deploy.ingressAnnotationProviders, ingress.DNSExternalAlias, ownerReference) } func getActiveClusterHostName(componentName, namespace string) string { @@ -301,103 +289,6 @@ func getHostName(componentName, namespace, clustername, dnsZone string) string { return fmt.Sprintf(hostnameTemplate, componentName, namespace, clustername, dnsZone) } -func parseClientCertificateConfiguration(clientCertificate radixv1.ClientCertificate) (certificate radixv1.ClientCertificate) { - verification := radixv1.VerificationTypeOff - certificate = radixv1.ClientCertificate{ - Verification: &verification, - PassCertificateToUpstream: utils.BoolPtr(false), - } - - if passUpstream := clientCertificate.PassCertificateToUpstream; passUpstream != nil { - certificate.PassCertificateToUpstream = passUpstream - } - - if verification := clientCertificate.Verification; verification != nil { - certificate.Verification = verification - } - - return -} - -func (deploy *Deployment) getIngressConfig( - appName string, - component radixv1.RadixCommonDeployComponent, - ingressName string, - ownerReference []metav1.OwnerReference, - aliasType dnsAliasType, - ingressSpec networkingv1.IngressSpec, - namespace string, -) (*networkingv1.Ingress, error) { - annotations := map[string]string{} - - for _, ia := range deploy.ingressAnnotationProviders { - providedAnnotations, err := ia.GetAnnotations(component, namespace) - if err != nil { - return nil, err - } - annotations = radixmaps.MergeMaps(annotations, providedAnnotations) - } - - ingress := &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: ingressName, - Annotations: annotations, - Labels: map[string]string{ - kube.RadixAppLabel: appName, - kube.RadixComponentLabel: component.GetName(), - kube.RadixAliasLabel: strconv.FormatBool(aliasType == dnsAlias), - kube.RadixAppAliasLabel: strconv.FormatBool(aliasType == dnsAppAlias), - kube.RadixExternalAliasLabel: strconv.FormatBool(aliasType == dnsExternalAlias), - kube.RadixActiveClusterAliasLabel: strconv.FormatBool(aliasType == dnsActiveClusterAlias), - }, - OwnerReferences: ownerReference, - }, - Spec: ingressSpec, - } - - return ingress, nil -} - -func getIngressSpec(hostname, serviceName, tlsSecretName string, servicePort int32) networkingv1.IngressSpec { - pathType := networkingv1.PathTypeImplementationSpecific - ingressClass := "nginx" - - return networkingv1.IngressSpec{ - IngressClassName: &ingressClass, - TLS: []networkingv1.IngressTLS{ - { - Hosts: []string{ - hostname, - }, - SecretName: tlsSecretName, - }, - }, - Rules: []networkingv1.IngressRule{ - { - Host: hostname, - IngressRuleValue: networkingv1.IngressRuleValue{ - HTTP: &networkingv1.HTTPIngressRuleValue{ - Paths: []networkingv1.HTTPIngressPath{ - { - Path: "/", - PathType: &pathType, - Backend: networkingv1.IngressBackend{ - Service: &networkingv1.IngressServiceBackend{ - Name: serviceName, - Port: networkingv1.ServiceBackendPort{ - Number: servicePort, - }, - }, - }, - }, - }, - }, - }, - }, - }, - } -} - func getPublicPortNumber(ports []radixv1.ComponentPort, publicPort string) int32 { for _, port := range ports { if strings.EqualFold(port.Name, publicPort) { diff --git a/pkg/apis/deployment/ingressannotationprovider_mock.go b/pkg/apis/deployment/ingressannotationprovider_mock.go deleted file mode 100644 index 2c5e90742..000000000 --- a/pkg/apis/deployment/ingressannotationprovider_mock.go +++ /dev/null @@ -1,50 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: ./pkg/apis/deployment/ingressannotationprovider.go - -// Package deployment is a generated GoMock package. -package deployment - -import ( - reflect "reflect" - - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - gomock "github.com/golang/mock/gomock" -) - -// MockIngressAnnotationProvider is a mock of IngressAnnotationProvider interface. -type MockIngressAnnotationProvider struct { - ctrl *gomock.Controller - recorder *MockIngressAnnotationProviderMockRecorder -} - -// MockIngressAnnotationProviderMockRecorder is the mock recorder for MockIngressAnnotationProvider. -type MockIngressAnnotationProviderMockRecorder struct { - mock *MockIngressAnnotationProvider -} - -// NewMockIngressAnnotationProvider creates a new mock instance. -func NewMockIngressAnnotationProvider(ctrl *gomock.Controller) *MockIngressAnnotationProvider { - mock := &MockIngressAnnotationProvider{ctrl: ctrl} - mock.recorder = &MockIngressAnnotationProviderMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockIngressAnnotationProvider) EXPECT() *MockIngressAnnotationProviderMockRecorder { - return m.recorder -} - -// GetAnnotations mocks base method. -func (m *MockIngressAnnotationProvider) GetAnnotations(component v1.RadixCommonDeployComponent, namespace string) (map[string]string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAnnotations", component, namespace) - ret0, _ := ret[0].(map[string]string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetAnnotations indicates an expected call of GetAnnotations. -func (mr *MockIngressAnnotationProviderMockRecorder) GetAnnotations(component, namespace interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAnnotations", reflect.TypeOf((*MockIngressAnnotationProvider)(nil).GetAnnotations), component, namespace) -} diff --git a/pkg/apis/deployment/oauthproxyresourcemanager.go b/pkg/apis/deployment/oauthproxyresourcemanager.go index a4a227b5b..84f3dba3f 100644 --- a/pkg/apis/deployment/oauthproxyresourcemanager.go +++ b/pkg/apis/deployment/oauthproxyresourcemanager.go @@ -9,6 +9,7 @@ import ( commonutils "github.com/equinor/radix-common/utils" radixmaps "github.com/equinor/radix-common/utils/maps" "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/securitycontext" @@ -24,16 +25,8 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" ) -const ( - oauthProxyPortName = "http" - oauthProxyPortNumber int32 = 4180 - authUrlAnnotation = "nginx.ingress.kubernetes.io/auth-url" - authSigninAnnotation = "nginx.ingress.kubernetes.io/auth-signin" - authResponseHeadersAnnotation = "nginx.ingress.kubernetes.io/auth-response-headers" -) - // NewOAuthProxyResourceManager creates a new OAuthProxyResourceManager -func NewOAuthProxyResourceManager(rd *v1.RadixDeployment, rr *v1.RadixRegistration, kubeutil *kube.Kube, oauth2DefaultConfig defaults.OAuth2Config, ingressAnnotationProviders []IngressAnnotationProvider, oauth2ProxyDockerImage string) AuxiliaryResourceManager { +func NewOAuthProxyResourceManager(rd *v1.RadixDeployment, rr *v1.RadixRegistration, kubeutil *kube.Kube, oauth2DefaultConfig defaults.OAuth2Config, ingressAnnotationProviders []ingress.AnnotationProvider, oauth2ProxyDockerImage string) AuxiliaryResourceManager { return &oauthProxyResourceManager{ rd: rd, rr: rr, @@ -48,7 +41,7 @@ type oauthProxyResourceManager struct { rd *v1.RadixDeployment rr *v1.RadixRegistration kubeutil *kube.Kube - ingressAnnotationProviders []IngressAnnotationProvider + ingressAnnotationProviders []ingress.AnnotationProvider oauth2DefaultConfig defaults.OAuth2Config oauth2ProxyDockerImage string } @@ -437,7 +430,7 @@ func (o *oauthProxyResourceManager) buildOAuthProxyIngressForComponentIngress(co Service: &networkingv1.IngressServiceBackend{ Name: utils.GetAuxiliaryComponentServiceName(component.GetName(), defaults.OAuthProxyAuxiliaryComponentSuffix), Port: networkingv1.ServiceBackendPort{ - Number: oauthProxyPortNumber, + Number: defaults.OAuthProxyPortNumber, }, }, }, @@ -604,8 +597,8 @@ func (o *oauthProxyResourceManager) buildServiceSpec(component v1.RadixCommonDep Selector: o.getLabelsForAuxComponent(component), Ports: []corev1.ServicePort{ { - Port: oauthProxyPortNumber, - TargetPort: intstr.FromString(oauthProxyPortName), + Port: defaults.OAuthProxyPortNumber, + TargetPort: intstr.FromString(defaults.OAuthProxyPortName), Protocol: corev1.ProtocolTCP, }, }, @@ -664,7 +657,7 @@ func (o *oauthProxyResourceManager) getCurrentAndDesiredDeployment(component v1. func (o *oauthProxyResourceManager) getDesiredDeployment(component v1.RadixCommonDeployComponent) (*appsv1.Deployment, error) { deploymentName := utils.GetAuxiliaryComponentDeploymentName(component.GetName(), defaults.OAuthProxyAuxiliaryComponentSuffix) - readinessProbe, err := getReadinessProbeWithDefaultsFromEnv(oauthProxyPortNumber) + readinessProbe, err := getReadinessProbeWithDefaultsFromEnv(defaults.OAuthProxyPortNumber) if err != nil { return nil, err } @@ -694,8 +687,8 @@ func (o *oauthProxyResourceManager) getDesiredDeployment(component v1.RadixCommo Env: o.getEnvVars(component), Ports: []corev1.ContainerPort{ { - Name: oauthProxyPortName, - ContainerPort: oauthProxyPortNumber, + Name: defaults.OAuthProxyPortName, + ContainerPort: defaults.OAuthProxyPortNumber, }, }, ReadinessProbe: readinessProbe, @@ -735,7 +728,7 @@ func (o *oauthProxyResourceManager) getEnvVars(component v1.RadixCommonDeployCom envVars = append(envVars, corev1.EnvVar{Name: "OAUTH2_PROXY_PASS_BASIC_AUTH", Value: "false"}) envVars = append(envVars, corev1.EnvVar{Name: "OAUTH2_PROXY_SKIP_PROVIDER_BUTTON", Value: "true"}) envVars = append(envVars, corev1.EnvVar{Name: "OAUTH2_PROXY_EMAIL_DOMAINS", Value: "*"}) - envVars = append(envVars, corev1.EnvVar{Name: "OAUTH2_PROXY_HTTP_ADDRESS", Value: fmt.Sprintf("http://:%v", oauthProxyPortNumber)}) + envVars = append(envVars, corev1.EnvVar{Name: "OAUTH2_PROXY_HTTP_ADDRESS", Value: fmt.Sprintf("http://:%v", defaults.OAuthProxyPortNumber)}) secretName := utils.GetAuxiliaryComponentSecretName(component.GetName(), defaults.OAuthProxyAuxiliaryComponentSuffix) envVars = append(envVars, o.createEnvVarWithSecretRef("OAUTH2_PROXY_COOKIE_SECRET", secretName, defaults.OAuthCookieSecretKeyName)) envVars = append(envVars, o.createEnvVarWithSecretRef("OAUTH2_PROXY_CLIENT_SECRET", secretName, defaults.OAuthClientSecretKeyName)) diff --git a/pkg/apis/deployment/oauthproxyresourcemanager_test.go b/pkg/apis/deployment/oauthproxyresourcemanager_test.go index f6a3c3962..2a3571aa0 100644 --- a/pkg/apis/deployment/oauthproxyresourcemanager_test.go +++ b/pkg/apis/deployment/oauthproxyresourcemanager_test.go @@ -10,6 +10,7 @@ import ( commonUtils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/defaults/k8s" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -39,7 +40,7 @@ type OAuthProxyResourceManagerTestSuite struct { secretProviderClient secretProviderClient.Interface kubeUtil *kube.Kube ctrl *gomock.Controller - ingressAnnotationProvider *MockIngressAnnotationProvider + ingressAnnotationProvider *ingress.MockAnnotationProvider oauth2Config *defaults.MockOAuth2Config } @@ -81,7 +82,7 @@ func (s *OAuthProxyResourceManagerTestSuite) SetupTest() { s.secretProviderClient = secretproviderfake.NewSimpleClientset() s.kubeUtil, _ = kube.New(s.kubeClient, s.radixClient, s.secretProviderClient) s.ctrl = gomock.NewController(s.T()) - s.ingressAnnotationProvider = NewMockIngressAnnotationProvider(s.ctrl) + s.ingressAnnotationProvider = ingress.NewMockAnnotationProvider(s.ctrl) s.oauth2Config = defaults.NewMockOAuth2Config(s.ctrl) } @@ -95,7 +96,7 @@ func (s *OAuthProxyResourceManagerTestSuite) TestNewOAuthProxyResourceManager() oauthConfig := defaults.NewMockOAuth2Config(ctrl) rd := utils.NewDeploymentBuilder().BuildRD() rr := utils.NewRegistrationBuilder().BuildRR() - ingressAnnotationProviders := []IngressAnnotationProvider{&MockIngressAnnotationProvider{}} + ingressAnnotationProviders := []ingress.AnnotationProvider{&ingress.MockAnnotationProvider{}} oauthManager := NewOAuthProxyResourceManager(rd, rr, s.kubeUtil, oauthConfig, ingressAnnotationProviders, "proxy:123") sut, ok := oauthManager.(*oauthProxyResourceManager) @@ -118,7 +119,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_NotPublicOrNoOAuth() { rr := utils.NewRegistrationBuilder().WithName(appName).BuildRR() for _, scenario := range scenarios { - sut := &oauthProxyResourceManager{scenario.rd, rr, s.kubeUtil, []IngressAnnotationProvider{}, s.oauth2Config, ""} + sut := &oauthProxyResourceManager{scenario.rd, rr, s.kubeUtil, []ingress.AnnotationProvider{}, s.oauth2Config, ""} err := sut.Sync() s.Nil(err) deploys, _ := s.kubeClient.AppsV1().Deployments(corev1.NamespaceAll).List(context.Background(), metav1.ListOptions{LabelSelector: s.getAppNameSelector(appName)}) @@ -176,7 +177,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyDeploymentCreat WithEnvironment(envName). WithComponent(utils.NewDeployComponentBuilder().WithName(componentName).WithPublicPort("http").WithAuthentication(&v1.Authentication{OAuth2: inputOAuth})). BuildRD() - sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []IngressAnnotationProvider{}, s.oauth2Config, ""} + sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []ingress.AnnotationProvider{}, s.oauth2Config, ""} err := sut.Sync() s.Nil(err) @@ -196,10 +197,10 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyDeploymentCreat s.Equal(sut.oauth2ProxyDockerImage, defaultContainer.Image) s.Len(defaultContainer.Ports, 1) - s.Equal(oauthProxyPortNumber, defaultContainer.Ports[0].ContainerPort) - s.Equal(oauthProxyPortName, defaultContainer.Ports[0].Name) + s.Equal(defaults.OAuthProxyPortNumber, defaultContainer.Ports[0].ContainerPort) + s.Equal(defaults.OAuthProxyPortName, defaultContainer.Ports[0].Name) s.NotNil(defaultContainer.ReadinessProbe) - s.Equal(oauthProxyPortNumber, defaultContainer.ReadinessProbe.TCPSocket.Port.IntVal) + s.Equal(defaults.OAuthProxyPortNumber, defaultContainer.ReadinessProbe.TCPSocket.Port.IntVal) s.Len(defaultContainer.Env, 29) s.Equal("oidc", s.getEnvVarValueByName("OAUTH2_PROXY_PROVIDER", defaultContainer.Env)) @@ -208,7 +209,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyDeploymentCreat s.Equal("false", s.getEnvVarValueByName("OAUTH2_PROXY_PASS_BASIC_AUTH", defaultContainer.Env)) s.Equal("true", s.getEnvVarValueByName("OAUTH2_PROXY_SKIP_PROVIDER_BUTTON", defaultContainer.Env)) s.Equal("*", s.getEnvVarValueByName("OAUTH2_PROXY_EMAIL_DOMAINS", defaultContainer.Env)) - s.Equal(fmt.Sprintf("http://:%v", oauthProxyPortNumber), s.getEnvVarValueByName("OAUTH2_PROXY_HTTP_ADDRESS", defaultContainer.Env)) + s.Equal(fmt.Sprintf("http://:%v", defaults.OAuthProxyPortNumber), s.getEnvVarValueByName("OAUTH2_PROXY_HTTP_ADDRESS", defaultContainer.Env)) s.Equal(returnOAuth.ClientID, s.getEnvVarValueByName("OAUTH2_PROXY_CLIENT_ID", defaultContainer.Env)) s.Equal(returnOAuth.Scope, s.getEnvVarValueByName("OAUTH2_PROXY_SCOPE", defaultContainer.Env)) s.Equal("true", s.getEnvVarValueByName("OAUTH2_PROXY_SET_XAUTHREQUEST", defaultContainer.Env)) @@ -254,7 +255,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxySecretAndRbacCr WithEnvironment(envName). WithComponent(utils.NewDeployComponentBuilder().WithName(componentName).WithPublicPort("http").WithAuthentication(&v1.Authentication{OAuth2: &v1.OAuth2{}})). BuildRD() - sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []IngressAnnotationProvider{}, s.oauth2Config, ""} + sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []ingress.AnnotationProvider{}, s.oauth2Config, ""} err := sut.Sync() s.Nil(err) @@ -278,7 +279,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyRbacCreated() { WithEnvironment(envName). WithComponent(utils.NewDeployComponentBuilder().WithName(componentName).WithPublicPort("http").WithAuthentication(&v1.Authentication{OAuth2: &v1.OAuth2{}})). BuildRD() - sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []IngressAnnotationProvider{}, s.oauth2Config, ""} + sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []ingress.AnnotationProvider{}, s.oauth2Config, ""} err := sut.Sync() s.Nil(err) @@ -357,7 +358,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxySecret_KeysGarb WithEnvironment(envName). WithComponent(utils.NewDeployComponentBuilder().WithName(componentName).WithPublicPort("http").WithAuthentication(&v1.Authentication{OAuth2: &v1.OAuth2{}})). BuildRD() - sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []IngressAnnotationProvider{}, s.oauth2Config, ""} + sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []ingress.AnnotationProvider{}, s.oauth2Config, ""} err = sut.Sync() s.Nil(err) @@ -392,7 +393,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyServiceCreated( WithEnvironment(envName). WithComponent(utils.NewDeployComponentBuilder().WithName(componentName).WithPublicPort("http").WithAuthentication(&v1.Authentication{OAuth2: &v1.OAuth2{}})). BuildRD() - sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []IngressAnnotationProvider{}, s.oauth2Config, ""} + sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []ingress.AnnotationProvider{}, s.oauth2Config, ""} err := sut.Sync() s.Nil(err) @@ -405,7 +406,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyServiceCreated( s.ElementsMatch([]metav1.OwnerReference{getOwnerReferenceOfDeployment(rd)}, actualServices.Items[0].OwnerReferences) s.Equal(corev1.ServiceTypeClusterIP, actualServices.Items[0].Spec.Type) s.Len(actualServices.Items[0].Spec.Ports, 1) - s.Equal(corev1.ServicePort{Port: oauthProxyPortNumber, TargetPort: intstr.FromString(oauthProxyPortName), Protocol: corev1.ProtocolTCP}, actualServices.Items[0].Spec.Ports[0]) + s.Equal(corev1.ServicePort{Port: defaults.OAuthProxyPortNumber, TargetPort: intstr.FromString(defaults.OAuthProxyPortName), Protocol: corev1.ProtocolTCP}, actualServices.Items[0].Spec.Ports[0]) } func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreated() { @@ -483,7 +484,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate expectedIngWebCall.Authentication.OAuth2.ProxyPrefix = "auth2" expectedIngWebAnnotations := map[string]string{"annotation2-1": "val2-1", "annotation2-2": "val2-2"} s.ingressAnnotationProvider.EXPECT().GetAnnotations(expectedIngWebCall, rd.Namespace).Times(2).Return(expectedIngWebAnnotations, nil) - sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []IngressAnnotationProvider{s.ingressAnnotationProvider}, s.oauth2Config, ""} + sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []ingress.AnnotationProvider{s.ingressAnnotationProvider}, s.oauth2Config, ""} err := sut.Sync() s.Nil(err) @@ -507,7 +508,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate Backend: networkingv1.IngressBackend{ Service: &networkingv1.IngressServiceBackend{ Name: utils.GetAuxiliaryComponentServiceName(componentName, defaults.OAuthProxyAuxiliaryComponentSuffix), - Port: networkingv1.ServiceBackendPort{Number: oauthProxyPortNumber}, + Port: networkingv1.ServiceBackendPort{Number: defaults.OAuthProxyPortNumber}, }, }, }}, @@ -578,7 +579,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyUninstall() { WithComponent(utils.NewDeployComponentBuilder().WithName(component2Name).WithPublicPort("http").WithAuthentication(&v1.Authentication{OAuth2: &v1.OAuth2{}})). BuildRD() s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(2).Return(&v1.OAuth2{}, nil) - sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []IngressAnnotationProvider{}, s.oauth2Config, ""} + sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []ingress.AnnotationProvider{}, s.oauth2Config, ""} err := sut.Sync() s.Nil(err) @@ -604,7 +605,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyUninstall() { WithComponent(utils.NewDeployComponentBuilder().WithName(component2Name).WithPublicPort("http").WithAuthentication(&v1.Authentication{})). BuildRD() s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(1).Return(&v1.OAuth2{}, nil) - sut = &oauthProxyResourceManager{rd, rr, s.kubeUtil, []IngressAnnotationProvider{}, s.oauth2Config, ""} + sut = &oauthProxyResourceManager{rd, rr, s.kubeUtil, []ingress.AnnotationProvider{}, s.oauth2Config, ""} err = sut.Sync() s.Nil(err) actualDeploys, _ = s.kubeClient.AppsV1().Deployments(envNs).List(context.Background(), metav1.ListOptions{}) diff --git a/pkg/apis/deployment/secrets.go b/pkg/apis/deployment/secrets.go index 2cb6dda15..92af69332 100644 --- a/pkg/apis/deployment/secrets.go +++ b/pkg/apis/deployment/secrets.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -100,7 +101,7 @@ func (deploy *Deployment) createOrUpdateSecretsForComponent(component radixv1.Ra } clientCertificateSecretName := utils.GetComponentClientCertificateSecretName(component.GetName()) - if auth := component.GetAuthentication(); auth != nil && component.IsPublic() && IsSecretRequiredForClientCertificate(auth.ClientCertificate) { + if auth := component.GetAuthentication(); auth != nil && component.IsPublic() && ingress.IsSecretRequiredForClientCertificate(auth.ClientCertificate) { if !deploy.kubeutil.SecretExists(namespace, clientCertificateSecretName) { if err := deploy.createClientCertificateSecret(namespace, deploy.registration.Name, component.GetName(), clientCertificateSecretName); err != nil { return err @@ -430,17 +431,6 @@ func (deploy *Deployment) removeOrphanedSecrets(ns, secretName string, secrets [ return nil } -func IsSecretRequiredForClientCertificate(clientCertificate *radixv1.ClientCertificate) bool { - if clientCertificate != nil { - certificateConfig := parseClientCertificateConfiguration(*clientCertificate) - if *certificateConfig.PassCertificateToUpstream || *certificateConfig.Verification != radixv1.VerificationTypeOff { - return true - } - } - - return false -} - // GarbageCollectSecrets delete secrets, excluding with names in the excludeSecretNames func (deploy *Deployment) GarbageCollectSecrets(secrets []*v1.Secret, excludeSecretNames []string) error { for _, secret := range secrets { diff --git a/pkg/apis/deployment/secrets_test.go b/pkg/apis/deployment/secrets_test.go index c73221159..aaf1f1369 100644 --- a/pkg/apis/deployment/secrets_test.go +++ b/pkg/apis/deployment/secrets_test.go @@ -5,7 +5,6 @@ import ( "os" "testing" - "github.com/equinor/radix-common/utils/pointers" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -129,34 +128,3 @@ func TestSecretDeployed_ClientCertificateSecretGetsSet(t *testing.T) { teardownSecretsTest() } - -func Test_IsSecretRequiredForClientCertificate(t *testing.T) { - type scenario struct { - clientCertificate *v1.ClientCertificate - expectedResult bool - } - scenarios := []scenario{ - {clientCertificate: nil, expectedResult: false}, - {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOff)}, expectedResult: false}, - {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOptional)}, expectedResult: true}, - {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOptionalNoCa)}, expectedResult: true}, - {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOn)}, expectedResult: true}, - {clientCertificate: &v1.ClientCertificate{}, expectedResult: false}, - {clientCertificate: &v1.ClientCertificate{PassCertificateToUpstream: pointers.Ptr(false)}, expectedResult: false}, - {clientCertificate: &v1.ClientCertificate{PassCertificateToUpstream: pointers.Ptr(true)}, expectedResult: true}, - {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOff), PassCertificateToUpstream: pointers.Ptr(true)}, expectedResult: true}, - {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOff), PassCertificateToUpstream: pointers.Ptr(false)}, expectedResult: false}, - {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOptional), PassCertificateToUpstream: pointers.Ptr(true)}, expectedResult: true}, - {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOptional), PassCertificateToUpstream: pointers.Ptr(false)}, expectedResult: true}, - } - - for _, ts := range scenarios { - t.Run("", func(t *testing.T) { - assert.Equal(t, ts.expectedResult, IsSecretRequiredForClientCertificate(ts.clientCertificate)) - }) - } -} - -func getVerificationTypePtr(verificationType v1.VerificationType) *v1.VerificationType { - return &verificationType -} diff --git a/pkg/apis/deployment/volumemount.go b/pkg/apis/deployment/volumemount.go index 025d6efd8..4aa2b233b 100644 --- a/pkg/apis/deployment/volumemount.go +++ b/pkg/apis/deployment/volumemount.go @@ -37,7 +37,7 @@ const ( csiVolumeNodeMountPathTemplate = "%s/%s/%s/%s/%s/%s" // ///// csiStorageClassProvisionerSecretNameParameter = "csi.storage.k8s.io/provisioner-secret-name" // Secret name, containing storage account name and key - csiStorageClassProvisionerSecretNamespaceParameter = "csi.storage.k8s.io/provisioner-secret-namespace" // Namespace of the secret + csiStorageClassProvisionerSecretNamespaceParameter = "csi.storage.k8s.io/provisioner-secret-namespace" // namespace of the secret csiStorageClassNodeStageSecretNameParameter = "csi.storage.k8s.io/node-stage-secret-name" // Usually equal to csiStorageClassProvisionerSecretNameParameter csiStorageClassNodeStageSecretNamespaceParameter = "csi.storage.k8s.io/node-stage-secret-namespace" // Usually equal to csiStorageClassProvisionerSecretNamespaceParameter csiAzureStorageClassSkuNameParameter = "skuName" // Available values: Standard_LRS (default), Premium_LRS, Standard_GRS, Standard_RAGRS. https://docs.microsoft.com/en-us/rest/api/storagerp/srp_sku_types diff --git a/pkg/apis/ingress/ingress.go b/pkg/apis/ingress/ingress.go index ff5db8dea..97ed98386 100644 --- a/pkg/apis/ingress/ingress.go +++ b/pkg/apis/ingress/ingress.go @@ -1,5 +1,26 @@ package ingress +import ( + "strconv" + + "github.com/equinor/radix-common/utils/maps" + "github.com/equinor/radix-operator/pkg/apis/kube" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/utils" + networkingv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type DNSAliasType int + +const ( + DNSDefaultAlias = iota + DNSActiveClusterAlias + DNSAlias + DNSAppAlias + DNSExternalAlias +) + // IngressConfiguration Holds all ingress annotation configurations type IngressConfiguration struct { AnnotationConfigurations []AnnotationConfiguration `yaml:"configuration"` @@ -10,3 +31,95 @@ type AnnotationConfiguration struct { Name string Annotations map[string]string } + +// GetIngressSpec Get Ingress spec +func GetIngressSpec(hostname, serviceName, tlsSecretName string, servicePort int32) networkingv1.IngressSpec { + pathType := networkingv1.PathTypeImplementationSpecific + ingressClass := "nginx" + + return networkingv1.IngressSpec{ + IngressClassName: &ingressClass, + TLS: []networkingv1.IngressTLS{ + { + Hosts: []string{ + hostname, + }, + SecretName: tlsSecretName, + }, + }, + Rules: []networkingv1.IngressRule{ + { + Host: hostname, + IngressRuleValue: networkingv1.IngressRuleValue{ + HTTP: &networkingv1.HTTPIngressRuleValue{ + Paths: []networkingv1.HTTPIngressPath{ + { + Path: "/", + PathType: &pathType, + Backend: networkingv1.IngressBackend{ + Service: &networkingv1.IngressServiceBackend{ + Name: serviceName, + Port: networkingv1.ServiceBackendPort{ + Number: servicePort, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +// ParseClientCertificateConfiguration Parses ClientCertificate configuration +func ParseClientCertificateConfiguration(clientCertificate radixv1.ClientCertificate) (certificate radixv1.ClientCertificate) { + verification := radixv1.VerificationTypeOff + certificate = radixv1.ClientCertificate{ + Verification: &verification, + PassCertificateToUpstream: utils.BoolPtr(false), + } + + if passUpstream := clientCertificate.PassCertificateToUpstream; passUpstream != nil { + certificate.PassCertificateToUpstream = passUpstream + } + + if verification := clientCertificate.Verification; verification != nil { + certificate.Verification = verification + } + + return +} + +// GetIngressConfig Gets Ingress configuration +func GetIngressConfig(namespace string, appName string, component radixv1.RadixCommonDeployComponent, ingressName string, ingressSpec networkingv1.IngressSpec, ingressProviders []AnnotationProvider, aliasType DNSAliasType, ownerReference []metav1.OwnerReference) (*networkingv1.Ingress, error) { + annotations := map[string]string{} + + for _, ia := range ingressProviders { + providedAnnotations, err := ia.GetAnnotations(component, namespace) + if err != nil { + return nil, err + } + annotations = maps.MergeMaps(annotations, providedAnnotations) + } + + ing := &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: ingressName, + Annotations: annotations, + Labels: map[string]string{ + kube.RadixAppLabel: appName, + kube.RadixComponentLabel: component.GetName(), + kube.RadixAliasLabel: strconv.FormatBool(aliasType == DNSAlias), + kube.RadixAppAliasLabel: strconv.FormatBool(aliasType == DNSAppAlias), + kube.RadixExternalAliasLabel: strconv.FormatBool(aliasType == DNSExternalAlias), + kube.RadixActiveClusterAliasLabel: strconv.FormatBool(aliasType == DNSActiveClusterAlias), + }, + OwnerReferences: ownerReference, + }, + Spec: ingressSpec, + } + + return ing, nil +} diff --git a/pkg/apis/deployment/ingressannotationprovider.go b/pkg/apis/ingress/ingressannotationprovider.go similarity index 57% rename from pkg/apis/deployment/ingressannotationprovider.go rename to pkg/apis/ingress/ingressannotationprovider.go index 2634ff58f..3bb307325 100644 --- a/pkg/apis/deployment/ingressannotationprovider.go +++ b/pkg/apis/ingress/ingressannotationprovider.go @@ -1,39 +1,38 @@ -package deployment +package ingress import ( "fmt" "strings" "github.com/equinor/radix-operator/pkg/apis/defaults" - "github.com/equinor/radix-operator/pkg/apis/ingress" - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" oauthutil "github.com/equinor/radix-operator/pkg/apis/utils/oauth" ) -type IngressAnnotationProvider interface { - GetAnnotations(component v1.RadixCommonDeployComponent, namespace string) (map[string]string, error) +type AnnotationProvider interface { + GetAnnotations(component radixv1.RadixCommonDeployComponent, namespace string) (map[string]string, error) } -func NewForceSslRedirectAnnotationProvider() IngressAnnotationProvider { +func NewForceSslRedirectAnnotationProvider() AnnotationProvider { return &forceSslRedirectAnnotationProvider{} } type forceSslRedirectAnnotationProvider struct{} -func (forceSslRedirectAnnotationProvider) GetAnnotations(component v1.RadixCommonDeployComponent, namespace string) (map[string]string, error) { +func (forceSslRedirectAnnotationProvider) GetAnnotations(_ radixv1.RadixCommonDeployComponent, _ string) (map[string]string, error) { return map[string]string{"nginx.ingress.kubernetes.io/force-ssl-redirect": "true"}, nil } -func NewIngressConfigurationAnnotationProvider(config ingress.IngressConfiguration) IngressAnnotationProvider { +func NewIngressConfigurationAnnotationProvider(config IngressConfiguration) AnnotationProvider { return &ingressConfigurationAnnotationProvider{config: config} } type ingressConfigurationAnnotationProvider struct { - config ingress.IngressConfiguration + config IngressConfiguration } -func (provider *ingressConfigurationAnnotationProvider) GetAnnotations(component v1.RadixCommonDeployComponent, namespace string) (map[string]string, error) { +func (provider *ingressConfigurationAnnotationProvider) GetAnnotations(component radixv1.RadixCommonDeployComponent, _ string) (map[string]string, error) { allAnnotations := make(map[string]string) for _, configuration := range component.GetIngressConfiguration() { @@ -46,7 +45,7 @@ func (provider *ingressConfigurationAnnotationProvider) GetAnnotations(component return allAnnotations, nil } -func (provider *ingressConfigurationAnnotationProvider) getAnnotationsFromConfiguration(name string, config ingress.IngressConfiguration) map[string]string { +func (provider *ingressConfigurationAnnotationProvider) getAnnotationsFromConfiguration(name string, config IngressConfiguration) map[string]string { for _, ingressConfig := range config.AnnotationConfigurations { if strings.EqualFold(ingressConfig.Name, name) { return ingressConfig.Annotations @@ -56,32 +55,41 @@ func (provider *ingressConfigurationAnnotationProvider) getAnnotationsFromConfig return nil } -func NewClientCertificateAnnotationProvider(certificateNamespace string) IngressAnnotationProvider { +func NewClientCertificateAnnotationProvider(certificateNamespace string) AnnotationProvider { return &clientCertificateAnnotationProvider{namespace: certificateNamespace} } +type ClientCertificateAnnotationProvider interface { + AnnotationProvider + GetNamespace() string +} + type clientCertificateAnnotationProvider struct { namespace string } -func (provider *clientCertificateAnnotationProvider) GetAnnotations(component v1.RadixCommonDeployComponent, namespace string) (map[string]string, error) { - result := make(map[string]string) +func (provider *clientCertificateAnnotationProvider) GetNamespace() string { + return provider.namespace +} + +func (provider *clientCertificateAnnotationProvider) GetAnnotations(component radixv1.RadixCommonDeployComponent, _ string) (map[string]string, error) { + annotations := make(map[string]string) if auth := component.GetAuthentication(); auth != nil { if clientCert := auth.ClientCertificate; clientCert != nil { if IsSecretRequiredForClientCertificate(clientCert) { - result["nginx.ingress.kubernetes.io/auth-tls-secret"] = fmt.Sprintf("%s/%s", provider.namespace, utils.GetComponentClientCertificateSecretName(component.GetName())) + annotations["nginx.ingress.kubernetes.io/auth-tls-secret"] = fmt.Sprintf("%s/%s", provider.namespace, utils.GetComponentClientCertificateSecretName(component.GetName())) } - certificateConfig := parseClientCertificateConfiguration(*clientCert) - result["nginx.ingress.kubernetes.io/auth-tls-verify-client"] = string(*certificateConfig.Verification) - result["nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream"] = utils.TernaryString(*certificateConfig.PassCertificateToUpstream, "true", "false") + certificateConfig := ParseClientCertificateConfiguration(*clientCert) + annotations["nginx.ingress.kubernetes.io/auth-tls-verify-client"] = string(*certificateConfig.Verification) + annotations["nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream"] = utils.TernaryString(*certificateConfig.PassCertificateToUpstream, "true", "false") } } - return result, nil + return annotations, nil } -func NewOAuth2AnnotationProvider(oauth2DefaultConfig defaults.OAuth2Config) IngressAnnotationProvider { +func NewOAuth2AnnotationProvider(oauth2DefaultConfig defaults.OAuth2Config) AnnotationProvider { return &oauth2AnnotationProvider{oauth2DefaultConfig: oauth2DefaultConfig} } @@ -89,7 +97,7 @@ type oauth2AnnotationProvider struct { oauth2DefaultConfig defaults.OAuth2Config } -func (provider *oauth2AnnotationProvider) GetAnnotations(component v1.RadixCommonDeployComponent, namespace string) (map[string]string, error) { +func (provider *oauth2AnnotationProvider) GetAnnotations(component radixv1.RadixCommonDeployComponent, namespace string) (map[string]string, error) { annotations := make(map[string]string) if auth := component.GetAuthentication(); component.IsPublic() && auth != nil && auth.OAuth2 != nil { @@ -100,11 +108,11 @@ func (provider *oauth2AnnotationProvider) GetAnnotations(component v1.RadixCommo svcName := utils.GetAuxiliaryComponentServiceName(component.GetName(), defaults.OAuthProxyAuxiliaryComponentSuffix) - // Documentation for Oauth2 proxy auth-request: https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview#configuring-for-use-with-the-nginx-auth_request-directive + // Documentation for OAuth2 proxy auth-request: https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview#configuring-for-use-with-the-nginx-auth_request-directive hostPath := fmt.Sprintf("https://$host%s", oauthutil.SanitizePathPrefix(oauth.ProxyPrefix)) - servicePath := fmt.Sprintf("http://%s.%s.svc.cluster.local:%d%s", svcName, namespace, oauthProxyPortNumber, oauthutil.SanitizePathPrefix(oauth.ProxyPrefix)) - annotations[authUrlAnnotation] = fmt.Sprintf("%s/auth", servicePath) - annotations[authSigninAnnotation] = fmt.Sprintf("%s/start?rd=$escaped_request_uri", hostPath) + servicePath := fmt.Sprintf("%s://%s.%s.svc.cluster.local:%d%s", "http", svcName, namespace, defaults.OAuthProxyPortNumber, oauthutil.SanitizePathPrefix(oauth.ProxyPrefix)) + annotations[defaults.AuthUrlAnnotation] = fmt.Sprintf("%s/auth", servicePath) + annotations[defaults.AuthSigninAnnotation] = fmt.Sprintf("%s/start?rd=$escaped_request_uri", hostPath) var authResponseHeaders []string if oauth.SetXAuthRequestHeaders != nil && *oauth.SetXAuthRequestHeaders { @@ -114,7 +122,7 @@ func (provider *oauth2AnnotationProvider) GetAnnotations(component v1.RadixCommo authResponseHeaders = append(authResponseHeaders, "Authorization") } if len(authResponseHeaders) > 0 { - annotations[authResponseHeadersAnnotation] = strings.Join(authResponseHeaders, ",") + annotations[defaults.AuthResponseHeadersAnnotation] = strings.Join(authResponseHeaders, ",") } } diff --git a/pkg/apis/ingress/ingressannotationprovider_mock.go b/pkg/apis/ingress/ingressannotationprovider_mock.go new file mode 100644 index 000000000..e390d7ebd --- /dev/null +++ b/pkg/apis/ingress/ingressannotationprovider_mock.go @@ -0,0 +1,50 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./pkg/apis/ingress/ingressannotationprovider.go + +// Package ingress is a generated GoMock package. +package ingress + +import ( + reflect "reflect" + + v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + gomock "github.com/golang/mock/gomock" +) + +// MockAnnotationProvider is a mock of AnnotationProvider interface. +type MockAnnotationProvider struct { + ctrl *gomock.Controller + recorder *MockAnnotationProviderMockRecorder +} + +// MockAnnotationProviderMockRecorder is the mock recorder for MockAnnotationProvider. +type MockAnnotationProviderMockRecorder struct { + mock *MockAnnotationProvider +} + +// NewMockAnnotationProvider creates a new mock instance. +func NewMockAnnotationProvider(ctrl *gomock.Controller) *MockAnnotationProvider { + mock := &MockAnnotationProvider{ctrl: ctrl} + mock.recorder = &MockAnnotationProviderMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAnnotationProvider) EXPECT() *MockAnnotationProviderMockRecorder { + return m.recorder +} + +// GetAnnotations mocks base method. +func (m *MockAnnotationProvider) GetAnnotations(component v1.RadixCommonDeployComponent, namespace string) (map[string]string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAnnotations", component, namespace) + ret0, _ := ret[0].(map[string]string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetAnnotations indicates an expected call of GetAnnotations. +func (mr *MockAnnotationProviderMockRecorder) GetAnnotations(component, namespace interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAnnotations", reflect.TypeOf((*MockAnnotationProvider)(nil).GetAnnotations), component, namespace) +} diff --git a/pkg/apis/deployment/ingressannotationprovider_test.go b/pkg/apis/ingress/ingressannotationprovider_test.go similarity index 61% rename from pkg/apis/deployment/ingressannotationprovider_test.go rename to pkg/apis/ingress/ingressannotationprovider_test.go index 30227677b..6b505a827 100644 --- a/pkg/apis/deployment/ingressannotationprovider_test.go +++ b/pkg/apis/ingress/ingressannotationprovider_test.go @@ -1,4 +1,4 @@ -package deployment +package ingress import ( "errors" @@ -6,8 +6,7 @@ import ( maputils "github.com/equinor/radix-common/utils/maps" "github.com/equinor/radix-operator/pkg/apis/defaults" - "github.com/equinor/radix-operator/pkg/apis/ingress" - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" @@ -20,7 +19,7 @@ func Test_NewForceSslRedirectAnnotationProvider(t *testing.T) { } func Test_NewIngressConfigurationAnnotationProvider(t *testing.T) { - cfg := ingress.IngressConfiguration{AnnotationConfigurations: []ingress.AnnotationConfiguration{{Name: "test"}}} + cfg := IngressConfiguration{AnnotationConfigurations: []AnnotationConfiguration{{Name: "test"}}} sut := NewIngressConfigurationAnnotationProvider(cfg) assert.IsType(t, &ingressConfigurationAnnotationProvider{}, sut) sutReal := sut.(*ingressConfigurationAnnotationProvider) @@ -28,10 +27,11 @@ func Test_NewIngressConfigurationAnnotationProvider(t *testing.T) { } func Test_NewClientCertificateAnnotationProvider(t *testing.T) { - sut := NewClientCertificateAnnotationProvider("anynamespace") - assert.IsType(t, &clientCertificateAnnotationProvider{}, sut) - sutReal := sut.(*clientCertificateAnnotationProvider) - assert.Equal(t, "anynamespace", sutReal.namespace) + expectedNamespace := "any-namespace" + sut := NewClientCertificateAnnotationProvider(expectedNamespace) + clientCertificateAnnotationProvider, converted := sut.(ClientCertificateAnnotationProvider) + assert.True(t, converted, "Expected type ClientCertificateAnnotationProvider") + assert.Equal(t, expectedNamespace, clientCertificateAnnotationProvider.GetNamespace()) } func Test_NewOAuth2AnnotationProvider(t *testing.T) { @@ -45,14 +45,14 @@ func Test_NewOAuth2AnnotationProvider(t *testing.T) { func Test_ForceSslRedirectAnnotations(t *testing.T) { sslAnnotations := forceSslRedirectAnnotationProvider{} expected := map[string]string{"nginx.ingress.kubernetes.io/force-ssl-redirect": "true"} - actual, err := sslAnnotations.GetAnnotations(&v1.RadixDeployComponent{}, "not-used-namespace-in-test") + actual, err := sslAnnotations.GetAnnotations(&radixv1.RadixDeployComponent{}, "not-used-namespace-in-test") assert.Nil(t, err) assert.Equal(t, expected, actual) } func Test_IngressConfigurationAnnotations(t *testing.T) { - config := ingress.IngressConfiguration{ - AnnotationConfigurations: []ingress.AnnotationConfiguration{ + config := IngressConfiguration{ + AnnotationConfigurations: []AnnotationConfiguration{ {Name: "ewma", Annotations: map[string]string{"ewma1": "x", "ewma2": "y"}}, {Name: "socket", Annotations: map[string]string{"socket1": "x", "socket2": "y", "socket3": "z"}}, {Name: "round-robin", Annotations: map[string]string{"round-robin1": "1"}}, @@ -60,70 +60,70 @@ func Test_IngressConfigurationAnnotations(t *testing.T) { } componentIngress := ingressConfigurationAnnotationProvider{config: config} - annotations, err := componentIngress.GetAnnotations(&v1.RadixDeployComponent{IngressConfiguration: []string{"socket"}}, "unused-namespace") + annotations, err := componentIngress.GetAnnotations(&radixv1.RadixDeployComponent{IngressConfiguration: []string{"socket"}}, "unused-namespace") assert.Nil(t, err) assert.Equal(t, 3, len(annotations)) assert.Equal(t, config.AnnotationConfigurations[1].Annotations, annotations) - annotations, err = componentIngress.GetAnnotations(&v1.RadixDeployComponent{IngressConfiguration: []string{"socket", "round-robin"}}, "unused-namespace") + annotations, err = componentIngress.GetAnnotations(&radixv1.RadixDeployComponent{IngressConfiguration: []string{"socket", "round-robin"}}, "unused-namespace") assert.Nil(t, err) assert.Equal(t, 4, len(annotations)) assert.Equal(t, maputils.MergeMaps(config.AnnotationConfigurations[1].Annotations, config.AnnotationConfigurations[2].Annotations), annotations) - annotations, err = componentIngress.GetAnnotations(&v1.RadixDeployComponent{IngressConfiguration: []string{"non-existing"}}, "unused-namespace") + annotations, err = componentIngress.GetAnnotations(&radixv1.RadixDeployComponent{IngressConfiguration: []string{"non-existing"}}, "unused-namespace") assert.Nil(t, err) assert.Equal(t, 0, len(annotations)) } func Test_ClientCertificateAnnotations(t *testing.T) { - verification := v1.VerificationTypeOptional + verification := radixv1.VerificationTypeOptional expect1 := make(map[string]string) expect1["nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream"] = "true" - expect1["nginx.ingress.kubernetes.io/auth-tls-verify-client"] = string(v1.VerificationTypeOff) + expect1["nginx.ingress.kubernetes.io/auth-tls-verify-client"] = string(radixv1.VerificationTypeOff) expect1["nginx.ingress.kubernetes.io/auth-tls-secret"] = utils.GetComponentClientCertificateSecretName("ns/name") expect2 := make(map[string]string) expect2["nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream"] = "false" - expect2["nginx.ingress.kubernetes.io/auth-tls-verify-client"] = string(v1.VerificationTypeOff) + expect2["nginx.ingress.kubernetes.io/auth-tls-verify-client"] = string(radixv1.VerificationTypeOff) expect3 := make(map[string]string) expect3["nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream"] = "false" expect3["nginx.ingress.kubernetes.io/auth-tls-verify-client"] = string(verification) expect3["nginx.ingress.kubernetes.io/auth-tls-secret"] = utils.GetComponentClientCertificateSecretName("ns/name") - config1 := &v1.Authentication{ - ClientCertificate: &v1.ClientCertificate{ + config1 := &radixv1.Authentication{ + ClientCertificate: &radixv1.ClientCertificate{ PassCertificateToUpstream: utils.BoolPtr(true), }, } - config2 := &v1.Authentication{ - ClientCertificate: &v1.ClientCertificate{ + config2 := &radixv1.Authentication{ + ClientCertificate: &radixv1.ClientCertificate{ PassCertificateToUpstream: utils.BoolPtr(false), }, } - config3 := &v1.Authentication{ - ClientCertificate: &v1.ClientCertificate{ + config3 := &radixv1.Authentication{ + ClientCertificate: &radixv1.ClientCertificate{ Verification: &verification, }, } - ingressAnnotations := clientCertificateAnnotationProvider{namespace: "ns"} - result, err := ingressAnnotations.GetAnnotations(&v1.RadixDeployComponent{Name: "name", Authentication: config1}, "unused-namespace") + ingressAnnotations := NewClientCertificateAnnotationProvider("ns") + result, err := ingressAnnotations.GetAnnotations(&radixv1.RadixDeployComponent{Name: "name", Authentication: config1}, "unused-namespace") assert.Nil(t, err) assert.Equal(t, expect1, result) - result, err = ingressAnnotations.GetAnnotations(&v1.RadixDeployComponent{Name: "name", Authentication: config2}, "unused-namespace") + result, err = ingressAnnotations.GetAnnotations(&radixv1.RadixDeployComponent{Name: "name", Authentication: config2}, "unused-namespace") assert.Nil(t, err) assert.Equal(t, expect2, result) - result, err = ingressAnnotations.GetAnnotations(&v1.RadixDeployComponent{Name: "name", Authentication: config3}, "unused-namespace") + result, err = ingressAnnotations.GetAnnotations(&radixv1.RadixDeployComponent{Name: "name", Authentication: config3}, "unused-namespace") assert.Nil(t, err) assert.Equal(t, expect3, result) - result, err = ingressAnnotations.GetAnnotations(&v1.RadixDeployComponent{Name: "name"}, "unused-namespace") + result, err = ingressAnnotations.GetAnnotations(&radixv1.RadixDeployComponent{Name: "name"}, "unused-namespace") assert.Nil(t, err) assert.Empty(t, result, "Expected Annotations to be empty") } @@ -150,7 +150,7 @@ func (s *OAuth2AnnotationsTestSuite) TearDownTest() { func (s *OAuth2AnnotationsTestSuite) Test_NonPublicComponent() { s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(0) sut := oauth2AnnotationProvider{oauth2DefaultConfig: s.oauth2Config} - actual, err := sut.GetAnnotations(&v1.RadixDeployComponent{Authentication: &v1.Authentication{OAuth2: &v1.OAuth2{ClientID: "1234"}}}, "unused-namespace") + actual, err := sut.GetAnnotations(&radixv1.RadixDeployComponent{Authentication: &radixv1.Authentication{OAuth2: &radixv1.OAuth2{ClientID: "1234"}}}, "unused-namespace") s.Nil(err) s.Len(actual, 0) } @@ -158,58 +158,58 @@ func (s *OAuth2AnnotationsTestSuite) Test_NonPublicComponent() { func (s *OAuth2AnnotationsTestSuite) Test_PublicComponentNoOAuth() { s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(0) sut := oauth2AnnotationProvider{oauth2DefaultConfig: s.oauth2Config} - actual, err := sut.GetAnnotations(&v1.RadixDeployComponent{PublicPort: "http", Authentication: &v1.Authentication{}}, "unused-namespace") + actual, err := sut.GetAnnotations(&radixv1.RadixDeployComponent{PublicPort: "http", Authentication: &radixv1.Authentication{}}, "unused-namespace") s.Nil(err) s.Len(actual, 0) } func (s *OAuth2AnnotationsTestSuite) Test_ComponentOAuthPassedToOAuth2Config() { - oauth := &v1.OAuth2{ClientID: "1234"} - s.oauth2Config.EXPECT().MergeWith(oauth).Times(1).Return(&v1.OAuth2{}, nil) + oauth := &radixv1.OAuth2{ClientID: "1234"} + s.oauth2Config.EXPECT().MergeWith(oauth).Times(1).Return(&radixv1.OAuth2{}, nil) sut := oauth2AnnotationProvider{oauth2DefaultConfig: s.oauth2Config} - sut.GetAnnotations(&v1.RadixDeployComponent{PublicPort: "http", Authentication: &v1.Authentication{OAuth2: oauth}}, "unused-namespace") + sut.GetAnnotations(&radixv1.RadixDeployComponent{PublicPort: "http", Authentication: &radixv1.Authentication{OAuth2: oauth}}, "unused-namespace") } func (s *OAuth2AnnotationsTestSuite) Test_AuthSigninAndUrlAnnotations() { - s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(1).Return(&v1.OAuth2{ProxyPrefix: "/anypath"}, nil) + s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(1).Return(&radixv1.OAuth2{ProxyPrefix: "/anypath"}, nil) expected := map[string]string{ "nginx.ingress.kubernetes.io/auth-signin": "https://$host/anypath/start?rd=$escaped_request_uri", "nginx.ingress.kubernetes.io/auth-url": "http://oauth-test-aux-oauth.appname-namespace.svc.cluster.local:4180/anypath/auth", } sut := oauth2AnnotationProvider{oauth2DefaultConfig: s.oauth2Config} - actual, err := sut.GetAnnotations(&v1.RadixDeployComponent{Name: "oauth-test", PublicPort: "http", Authentication: &v1.Authentication{OAuth2: &v1.OAuth2{}}}, "appname-namespace") + actual, err := sut.GetAnnotations(&radixv1.RadixDeployComponent{Name: "oauth-test", PublicPort: "http", Authentication: &radixv1.Authentication{OAuth2: &radixv1.OAuth2{}}}, "appname-namespace") s.Nil(err) s.Equal(expected, actual) } func (s *OAuth2AnnotationsTestSuite) Test_AuthResponseHeaderAnnotations_All() { - s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(1).Return(&v1.OAuth2{SetXAuthRequestHeaders: utils.BoolPtr(true), SetAuthorizationHeader: utils.BoolPtr(true)}, nil) + s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(1).Return(&radixv1.OAuth2{SetXAuthRequestHeaders: utils.BoolPtr(true), SetAuthorizationHeader: utils.BoolPtr(true)}, nil) sut := oauth2AnnotationProvider{oauth2DefaultConfig: s.oauth2Config} - actual, err := sut.GetAnnotations(&v1.RadixDeployComponent{PublicPort: "http", Authentication: &v1.Authentication{OAuth2: &v1.OAuth2{}}}, "unused-namespace") + actual, err := sut.GetAnnotations(&radixv1.RadixDeployComponent{PublicPort: "http", Authentication: &radixv1.Authentication{OAuth2: &radixv1.OAuth2{}}}, "unused-namespace") s.Nil(err) s.Equal("X-Auth-Request-Access-Token,X-Auth-Request-User,X-Auth-Request-Groups,X-Auth-Request-Email,X-Auth-Request-Preferred-Username,Authorization", actual["nginx.ingress.kubernetes.io/auth-response-headers"]) } func (s *OAuth2AnnotationsTestSuite) Test_AuthResponseHeaderAnnotations_XAuthHeadersOnly() { - s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(1).Return(&v1.OAuth2{SetXAuthRequestHeaders: utils.BoolPtr(true), SetAuthorizationHeader: utils.BoolPtr(false)}, nil) + s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(1).Return(&radixv1.OAuth2{SetXAuthRequestHeaders: utils.BoolPtr(true), SetAuthorizationHeader: utils.BoolPtr(false)}, nil) sut := oauth2AnnotationProvider{oauth2DefaultConfig: s.oauth2Config} - actual, err := sut.GetAnnotations(&v1.RadixDeployComponent{PublicPort: "http", Authentication: &v1.Authentication{OAuth2: &v1.OAuth2{}}}, "unused-namespace") + actual, err := sut.GetAnnotations(&radixv1.RadixDeployComponent{PublicPort: "http", Authentication: &radixv1.Authentication{OAuth2: &radixv1.OAuth2{}}}, "unused-namespace") s.Nil(err) s.Equal("X-Auth-Request-Access-Token,X-Auth-Request-User,X-Auth-Request-Groups,X-Auth-Request-Email,X-Auth-Request-Preferred-Username", actual["nginx.ingress.kubernetes.io/auth-response-headers"]) } func (s *OAuth2AnnotationsTestSuite) Test_AuthResponseHeaderAnnotations_AuthorizationHeaderOnly() { - s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(1).Return(&v1.OAuth2{SetXAuthRequestHeaders: utils.BoolPtr(false), SetAuthorizationHeader: utils.BoolPtr(true)}, nil) + s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(1).Return(&radixv1.OAuth2{SetXAuthRequestHeaders: utils.BoolPtr(false), SetAuthorizationHeader: utils.BoolPtr(true)}, nil) sut := oauth2AnnotationProvider{oauth2DefaultConfig: s.oauth2Config} - actual, err := sut.GetAnnotations(&v1.RadixDeployComponent{PublicPort: "http", Authentication: &v1.Authentication{OAuth2: &v1.OAuth2{}}}, "unused-namespace") + actual, err := sut.GetAnnotations(&radixv1.RadixDeployComponent{PublicPort: "http", Authentication: &radixv1.Authentication{OAuth2: &radixv1.OAuth2{}}}, "unused-namespace") s.Nil(err) s.Equal("Authorization", actual["nginx.ingress.kubernetes.io/auth-response-headers"]) } func (s *OAuth2AnnotationsTestSuite) Test_OAuthConfig_ApplyTo_ReturnError() { - s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(1).Return(&v1.OAuth2{SetXAuthRequestHeaders: utils.BoolPtr(false), SetAuthorizationHeader: utils.BoolPtr(true)}, errors.New("any error")) + s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(1).Return(&radixv1.OAuth2{SetXAuthRequestHeaders: utils.BoolPtr(false), SetAuthorizationHeader: utils.BoolPtr(true)}, errors.New("any error")) sut := oauth2AnnotationProvider{oauth2DefaultConfig: s.oauth2Config} - actual, err := sut.GetAnnotations(&v1.RadixDeployComponent{PublicPort: "http", Authentication: &v1.Authentication{OAuth2: &v1.OAuth2{}}}, "unused-namespace") + actual, err := sut.GetAnnotations(&radixv1.RadixDeployComponent{PublicPort: "http", Authentication: &radixv1.Authentication{OAuth2: &radixv1.OAuth2{}}}, "unused-namespace") s.Error(err) s.Nil(actual) } diff --git a/pkg/apis/ingress/secret.go b/pkg/apis/ingress/secret.go new file mode 100644 index 000000000..dcdceb089 --- /dev/null +++ b/pkg/apis/ingress/secret.go @@ -0,0 +1,15 @@ +package ingress + +import "github.com/equinor/radix-operator/pkg/apis/radix/v1" + +// IsSecretRequiredForClientCertificate Check is Secret is required for thr ClientCertificate +func IsSecretRequiredForClientCertificate(clientCertificate *v1.ClientCertificate) bool { + if clientCertificate != nil { + certificateConfig := ParseClientCertificateConfiguration(*clientCertificate) + if *certificateConfig.PassCertificateToUpstream || *certificateConfig.Verification != v1.VerificationTypeOff { + return true + } + } + + return false +} diff --git a/pkg/apis/ingress/secret_test.go b/pkg/apis/ingress/secret_test.go new file mode 100644 index 000000000..489e91a65 --- /dev/null +++ b/pkg/apis/ingress/secret_test.go @@ -0,0 +1,40 @@ +package ingress + +import ( + "testing" + + "github.com/equinor/radix-common/utils/pointers" + "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/stretchr/testify/assert" +) + +func Test_IsSecretRequiredForClientCertificate(t *testing.T) { + type scenario struct { + clientCertificate *v1.ClientCertificate + expectedResult bool + } + scenarios := []scenario{ + {clientCertificate: nil, expectedResult: false}, + {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOff)}, expectedResult: false}, + {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOptional)}, expectedResult: true}, + {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOptionalNoCa)}, expectedResult: true}, + {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOn)}, expectedResult: true}, + {clientCertificate: &v1.ClientCertificate{}, expectedResult: false}, + {clientCertificate: &v1.ClientCertificate{PassCertificateToUpstream: pointers.Ptr(false)}, expectedResult: false}, + {clientCertificate: &v1.ClientCertificate{PassCertificateToUpstream: pointers.Ptr(true)}, expectedResult: true}, + {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOff), PassCertificateToUpstream: pointers.Ptr(true)}, expectedResult: true}, + {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOff), PassCertificateToUpstream: pointers.Ptr(false)}, expectedResult: false}, + {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOptional), PassCertificateToUpstream: pointers.Ptr(true)}, expectedResult: true}, + {clientCertificate: &v1.ClientCertificate{Verification: getVerificationTypePtr(v1.VerificationTypeOptional), PassCertificateToUpstream: pointers.Ptr(false)}, expectedResult: true}, + } + + for _, ts := range scenarios { + t.Run("", func(t *testing.T) { + assert.Equal(t, ts.expectedResult, IsSecretRequiredForClientCertificate(ts.clientCertificate)) + }) + } +} + +func getVerificationTypePtr(verificationType v1.VerificationType) *v1.VerificationType { + return &verificationType +} diff --git a/pkg/apis/kube/namespaces.go b/pkg/apis/kube/namespaces.go index fc4990a14..6ab7f7204 100644 --- a/pkg/apis/kube/namespaces.go +++ b/pkg/apis/kube/namespaces.go @@ -32,7 +32,7 @@ func (kubeutil *Kube) ApplyNamespace(name string, labels map[string]string, owne oldNamespace, err := kubeutil.getNamespace(name) if err != nil && k8errs.IsNotFound(err) { - log.Debugf("Namespace object %s doesn't exists, create the object", name) + log.Debugf("namespace object %s doesn't exists, create the object", name) _, err := kubeutil.kubeClient.CoreV1().Namespaces().Create(context.TODO(), &namespace, metav1.CreateOptions{}) return err } @@ -114,7 +114,7 @@ func (watcher NamespaceWatcherImpl) WaitFor(namespace string) error { return err } - log.Infof("Namespace %s exists and is active", namespace) + log.Infof("namespace %s exists and is active", namespace) return nil } @@ -127,7 +127,7 @@ func waitForNamespace(client kubernetes.Interface, namespace string) error { ns, err := client.CoreV1().Namespaces().Get(context.TODO(), namespace, metav1.GetOptions{}) if err != nil { if k8errs.IsNotFound(err) || k8errs.IsForbidden(err) { - return false, nil //the environment namespace or the rolebinding for the cluster-role radix-pipeline-env are not yet created + return false, nil // the environment namespace or the rolebinding for the cluster-role radix-pipeline-env are not yet created } return false, err } diff --git a/radix-operator/deployment/handler.go b/radix-operator/deployment/handler.go index a7d351577..679ab0a27 100644 --- a/radix-operator/deployment/handler.go +++ b/radix-operator/deployment/handler.go @@ -168,15 +168,15 @@ func (t *Handler) Sync(namespace, name string, eventRecorder record.EventRecorde return err } - ingressAnnotations := []deployment.IngressAnnotationProvider{ - deployment.NewForceSslRedirectAnnotationProvider(), - deployment.NewIngressConfigurationAnnotationProvider(t.ingressConfiguration), - deployment.NewClientCertificateAnnotationProvider(syncRD.Namespace), - deployment.NewOAuth2AnnotationProvider(t.oauth2DefaultConfig), + ingressAnnotations := []ingress.AnnotationProvider{ + ingress.NewForceSslRedirectAnnotationProvider(), + ingress.NewIngressConfigurationAnnotationProvider(t.ingressConfiguration), + ingress.NewClientCertificateAnnotationProvider(syncRD.Namespace), + ingress.NewOAuth2AnnotationProvider(t.oauth2DefaultConfig), } auxResourceManagers := []deployment.AuxiliaryResourceManager{ - deployment.NewOAuthProxyResourceManager(syncRD, radixRegistration, t.kubeutil, t.oauth2DefaultConfig, []deployment.IngressAnnotationProvider{deployment.NewForceSslRedirectAnnotationProvider()}, t.oauth2ProxyDockerImage), + deployment.NewOAuthProxyResourceManager(syncRD, radixRegistration, t.kubeutil, t.oauth2DefaultConfig, []ingress.AnnotationProvider{ingress.NewForceSslRedirectAnnotationProvider()}, t.oauth2ProxyDockerImage), } deployment := t.deploymentSyncerFactory.CreateDeploymentSyncer(t.kubeclient, t.kubeutil, t.radixclient, t.prometheusperatorclient, radixRegistration, syncRD, t.tenantId, t.kubernetesApiPort, t.deploymentHistoryLimit, ingressAnnotations, auxResourceManagers) diff --git a/radix-operator/deployment/handler_test.go b/radix-operator/deployment/handler_test.go index c959d90c2..a6fce1ae4 100644 --- a/radix-operator/deployment/handler_test.go +++ b/radix-operator/deployment/handler_test.go @@ -131,14 +131,14 @@ func (s *handlerSuite) Test_Sync() { factory := deployment.NewMockDeploymentSyncerFactory(ctrl) oauthConfig := defaults.NewOAuth2Config() ingressConfig := ingress.IngressConfiguration{AnnotationConfigurations: []ingress.AnnotationConfiguration{{Name: "test"}}} - expectedIngressAnnotations := []deployment.IngressAnnotationProvider{ - deployment.NewForceSslRedirectAnnotationProvider(), - deployment.NewIngressConfigurationAnnotationProvider(ingressConfig), - deployment.NewClientCertificateAnnotationProvider(activeRd.Namespace), - deployment.NewOAuth2AnnotationProvider(oauthConfig), + expectedIngressAnnotations := []ingress.AnnotationProvider{ + ingress.NewForceSslRedirectAnnotationProvider(), + ingress.NewIngressConfigurationAnnotationProvider(ingressConfig), + ingress.NewClientCertificateAnnotationProvider(activeRd.Namespace), + ingress.NewOAuth2AnnotationProvider(oauthConfig), } expectedAuxResources := []deployment.AuxiliaryResourceManager{ - deployment.NewOAuthProxyResourceManager(activeRd, rr, s.kubeUtil, oauthConfig, []deployment.IngressAnnotationProvider{deployment.NewForceSslRedirectAnnotationProvider()}, "oauth:123"), + deployment.NewOAuthProxyResourceManager(activeRd, rr, s.kubeUtil, oauthConfig, []ingress.AnnotationProvider{ingress.NewForceSslRedirectAnnotationProvider()}, "oauth:123"), } factory. EXPECT(). From a551ae2727e59e2d16db6c669baac1449b7e64b5 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 17 Nov 2023 16:07:12 +0100 Subject: [PATCH 060/121] Added args ingress and oauthconfig to dnsalias --- pkg/apis/dnsalias/syncer.go | 28 ++++++---- pkg/apis/dnsalias/syncer_test.go | 53 +++++++++++-------- .../ingress/ingressannotationprovider_mock.go | 52 ++++++++++++++++++ radix-operator/dnsalias/handler.go | 2 +- radix-operator/dnsalias/handler_test.go | 6 +-- .../dnsalias/internal/syncerfactory.go | 10 ++-- .../dnsalias/internal/syncerfactory_mock.go | 10 ++-- 7 files changed, 116 insertions(+), 45 deletions(-) diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 117ca8fbb..abb2b623f 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -4,6 +4,8 @@ import ( "fmt" "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -21,21 +23,25 @@ type Syncer interface { // DNSAlias is the aggregate-root for manipulating RadixDNSAliases type syncer struct { - kubeClient kubernetes.Interface - radixClient radixclient.Interface - kubeUtil *kube.Kube - radixDNSAlias *radixv1.RadixDNSAlias - dnsConfig *dnsalias.DNSConfig + kubeClient kubernetes.Interface + radixClient radixclient.Interface + kubeUtil *kube.Kube + radixDNSAlias *radixv1.RadixDNSAlias + dnsConfig *dnsalias.DNSConfig + ingressConfiguration ingress.IngressConfiguration + oauth2Config defaults.OAuth2Config } // NewSyncer is the constructor for RadixDNSAlias syncer -func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { +func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { return &syncer{ - kubeClient: kubeClient, - radixClient: radixClient, - kubeUtil: kubeUtil, - dnsConfig: dnsConfig, - radixDNSAlias: radixDNSAlias, + kubeClient: kubeClient, + radixClient: radixClient, + kubeUtil: kubeUtil, + dnsConfig: dnsConfig, + ingressConfiguration: ingressConfiguration, + oauth2Config: oauth2Config, + radixDNSAlias: radixDNSAlias, } } diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 9c7a3e3b3..41dc79f0b 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -6,7 +6,9 @@ import ( "testing" dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -25,11 +27,13 @@ import ( type syncerTestSuite struct { suite.Suite - kubeClient *kubefake.Clientset - radixClient *radixfake.Clientset - kubeUtil *kube.Kube - promClient *prometheusfake.Clientset - dnsConfig *dnsalias2.DNSConfig + kubeClient *kubefake.Clientset + radixClient *radixfake.Clientset + kubeUtil *kube.Kube + promClient *prometheusfake.Clientset + dnsConfig *dnsalias2.DNSConfig + oauthConfig defaults.OAuth2Config + ingressConfig ingress.IngressConfiguration } func TestSyncerTestSuite(t *testing.T) { @@ -41,11 +45,14 @@ func (s *syncerTestSuite) SetupTest() { s.radixClient = radixfake.NewSimpleClientset() s.promClient = prometheusfake.NewSimpleClientset() s.dnsConfig = &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} + s.oauthConfig = defaults.NewOAuth2Config() + s.ingressConfig = ingress.IngressConfiguration{AnnotationConfigurations: []ingress.AnnotationConfiguration{{Name: "test"}}} + s.kubeUtil, _ = kube.New(s.kubeClient, s.radixClient, secretproviderfake.NewSimpleClientset()) } func (s *syncerTestSuite) createSyncer(radixDNSAlias *radixv1.RadixDNSAlias) dnsalias.Syncer { - return dnsalias.NewSyncer(s.kubeClient, s.kubeUtil, s.radixClient, s.dnsConfig, radixDNSAlias) + return dnsalias.NewSyncer(s.kubeClient, s.kubeUtil, s.radixClient, s.dnsConfig, s.ingressConfig, s.oauthConfig, radixDNSAlias) } type testIngress struct { @@ -210,18 +217,18 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { s.Require().Len(ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") if len(ingresses.Items) == len(ts.expectedIngress) { - for _, ingress := range ingresses.Items { - if expectedIngress, ok := ts.expectedIngress[ingress.Name]; ok { - s.Require().Len(ingress.Spec.Rules, 1, "rules count") - s.Assert().Equal(expectedIngress.appName, ingress.GetLabels()[kube.RadixAppLabel], "app name") - s.Assert().Equal(utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ingress.GetNamespace(), "namespace") - s.Assert().Equal(expectedIngress.component, ingress.GetLabels()[kube.RadixComponentLabel], "component name") - s.Assert().Equal(expectedIngress.host, ingress.Spec.Rules[0].Host, "rule host") - s.Assert().Equal("/", ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") - s.Assert().Equal(expectedIngress.component, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") - s.Assert().Equal(expectedIngress.port, ingress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") - if len(ingress.ObjectMeta.OwnerReferences) > 0 { - ownerRef := ingress.ObjectMeta.OwnerReferences[0] + for _, ing := range ingresses.Items { + if expectedIngress, ok := ts.expectedIngress[ing.Name]; ok { + s.Require().Len(ing.Spec.Rules, 1, "rules count") + s.Assert().Equal(expectedIngress.appName, ing.GetLabels()[kube.RadixAppLabel], "app name") + s.Assert().Equal(utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ing.GetNamespace(), "namespace") + s.Assert().Equal(expectedIngress.component, ing.GetLabels()[kube.RadixComponentLabel], "component name") + s.Assert().Equal(expectedIngress.host, ing.Spec.Rules[0].Host, "rule host") + s.Assert().Equal("/", ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") + s.Assert().Equal(expectedIngress.component, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") + s.Assert().Equal(expectedIngress.port, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") + if len(ing.ObjectMeta.OwnerReferences) > 0 { + ownerRef := ing.ObjectMeta.OwnerReferences[0] s.Assert().Equal(radix.APIVersion, ownerRef.APIVersion, "ownerRef.APIVersion") s.Assert().Equal(radix.KindRadixDNSAlias, ownerRef.Kind, "ownerRef.Kind") s.Assert().Equal(radixDNSAlias.GetName(), ownerRef.Name, "ownerRef.Name") @@ -231,8 +238,8 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { continue } assert.Fail(t, fmt.Sprintf("found not expected ingress %s for: appName %s, host %s, service %s, port %d", - ingress.GetName(), ingress.GetLabels()[kube.RadixAppLabel], ingress.Spec.Rules[0].Host, ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, - ingress.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port.Number)) + ing.GetName(), ing.GetLabels()[kube.RadixAppLabel], ing.Spec.Rules[0].Host, ing.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, + ing.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port.Number)) } } @@ -242,9 +249,9 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses map[string]testIngress, appNameForNamespace, envNameForNamespace string, config *dnsalias2.DNSConfig) error { for name, ing := range testIngresses { - ingress := dnsalias.BuildRadixDNSAliasIngress(ing.appName, ing.alias, ing.component, ing.port, nil, config) - ingress.SetName(name) // override built name with expected name for test purpose - _, err := dnsalias.CreateRadixDNSAliasIngress(kubeClient, appNameForNamespace, envNameForNamespace, ingress) + ing := dnsalias.BuildRadixDNSAliasIngress(ing.appName, ing.alias, ing.component, ing.port, nil, config) + ing.SetName(name) // override built name with expected name for test purpose + _, err := dnsalias.CreateRadixDNSAliasIngress(kubeClient, appNameForNamespace, envNameForNamespace, ing) if err != nil { return err } diff --git a/pkg/apis/ingress/ingressannotationprovider_mock.go b/pkg/apis/ingress/ingressannotationprovider_mock.go index e390d7ebd..2e5f69447 100644 --- a/pkg/apis/ingress/ingressannotationprovider_mock.go +++ b/pkg/apis/ingress/ingressannotationprovider_mock.go @@ -48,3 +48,55 @@ func (mr *MockAnnotationProviderMockRecorder) GetAnnotations(component, namespac mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAnnotations", reflect.TypeOf((*MockAnnotationProvider)(nil).GetAnnotations), component, namespace) } + +// MockClientCertificateAnnotationProvider is a mock of ClientCertificateAnnotationProvider interface. +type MockClientCertificateAnnotationProvider struct { + ctrl *gomock.Controller + recorder *MockClientCertificateAnnotationProviderMockRecorder +} + +// MockClientCertificateAnnotationProviderMockRecorder is the mock recorder for MockClientCertificateAnnotationProvider. +type MockClientCertificateAnnotationProviderMockRecorder struct { + mock *MockClientCertificateAnnotationProvider +} + +// NewMockClientCertificateAnnotationProvider creates a new mock instance. +func NewMockClientCertificateAnnotationProvider(ctrl *gomock.Controller) *MockClientCertificateAnnotationProvider { + mock := &MockClientCertificateAnnotationProvider{ctrl: ctrl} + mock.recorder = &MockClientCertificateAnnotationProviderMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockClientCertificateAnnotationProvider) EXPECT() *MockClientCertificateAnnotationProviderMockRecorder { + return m.recorder +} + +// GetAnnotations mocks base method. +func (m *MockClientCertificateAnnotationProvider) GetAnnotations(component v1.RadixCommonDeployComponent, namespace string) (map[string]string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAnnotations", component, namespace) + ret0, _ := ret[0].(map[string]string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetAnnotations indicates an expected call of GetAnnotations. +func (mr *MockClientCertificateAnnotationProviderMockRecorder) GetAnnotations(component, namespace interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAnnotations", reflect.TypeOf((*MockClientCertificateAnnotationProvider)(nil).GetAnnotations), component, namespace) +} + +// GetNamespace mocks base method. +func (m *MockClientCertificateAnnotationProvider) GetNamespace() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetNamespace") + ret0, _ := ret[0].(string) + return ret0 +} + +// GetNamespace indicates an expected call of GetNamespace. +func (mr *MockClientCertificateAnnotationProviderMockRecorder) GetNamespace() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNamespace", reflect.TypeOf((*MockClientCertificateAnnotationProvider)(nil).GetNamespace)) +} diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go index 2ffc0aa9d..209311960 100644 --- a/radix-operator/dnsalias/handler.go +++ b/radix-operator/dnsalias/handler.go @@ -99,7 +99,7 @@ func (h *handler) Sync(_, name string, eventRecorder record.EventRecorder) error syncingAlias := radixDNSAlias.DeepCopy() logger.Debugf("Sync RadixDNSAlias %s", name) - syncer := h.syncerFactory.CreateSyncer(h.kubeClient, h.kubeUtil, h.radixClient, h.dnsConfig, syncingAlias) + syncer := h.syncerFactory.CreateSyncer(h.kubeClient, h.kubeUtil, h.radixClient, h.dnsConfig, h.ingressConfiguration, h.oauth2DefaultConfig, syncingAlias) err = syncer.OnSync() if err != nil { return err diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index c4de5c60d..5704f94c0 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -46,7 +46,7 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) - s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any()).Times(0) + s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any()).Times(0) s.syncer.EXPECT().OnSync().Times(0) err := handler.Sync("", alias1, s.EventRecorder) @@ -59,7 +59,7 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) expectedError := fmt.Errorf("some error") - s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any()).Return(s.syncer).Times(1) + s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any()).Return(s.syncer).Times(1) s.syncer.EXPECT().OnSync().Return(expectedError).Times(1) actualError := handler.Sync("", alias1, s.EventRecorder) @@ -71,7 +71,7 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsNoError() { s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1, 8080), "create existing RadixDNSAlias") handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) - s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any()).Return(s.syncer).Times(1) + s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any()).Return(s.syncer).Times(1) s.syncer.EXPECT().OnSync().Return(nil).Times(1) err := handler.Sync("", alias1, s.EventRecorder) diff --git a/radix-operator/dnsalias/internal/syncerfactory.go b/radix-operator/dnsalias/internal/syncerfactory.go index e04abc719..dcf908379 100644 --- a/radix-operator/dnsalias/internal/syncerfactory.go +++ b/radix-operator/dnsalias/internal/syncerfactory.go @@ -2,7 +2,9 @@ package internal import ( "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/defaults" dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -11,7 +13,7 @@ import ( // SyncerFactory defines a factory to create a DNS alias Syncer type SyncerFactory interface { - CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer + CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer } // SyncerFactoryFunc is an adapter that can be used to convert @@ -21,10 +23,12 @@ type SyncerFactoryFunc func( kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, + ingressConfiguration ingress.IngressConfiguration, + oauth2Config defaults.OAuth2Config, radixDNSAlias *radixv1.RadixDNSAlias, ) dnsaliasapi.Syncer // CreateSyncer Create a DNS alias Syncer -func (f SyncerFactoryFunc) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer { - return f(kubeClient, kubeUtil, radixClient, dnsConfig, radixDNSAlias) +func (f SyncerFactoryFunc) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer { + return f(kubeClient, kubeUtil, radixClient, dnsConfig, ingressConfiguration, oauth2Config, radixDNSAlias) } diff --git a/radix-operator/dnsalias/internal/syncerfactory_mock.go b/radix-operator/dnsalias/internal/syncerfactory_mock.go index e5616b5f2..c749612d2 100644 --- a/radix-operator/dnsalias/internal/syncerfactory_mock.go +++ b/radix-operator/dnsalias/internal/syncerfactory_mock.go @@ -8,7 +8,9 @@ import ( reflect "reflect" dnsalias "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + defaults "github.com/equinor/radix-operator/pkg/apis/defaults" dnsalias0 "github.com/equinor/radix-operator/pkg/apis/dnsalias" + ingress "github.com/equinor/radix-operator/pkg/apis/ingress" kube "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" versioned "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -40,15 +42,15 @@ func (m *MockSyncerFactory) EXPECT() *MockSyncerFactoryMockRecorder { } // CreateSyncer mocks base method. -func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, dnsConfig *dnsalias.DNSConfig, radixDNSAlias *v1.RadixDNSAlias) dnsalias0.Syncer { +func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, radixDNSAlias *v1.RadixDNSAlias) dnsalias0.Syncer { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateSyncer", kubeClient, kubeUtil, radixClient, dnsConfig, radixDNSAlias) + ret := m.ctrl.Call(m, "CreateSyncer", kubeClient, kubeUtil, radixClient, dnsConfig, ingressConfiguration, oauth2Config, radixDNSAlias) ret0, _ := ret[0].(dnsalias0.Syncer) return ret0 } // CreateSyncer indicates an expected call of CreateSyncer. -func (mr *MockSyncerFactoryMockRecorder) CreateSyncer(kubeClient, kubeUtil, radixClient, dnsConfig, radixDNSAlias interface{}) *gomock.Call { +func (mr *MockSyncerFactoryMockRecorder) CreateSyncer(kubeClient, kubeUtil, radixClient, dnsConfig, ingressConfiguration, oauth2Config, radixDNSAlias interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSyncer", reflect.TypeOf((*MockSyncerFactory)(nil).CreateSyncer), kubeClient, kubeUtil, radixClient, dnsConfig, radixDNSAlias) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSyncer", reflect.TypeOf((*MockSyncerFactory)(nil).CreateSyncer), kubeClient, kubeUtil, radixClient, dnsConfig, ingressConfiguration, oauth2Config, radixDNSAlias) } From e3935d7b68b368a4847c9946a11568f40dac616c Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 17 Nov 2023 16:43:19 +0100 Subject: [PATCH 061/121] Replaced registration of ingress by RadixDNSAlias. Needs to fix unit-tests --- pkg/apis/dnsalias/errors.go | 8 ++++ pkg/apis/dnsalias/ingress.go | 44 -------------------- pkg/apis/dnsalias/internal/ownerreference.go | 11 ++--- pkg/apis/dnsalias/syncer.go | 38 +++++++++++++++-- pkg/apis/dnsalias/syncer_test.go | 22 ++++++---- pkg/apis/ingress/ingress.go | 11 +++-- pkg/apis/utils/annotations/annotations.go | 4 +- 7 files changed, 71 insertions(+), 67 deletions(-) create mode 100644 pkg/apis/dnsalias/errors.go diff --git a/pkg/apis/dnsalias/errors.go b/pkg/apis/dnsalias/errors.go new file mode 100644 index 000000000..c26b0dc12 --- /dev/null +++ b/pkg/apis/dnsalias/errors.go @@ -0,0 +1,8 @@ +package dnsalias + +import "fmt" + +// DeployComponentNotFoundByName Deploy component not found +func DeployComponentNotFoundByName(appName, envName, componentName, deploymentName string) error { + return fmt.Errorf("component %s not found in environment %s in application %s for deployment %s", componentName, envName, appName, deploymentName) +} diff --git a/pkg/apis/dnsalias/ingress.go b/pkg/apis/dnsalias/ingress.go index 8002b1554..4f6afd19e 100644 --- a/pkg/apis/dnsalias/ingress.go +++ b/pkg/apis/dnsalias/ingress.go @@ -4,13 +4,7 @@ import ( "context" "fmt" - "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" - "github.com/equinor/radix-operator/pkg/apis/defaults" - "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" - "github.com/equinor/radix-operator/pkg/apis/utils/annotations" - "github.com/equinor/radix-operator/pkg/apis/utils/labels" networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -21,44 +15,6 @@ func CreateRadixDNSAliasIngress(kubeClient kubernetes.Interface, appName, envNam return kubeClient.NetworkingV1().Ingresses(utils.GetEnvironmentNamespace(appName, envName)).Create(context.Background(), ingress, metav1.CreateOptions{}) } -// BuildRadixDNSAliasIngress Build an Ingress for a RadixDNSAlias -func BuildRadixDNSAliasIngress(appName, alias, service string, port int32, owner *v1.RadixDNSAlias, config *dnsalias.DNSConfig) *networkingv1.Ingress { - pathTypeImplementationSpecific := networkingv1.PathTypeImplementationSpecific - ingressName := GetDNSAliasIngressName(service, alias) - host := GetDNSAliasHost(alias, config.DNSZone) - ingress := networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: ingressName, - Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(service)), - Annotations: annotations.ForManagedByRadixDNSAliasIngress(alias), - }, - Spec: networkingv1.IngressSpec{ - TLS: []networkingv1.IngressTLS{ - { - Hosts: []string{host}, - SecretName: defaults.TLSSecretName, - }, - }, - Rules: []networkingv1.IngressRule{ - { - Host: host, - IngressRuleValue: networkingv1.IngressRuleValue{ - HTTP: &networkingv1.HTTPIngressRuleValue{Paths: []networkingv1.HTTPIngressPath{ - {Path: "/", PathType: &pathTypeImplementationSpecific, Backend: networkingv1.IngressBackend{ - Service: &networkingv1.IngressServiceBackend{Name: service, Port: networkingv1.ServiceBackendPort{ - Number: port, - }}, - }}}, - }}, - }, - }, - }} - if owner != nil { - ingress.SetOwnerReferences([]metav1.OwnerReference{internal.GetOwnerReference(owner)}) - } - return &ingress -} - // GetDNSAliasIngressName Gets name of the ingress for the custom DNS alias func GetDNSAliasIngressName(service string, alias string) string { return fmt.Sprintf("%s.%s.custom-alias", service, alias) diff --git a/pkg/apis/dnsalias/internal/ownerreference.go b/pkg/apis/dnsalias/internal/ownerreference.go index d5388b9e4..a9658fc2b 100644 --- a/pkg/apis/dnsalias/internal/ownerreference.go +++ b/pkg/apis/dnsalias/internal/ownerreference.go @@ -7,13 +7,14 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// GetOwnerReference Gets RadixDNSAlias as an owner reference -func GetOwnerReference(alias *radixv1.RadixDNSAlias) metav1.OwnerReference { - return metav1.OwnerReference{ +// GetOwnerReferences Gets RadixDNSAlias as an owner reference +func GetOwnerReferences(radixDNSAlias *radixv1.RadixDNSAlias) []metav1.OwnerReference { + return []metav1.OwnerReference{{ APIVersion: radix.APIVersion, Kind: radix.KindRadixDNSAlias, - Name: alias.Name, - UID: alias.UID, + Name: radixDNSAlias.Name, + UID: radixDNSAlias.UID, Controller: pointers.Ptr(true), + }, } } diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index abb2b623f..e0ba0c109 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -3,12 +3,15 @@ package dnsalias import ( "fmt" + commonUtils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" + "github.com/equinor/radix-operator/pkg/apis/utils/annotations" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -29,7 +32,7 @@ type syncer struct { radixDNSAlias *radixv1.RadixDNSAlias dnsConfig *dnsalias.DNSConfig ingressConfiguration ingress.IngressConfiguration - oauth2Config defaults.OAuth2Config + oauth2DefaultConfig defaults.OAuth2Config } // NewSyncer is the constructor for RadixDNSAlias syncer @@ -40,7 +43,7 @@ func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient kubeUtil: kubeUtil, dnsConfig: dnsConfig, ingressConfiguration: ingressConfiguration, - oauth2Config: oauth2Config, + oauth2DefaultConfig: oauth2Config, radixDNSAlias: radixDNSAlias, } } @@ -92,6 +95,33 @@ func (s *syncer) createIngress() error { func (s *syncer) buildIngress() (*networkingv1.Ingress, error) { aliasSpec := s.radixDNSAlias.Spec - alias := s.radixDNSAlias.GetName() - return BuildRadixDNSAliasIngress(aliasSpec.AppName, alias, aliasSpec.Component, aliasSpec.Port, s.radixDNSAlias, s.dnsConfig), nil + appName := aliasSpec.AppName + envName := aliasSpec.Environment + componentName := aliasSpec.Component + envNamespace := utils.GetEnvironmentNamespace(appName, envName) + ingressAnnotations := []ingress.AnnotationProvider{ + ingress.NewForceSslRedirectAnnotationProvider(), + ingress.NewIngressConfigurationAnnotationProvider(s.ingressConfiguration), + ingress.NewClientCertificateAnnotationProvider(envNamespace), + ingress.NewOAuth2AnnotationProvider(s.oauth2DefaultConfig), + } + radixDeployment, err := s.kubeUtil.GetActiveDeployment(envNamespace) + if err != nil { + return nil, err + } + deployComponent := radixDeployment.GetCommonComponentByName(componentName) + if commonUtils.IsNil(deployComponent) { + return nil, DeployComponentNotFoundByName(appName, envName, componentName, radixDeployment.GetName()) + } + + aliasName := s.radixDNSAlias.GetName() + ingressName := GetDNSAliasIngressName(componentName, aliasName) + hostName := GetDNSAliasHost(aliasName, s.dnsConfig.DNSZone) + ingressSpec := ingress.GetIngressSpec(hostName, componentName, defaults.TLSSecretName, aliasSpec.Port) + ingressConfig, err := ingress.GetIngressConfig(envNamespace, appName, deployComponent, ingressName, ingressSpec, ingressAnnotations, ingress.DNSAlias, internal.GetOwnerReferences(s.radixDNSAlias)) + if err != nil { + return nil, err + } + ingressConfig.ObjectMeta.Annotations = annotations.Merge(ingressConfig.ObjectMeta.Annotations, annotations.ForManagedByRadixDNSAliasIngress(aliasName)) + return ingressConfig, nil } diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 41dc79f0b..96d8f00f1 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -17,6 +17,7 @@ import ( radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" @@ -201,7 +202,11 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component, Port: ts.dnsAlias.Port}} s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Alias, radixDNSAlias.Spec), "create existing alias") cfg := &dnsalias2.DNSConfig{DNSZone: ts.dnsZone} + + // TODO fix registration below s.Require().NoError(registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1, cfg), "create existing ingresses") + require.Fail(t, "fix registration above") + syncer := s.createSyncer(radixDNSAlias) err := syncer.OnSync() commonTest.AssertError(s.T(), ts.expectedError, err) @@ -248,13 +253,14 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { } func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses map[string]testIngress, appNameForNamespace, envNameForNamespace string, config *dnsalias2.DNSConfig) error { - for name, ing := range testIngresses { - ing := dnsalias.BuildRadixDNSAliasIngress(ing.appName, ing.alias, ing.component, ing.port, nil, config) - ing.SetName(name) // override built name with expected name for test purpose - _, err := dnsalias.CreateRadixDNSAliasIngress(kubeClient, appNameForNamespace, envNameForNamespace, ing) - if err != nil { - return err - } - } + // TODO - rework pre-registration + // for name, ing := range testIngresses { + // ing := dnsalias.BuildRadixDNSAliasIngress(ing.appName, ing.alias, ing.component, ing.port, nil, config) + // ing.SetName(name) // override built name with expected name for test purpose + // _, err := dnsalias.CreateRadixDNSAliasIngress(kubeClient, appNameForNamespace, envNameForNamespace, ing) + // if err != nil { + // return err + // } + // } return nil } diff --git a/pkg/apis/ingress/ingress.go b/pkg/apis/ingress/ingress.go index 97ed98386..7bf5997c0 100644 --- a/pkg/apis/ingress/ingress.go +++ b/pkg/apis/ingress/ingress.go @@ -93,11 +93,14 @@ func ParseClientCertificateConfiguration(clientCertificate radixv1.ClientCertifi } // GetIngressConfig Gets Ingress configuration -func GetIngressConfig(namespace string, appName string, component radixv1.RadixCommonDeployComponent, ingressName string, ingressSpec networkingv1.IngressSpec, ingressProviders []AnnotationProvider, aliasType DNSAliasType, ownerReference []metav1.OwnerReference) (*networkingv1.Ingress, error) { - annotations := map[string]string{} +func GetIngressConfig(namespace string, appName string, component radixv1.RadixCommonDeployComponent, + ingressName string, ingressSpec networkingv1.IngressSpec, + ingressProviders []AnnotationProvider, aliasType DNSAliasType, + ownerReference []metav1.OwnerReference) (*networkingv1.Ingress, error) { - for _, ia := range ingressProviders { - providedAnnotations, err := ia.GetAnnotations(component, namespace) + annotations := map[string]string{} + for _, ingressProvider := range ingressProviders { + providedAnnotations, err := ingressProvider.GetAnnotations(component, namespace) if err != nil { return nil, err } diff --git a/pkg/apis/utils/annotations/annotations.go b/pkg/apis/utils/annotations/annotations.go index 83bbe77e2..820cfde27 100644 --- a/pkg/apis/utils/annotations/annotations.go +++ b/pkg/apis/utils/annotations/annotations.go @@ -14,8 +14,8 @@ const ( ) // Merge multiple maps into one -func Merge(labels ...map[string]string) map[string]string { - return maputils.MergeMaps(labels...) +func Merge(annotations ...map[string]string) map[string]string { + return maputils.MergeMaps(annotations...) } // ForRadixBranch returns annotations describing a branch name From 10f574ef18e7339326959c7d0f57c721177ed1ca Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 20 Nov 2023 15:31:28 +0100 Subject: [PATCH 062/121] Do not sync dnsaliases whyle there is no deployment existing --- pkg/apis/dnsalias/syncer.go | 9 +++++++++ pkg/apis/radix/register.go | 2 ++ 2 files changed, 11 insertions(+) diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index e0ba0c109..7f1fd35d5 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -9,12 +9,14 @@ import ( "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/annotations" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" ) @@ -58,6 +60,7 @@ func (s *syncer) OnSync() error { return err } return s.syncStatus() + } func (s *syncer) syncAlias() error { @@ -86,6 +89,9 @@ func (s *syncer) syncAlias() error { func (s *syncer) createIngress() error { ingress, err := s.buildIngress() if err != nil { + if errors.IsNotFound(err) { + return nil + } return err } aliasSpec := s.radixDNSAlias.Spec @@ -109,6 +115,9 @@ func (s *syncer) buildIngress() (*networkingv1.Ingress, error) { if err != nil { return nil, err } + if radixDeployment == nil { + return nil, errors.NewNotFound(schema.GroupResource{Group: radix.GroupName, Resource: radix.ResourceRadixDeployment}, "active") + } deployComponent := radixDeployment.GetCommonComponentByName(componentName) if commonUtils.IsNil(deployComponent) { return nil, DeployComponentNotFoundByName(appName, envName, componentName, radixDeployment.GetName()) diff --git a/pkg/apis/radix/register.go b/pkg/apis/radix/register.go index 07d964010..2c9509203 100644 --- a/pkg/apis/radix/register.go +++ b/pkg/apis/radix/register.go @@ -27,4 +27,6 @@ const ( ResourceRadixRegistrations = "radixregistrations" // ResourceRadixDNSAliases RadixDNSAliases API resource ResourceRadixDNSAliases = "radixdnsaliases" + // ResourceRadixDeployment RadixDeployment API resource + ResourceRadixDeployment = "radixdeployment" ) From b053e7cb0a8de0c5bf083b072a1d0eb7bde6f969 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 21 Nov 2023 09:56:26 +0100 Subject: [PATCH 063/121] Update refs --- go.sum | 4 ---- 1 file changed, 4 deletions(-) diff --git a/go.sum b/go.sum index 87cc12ba4..b453a127b 100644 --- a/go.sum +++ b/go.sum @@ -72,10 +72,6 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/equinor/radix-common v1.5.0 h1:z5hQHlKG2x16/NnV4b9ynf9n5ZageYUewE4MANdA96Y= -github.com/equinor/radix-common v1.5.0/go.mod h1:UZ69U56VFtTxABi5JjGdaqn9Df5ilfTTqzUQ0riofVM= -github.com/equinor/radix-common v1.6.1-0.20231114095949-d7354edaf04c h1:lX3lWLliPowJHMs3yp327ExdlkJvvpqU5ErRxJyV7Zg= -github.com/equinor/radix-common v1.6.1-0.20231114095949-d7354edaf04c/go.mod h1:9hHvudaiqmoIjCqKlsW14jMj8qU/b/wMXUwkffd9MUw= github.com/equinor/radix-common v1.6.1 h1:gTGvSVSgd4DUQh4y05okzzfxlRqKJEjYbfEwSPJXRnM= github.com/equinor/radix-common v1.6.1/go.mod h1:9hHvudaiqmoIjCqKlsW14jMj8qU/b/wMXUwkffd9MUw= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= From e33be732e867824bb5b232fac0e83e4a8821c39a Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 21 Nov 2023 17:09:58 +0100 Subject: [PATCH 064/121] Added deletion of dns aliases on deleting radix environments, create/update/swap/delete aliases. Needs to fox deleting radix environments on deleting application --- .../applicationconfig/applicationconfig.go | 2 + pkg/apis/applicationconfig/dns_alias.go | 54 ++++++++++--------- pkg/apis/applicationconfig/ownerreference.go | 6 +-- pkg/apis/dnsalias/status.go | 12 ++--- pkg/apis/environment/environment.go | 52 +++++++++++++++--- pkg/apis/kube/kube.go | 2 + pkg/apis/kube/radix_dns_alias.go | 21 ++++++-- pkg/apis/kube/radix_environment.go | 25 ++++++--- pkg/apis/utils/environment_builder.go | 2 + radix-operator/environment/controller.go | 4 +- 10 files changed, 129 insertions(+), 51 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index d94b66491..0cc5ed470 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -269,6 +269,8 @@ func patchDifference(repository radixTypes.RadixEnvironmentInterface, oldRe *rad radixEnvironment.ObjectMeta.Labels = newRe.ObjectMeta.Labels radixEnvironment.ObjectMeta.OwnerReferences = newRe.ObjectMeta.OwnerReferences radixEnvironment.ObjectMeta.Annotations = newRe.ObjectMeta.Annotations + radixEnvironment.ObjectMeta.Finalizers = newRe.ObjectMeta.Finalizers + radixEnvironment.ObjectMeta.DeletionTimestamp = newRe.ObjectMeta.DeletionTimestamp radixEnvironment.Spec = newRe.Spec radixEnvironment.Status = newRe.Status diff --git a/pkg/apis/applicationconfig/dns_alias.go b/pkg/apis/applicationconfig/dns_alias.go index 53d6d6e4b..0ffad3277 100644 --- a/pkg/apis/applicationconfig/dns_alias.go +++ b/pkg/apis/applicationconfig/dns_alias.go @@ -19,6 +19,8 @@ func (app *ApplicationConfig) createOrUpdateDNSAliases() error { return err } var errs []error + var radixDNSAliasesToCreate []*radixv1.RadixDNSAlias + var radixDNSAliasesToUpdate []*radixv1.RadixDNSAlias for _, dnsAlias := range app.config.Spec.DNSAlias { port, err := app.getPortForDNSAlias(dnsAlias) if err != nil { @@ -28,24 +30,36 @@ func (app *ApplicationConfig) createOrUpdateDNSAliases() error { switch { case !strings.EqualFold(appName, existingRadixDNSAlias.Spec.AppName): errs = append(errs, fmt.Errorf("existing DNS alias %s is used by the application %s", dnsAlias.Alias, existingRadixDNSAlias.Spec.AppName)) + delete(existingRadixDNSAliasesMap, dnsAlias.Alias) + continue case strings.EqualFold(dnsAlias.Environment, existingRadixDNSAlias.Spec.Environment) && - strings.EqualFold(dnsAlias.Component, existingRadixDNSAlias.Spec.Component) && - port == existingRadixDNSAlias.Spec.Port: - // No changes - default: - if err = app.updateRadixDNSAlias(existingRadixDNSAlias, dnsAlias, port); err != nil { - errs = append(errs, err) + strings.EqualFold(dnsAlias.Component, existingRadixDNSAlias.Spec.Component): + if port != existingRadixDNSAlias.Spec.Port { + updatingRadixDNSAlias := existingRadixDNSAlias.DeepCopy() + updatingRadixDNSAlias.Spec.Port = port + radixDNSAliasesToUpdate = append(radixDNSAliasesToUpdate, updatingRadixDNSAlias) } + delete(existingRadixDNSAliasesMap, dnsAlias.Alias) + continue } - delete(existingRadixDNSAliasesMap, dnsAlias.Alias) - continue } - if err = app.createRadixDNSAlias(appName, dnsAlias, port); err != nil { + radixDNSAliasesToCreate = append(radixDNSAliasesToCreate, app.buildRadixDNSAlias(appName, dnsAlias, port)) + } + if len(errs) > 0 { + return errors.Concat(errs) + } + for _, radixDNSAlias := range existingRadixDNSAliasesMap { + if err = app.kubeutil.DeleteRadixDNSAliases(radixDNSAlias); err != nil { errs = append(errs, err) } } - for _, radixDNSAlias := range existingRadixDNSAliasesMap { - if err = app.kubeutil.DeleteRadixDNSAlias(radixDNSAlias); err != nil { + for _, radixDNSAlias := range radixDNSAliasesToUpdate { + if err = app.kubeutil.UpdateRadixDNSAlias(radixDNSAlias); err != nil { + errs = append(errs, err) + } + } + for _, radixDNSAlias := range radixDNSAliasesToCreate { + if err = app.kubeutil.CreateRadixDNSAlias(radixDNSAlias); err != nil { errs = append(errs, err) } } @@ -59,20 +73,13 @@ func getComponentPublicPort(component *radixv1.RadixComponent) *radixv1.Componen return nil } -func (app *ApplicationConfig) updateRadixDNSAlias(radixDNSAlias *radixv1.RadixDNSAlias, dnsAlias radixv1.DNSAlias, port int32) error { - updatedRadixDNSAlias := radixDNSAlias.DeepCopy() - updatedRadixDNSAlias.Spec.Environment = dnsAlias.Environment - updatedRadixDNSAlias.Spec.Component = dnsAlias.Component - updatedRadixDNSAlias.Spec.Port = port - return app.kubeutil.UpdateRadixDNSAlias(updatedRadixDNSAlias) -} - -func (app *ApplicationConfig) createRadixDNSAlias(appName string, dnsAlias radixv1.DNSAlias, port int32) error { - radixDNSAlias := radixv1.RadixDNSAlias{ +func (app *ApplicationConfig) buildRadixDNSAlias(appName string, dnsAlias radixv1.DNSAlias, port int32) *radixv1.RadixDNSAlias { + return &radixv1.RadixDNSAlias{ ObjectMeta: metav1.ObjectMeta{ Name: dnsAlias.Alias, - Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(dnsAlias.Component)), - OwnerReferences: []metav1.OwnerReference{getOwnerReferenceOfApplication(app.config)}, + Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(dnsAlias.Component), labels.ForEnvironmentName(dnsAlias.Environment)), + OwnerReferences: []metav1.OwnerReference{getOwnerReferenceOfRadixRegistration(app.registration)}, + // Finalizers: []string{kube.RadixDNSAliasFinalizer}, }, Spec: radixv1.RadixDNSAliasSpec{ AppName: appName, @@ -81,5 +88,4 @@ func (app *ApplicationConfig) createRadixDNSAlias(appName string, dnsAlias radix Port: port, }, } - return app.kubeutil.CreateRadixDNSAlias(&radixDNSAlias) } diff --git a/pkg/apis/applicationconfig/ownerreference.go b/pkg/apis/applicationconfig/ownerreference.go index 798512f71..1db78de08 100644 --- a/pkg/apis/applicationconfig/ownerreference.go +++ b/pkg/apis/applicationconfig/ownerreference.go @@ -7,12 +7,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func getOwnerReferenceOfApplication(radixApplication *radixv1.RadixApplication) metav1.OwnerReference { +func getOwnerReferenceOfRadixRegistration(radixRegistration *radixv1.RadixRegistration) metav1.OwnerReference { return metav1.OwnerReference{ APIVersion: radix.APIVersion, Kind: radix.KindRadixApplication, - Name: radixApplication.Name, - UID: radixApplication.UID, + Name: radixRegistration.Name, + UID: radixRegistration.UID, Controller: utils.BoolPtr(true), } } diff --git a/pkg/apis/dnsalias/status.go b/pkg/apis/dnsalias/status.go index 085a042c9..9eaf4a864 100644 --- a/pkg/apis/dnsalias/status.go +++ b/pkg/apis/dnsalias/status.go @@ -31,12 +31,12 @@ func (s *syncer) restoreStatus() error { func (s *syncer) syncStatus() error { // syncCompleteTime := metav1.Now() - err := s.updateStatus(func(currStatus *radixv1.RadixDNSAliasStatus) { - // currStatus.Reconciled = &syncCompleteTime - }) - if err != nil { - return fmt.Errorf("failed to sync status: %v", err) - } + // err := s.updateStatus(func(currStatus *radixv1.RadixDNSAliasStatus) { + // // currStatus.Reconciled = &syncCompleteTime + // }) + // if err != nil { + // return fmt.Errorf("failed to sync status: %v", err) + // } return nil } diff --git a/pkg/apis/environment/environment.go b/pkg/apis/environment/environment.go index 4328566fe..e716414ad 100644 --- a/pkg/apis/environment/environment.go +++ b/pkg/apis/environment/environment.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/defaults/k8s" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -11,6 +12,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" + radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/sirupsen/logrus" rbac "k8s.io/api/rbac/v1" @@ -57,9 +59,14 @@ func NewEnvironment( // OnSync is called by the handler when changes are applied and must be // reconciled with current state. func (env *Environment) OnSync(time metav1.Time) error { + re := env.config + + if handled, err := env.handleDeletedRadixEnvironment(re); handled || err != nil { + return err + } // create a globally unique namespace name - namespaceName := utils.GetEnvironmentNamespace(env.config.Spec.AppName, env.config.Spec.EnvName) + namespaceName := utils.GetEnvironmentNamespace(re.Spec.AppName, re.Spec.EnvName) err := env.ApplyNamespace(namespaceName) if err != nil { @@ -86,26 +93,59 @@ func (env *Environment) OnSync(time metav1.Time) error { return fmt.Errorf("failed to apply limit range on namespace %s: %v", namespaceName, err) } - err = env.networkPolicy.UpdateEnvEgressRules(env.config.Spec.Egress.Rules, env.config.Spec.Egress.AllowRadix, env.config.Spec.EnvName) + err = env.networkPolicy.UpdateEnvEgressRules(re.Spec.Egress.Rules, re.Spec.Egress.AllowRadix, re.Spec.EnvName) if err != nil { - errmsg := fmt.Sprintf("failed to add egress rules in %s, environment %s: ", env.config.Spec.AppName, env.config.Spec.EnvName) + errmsg := fmt.Sprintf("failed to add egress rules in %s, environment %s: ", re.Spec.AppName, re.Spec.EnvName) return fmt.Errorf("%s%v", errmsg, err) } - isOrphaned := !existsInAppConfig(env.appConfig, env.config.Spec.EnvName) + isOrphaned := !existsInAppConfig(env.appConfig, re.Spec.EnvName) - err = env.updateRadixEnvironmentStatus(env.config, func(currStatus *v1.RadixEnvironmentStatus) { + err = env.updateRadixEnvironmentStatus(re, func(currStatus *v1.RadixEnvironmentStatus) { currStatus.Orphaned = isOrphaned // time is parameterized for testability currStatus.Reconciled = time }) if err != nil { - return fmt.Errorf("failed to update status on environment %s: %v", env.config.Spec.EnvName, err) + return fmt.Errorf("failed to update status on environment %s: %v", re.Spec.EnvName, err) } env.logger.Debugf("Environment %s reconciled", namespaceName) return nil } +func (env *Environment) handleDeletedRadixEnvironment(re *v1.RadixEnvironment) (bool, error) { + if re.ObjectMeta.DeletionTimestamp == nil { + return false, nil + } + finalizerIndex := slice.FindIndex(re.ObjectMeta.Finalizers, func(val string) bool { + return val == kube.RadixEnvironmentFinalizer + }) + if finalizerIndex < 0 { + logrus.Info("missing finalizer %s in the Radix environment %s in the application %s. Exist finalizers: %d. Skip dependency handling", + kube.RadixEnvironmentFinalizer, re.Name, re.Spec.AppName, len(re.ObjectMeta.Finalizers)) + return false, nil + } + err := env.handleDeletedRadixEnvironmentDependencies(re) + if err != nil { + return true, err + } + updatingRE := re.DeepCopy() + updatingRE.ObjectMeta.Finalizers = append(re.ObjectMeta.Finalizers[:finalizerIndex], re.ObjectMeta.Finalizers[finalizerIndex+1:]...) + logrus.Debug("removed finalizer %s from the Radix environment %s in the application %s. LEft finalizers: %d", + kube.RadixEnvironmentFinalizer, updatingRE.Name, updatingRE.Spec.AppName, len(updatingRE.ObjectMeta.Finalizers)) + return true, env.kubeutil.UpdateRadixEnvironment(updatingRE) +} + +func (env *Environment) handleDeletedRadixEnvironmentDependencies(re *v1.RadixEnvironment) error { + radixDNSAliasList, err := env.kubeutil.GetRadixDNSAliasWithSelector(radixlabels.Merge(radixlabels.ForApplicationName(re.Spec.AppName), radixlabels.ForEnvironmentName(re.GetName())).String()) + if err != nil { + return err + } + return env.kubeutil.DeleteRadixDNSAliases(slice.Reduce(radixDNSAliasList.Items, []*v1.RadixDNSAlias{}, func(acc []*v1.RadixDNSAlias, radixDNSAlias v1.RadixDNSAlias) []*v1.RadixDNSAlias { + return append(acc, &radixDNSAlias) + })...) +} + func (env *Environment) updateRadixEnvironmentStatus(rEnv *v1.RadixEnvironment, changeStatusFunc func(currStatus *v1.RadixEnvironmentStatus)) error { radixEnvironmentInterface := env.radixclient.RadixV1().RadixEnvironments() return retry.RetryOnConflict(retry.DefaultRetry, func() error { diff --git a/pkg/apis/kube/kube.go b/pkg/apis/kube/kube.go index c653429d4..9ba59ae3d 100644 --- a/pkg/apis/kube/kube.go +++ b/pkg/apis/kube/kube.go @@ -27,6 +27,8 @@ const ( RadixDeploymentPromotedFromDeploymentAnnotation = "radix.equinor.com/radix-deployment-promoted-from-deployment" RadixDeploymentPromotedFromEnvironmentAnnotation = "radix.equinor.com/radix-deployment-promoted-from-environment" ManagedByRadixDNSAliasIngressAnnotation = "radix.equinor.com/managed-by-radix-dns-alias" + RadixEnvironmentFinalizer = "radix.equinor.com/environment-finalizer" + RadixDNSAliasFinalizer = "radix.equinor.com/dns-alias-finalizer" // See https://github.com/equinor/radix-velero-plugin/blob/master/velero-plugins/deployment/restore.go RestoredStatusAnnotation = "equinor.com/velero-restored-status" diff --git a/pkg/apis/kube/radix_dns_alias.go b/pkg/apis/kube/radix_dns_alias.go index f636e08b7..838aa82e3 100644 --- a/pkg/apis/kube/radix_dns_alias.go +++ b/pkg/apis/kube/radix_dns_alias.go @@ -38,7 +38,7 @@ func (kubeutil *Kube) ListRadixDNSAlias() ([]*radixv1.RadixDNSAlias, error) { return kubeutil.ListRadixDNSAliasWithSelector("") } -// ListRadixDNSAliasWithSelector List radix DNS aliases with selector +// ListRadixDNSAliasWithSelector List RadixDNSAliases with selector func (kubeutil *Kube) ListRadixDNSAliasWithSelector(labelSelectorString string) ([]*radixv1.RadixDNSAlias, error) { if kubeutil.RadixDNSAliasLister != nil { selector, err := labels.Parse(labelSelectorString) @@ -52,13 +52,18 @@ func (kubeutil *Kube) ListRadixDNSAliasWithSelector(labelSelectorString string) return aliases, nil } - aliasList, err := kubeutil.radixclient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{LabelSelector: labelSelectorString}) + aliasList, err := kubeutil.GetRadixDNSAliasWithSelector(labelSelectorString) if err != nil { return nil, fmt.Errorf("failed to get all RadixDNSAliases. Error was %v", err) } return slice.PointersOf(aliasList.Items).([]*radixv1.RadixDNSAlias), nil } +// GetRadixDNSAliasWithSelector Get RadixDNSAliases with selector +func (kubeutil *Kube) GetRadixDNSAliasWithSelector(labelSelectorString string) (*radixv1.RadixDNSAliasList, error) { + return kubeutil.radixclient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{LabelSelector: labelSelectorString}) +} + // GetRadixDNSAliasMapWithSelector Gets a map of RadixDNSAliases by an optional selector func GetRadixDNSAliasMapWithSelector(radixClient radixclient.Interface, labelSelectorString string) (map[string]*radixv1.RadixDNSAlias, error) { radixDNSAliases, err := radixClient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{LabelSelector: labelSelectorString}) @@ -77,7 +82,13 @@ func (kubeutil *Kube) UpdateRadixDNSAlias(radixDNSAlias *radixv1.RadixDNSAlias) return err } -// DeleteRadixDNSAlias Delete RadixDNSAliases -func (kubeutil *Kube) DeleteRadixDNSAlias(radixDNSAlias *radixv1.RadixDNSAlias) error { - return kubeutil.radixclient.RadixV1().RadixDNSAliases().Delete(context.Background(), radixDNSAlias.GetName(), metav1.DeleteOptions{}) +// DeleteRadixDNSAliases Delete RadixDNSAliases +func (kubeutil *Kube) DeleteRadixDNSAliases(radixDNSAliases ...*radixv1.RadixDNSAlias) error { + for _, radixDNSAlias := range radixDNSAliases { + err := kubeutil.radixclient.RadixV1().RadixDNSAliases().Delete(context.Background(), radixDNSAlias.GetName(), metav1.DeleteOptions{}) + if err != nil { + return err + } + } + return nil } diff --git a/pkg/apis/kube/radix_environment.go b/pkg/apis/kube/radix_environment.go index b86d26783..08b4fb25e 100644 --- a/pkg/apis/kube/radix_environment.go +++ b/pkg/apis/kube/radix_environment.go @@ -2,16 +2,18 @@ package kube import ( "context" + "fmt" - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils/slice" + log "github.com/sirupsen/logrus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" ) // GetEnvironment Gets environment using lister from cache if present -func (kubeutil *Kube) GetEnvironment(name string) (*v1.RadixEnvironment, error) { - var environment *v1.RadixEnvironment +func (kubeutil *Kube) GetEnvironment(name string) (*radixv1.RadixEnvironment, error) { + var environment *radixv1.RadixEnvironment var err error if kubeutil.ReLister != nil { @@ -30,8 +32,8 @@ func (kubeutil *Kube) GetEnvironment(name string) (*v1.RadixEnvironment, error) } // ListEnvironments lists environments from cache if lister is present -func (kubeutil *Kube) ListEnvironments() ([]*v1.RadixEnvironment, error) { - var environments []*v1.RadixEnvironment +func (kubeutil *Kube) ListEnvironments() ([]*radixv1.RadixEnvironment, error) { + var environments []*radixv1.RadixEnvironment var err error if kubeutil.ReLister != nil { @@ -45,8 +47,19 @@ func (kubeutil *Kube) ListEnvironments() ([]*v1.RadixEnvironment, error) { return nil, err } - environments = slice.PointersOf(list.Items).([]*v1.RadixEnvironment) + environments = slice.PointersOf(list.Items).([]*radixv1.RadixEnvironment) } return environments, nil } + +// UpdateRadixEnvironment Updates changes of Radix environment if any +func (kubeutil *Kube) UpdateRadixEnvironment(radixEnvironment *radixv1.RadixEnvironment) error { + log.Debugf("Update Radix environment %s in the application %s", radixEnvironment.Name, radixEnvironment.Spec.AppName) + _, err := kubeutil.RadixClient().RadixV1().RadixEnvironments().Update(context.TODO(), radixEnvironment, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("failed to patch Radix environment object: %v", err) + } + log.Debugf("Updated Radix environment: %s in the application %s", radixEnvironment.Name, radixEnvironment.Spec.AppName) + return err +} diff --git a/pkg/apis/utils/environment_builder.go b/pkg/apis/utils/environment_builder.go index ce093dc7b..eeeba63cd 100644 --- a/pkg/apis/utils/environment_builder.go +++ b/pkg/apis/utils/environment_builder.go @@ -3,6 +3,7 @@ package utils import ( "time" + "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix" rx "github.com/equinor/radix-operator/pkg/apis/radix/v1" meta "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -164,6 +165,7 @@ func (eb *EnvironmentBuilderStruct) BuildRE() *rx.RadixEnvironment { ResourceVersion: eb.ResourceVersion, UID: eb.UID, OwnerReferences: eb.Owners, + Finalizers: []string{kube.RadixEnvironmentFinalizer}, }, Spec: rx.RadixEnvironmentSpec{ AppName: eb.AppName, diff --git a/radix-operator/environment/controller.go b/radix-operator/environment/controller.go index 391c117f4..d1bb945ce 100644 --- a/radix-operator/environment/controller.go +++ b/radix-operator/environment/controller.go @@ -190,7 +190,9 @@ func NewController(client kubernetes.Interface, func deepEqual(old, new *v1.RadixEnvironment) bool { if !reflect.DeepEqual(new.Spec, old.Spec) || !reflect.DeepEqual(new.ObjectMeta.Labels, old.ObjectMeta.Labels) || - !reflect.DeepEqual(new.ObjectMeta.Annotations, old.ObjectMeta.Annotations) { + !reflect.DeepEqual(new.ObjectMeta.Annotations, old.ObjectMeta.Annotations) || + !reflect.DeepEqual(new.ObjectMeta.DeletionTimestamp, old.ObjectMeta.DeletionTimestamp) || + !reflect.DeepEqual(new.ObjectMeta.Finalizers, old.ObjectMeta.Finalizers) { return false } From 921b40cc7dafd57d53dde08450e0843ab14b0802 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 23 Nov 2023 16:23:46 +0100 Subject: [PATCH 065/121] Fixing sync of oauth ingresses --- pkg/apis/applicationconfig/dns_alias_test.go | 4 +- pkg/apis/defaults/k8s/k8s.go | 2 + pkg/apis/deployment/deployment.go | 3 +- .../deployment/oauthproxyresourcemanager.go | 166 ++++-------------- .../oauthproxyresourcemanager_test.go | 20 +-- pkg/apis/dnsalias/syncer.go | 122 ++++++++----- pkg/apis/dnsalias/syncer_test.go | 2 +- pkg/apis/environment/environment.go | 6 +- pkg/apis/ingress/oauth.go | 95 ++++++++++ pkg/apis/ingress/ownerreferences.go | 21 +++ pkg/apis/kube/ingress.go | 28 +-- pkg/apis/radixvalidators/errors.go | 6 +- pkg/apis/utils/labels/labels.go | 10 ++ pkg/apis/utils/oauth/oauth.go | 17 ++ radix-operator/deployment/handler.go | 2 +- radix-operator/deployment/handler_test.go | 2 +- radix-operator/dnsalias/controller.go | 9 +- radix-operator/dnsalias/handler.go | 7 +- .../dnsalias/internal/syncerfactory.go | 7 +- .../dnsalias/internal/syncerfactory_mock.go | 8 +- radix-operator/environment/handler.go | 10 +- 21 files changed, 320 insertions(+), 227 deletions(-) create mode 100644 pkg/apis/ingress/oauth.go create mode 100644 pkg/apis/ingress/ownerreferences.go diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go index 2e4d5664a..5bc6f2267 100644 --- a/pkg/apis/applicationconfig/dns_alias_test.go +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -246,11 +246,11 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { require.NoError(t, err) if ts.expectedRadixDNSAliases == nil { - require.Len(t, radixDNSAliases.Items, 0, "not expected Radix DNS aliases") + require.Len(t, radixDNSAliases.Items, 0, "not expected RadixDNSAliases") return } - require.Len(t, radixDNSAliases.Items, len(ts.expectedRadixDNSAliases), "not matching expected Radix DNS aliases count") + require.Len(t, radixDNSAliases.Items, len(ts.expectedRadixDNSAliases), "not matching expected RadixDNSAliases count") if len(radixDNSAliases.Items) == len(ts.expectedRadixDNSAliases) { for _, radixDNSAlias := range radixDNSAliases.Items { if expectedDNSAlias, ok := ts.expectedRadixDNSAliases[radixDNSAlias.Name]; ok { diff --git a/pkg/apis/defaults/k8s/k8s.go b/pkg/apis/defaults/k8s/k8s.go index 93b5fd0ff..d04c40bf0 100644 --- a/pkg/apis/defaults/k8s/k8s.go +++ b/pkg/apis/defaults/k8s/k8s.go @@ -10,4 +10,6 @@ const ( KindRoleBinding = "RoleBinding" KindServiceAccount = "ServiceAccount" KindGroup = "Group" + KindIngress = "Ingress" + APIVersionNetworking = "networking.k8s.io/v1" ) diff --git a/pkg/apis/deployment/deployment.go b/pkg/apis/deployment/deployment.go index 7c79f61b7..600ec767c 100644 --- a/pkg/apis/deployment/deployment.go +++ b/pkg/apis/deployment/deployment.go @@ -74,7 +74,7 @@ func NewDeploymentSyncer(kubeclient kubernetes.Interface, kubeutil *kube.Kube, r } } -// GetDeploymentComponent Gets the index of and the component given name +// GetDeploymentComponent Gets the index of and the component given name. Used by Radix API. func GetDeploymentComponent(rd *v1.RadixDeployment, name string) (int, *v1.RadixDeployComponent) { for index, component := range rd.Spec.Components { if strings.EqualFold(component.Name, name) { @@ -275,6 +275,7 @@ func (deploy *Deployment) syncDeployment() error { func (deploy *Deployment) syncAuxiliaryResources() error { for _, aux := range deploy.auxResourceManagers { + log.Debugf("sync AuxiliaryResource for the RadixDeployment %s", deploy.radixDeployment.GetName()) if err := aux.Sync(); err != nil { return err } diff --git a/pkg/apis/deployment/oauthproxyresourcemanager.go b/pkg/apis/deployment/oauthproxyresourcemanager.go index e2ec74509..818c8c2e4 100644 --- a/pkg/apis/deployment/oauthproxyresourcemanager.go +++ b/pkg/apis/deployment/oauthproxyresourcemanager.go @@ -7,7 +7,6 @@ import ( "reflect" commonutils "github.com/equinor/radix-common/utils" - radixmaps "github.com/equinor/radix-common/utils/maps" "github.com/equinor/radix-common/utils/pointers" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/ingress" @@ -15,11 +14,11 @@ import ( v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/securitycontext" "github.com/equinor/radix-operator/pkg/apis/utils" + radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" oauthutil "github.com/equinor/radix-operator/pkg/apis/utils/oauth" log "github.com/sirupsen/logrus" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -58,6 +57,7 @@ func (o *oauthProxyResourceManager) Sync() error { func (o *oauthProxyResourceManager) syncComponent(component *v1.RadixDeployComponent) error { if auth := component.GetAuthentication(); component.IsPublic() && auth != nil && auth.OAuth2 != nil { + log.Debugf("sync oauth proxy for the component %s", component.GetName()) componentWithOAuthDefaults := component.DeepCopy() oauth, err := o.oauth2DefaultConfig.MergeWith(componentWithOAuthDefaults.Authentication.OAuth2) if err != nil { @@ -65,9 +65,8 @@ func (o *oauthProxyResourceManager) syncComponent(component *v1.RadixDeployCompo } componentWithOAuthDefaults.Authentication.OAuth2 = oauth return o.install(componentWithOAuthDefaults) - } else { - return o.uninstall(component) } + return o.uninstall(component) } func (o *oauthProxyResourceManager) GarbageCollect() error { @@ -163,9 +162,9 @@ func (o *oauthProxyResourceManager) garbageCollectIngresses() error { return err } - for _, ingress := range ingresses { - if o.isEligibleForGarbageCollection(ingress) { - err := o.kubeutil.KubeClient().NetworkingV1().Ingresses(ingress.Namespace).Delete(context.TODO(), ingress.Name, metav1.DeleteOptions{}) + for _, ing := range ingresses { + if o.isEligibleForGarbageCollection(ing) { + err := o.kubeutil.KubeClient().NetworkingV1().Ingresses(ing.Namespace).Delete(context.TODO(), ing.Name, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { return err } @@ -194,12 +193,12 @@ func (o *oauthProxyResourceManager) garbageCollectRoles() error { } func (o *oauthProxyResourceManager) garbageCollectRoleBinding() error { - rolebindings, err := o.kubeutil.ListRoleBindings(o.rd.Namespace) + roleBindings, err := o.kubeutil.ListRoleBindings(o.rd.Namespace) if err != nil { return err } - for _, rolebinding := range rolebindings { + for _, rolebinding := range roleBindings { if o.isEligibleForGarbageCollection(rolebinding) { err := o.kubeutil.KubeClient().RbacV1().RoleBindings(rolebinding.Namespace).Delete(context.TODO(), rolebinding.Name, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { @@ -226,6 +225,7 @@ func (o *oauthProxyResourceManager) isEligibleForGarbageCollection(object metav1 } func (o *oauthProxyResourceManager) install(component v1.RadixCommonDeployComponent) error { + log.Debugf("install the oauth proxy for the component %s", component.GetName()) if err := o.createOrUpdateSecret(component); err != nil { return err } @@ -246,6 +246,7 @@ func (o *oauthProxyResourceManager) install(component v1.RadixCommonDeployCompon } func (o *oauthProxyResourceManager) uninstall(component v1.RadixCommonDeployComponent) error { + log.Debugf("uninstall oauth proxy for the component %s", component.GetName()) if err := o.deleteDeployment(component); err != nil { return err } @@ -270,7 +271,7 @@ func (o *oauthProxyResourceManager) uninstall(component v1.RadixCommonDeployComp } func (o *oauthProxyResourceManager) deleteDeployment(component v1.RadixCommonDeployComponent) error { - selector := labels.SelectorFromValidatedSet(o.getLabelsForAuxComponent(component)).String() + selector := labels.SelectorFromValidatedSet(radixlabels.ForAuxComponent(o.rd.Spec.AppName, component)).String() deployments, err := o.kubeutil.ListDeploymentsWithSelector(o.rd.Namespace, selector) if err != nil { return err @@ -286,14 +287,14 @@ func (o *oauthProxyResourceManager) deleteDeployment(component v1.RadixCommonDep } func (o *oauthProxyResourceManager) deleteIngresses(component v1.RadixCommonDeployComponent) error { - selector := labels.SelectorFromValidatedSet(o.getLabelsForAuxComponent(component)).String() + selector := labels.SelectorFromValidatedSet(radixlabels.ForAuxComponent(o.rd.Spec.AppName, component)).String() ingresses, err := o.kubeutil.ListIngressesWithSelector(o.rd.Namespace, selector) if err != nil { return err } - for _, ingress := range ingresses { - if err := o.kubeutil.KubeClient().NetworkingV1().Ingresses(ingress.Namespace).Delete(context.TODO(), ingress.Name, metav1.DeleteOptions{}); err != nil { + for _, ing := range ingresses { + if err := o.kubeutil.KubeClient().NetworkingV1().Ingresses(ing.Namespace).Delete(context.TODO(), ing.Name, metav1.DeleteOptions{}); err != nil { return err } } @@ -302,7 +303,7 @@ func (o *oauthProxyResourceManager) deleteIngresses(component v1.RadixCommonDepl } func (o *oauthProxyResourceManager) deleteServices(component v1.RadixCommonDeployComponent) error { - selector := labels.SelectorFromValidatedSet(o.getLabelsForAuxComponent(component)).String() + selector := labels.SelectorFromValidatedSet(radixlabels.ForAuxComponent(o.rd.Spec.AppName, component)).String() services, err := o.kubeutil.ListServicesWithSelector(o.rd.Namespace, selector) if err != nil { return err @@ -318,7 +319,7 @@ func (o *oauthProxyResourceManager) deleteServices(component v1.RadixCommonDeplo } func (o *oauthProxyResourceManager) deleteSecrets(component v1.RadixCommonDeployComponent) error { - selector := labels.SelectorFromValidatedSet(o.getLabelsForAuxComponent(component)).String() + selector := labels.SelectorFromValidatedSet(radixlabels.ForAuxComponent(o.rd.Spec.AppName, component)).String() secrets, err := o.kubeutil.ListSecretsWithSelector(o.rd.Namespace, selector) if err != nil { return err @@ -335,13 +336,13 @@ func (o *oauthProxyResourceManager) deleteSecrets(component v1.RadixCommonDeploy } func (o *oauthProxyResourceManager) deleteRoleBindings(component v1.RadixCommonDeployComponent) error { - selector := labels.SelectorFromValidatedSet(o.getLabelsForAuxComponent(component)).String() - rolebindings, err := o.kubeutil.ListRoleBindingsWithSelector(o.rd.Namespace, selector) + selector := labels.SelectorFromValidatedSet(radixlabels.ForAuxComponent(o.rd.Spec.AppName, component)).String() + roleBindings, err := o.kubeutil.ListRoleBindingsWithSelector(o.rd.Namespace, selector) if err != nil { return err } - for _, rolebinding := range rolebindings { + for _, rolebinding := range roleBindings { if err := o.kubeutil.KubeClient().RbacV1().RoleBindings(rolebinding.Namespace).Delete(context.TODO(), rolebinding.Name, metav1.DeleteOptions{}); err != nil { return err } @@ -351,7 +352,7 @@ func (o *oauthProxyResourceManager) deleteRoleBindings(component v1.RadixCommonD } func (o *oauthProxyResourceManager) deleteRoles(component v1.RadixCommonDeployComponent) error { - selector := labels.SelectorFromValidatedSet(o.getLabelsForAuxComponent(component)).String() + selector := labels.SelectorFromValidatedSet(radixlabels.ForAuxComponent(o.rd.Spec.AppName, component)).String() roles, err := o.kubeutil.ListRolesWithSelector(o.rd.Namespace, selector) if err != nil { return err @@ -367,99 +368,22 @@ func (o *oauthProxyResourceManager) deleteRoles(component v1.RadixCommonDeployCo } func (o *oauthProxyResourceManager) createOrUpdateIngresses(component v1.RadixCommonDeployComponent) error { + namespace := o.rd.Namespace + log.Debugf("create of update ingresses for the component %s in the namespace %s", component.GetName(), namespace) listOptions := metav1.ListOptions{LabelSelector: getLabelSelectorForComponent(component)} - ingresses, err := o.kubeutil.KubeClient().NetworkingV1().Ingresses(o.rd.Namespace).List(context.TODO(), listOptions) + ingresses, err := o.kubeutil.KubeClient().NetworkingV1().Ingresses(namespace).List(context.TODO(), listOptions) if err != nil { return err } - for _, ingress := range ingresses.Items { - auxIngress, err := o.buildOAuthProxyIngressForComponentIngress(component, ingress, o.rd.Namespace) - if err != nil { + for _, ing := range ingresses.Items { + if err := ingress.CreateOrUpdateOAuthProxyIngressForComponentIngress(o.kubeutil, namespace, o.rd.Spec.AppName, component, &ing, o.ingressAnnotationProviders); err != nil { return err } - if auxIngress != nil { - if err := o.kubeutil.ApplyIngress(o.rd.Namespace, auxIngress); err != nil { - return err - } - } } - return nil } -func (o *oauthProxyResourceManager) buildOAuthProxyIngressForComponentIngress(component v1.RadixCommonDeployComponent, componentIngress networkingv1.Ingress, namespace string) (*networkingv1.Ingress, error) { - if len(componentIngress.Spec.Rules) == 0 { - return nil, nil - } - sourceHost := componentIngress.Spec.Rules[0] - pathType := networkingv1.PathTypeImplementationSpecific - annotations := map[string]string{} - - for _, ia := range o.ingressAnnotationProviders { - providedAnnotations, err := ia.GetAnnotations(component, namespace) - if err != nil { - return nil, err - } - annotations = radixmaps.MergeMaps(annotations, providedAnnotations) - } - - var tls []networkingv1.IngressTLS - for _, sourceTls := range componentIngress.Spec.TLS { - tls = append(tls, *sourceTls.DeepCopy()) - } - - ingress := &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: o.getIngressName(componentIngress.GetName()), - Annotations: annotations, - OwnerReferences: o.getOwnerReferenceOfIngress(&componentIngress), - }, - Spec: networkingv1.IngressSpec{ - IngressClassName: componentIngress.Spec.IngressClassName, - TLS: tls, - Rules: []networkingv1.IngressRule{ - { - Host: sourceHost.Host, - IngressRuleValue: networkingv1.IngressRuleValue{ - HTTP: &networkingv1.HTTPIngressRuleValue{ - Paths: []networkingv1.HTTPIngressPath{ - { - Path: oauthutil.SanitizePathPrefix(component.GetAuthentication().OAuth2.ProxyPrefix), - PathType: &pathType, - Backend: networkingv1.IngressBackend{ - Service: &networkingv1.IngressServiceBackend{ - Name: utils.GetAuxiliaryComponentServiceName(component.GetName(), defaults.OAuthProxyAuxiliaryComponentSuffix), - Port: networkingv1.ServiceBackendPort{ - Number: defaults.OAuthProxyPortNumber, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - - o.mergeAuxComponentResourceLabels(ingress, component) - return ingress, nil -} - -func (o *oauthProxyResourceManager) getOwnerReferenceOfIngress(ingress *networkingv1.Ingress) []metav1.OwnerReference { - return []metav1.OwnerReference{ - { - APIVersion: "networking.k8s.io/v1", - Kind: "Ingress", - Name: ingress.Name, - UID: ingress.UID, - Controller: utils.BoolPtr(true), - }, - } -} - func (o *oauthProxyResourceManager) createOrUpdateService(component v1.RadixCommonDeployComponent) error { service := o.buildServiceSpec(component) return o.kubeutil.ApplyService(o.rd.Namespace, service) @@ -478,7 +402,7 @@ func (o *oauthProxyResourceManager) createOrUpdateSecret(component v1.RadixCommo return err } } else { - o.mergeAuxComponentResourceLabels(secret, component) + oauthutil.MergeAuxComponentResourceLabels(secret, o.rd.Spec.AppName, component) if component.GetAuthentication().OAuth2.SessionStoreType != v1.SessionStoreRedis { if secret.Data != nil && len(secret.Data[defaults.OAuthRedisPasswordKeyName]) > 0 { delete(secret.Data, defaults.OAuthRedisPasswordKeyName) @@ -490,10 +414,6 @@ func (o *oauthProxyResourceManager) createOrUpdateSecret(component v1.RadixCommo return err } -func (o *oauthProxyResourceManager) mergeAuxComponentResourceLabels(object metav1.Object, component v1.RadixCommonDeployComponent) { - object.SetLabels(labels.Merge(object.GetLabels(), o.getLabelsForAuxComponent(component))) -} - func (o *oauthProxyResourceManager) createOrUpdateRbac(component v1.RadixCommonDeployComponent) error { if err := o.createOrUpdateAppAdminRbac(component); err != nil { return err @@ -512,7 +432,7 @@ func (o *oauthProxyResourceManager) createOrUpdateAppAdminRbac(component v1.Radi role := kube.CreateAppRole( o.rd.Spec.AppName, roleName, - o.getLabelsForAuxComponent(component), + radixlabels.ForAuxComponent(o.rd.Spec.AppName, component), kube.ManageSecretsRule([]string{secretName}), kube.UpdateDeploymentsRule([]string{deploymentName}), ) @@ -542,7 +462,7 @@ func (o *oauthProxyResourceManager) createOrUpdateAppReaderRbac(component v1.Rad role := kube.CreateAppRole( o.rd.Spec.AppName, roleName, - o.getLabelsForAuxComponent(component), + radixlabels.ForAuxComponent(o.rd.Spec.AppName, component), kube.ReadSecretsRule([]string{secretName}), ) @@ -562,10 +482,6 @@ func (o *oauthProxyResourceManager) getRoleAndRoleBindingName(prefix, componentN return fmt.Sprintf("%s-%s", prefix, deploymentName) } -func (o *oauthProxyResourceManager) getIngressName(sourceIngressName string) string { - return fmt.Sprintf("%s-%s", sourceIngressName, defaults.OAuthProxyAuxiliaryComponentSuffix) -} - func (o *oauthProxyResourceManager) buildSecretSpec(component v1.RadixCommonDeployComponent) (*corev1.Secret, error) { secretName := utils.GetAuxiliaryComponentSecretName(component.GetName(), defaults.OAuthProxyAuxiliaryComponentSuffix) @@ -576,7 +492,7 @@ func (o *oauthProxyResourceManager) buildSecretSpec(component v1.RadixCommonDepl }, Data: make(map[string][]byte), } - o.mergeAuxComponentResourceLabels(secret, component) + oauthutil.MergeAuxComponentResourceLabels(secret, o.rd.Spec.AppName, component) cookieSecret, err := o.generateRandomCookieSecret() if err != nil { return nil, err @@ -595,7 +511,7 @@ func (o *oauthProxyResourceManager) buildServiceSpec(component v1.RadixCommonDep }, Spec: corev1.ServiceSpec{ Type: corev1.ServiceTypeClusterIP, - Selector: o.getLabelsForAuxComponent(component), + Selector: radixlabels.ForAuxComponent(o.rd.Spec.AppName, component), Ports: []corev1.ServicePort{ { Port: defaults.OAuthProxyPortNumber, @@ -605,18 +521,10 @@ func (o *oauthProxyResourceManager) buildServiceSpec(component v1.RadixCommonDep }, }, } - o.mergeAuxComponentResourceLabels(service, component) + oauthutil.MergeAuxComponentResourceLabels(service, o.rd.Spec.AppName, component) return service } -func (o *oauthProxyResourceManager) getLabelsForAuxComponent(component v1.RadixCommonDeployComponent) map[string]string { - return map[string]string{ - kube.RadixAppLabel: o.rd.Spec.AppName, - kube.RadixAuxiliaryComponentLabel: component.GetName(), - kube.RadixAuxiliaryComponentTypeLabel: defaults.OAuthProxyAuxiliaryComponentType, - } -} - func (o *oauthProxyResourceManager) generateRandomCookieSecret() ([]byte, error) { randomBytes := commonutils.GenerateRandomKey(32) // Extra check to make sure correct number of bytes are returned for the random key @@ -678,11 +586,11 @@ func (o *oauthProxyResourceManager) getDesiredDeployment(component v1.RadixCommo Spec: appsv1.DeploymentSpec{ Replicas: pointers.Ptr(replicas), Selector: &metav1.LabelSelector{ - MatchLabels: o.getLabelsForAuxComponent(component), + MatchLabels: radixlabels.ForAuxComponent(o.rd.Spec.AppName, component), }, Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: o.getLabelsForAuxComponent(component), + Labels: radixlabels.ForAuxComponent(o.rd.Spec.AppName, component), }, Spec: corev1.PodSpec{ Containers: []corev1.Container{ @@ -707,7 +615,7 @@ func (o *oauthProxyResourceManager) getDesiredDeployment(component v1.RadixCommo }, } - o.mergeAuxComponentResourceLabels(desiredDeployment, component) + oauthutil.MergeAuxComponentResourceLabels(desiredDeployment, o.rd.Spec.AppName, component) return desiredDeployment, nil } @@ -727,19 +635,19 @@ func (o *oauthProxyResourceManager) getEnvVars(component v1.RadixCommonDeployCom } } - // Radix envvars + // Radix env-vars if v, ok := component.GetEnvironmentVariables()[defaults.RadixRestartEnvironmentVariable]; ok { envVars = append(envVars, corev1.EnvVar{Name: defaults.RadixRestartEnvironmentVariable, Value: v}) } - // oauth2-proxy envvars + // oauth2-proxy env-vars envVars = append(envVars, corev1.EnvVar{Name: "OAUTH2_PROXY_PROVIDER", Value: "oidc"}) envVars = append(envVars, corev1.EnvVar{Name: "OAUTH2_PROXY_COOKIE_HTTPONLY", Value: "true"}) envVars = append(envVars, corev1.EnvVar{Name: "OAUTH2_PROXY_COOKIE_SECURE", Value: "true"}) envVars = append(envVars, corev1.EnvVar{Name: "OAUTH2_PROXY_PASS_BASIC_AUTH", Value: "false"}) envVars = append(envVars, corev1.EnvVar{Name: "OAUTH2_PROXY_SKIP_PROVIDER_BUTTON", Value: "true"}) envVars = append(envVars, corev1.EnvVar{Name: "OAUTH2_PROXY_EMAIL_DOMAINS", Value: "*"}) - envVars = append(envVars, corev1.EnvVar{Name: "OAUTH2_PROXY_HTTP_ADDRESS", Value: fmt.Sprintf("http://:%v", defaults.OAuthProxyPortNumber)}) + envVars = append(envVars, corev1.EnvVar{Name: "OAUTH2_PROXY_HTTP_ADDRESS", Value: fmt.Sprintf("%s://:%v", "http", defaults.OAuthProxyPortNumber)}) secretName := utils.GetAuxiliaryComponentSecretName(component.GetName(), defaults.OAuthProxyAuxiliaryComponentSuffix) envVars = append(envVars, o.createEnvVarWithSecretRef("OAUTH2_PROXY_COOKIE_SECRET", secretName, defaults.OAuthCookieSecretKeyName)) envVars = append(envVars, o.createEnvVarWithSecretRef("OAUTH2_PROXY_CLIENT_SECRET", secretName, defaults.OAuthClientSecretKeyName)) diff --git a/pkg/apis/deployment/oauthproxyresourcemanager_test.go b/pkg/apis/deployment/oauthproxyresourcemanager_test.go index d8bf792a8..525a24cab 100644 --- a/pkg/apis/deployment/oauthproxyresourcemanager_test.go +++ b/pkg/apis/deployment/oauthproxyresourcemanager_test.go @@ -127,7 +127,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_ComponentRestartEnvVar() s.oauth2Config.EXPECT().MergeWith(gomock.Any()).AnyTimes().Return(&v1.OAuth2{}, nil) for _, test := range tests { s.Run(test.name, func() { - sut := &oauthProxyResourceManager{test.rd, rr, s.kubeUtil, []IngressAnnotationProvider{}, s.oauth2Config, ""} + sut := &oauthProxyResourceManager{test.rd, rr, s.kubeUtil, []ingress.AnnotationProvider{}, s.oauth2Config, ""} err := sut.Sync() s.Nil(err) deploys, _ := s.kubeClient.AppsV1().Deployments(corev1.NamespaceAll).List(context.Background(), metav1.ListOptions{LabelSelector: s.getAppNameSelector(appName)}) @@ -239,7 +239,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OauthDeploymentReplicas() s.oauth2Config.EXPECT().MergeWith(gomock.Any()).AnyTimes().Return(&v1.OAuth2{}, nil) for _, test := range tests { s.Run(test.name, func() { - sut := &oauthProxyResourceManager{test.rd, rr, s.kubeUtil, []IngressAnnotationProvider{}, s.oauth2Config, ""} + sut := &oauthProxyResourceManager{test.rd, rr, s.kubeUtil, []ingress.AnnotationProvider{}, s.oauth2Config, ""} err := sut.Sync() s.Nil(err) deploys, _ := s.kubeClient.AppsV1().Deployments(corev1.NamespaceAll).List(context.Background(), metav1.ListOptions{LabelSelector: s.getAppNameSelector(appName)}) @@ -630,7 +630,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate actualIngress := getIngress(fmt.Sprintf("%s-%s", ingServer.Name, defaults.OAuthProxyAuxiliaryComponentSuffix), actualIngresses.Items) s.NotNil(actualIngress) s.Equal(expectedIngServerAnnotations, actualIngress.Annotations) - s.ElementsMatch(sut.getOwnerReferenceOfIngress(&ingServer), actualIngress.OwnerReferences) + s.ElementsMatch(ingress.GetOwnerReferenceOfIngress(&ingServer), actualIngress.OwnerReferences) s.Equal(ingServer.Spec.IngressClassName, actualIngress.Spec.IngressClassName) s.Equal(ingServer.Spec.TLS, actualIngress.Spec.TLS) s.Equal(ingServer.Spec.Rules[0].Host, actualIngress.Spec.Rules[0].Host) @@ -640,7 +640,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate actualIngress = getIngress(fmt.Sprintf("%s-%s", ingWeb1.Name, defaults.OAuthProxyAuxiliaryComponentSuffix), actualIngresses.Items) s.NotNil(actualIngress) s.Equal(expectedIngWebAnnotations, actualIngress.Annotations) - s.ElementsMatch(sut.getOwnerReferenceOfIngress(&ingWeb1), actualIngress.OwnerReferences) + s.ElementsMatch(ingress.GetOwnerReferenceOfIngress(&ingWeb1), actualIngress.OwnerReferences) s.Equal(ingWeb1.Spec.IngressClassName, actualIngress.Spec.IngressClassName) s.Equal(ingWeb1.Spec.TLS, actualIngress.Spec.TLS) s.Equal(ingWeb1.Spec.Rules[0].Host, actualIngress.Spec.Rules[0].Host) @@ -649,7 +649,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate actualIngress = getIngress(fmt.Sprintf("%s-%s", ingWeb2.Name, defaults.OAuthProxyAuxiliaryComponentSuffix), actualIngresses.Items) s.NotNil(actualIngress) s.Equal(expectedIngWebAnnotations, actualIngress.Annotations) - s.ElementsMatch(sut.getOwnerReferenceOfIngress(&ingWeb2), actualIngress.OwnerReferences) + s.ElementsMatch(ingress.GetOwnerReferenceOfIngress(&ingWeb2), actualIngress.OwnerReferences) s.Equal(ingWeb2.Spec.IngressClassName, actualIngress.Spec.IngressClassName) s.Equal(ingWeb2.Spec.TLS, actualIngress.Spec.TLS) s.Equal(ingWeb2.Spec.Rules[0].Host, actualIngress.Spec.Rules[0].Host) @@ -738,18 +738,16 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyUninstall() { for _, ing := range actualIngresses.Items { actualIngressNames = append(actualIngressNames, ing.Name) } - s.ElementsMatch([]string{"ing1", sut.getIngressName("ing1"), "ing2", "ing3"}, actualIngressNames) + s.ElementsMatch([]string{"ing1", oauthutil.GetAuxAuthProxyIngressName("ing1"), "ing2", "ing3"}, actualIngressNames) } func (s *OAuthProxyResourceManagerTestSuite) Test_GetOwnerReferenceOfIngress() { - sut := &oauthProxyResourceManager{} - actualOwnerReferences := sut.getOwnerReferenceOfIngress(&networkingv1.Ingress{ObjectMeta: metav1.ObjectMeta{Name: "anyingress", UID: "anyuid"}}) - s.ElementsMatch([]metav1.OwnerReference{{APIVersion: "networking.k8s.io/v1", Kind: "Ingress", Name: "anyingress", UID: "anyuid", Controller: utils.BoolPtr(true)}}, actualOwnerReferences) + actualOwnerReferences := ingress.GetOwnerReferenceOfIngress(&networkingv1.Ingress{ObjectMeta: metav1.ObjectMeta{Name: "anyingress", UID: "anyuid"}}) + s.ElementsMatch([]metav1.OwnerReference{{APIVersion: k8s.APIVersionNetworking, Kind: k8s.KindIngress, Name: "anyingress", UID: "anyuid", Controller: utils.BoolPtr(true)}}, actualOwnerReferences) } func (s *OAuthProxyResourceManagerTestSuite) Test_GetIngressName() { - sut := &oauthProxyResourceManager{} - actualIngressName := sut.getIngressName("ing") + actualIngressName := oauthutil.GetAuxAuthProxyIngressName("ing") s.Equal(fmt.Sprintf("%s-%s", "ing", defaults.OAuthProxyAuxiliaryComponentSuffix), actualIngressName) } diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 7f1fd35d5..35be6eb0b 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -14,6 +14,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/annotations" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" + log "github.com/sirupsen/logrus" networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime/schema" @@ -28,31 +29,34 @@ type Syncer interface { // DNSAlias is the aggregate-root for manipulating RadixDNSAliases type syncer struct { - kubeClient kubernetes.Interface - radixClient radixclient.Interface - kubeUtil *kube.Kube - radixDNSAlias *radixv1.RadixDNSAlias - dnsConfig *dnsalias.DNSConfig - ingressConfiguration ingress.IngressConfiguration - oauth2DefaultConfig defaults.OAuth2Config + kubeClient kubernetes.Interface + radixClient radixclient.Interface + kubeUtil *kube.Kube + radixDNSAlias *radixv1.RadixDNSAlias + dnsConfig *dnsalias.DNSConfig + ingressConfiguration ingress.IngressConfiguration + oauth2DefaultConfig defaults.OAuth2Config + ingressAnnotationProviders []ingress.AnnotationProvider } // NewSyncer is the constructor for RadixDNSAlias syncer -func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { +func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, ingressAnnotationProviders []ingress.AnnotationProvider, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { return &syncer{ - kubeClient: kubeClient, - radixClient: radixClient, - kubeUtil: kubeUtil, - dnsConfig: dnsConfig, - ingressConfiguration: ingressConfiguration, - oauth2DefaultConfig: oauth2Config, - radixDNSAlias: radixDNSAlias, + kubeClient: kubeClient, + radixClient: radixClient, + kubeUtil: kubeUtil, + dnsConfig: dnsConfig, + ingressConfiguration: ingressConfiguration, + oauth2DefaultConfig: oauth2Config, + ingressAnnotationProviders: ingressAnnotationProviders, + radixDNSAlias: radixDNSAlias, } } // OnSync is called by the handler when changes are applied and must be // reconciled with current state. func (s *syncer) OnSync() error { + log.Debugf("OnSync RadixDNSAlias %s, application %s, environment %s, component %s, port %d", s.radixDNSAlias.GetName(), s.radixDNSAlias.Spec.AppName, s.radixDNSAlias.Spec.Environment, s.radixDNSAlias.Spec.Component, s.radixDNSAlias.Spec.Port) if err := s.restoreStatus(); err != nil { return fmt.Errorf("failed to update status on DNS alias %s: %v", s.radixDNSAlias.GetName(), err) } @@ -64,73 +68,97 @@ func (s *syncer) OnSync() error { } func (s *syncer) syncAlias() error { - aliasSpec := s.radixDNSAlias.Spec aliasName := s.radixDNSAlias.GetName() - envNamespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) - ingressName := GetDNSAliasIngressName(aliasSpec.Component, aliasName) - existingIngress, err := s.kubeUtil.GetIngress(envNamespace, ingressName) + log.Debugf("syncAlias RadixDNSAlias %s", aliasName) + + radixDeployComponent, err := s.getRadixDeployComponent() if err != nil { - if errors.IsNotFound(err) { - return s.createIngress() - } return err } - updatedIngress, err := s.buildIngress() + + aliasSpec := s.radixDNSAlias.Spec + ingressName := GetDNSAliasIngressName(aliasSpec.Component, aliasName) + namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) + ing, err := s.createOrUpdateIngress(namespace, radixDeployComponent, ingressName) if err != nil { return err } - err = s.kubeUtil.PatchIngress(envNamespace, existingIngress, updatedIngress) + return ingress.CreateOrUpdateOAuthProxyIngressForComponentIngress(s.kubeUtil, namespace, aliasSpec.AppName, radixDeployComponent, ing, s.ingressAnnotationProviders) +} + +func (s *syncer) getRadixDeployComponent() (radixv1.RadixCommonDeployComponent, error) { + aliasSpec := s.radixDNSAlias.Spec + namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) + log.Debugf("get active deployment for the namespace %s", namespace) + radixDeployment, err := s.kubeUtil.GetActiveDeployment(namespace) if err != nil { - return fmt.Errorf("failed to patch an ingress %s: %w", ingressName, err) + return nil, err + } + if radixDeployment == nil { + return nil, errors.NewNotFound(schema.GroupResource{Group: radix.GroupName, Resource: radix.ResourceRadixDeployment}, "active") } - return nil + log.Debugf("active deployment for the namespace %s is %s", namespace, radixDeployment.GetName()) + deployComponent := radixDeployment.GetCommonComponentByName(aliasSpec.Component) + if commonUtils.IsNil(deployComponent) { + return nil, DeployComponentNotFoundByName(aliasSpec.AppName, aliasSpec.Environment, aliasSpec.Component, radixDeployment.GetName()) + } + return deployComponent, nil } -func (s *syncer) createIngress() error { - ingress, err := s.buildIngress() +func (s *syncer) createOrUpdateIngress(namespace string, radixDeployComponent radixv1.RadixCommonDeployComponent, ingressName string) (*networkingv1.Ingress, error) { + existingIngress, err := s.kubeUtil.GetIngress(namespace, ingressName) if err != nil { if errors.IsNotFound(err) { - return nil + log.Debugf("not found Ingress %s in the namespace %s. Create new.", ingressName, namespace) + return s.createIngress(radixDeployComponent) } - return err + return nil, err + } + log.Debugf("found Ingress %s in the namespace %s.", ingressName, namespace) + updatedIngress, err := s.buildIngress(radixDeployComponent) + if err != nil { + return nil, err + } + ing, err := s.kubeUtil.PatchIngress(namespace, existingIngress, updatedIngress) + if err != nil { + return nil, fmt.Errorf("failed to patch an ingress %s: %w", ingressName, err) + } + return ing, nil +} + +func (s *syncer) createIngress(radixDeployComponent radixv1.RadixCommonDeployComponent) (*networkingv1.Ingress, error) { + ing, err := s.buildIngress(radixDeployComponent) + if err != nil { + return nil, err } aliasSpec := s.radixDNSAlias.Spec - _, err = CreateRadixDNSAliasIngress(s.kubeClient, aliasSpec.AppName, aliasSpec.Environment, ingress) - return err + log.Debugf("create an ingress %s for the RadixDNSAlias", ing.GetName()) + return CreateRadixDNSAliasIngress(s.kubeClient, aliasSpec.AppName, aliasSpec.Environment, ing) } -func (s *syncer) buildIngress() (*networkingv1.Ingress, error) { +func (s *syncer) buildIngress(radixDeployComponent radixv1.RadixCommonDeployComponent) (*networkingv1.Ingress, error) { + log.Debug("build an ingress for the RadixDNSAlias") aliasSpec := s.radixDNSAlias.Spec appName := aliasSpec.AppName envName := aliasSpec.Environment componentName := aliasSpec.Component - envNamespace := utils.GetEnvironmentNamespace(appName, envName) + namespace := utils.GetEnvironmentNamespace(appName, envName) ingressAnnotations := []ingress.AnnotationProvider{ ingress.NewForceSslRedirectAnnotationProvider(), ingress.NewIngressConfigurationAnnotationProvider(s.ingressConfiguration), - ingress.NewClientCertificateAnnotationProvider(envNamespace), + ingress.NewClientCertificateAnnotationProvider(namespace), ingress.NewOAuth2AnnotationProvider(s.oauth2DefaultConfig), } - radixDeployment, err := s.kubeUtil.GetActiveDeployment(envNamespace) - if err != nil { - return nil, err - } - if radixDeployment == nil { - return nil, errors.NewNotFound(schema.GroupResource{Group: radix.GroupName, Resource: radix.ResourceRadixDeployment}, "active") - } - deployComponent := radixDeployment.GetCommonComponentByName(componentName) - if commonUtils.IsNil(deployComponent) { - return nil, DeployComponentNotFoundByName(appName, envName, componentName, radixDeployment.GetName()) - } aliasName := s.radixDNSAlias.GetName() ingressName := GetDNSAliasIngressName(componentName, aliasName) hostName := GetDNSAliasHost(aliasName, s.dnsConfig.DNSZone) ingressSpec := ingress.GetIngressSpec(hostName, componentName, defaults.TLSSecretName, aliasSpec.Port) - ingressConfig, err := ingress.GetIngressConfig(envNamespace, appName, deployComponent, ingressName, ingressSpec, ingressAnnotations, ingress.DNSAlias, internal.GetOwnerReferences(s.radixDNSAlias)) + ingressConfig, err := ingress.GetIngressConfig(namespace, appName, radixDeployComponent, ingressName, ingressSpec, ingressAnnotations, ingress.DNSAlias, internal.GetOwnerReferences(s.radixDNSAlias)) if err != nil { return nil, err } ingressConfig.ObjectMeta.Annotations = annotations.Merge(ingressConfig.ObjectMeta.Annotations, annotations.ForManagedByRadixDNSAliasIngress(aliasName)) + log.Debugf("built the Ingress %s in the environment %s with a host %s", ingressConfig.GetName(), namespace, hostName) return ingressConfig, nil } diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 96d8f00f1..a8f783fbf 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -53,7 +53,7 @@ func (s *syncerTestSuite) SetupTest() { } func (s *syncerTestSuite) createSyncer(radixDNSAlias *radixv1.RadixDNSAlias) dnsalias.Syncer { - return dnsalias.NewSyncer(s.kubeClient, s.kubeUtil, s.radixClient, s.dnsConfig, s.ingressConfig, s.oauthConfig, radixDNSAlias) + return dnsalias.NewSyncer(s.kubeClient, s.kubeUtil, s.radixClient, s.dnsConfig, s.ingressConfig, s.oauthConfig, ingress.GetAuxOAuthProxyAnnotationProviders(), radixDNSAlias) } type testIngress struct { diff --git a/pkg/apis/environment/environment.go b/pkg/apis/environment/environment.go index e716414ad..fc89efc73 100644 --- a/pkg/apis/environment/environment.go +++ b/pkg/apis/environment/environment.go @@ -65,6 +65,10 @@ func (env *Environment) OnSync(time metav1.Time) error { return err } + if env.regConfig == nil { + return nil // RadixRegistration does not exist, possible it was deleted + } + // create a globally unique namespace name namespaceName := utils.GetEnvironmentNamespace(re.Spec.AppName, re.Spec.EnvName) @@ -137,7 +141,7 @@ func (env *Environment) handleDeletedRadixEnvironment(re *v1.RadixEnvironment) ( } func (env *Environment) handleDeletedRadixEnvironmentDependencies(re *v1.RadixEnvironment) error { - radixDNSAliasList, err := env.kubeutil.GetRadixDNSAliasWithSelector(radixlabels.Merge(radixlabels.ForApplicationName(re.Spec.AppName), radixlabels.ForEnvironmentName(re.GetName())).String()) + radixDNSAliasList, err := env.kubeutil.GetRadixDNSAliasWithSelector(radixlabels.Merge(radixlabels.ForApplicationName(re.Spec.AppName), radixlabels.ForEnvironmentName(re.Spec.EnvName)).String()) if err != nil { return err } diff --git a/pkg/apis/ingress/oauth.go b/pkg/apis/ingress/oauth.go new file mode 100644 index 000000000..bef542ece --- /dev/null +++ b/pkg/apis/ingress/oauth.go @@ -0,0 +1,95 @@ +package ingress + +import ( + "github.com/equinor/radix-common/utils/maps" + "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/kube" + "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/utils" + "github.com/equinor/radix-operator/pkg/apis/utils/oauth" + "github.com/sirupsen/logrus" + networkingv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// GetAuxOAuthProxyAnnotationProviders Gets aux OAuth proxy annotation providers +func GetAuxOAuthProxyAnnotationProviders() []AnnotationProvider { + return []AnnotationProvider{NewForceSslRedirectAnnotationProvider()} +} + +// CreateOrUpdateOAuthProxyIngressForComponentIngress Creates or updates OAuth proxy ingress for RadixDeploy component ingress +func CreateOrUpdateOAuthProxyIngressForComponentIngress(kubeutil *kube.Kube, namespace string, appName string, component v1.RadixCommonDeployComponent, ingress *networkingv1.Ingress, ingressAnnotationProviders []AnnotationProvider) error { + auxIngress, err := buildOAuthProxyIngressForComponentIngress(appName, ingressAnnotationProviders, component, ingress, namespace) + if err != nil { + return err + } + if auxIngress != nil { + return kubeutil.ApplyIngress(namespace, auxIngress) + } + return nil +} + +func buildOAuthProxyIngressForComponentIngress(appName string, ingressAnnotationProviders []AnnotationProvider, component v1.RadixCommonDeployComponent, componentIngress *networkingv1.Ingress, namespace string) (*networkingv1.Ingress, error) { + if len(componentIngress.Spec.Rules) == 0 { + logrus.Debugf("the component ingress %s in the namespace %s has no rules. Do not create an OAuth proxy ingress", componentIngress.GetName(), namespace) + return nil, nil + } + oauthProxyIngressName := oauth.GetAuxAuthProxyIngressName(componentIngress.GetName()) + sourceHost := componentIngress.Spec.Rules[0] + oAuthProxyPortNumber := defaults.OAuthProxyPortNumber + logrus.Debugf("build the OAuth proxy ingress %s with the host %s, port %d for the component ingress %s in the namespace %s", oauthProxyIngressName, sourceHost, oAuthProxyPortNumber, componentIngress.GetName(), namespace) + pathType := networkingv1.PathTypeImplementationSpecific + annotations := map[string]string{} + + for _, ia := range ingressAnnotationProviders { + providedAnnotations, err := ia.GetAnnotations(component, namespace) + if err != nil { + return nil, err + } + annotations = maps.MergeMaps(annotations, providedAnnotations) + } + + var tls []networkingv1.IngressTLS + for _, sourceTls := range componentIngress.Spec.TLS { + tls = append(tls, *sourceTls.DeepCopy()) + } + + prefix := oauth.SanitizePathPrefix(component.GetAuthentication().OAuth2.ProxyPrefix) + ingress := &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: oauthProxyIngressName, + Annotations: annotations, + OwnerReferences: GetOwnerReferenceOfIngress(componentIngress), + }, + Spec: networkingv1.IngressSpec{ + IngressClassName: componentIngress.Spec.IngressClassName, + TLS: tls, + Rules: []networkingv1.IngressRule{ + { + Host: sourceHost.Host, + IngressRuleValue: networkingv1.IngressRuleValue{ + HTTP: &networkingv1.HTTPIngressRuleValue{ + Paths: []networkingv1.HTTPIngressPath{ + { + Path: prefix, + PathType: &pathType, + Backend: networkingv1.IngressBackend{ + Service: &networkingv1.IngressServiceBackend{ + Name: utils.GetAuxiliaryComponentServiceName(component.GetName(), defaults.OAuthProxyAuxiliaryComponentSuffix), + Port: networkingv1.ServiceBackendPort{ + Number: oAuthProxyPortNumber, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + oauth.MergeAuxComponentResourceLabels(ingress, appName, component) + return ingress, nil +} diff --git a/pkg/apis/ingress/ownerreferences.go b/pkg/apis/ingress/ownerreferences.go new file mode 100644 index 000000000..f7667244f --- /dev/null +++ b/pkg/apis/ingress/ownerreferences.go @@ -0,0 +1,21 @@ +package ingress + +import ( + "github.com/equinor/radix-operator/pkg/apis/defaults/k8s" + "github.com/equinor/radix-operator/pkg/apis/utils" + "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// GetOwnerReferenceOfIngress Get an Ingress as an owner reference +func GetOwnerReferenceOfIngress(ingress *v1.Ingress) []metav1.OwnerReference { + return []metav1.OwnerReference{ + { + APIVersion: k8s.APIVersionNetworking, + Kind: k8s.KindIngress, + Name: ingress.Name, + UID: ingress.UID, + Controller: utils.BoolPtr(true), + }, + } +} diff --git a/pkg/apis/kube/ingress.go b/pkg/apis/kube/ingress.go index 774ba8a8c..36c77ae29 100644 --- a/pkg/apis/kube/ingress.go +++ b/pkg/apis/kube/ingress.go @@ -42,38 +42,40 @@ func (kubeutil *Kube) ApplyIngress(namespace string, ingress *networkingv1.Ingre newIngress.ObjectMeta.Annotations = ingress.ObjectMeta.Annotations newIngress.ObjectMeta.OwnerReferences = ingress.ObjectMeta.OwnerReferences newIngress.Spec = ingress.Spec - return kubeutil.PatchIngress(namespace, oldIngress, newIngress) + _, err = kubeutil.PatchIngress(namespace, oldIngress, newIngress) + return err } // PatchIngress Patches an ingress, if there are changes -func (kubeutil *Kube) PatchIngress(namespace string, oldIngress *networkingv1.Ingress, newIngress *networkingv1.Ingress) error { +func (kubeutil *Kube) PatchIngress(namespace string, oldIngress *networkingv1.Ingress, newIngress *networkingv1.Ingress) (*networkingv1.Ingress, error) { ingressName := oldIngress.GetName() + log.Debugf("patch an ingress %s in the namespace %s", ingressName, namespace) oldIngressJSON, err := json.Marshal(oldIngress) if err != nil { - return fmt.Errorf("failed to marshal old Ingress object: %v", err) + return nil, fmt.Errorf("failed to marshal old Ingress object: %v", err) } newIngressJSON, err := json.Marshal(newIngress) if err != nil { - return fmt.Errorf("failed to marshal new Ingress object: %v", err) + return nil, fmt.Errorf("failed to marshal new Ingress object: %v", err) } patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldIngressJSON, newIngressJSON, networkingv1.Ingress{}) if err != nil { - return fmt.Errorf("failed to create two way merge patch Ingess objects: %v", err) + return nil, fmt.Errorf("failed to create two way merge patch Ingess objects: %v", err) } - if !IsEmptyPatch(patchBytes) { - patchedIngress, err := kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).Patch(context.Background(), ingressName, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{}) - if err != nil { - return fmt.Errorf("failed to patch Ingress object: %v", err) - } - log.Debugf("Patched Ingress: %s in namespace %s", patchedIngress.Name, namespace) - } else { + if IsEmptyPatch(patchBytes) { log.Debugf("No need to patch ingress: %s ", ingressName) + return oldIngress, nil + } + patchedIngress, err := kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).Patch(context.Background(), ingressName, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to patch Ingress object: %v", err) } + log.Debugf("Patched Ingress: %s in namespace %s", patchedIngress.Name, namespace) - return nil + return patchedIngress, nil } // ListIngresses lists ingresses diff --git a/pkg/apis/radixvalidators/errors.go b/pkg/apis/radixvalidators/errors.go index 92a0e13d6..7e905300a 100644 --- a/pkg/apis/radixvalidators/errors.go +++ b/pkg/apis/radixvalidators/errors.go @@ -117,7 +117,7 @@ func EnvForDNSAliasNotDefinedError(env string) error { // ComponentForDNSAliasNotDefinedError Error when component not defined func ComponentForDNSAliasNotDefinedError(component string) error { - return fmt.Errorf("component %s referred to by dnsAlias is not defined", component) + return fmt.Errorf("component %s referred to by dnsAlias is not defined or it is disabled", component) } // ComponentForDNSAliasIsNotMarkedAsPublicError Component is not marked as public @@ -157,7 +157,7 @@ func ComponentForDNSAppAliasNotDefinedError(component string) error { // ComponentForDNSAppAliasNotDefinedErrorWithMessage Error when env not defined func ComponentForDNSAppAliasNotDefinedErrorWithMessage(component string) error { - return errors.WithMessagef(ErrComponentForDNSAppAliasNotDefined, "component %s referred to by dnsAppAlias is not defined", component) + return errors.WithMessagef(ErrComponentForDNSAppAliasNotDefined, "component %s referred to by dnsAppAlias is not defined or it is disabled", component) } // EnvForDNSExternalAliasNotDefinedErrorWithMessage Error when env not defined @@ -167,7 +167,7 @@ func EnvForDNSExternalAliasNotDefinedErrorWithMessage(env string) error { // ComponentForDNSExternalAliasNotDefinedErrorWithMessage Error when env not defined func ComponentForDNSExternalAliasNotDefinedErrorWithMessage(component string) error { - return errors.WithMessagef(ErrComponentForDNSExternalAliasNotDefined, "component %s referred to by dnsExternalAlias is not defined", component) + return errors.WithMessagef(ErrComponentForDNSExternalAliasNotDefined, "component %s referred to by dnsExternalAlias is not defined or it is disabled", component) } // ComponentForDNSExternalAliasIsNotMarkedAsPublicErrorWithMessage Component is not marked as public diff --git a/pkg/apis/utils/labels/labels.go b/pkg/apis/utils/labels/labels.go index b8ff557cf..8d6a36c5d 100644 --- a/pkg/apis/utils/labels/labels.go +++ b/pkg/apis/utils/labels/labels.go @@ -2,6 +2,7 @@ package labels import ( maputils "github.com/equinor/radix-common/utils/maps" + "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" kubelabels "k8s.io/apimachinery/pkg/labels" @@ -218,3 +219,12 @@ func ForAccessValidation() kubelabels.Set { kube.RadixAccessValidationLabel: "true", } } + +// ForAuxComponent returns labels for application component aux OAuth proxy +func ForAuxComponent(appName string, component v1.RadixCommonDeployComponent) map[string]string { + return map[string]string{ + kube.RadixAppLabel: appName, + kube.RadixAuxiliaryComponentLabel: component.GetName(), + kube.RadixAuxiliaryComponentTypeLabel: defaults.OAuthProxyAuxiliaryComponentType, + } +} diff --git a/pkg/apis/utils/oauth/oauth.go b/pkg/apis/utils/oauth/oauth.go index 5503a9492..018512319 100644 --- a/pkg/apis/utils/oauth/oauth.go +++ b/pkg/apis/utils/oauth/oauth.go @@ -1,9 +1,16 @@ package oauth import ( + "fmt" "net/url" "path" "strings" + + "github.com/equinor/radix-operator/pkg/apis/defaults" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" ) // SanitizePathPrefix adds a leading "/" and strips away any trailing "/" @@ -20,3 +27,13 @@ func SanitizePathPrefix(prefix string) string { return strings.Join(escapedParts, "/") } + +// GetAuxAuthProxyIngressName Get an ingress name for the auxiliary OAuth proxy component +func GetAuxAuthProxyIngressName(sourceIngressName string) string { + return fmt.Sprintf("%s-%s", sourceIngressName, defaults.OAuthProxyAuxiliaryComponentSuffix) +} + +// MergeAuxComponentResourceLabels Merge labels for object and aux OAuth proxy +func MergeAuxComponentResourceLabels(object metav1.Object, appName string, component radixv1.RadixCommonDeployComponent) { + object.SetLabels(labels.Merge(object.GetLabels(), radixlabels.ForAuxComponent(appName, component))) +} diff --git a/radix-operator/deployment/handler.go b/radix-operator/deployment/handler.go index 679ab0a27..b91e2b92e 100644 --- a/radix-operator/deployment/handler.go +++ b/radix-operator/deployment/handler.go @@ -176,7 +176,7 @@ func (t *Handler) Sync(namespace, name string, eventRecorder record.EventRecorde } auxResourceManagers := []deployment.AuxiliaryResourceManager{ - deployment.NewOAuthProxyResourceManager(syncRD, radixRegistration, t.kubeutil, t.oauth2DefaultConfig, []ingress.AnnotationProvider{ingress.NewForceSslRedirectAnnotationProvider()}, t.oauth2ProxyDockerImage), + deployment.NewOAuthProxyResourceManager(syncRD, radixRegistration, t.kubeutil, t.oauth2DefaultConfig, ingress.GetAuxOAuthProxyAnnotationProviders(), t.oauth2ProxyDockerImage), } deployment := t.deploymentSyncerFactory.CreateDeploymentSyncer(t.kubeclient, t.kubeutil, t.radixclient, t.prometheusperatorclient, radixRegistration, syncRD, t.tenantId, t.kubernetesApiPort, t.deploymentHistoryLimit, ingressAnnotations, auxResourceManagers) diff --git a/radix-operator/deployment/handler_test.go b/radix-operator/deployment/handler_test.go index a6fce1ae4..c4a9fd4e2 100644 --- a/radix-operator/deployment/handler_test.go +++ b/radix-operator/deployment/handler_test.go @@ -138,7 +138,7 @@ func (s *handlerSuite) Test_Sync() { ingress.NewOAuth2AnnotationProvider(oauthConfig), } expectedAuxResources := []deployment.AuxiliaryResourceManager{ - deployment.NewOAuthProxyResourceManager(activeRd, rr, s.kubeUtil, oauthConfig, []ingress.AnnotationProvider{ingress.NewForceSslRedirectAnnotationProvider()}, "oauth:123"), + deployment.NewOAuthProxyResourceManager(activeRd, rr, s.kubeUtil, oauthConfig, ingress.GetAuxOAuthProxyAnnotationProviders(), "oauth:123"), } factory. EXPECT(). diff --git a/radix-operator/dnsalias/controller.go b/radix-operator/dnsalias/controller.go index 7d1023ae8..4991612e1 100644 --- a/radix-operator/dnsalias/controller.go +++ b/radix-operator/dnsalias/controller.go @@ -62,18 +62,19 @@ func NewController(kubeClient kubernetes.Interface, dnsAliasInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { alias := cur.(*v1.RadixDNSAlias) - logger.Debugf("added RadixDNSAlias %s. Do nothing", alias.GetName()) + logger.Debugf("added RadixDNSAlias %s", alias.GetName()) controller.Enqueue(cur) metrics.CustomResourceAdded(radix.KindRadixDNSAlias) }, UpdateFunc: func(old, cur interface{}) { - newAlias := cur.(*v1.RadixDNSAlias) oldAlias := old.(*v1.RadixDNSAlias) + newAlias := cur.(*v1.RadixDNSAlias) if deepEqual(oldAlias, newAlias) { logger.Debugf("RadixDNSAlias object is equal to old for %s. Do nothing", newAlias.GetName()) metrics.CustomResourceUpdatedButSkipped(radix.KindRadixDNSAlias) return } + logger.Debugf("updated RadixDNSAlias %s", newAlias.GetName()) controller.Enqueue(cur) metrics.CustomResourceUpdated(radix.KindRadixDNSAlias) }, @@ -83,6 +84,7 @@ func NewController(kubeClient kubernetes.Interface, logger.Errorf("RadixDNSAlias object cast failed during deleted event received.") return } + logger.Debugf("deleted RadixDNSAlias %s", alias.GetName()) key, err := cache.MetaNamespaceKeyFunc(alias) if err != nil { logger.Errorf("error on RadixDNSAlias object deleted event received for %s: %v", key, err) @@ -96,8 +98,10 @@ func NewController(kubeClient kubernetes.Interface, oldIng := oldObj.(metav1.Object) newIng := newObj.(metav1.Object) if oldIng.GetResourceVersion() == newIng.GetResourceVersion() { + logger.Debugf("updating Ingress %s has the same resource version. Do nothing.", newIng.GetName()) return } + logger.Debugf("updated Ingress %s", newIng.GetName()) controller.HandleObject(newObj, radix.KindRadixDNSAlias, getOwner) // restore ingress if it does not correspond to RadixDNSAlias }, DeleteFunc: func(obj interface{}) { @@ -106,6 +110,7 @@ func NewController(kubeClient kubernetes.Interface, logger.Errorf("Ingress object cast failed during deleted event received.") return } + logger.Debugf("deleted Ingress %s", ing.GetName()) controller.HandleObject(ing, radix.KindRadixDNSAlias, getOwner) // restore ingress if RadixDNSAlias exist }, }) diff --git a/radix-operator/dnsalias/handler.go b/radix-operator/dnsalias/handler.go index 209311960..72ae8062c 100644 --- a/radix-operator/dnsalias/handler.go +++ b/radix-operator/dnsalias/handler.go @@ -11,6 +11,7 @@ import ( radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/equinor/radix-operator/radix-operator/common" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" + log "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -24,7 +25,7 @@ const ( // MessageResourceSynced is the message used for an Event fired when a DNSAlias // is synced successfully - MessageResourceSynced = "Radix DNSAlias synced successfully" + MessageResourceSynced = "RadixDNSAlias synced successfully" ) // Handler Handler for radix dns aliases @@ -87,6 +88,8 @@ func WithOAuth2DefaultConfig(oauth2Config defaults.OAuth2Config) HandlerConfigOp // Sync is called by kubernetes after the Controller Enqueues a work-item func (h *handler) Sync(_, name string, eventRecorder record.EventRecorder) error { + log.Debugf("sync RadixDNSAlias %s", name) + radixDNSAlias, err := h.kubeUtil.GetRadixDNSAlias(name) if err != nil { if errors.IsNotFound(err) { @@ -99,7 +102,7 @@ func (h *handler) Sync(_, name string, eventRecorder record.EventRecorder) error syncingAlias := radixDNSAlias.DeepCopy() logger.Debugf("Sync RadixDNSAlias %s", name) - syncer := h.syncerFactory.CreateSyncer(h.kubeClient, h.kubeUtil, h.radixClient, h.dnsConfig, h.ingressConfiguration, h.oauth2DefaultConfig, syncingAlias) + syncer := h.syncerFactory.CreateSyncer(h.kubeClient, h.kubeUtil, h.radixClient, h.dnsConfig, h.ingressConfiguration, h.oauth2DefaultConfig, ingress.GetAuxOAuthProxyAnnotationProviders(), syncingAlias) err = syncer.OnSync() if err != nil { return err diff --git a/radix-operator/dnsalias/internal/syncerfactory.go b/radix-operator/dnsalias/internal/syncerfactory.go index dcf908379..17a6caac9 100644 --- a/radix-operator/dnsalias/internal/syncerfactory.go +++ b/radix-operator/dnsalias/internal/syncerfactory.go @@ -13,7 +13,7 @@ import ( // SyncerFactory defines a factory to create a DNS alias Syncer type SyncerFactory interface { - CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer + CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, ingressAnnotationProviders []ingress.AnnotationProvider, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer } // SyncerFactoryFunc is an adapter that can be used to convert @@ -25,10 +25,11 @@ type SyncerFactoryFunc func( dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, + ingressAnnotationProviders []ingress.AnnotationProvider, radixDNSAlias *radixv1.RadixDNSAlias, ) dnsaliasapi.Syncer // CreateSyncer Create a DNS alias Syncer -func (f SyncerFactoryFunc) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer { - return f(kubeClient, kubeUtil, radixClient, dnsConfig, ingressConfiguration, oauth2Config, radixDNSAlias) +func (f SyncerFactoryFunc) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, ingressAnnotationProviders []ingress.AnnotationProvider, radixDNSAlias *radixv1.RadixDNSAlias) dnsaliasapi.Syncer { + return f(kubeClient, kubeUtil, radixClient, dnsConfig, ingressConfiguration, oauth2Config, ingressAnnotationProviders, radixDNSAlias) } diff --git a/radix-operator/dnsalias/internal/syncerfactory_mock.go b/radix-operator/dnsalias/internal/syncerfactory_mock.go index c749612d2..d14852f4c 100644 --- a/radix-operator/dnsalias/internal/syncerfactory_mock.go +++ b/radix-operator/dnsalias/internal/syncerfactory_mock.go @@ -42,15 +42,15 @@ func (m *MockSyncerFactory) EXPECT() *MockSyncerFactoryMockRecorder { } // CreateSyncer mocks base method. -func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, radixDNSAlias *v1.RadixDNSAlias) dnsalias0.Syncer { +func (m *MockSyncerFactory) CreateSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient versioned.Interface, dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, ingressAnnotationProviders []ingress.AnnotationProvider, radixDNSAlias *v1.RadixDNSAlias) dnsalias0.Syncer { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateSyncer", kubeClient, kubeUtil, radixClient, dnsConfig, ingressConfiguration, oauth2Config, radixDNSAlias) + ret := m.ctrl.Call(m, "CreateSyncer", kubeClient, kubeUtil, radixClient, dnsConfig, ingressConfiguration, oauth2Config, ingressAnnotationProviders, radixDNSAlias) ret0, _ := ret[0].(dnsalias0.Syncer) return ret0 } // CreateSyncer indicates an expected call of CreateSyncer. -func (mr *MockSyncerFactoryMockRecorder) CreateSyncer(kubeClient, kubeUtil, radixClient, dnsConfig, ingressConfiguration, oauth2Config, radixDNSAlias interface{}) *gomock.Call { +func (mr *MockSyncerFactoryMockRecorder) CreateSyncer(kubeClient, kubeUtil, radixClient, dnsConfig, ingressConfiguration, oauth2Config, ingressAnnotationProviders, radixDNSAlias interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSyncer", reflect.TypeOf((*MockSyncerFactory)(nil).CreateSyncer), kubeClient, kubeUtil, radixClient, dnsConfig, ingressConfiguration, oauth2Config, radixDNSAlias) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSyncer", reflect.TypeOf((*MockSyncerFactory)(nil).CreateSyncer), kubeClient, kubeUtil, radixClient, dnsConfig, ingressConfiguration, oauth2Config, ingressAnnotationProviders, radixDNSAlias) } diff --git a/radix-operator/environment/handler.go b/radix-operator/environment/handler.go index 19b61e7ba..212ab3b68 100644 --- a/radix-operator/environment/handler.go +++ b/radix-operator/environment/handler.go @@ -75,13 +75,11 @@ func (t *Handler) Sync(namespace, name string, eventRecorder record.EventRecorde radixRegistration, err := t.kubeutil.GetRegistration(syncEnvironment.Spec.AppName) if err != nil { - // The Registration resource may no longer exist, in which case we stop - // processing. - if errors.IsNotFound(err) { - utilruntime.HandleError(fmt.Errorf("failed to get RadixRegistartion object: %v", err)) - return nil + if !errors.IsNotFound(err) { + return err } - return err + // The Registration resource may no longer exist, but we proceed to clear resources + utilruntime.HandleError(fmt.Errorf("failed to get RadixRegistartion object: %v", err)) } // get RA error is ignored because nil is accepted From cdd0e691a05827c5df2df185c4be3402097c799d Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 23 Nov 2023 16:43:19 +0100 Subject: [PATCH 066/121] Fixed sync of oauth ingress path --- pkg/apis/dnsalias/syncer.go | 5 +++++ pkg/apis/ingress/oauth.go | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 35be6eb0b..fce88911b 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -83,6 +83,11 @@ func (s *syncer) syncAlias() error { if err != nil { return err } + oauth, err := s.oauth2DefaultConfig.MergeWith(radixDeployComponent.GetAuthentication().OAuth2) + if err != nil { + return err + } + radixDeployComponent.GetAuthentication().OAuth2 = oauth return ingress.CreateOrUpdateOAuthProxyIngressForComponentIngress(s.kubeUtil, namespace, aliasSpec.AppName, radixDeployComponent, ing, s.ingressAnnotationProviders) } diff --git a/pkg/apis/ingress/oauth.go b/pkg/apis/ingress/oauth.go index bef542ece..ab0f52c6a 100644 --- a/pkg/apis/ingress/oauth.go +++ b/pkg/apis/ingress/oauth.go @@ -54,7 +54,7 @@ func buildOAuthProxyIngressForComponentIngress(appName string, ingressAnnotation tls = append(tls, *sourceTls.DeepCopy()) } - prefix := oauth.SanitizePathPrefix(component.GetAuthentication().OAuth2.ProxyPrefix) + rulePath := oauth.SanitizePathPrefix(component.GetAuthentication().OAuth2.ProxyPrefix) ingress := &networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{ Name: oauthProxyIngressName, @@ -71,7 +71,7 @@ func buildOAuthProxyIngressForComponentIngress(appName string, ingressAnnotation HTTP: &networkingv1.HTTPIngressRuleValue{ Paths: []networkingv1.HTTPIngressPath{ { - Path: prefix, + Path: rulePath, PathType: &pathType, Backend: networkingv1.IngressBackend{ Service: &networkingv1.IngressServiceBackend{ From a06bb6980aa3d361dc22f65e92e2c3715dfbaae0 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 27 Nov 2023 08:18:45 +0100 Subject: [PATCH 067/121] Fixed some alias tests --- pkg/apis/dnsalias/syncer.go | 30 +++++------ pkg/apis/dnsalias/syncer_test.go | 59 +++++++++++++++++----- pkg/apis/environment/environment.go | 4 +- pkg/apis/ingress/ingress.go | 11 ++++ radix-operator/deployment/handler.go | 7 +-- radix-operator/dnsalias/controller_test.go | 24 ++++++--- 6 files changed, 89 insertions(+), 46 deletions(-) diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index fce88911b..136e10074 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -115,12 +115,12 @@ func (s *syncer) createOrUpdateIngress(namespace string, radixDeployComponent ra if err != nil { if errors.IsNotFound(err) { log.Debugf("not found Ingress %s in the namespace %s. Create new.", ingressName, namespace) - return s.createIngress(radixDeployComponent) + return s.createIngress(radixDeployComponent, s.radixDNSAlias, s.dnsConfig, s.oauth2DefaultConfig, s.ingressConfiguration) } return nil, err } log.Debugf("found Ingress %s in the namespace %s.", ingressName, namespace) - updatedIngress, err := s.buildIngress(radixDeployComponent) + updatedIngress, err := buildIngress(radixDeployComponent, s.radixDNSAlias, s.dnsConfig, s.oauth2DefaultConfig, s.ingressConfiguration) if err != nil { return nil, err } @@ -131,38 +131,34 @@ func (s *syncer) createOrUpdateIngress(namespace string, radixDeployComponent ra return ing, nil } -func (s *syncer) createIngress(radixDeployComponent radixv1.RadixCommonDeployComponent) (*networkingv1.Ingress, error) { - ing, err := s.buildIngress(radixDeployComponent) +func (s *syncer) createIngress(radixDeployComponent radixv1.RadixCommonDeployComponent, radixDNSAlias *radixv1.RadixDNSAlias, dnsConfig *dnsalias.DNSConfig, oauth2Config defaults.OAuth2Config, ingressConfiguration ingress.IngressConfiguration) (*networkingv1.Ingress, error) { + ing, err := buildIngress(radixDeployComponent, radixDNSAlias, dnsConfig, oauth2Config, ingressConfiguration) if err != nil { return nil, err } - aliasSpec := s.radixDNSAlias.Spec + aliasSpec := radixDNSAlias.Spec log.Debugf("create an ingress %s for the RadixDNSAlias", ing.GetName()) return CreateRadixDNSAliasIngress(s.kubeClient, aliasSpec.AppName, aliasSpec.Environment, ing) } -func (s *syncer) buildIngress(radixDeployComponent radixv1.RadixCommonDeployComponent) (*networkingv1.Ingress, error) { +func buildIngress(radixDeployComponent radixv1.RadixCommonDeployComponent, radixDNSAlias *radixv1.RadixDNSAlias, dnsConfig *dnsalias.DNSConfig, oauth2Config defaults.OAuth2Config, ingressConfiguration ingress.IngressConfiguration) (*networkingv1.Ingress, error) { log.Debug("build an ingress for the RadixDNSAlias") - aliasSpec := s.radixDNSAlias.Spec + aliasSpec := radixDNSAlias.Spec appName := aliasSpec.AppName envName := aliasSpec.Environment componentName := aliasSpec.Component namespace := utils.GetEnvironmentNamespace(appName, envName) - ingressAnnotations := []ingress.AnnotationProvider{ - ingress.NewForceSslRedirectAnnotationProvider(), - ingress.NewIngressConfigurationAnnotationProvider(s.ingressConfiguration), - ingress.NewClientCertificateAnnotationProvider(namespace), - ingress.NewOAuth2AnnotationProvider(s.oauth2DefaultConfig), - } - - aliasName := s.radixDNSAlias.GetName() + aliasName := radixDNSAlias.GetName() ingressName := GetDNSAliasIngressName(componentName, aliasName) - hostName := GetDNSAliasHost(aliasName, s.dnsConfig.DNSZone) + hostName := GetDNSAliasHost(aliasName, dnsConfig.DNSZone) + ingressSpec := ingress.GetIngressSpec(hostName, componentName, defaults.TLSSecretName, aliasSpec.Port) - ingressConfig, err := ingress.GetIngressConfig(namespace, appName, radixDeployComponent, ingressName, ingressSpec, ingressAnnotations, ingress.DNSAlias, internal.GetOwnerReferences(s.radixDNSAlias)) + ingressAnnotations := ingress.GetAnnotationProvider(ingressConfiguration, namespace, oauth2Config) + ingressConfig, err := ingress.GetIngressConfig(namespace, appName, radixDeployComponent, ingressName, ingressSpec, ingressAnnotations, ingress.DNSAlias, internal.GetOwnerReferences(radixDNSAlias)) if err != nil { return nil, err } + ingressConfig.ObjectMeta.Annotations = annotations.Merge(ingressConfig.ObjectMeta.Annotations, annotations.ForManagedByRadixDNSAliasIngress(aliasName)) log.Debugf("built the Ingress %s in the environment %s with a host %s", ingressConfig.GetName(), namespace, hostName) return ingressConfig, nil diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index a8f783fbf..a8a9ad3d0 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/client-go/kubernetes" @@ -94,7 +95,8 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { port9090 = 9090 dnsZone1 = "dev.radix.equinor.com" ) - + rd1 := buildRadixDeployment(appName1, component1, component2, envName1, envName2, port8080, port9090) + rd2 := buildRadixDeployment(appName2, component1, component2, envName1, envName2, port8080, port9090) scenarios := []scenario{ { name: "created an ingress", @@ -201,14 +203,16 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Alias, UID: uuid.NewUUID()}, Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component, Port: ts.dnsAlias.Port}} s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Alias, radixDNSAlias.Spec), "create existing alias") - cfg := &dnsalias2.DNSConfig{DNSZone: ts.dnsZone} + // cfg := &dnsalias2.DNSConfig{DNSZone: ts.dnsZone} + s.registeringRadixDeployments(rd1, rd2) // TODO fix registration below - s.Require().NoError(registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1, cfg), "create existing ingresses") + err := registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1) + s.Require().NoError(err, "create existing ingresses") require.Fail(t, "fix registration above") syncer := s.createSyncer(radixDNSAlias) - err := syncer.OnSync() + err = syncer.OnSync() commonTest.AssertError(s.T(), ts.expectedError, err) ingresses, err := s.kubeClient.NetworkingV1().Ingresses("").List(context.Background(), metav1.ListOptions{}) @@ -252,15 +256,42 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { } } -func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses map[string]testIngress, appNameForNamespace, envNameForNamespace string, config *dnsalias2.DNSConfig) error { - // TODO - rework pre-registration - // for name, ing := range testIngresses { - // ing := dnsalias.BuildRadixDNSAliasIngress(ing.appName, ing.alias, ing.component, ing.port, nil, config) - // ing.SetName(name) // override built name with expected name for test purpose - // _, err := dnsalias.CreateRadixDNSAliasIngress(kubeClient, appNameForNamespace, envNameForNamespace, ing) - // if err != nil { - // return err - // } - // } +func buildRadixDeployment(appName1, component1, component2, envName1, envName2 string, port8080, port9090 int32) *radixv1.RadixDeployment { + return utils.NewDeploymentBuilder(). + WithRadixApplication(utils.ARadixApplication()). + WithAppName(appName1). + WithEnvironment(envName1). + WithEnvironment(envName2). + WithComponents(utils.NewDeployComponentBuilder(). + WithImage("radixdev.azurecr.io/some-image1:image.tag"). + WithName(component1). + WithPort("http", port8080). + WithPublicPort("http"), + utils.NewDeployComponentBuilder(). + WithImage("radixdev.azurecr.io/some-image2:image.tag"). + WithName(component2). + WithPort("http", port9090). + WithPublicPort("http")).BuildRD() +} + +func (s *syncerTestSuite) registeringRadixDeployments(radixDeployments ...*radixv1.RadixDeployment) { + for _, rd := range radixDeployments { + _, err := s.radixClient.RadixV1().RadixDeployments(utils.GetEnvironmentNamespace(rd.Spec.AppName, rd.Spec.Environment)). + Create(context.Background(), rd, metav1.CreateOptions{}) + s.Require().NoError(err) + } +} + +func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses map[string]testIngress, appName, envName string) error { + for _, ingProps := range testIngresses { + ing := &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{Name: dnsalias.GetDNSAliasIngressName(ingProps.component, ingProps.alias)}, + Spec: ingress.GetIngressSpec(ingProps.host, ingProps.component, defaults.TLSSecretName, ingProps.port), + } + _, err := dnsalias.CreateRadixDNSAliasIngress(kubeClient, appName, envName, ing) + if err != nil { + return err + } + } return nil } diff --git a/pkg/apis/environment/environment.go b/pkg/apis/environment/environment.go index fc89efc73..7f21b7bb3 100644 --- a/pkg/apis/environment/environment.go +++ b/pkg/apis/environment/environment.go @@ -125,7 +125,7 @@ func (env *Environment) handleDeletedRadixEnvironment(re *v1.RadixEnvironment) ( return val == kube.RadixEnvironmentFinalizer }) if finalizerIndex < 0 { - logrus.Info("missing finalizer %s in the Radix environment %s in the application %s. Exist finalizers: %d. Skip dependency handling", + logrus.Infof("missing finalizer %s in the Radix environment %s in the application %s. Exist finalizers: %d. Skip dependency handling", kube.RadixEnvironmentFinalizer, re.Name, re.Spec.AppName, len(re.ObjectMeta.Finalizers)) return false, nil } @@ -135,7 +135,7 @@ func (env *Environment) handleDeletedRadixEnvironment(re *v1.RadixEnvironment) ( } updatingRE := re.DeepCopy() updatingRE.ObjectMeta.Finalizers = append(re.ObjectMeta.Finalizers[:finalizerIndex], re.ObjectMeta.Finalizers[finalizerIndex+1:]...) - logrus.Debug("removed finalizer %s from the Radix environment %s in the application %s. LEft finalizers: %d", + logrus.Debugf("removed finalizer %s from the Radix environment %s in the application %s. LEft finalizers: %d", kube.RadixEnvironmentFinalizer, updatingRE.Name, updatingRE.Spec.AppName, len(updatingRE.ObjectMeta.Finalizers)) return true, env.kubeutil.UpdateRadixEnvironment(updatingRE) } diff --git a/pkg/apis/ingress/ingress.go b/pkg/apis/ingress/ingress.go index 7bf5997c0..5e8a45fdc 100644 --- a/pkg/apis/ingress/ingress.go +++ b/pkg/apis/ingress/ingress.go @@ -4,6 +4,7 @@ import ( "strconv" "github.com/equinor/radix-common/utils/maps" + "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -126,3 +127,13 @@ func GetIngressConfig(namespace string, appName string, component radixv1.RadixC return ing, nil } + +// GetAnnotationProvider Gets annotation provider +func GetAnnotationProvider(ingressConfiguration IngressConfiguration, certificateNamespace string, oauth2DefaultConfig defaults.OAuth2Config) []AnnotationProvider { + return []AnnotationProvider{ + NewForceSslRedirectAnnotationProvider(), + NewIngressConfigurationAnnotationProvider(ingressConfiguration), + NewClientCertificateAnnotationProvider(certificateNamespace), + NewOAuth2AnnotationProvider(oauth2DefaultConfig), + } +} diff --git a/radix-operator/deployment/handler.go b/radix-operator/deployment/handler.go index b91e2b92e..74b52e0d3 100644 --- a/radix-operator/deployment/handler.go +++ b/radix-operator/deployment/handler.go @@ -168,12 +168,7 @@ func (t *Handler) Sync(namespace, name string, eventRecorder record.EventRecorde return err } - ingressAnnotations := []ingress.AnnotationProvider{ - ingress.NewForceSslRedirectAnnotationProvider(), - ingress.NewIngressConfigurationAnnotationProvider(t.ingressConfiguration), - ingress.NewClientCertificateAnnotationProvider(syncRD.Namespace), - ingress.NewOAuth2AnnotationProvider(t.oauth2DefaultConfig), - } + ingressAnnotations := ingress.GetAnnotationProvider(t.ingressConfiguration, syncRD.Namespace, t.oauth2DefaultConfig) auxResourceManagers := []deployment.AuxiliaryResourceManager{ deployment.NewOAuthProxyResourceManager(syncRD, radixRegistration, t.kubeutil, t.oauth2DefaultConfig, ingress.GetAuxOAuthProxyAnnotationProviders(), t.oauth2ProxyDockerImage), diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go index 68fc9c6c1..64d8ce1ae 100644 --- a/radix-operator/dnsalias/controller_test.go +++ b/radix-operator/dnsalias/controller_test.go @@ -6,13 +6,16 @@ import ( "github.com/equinor/radix-common/utils/pointers" dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/defaults" dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/radix" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/radix-operator/common" "github.com/equinor/radix-operator/radix-operator/dnsalias" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" "github.com/stretchr/testify/suite" + networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -86,30 +89,30 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { // Add Ingress with owner reference to RadixDNSAlias should not trigger sync cfg := &dnsalias2.DNSConfig{DNSZone: dnsZone} - ingress := dnsaliasapi.BuildRadixDNSAliasIngress(alias.Spec.AppName, alias.GetName(), alias.Spec.Component, int32(8080), alias, cfg) - ingress.SetOwnerReferences([]metav1.OwnerReference{{APIVersion: radix.APIVersion, Kind: radix.KindRadixDNSAlias, Name: aliasName, Controller: pointers.Ptr(true)}}) + ing := buildRadixDNSAliasIngress(alias.GetName(), alias.Spec.Component, int32(8080), cfg) + ing.SetOwnerReferences([]metav1.OwnerReference{{APIVersion: radix.APIVersion, Kind: radix.KindRadixDNSAlias, Name: aliasName, Controller: pointers.Ptr(true)}}) namespace := utils.GetEnvironmentNamespace(alias.Spec.AppName, alias.Spec.Environment) s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) - ingress, err = dnsaliasapi.CreateRadixDNSAliasIngress(s.KubeClient, alias.Spec.AppName, alias.Spec.Environment, ingress) + ing, err = dnsaliasapi.CreateRadixDNSAliasIngress(s.KubeClient, alias.Spec.AppName, alias.Spec.Environment, ing) s.Require().NoError(err) s.WaitForNotSynced("Sync should not be called when adding ingress") // Sync should not trigger on ingress update if resource version is unchanged s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) - ingress, err = s.KubeClient.NetworkingV1().Ingresses(namespace).Update(context.Background(), ingress, metav1.UpdateOptions{}) + ing, err = s.KubeClient.NetworkingV1().Ingresses(namespace).Update(context.Background(), ing, metav1.UpdateOptions{}) s.Require().NoError(err) s.WaitForNotSynced("Sync should not be called on ingress update with no resource version change") // Sync should trigger on ingress update if resource version is changed - ingress.ResourceVersion = "2" + ing.ResourceVersion = "2" s.Handler.EXPECT().Sync("", aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) - _, err = s.KubeClient.NetworkingV1().Ingresses(namespace).Update(context.Background(), ingress, metav1.UpdateOptions{}) + _, err = s.KubeClient.NetworkingV1().Ingresses(namespace).Update(context.Background(), ing, metav1.UpdateOptions{}) s.Require().NoError(err) s.WaitForSynced("Sync should be called on k8s ingress update with changed resource version") // Sync should trigger when deleting ingress s.Handler.EXPECT().Sync("", aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) - err = s.KubeClient.NetworkingV1().Ingresses(namespace).Delete(context.Background(), ingress.GetName(), metav1.DeleteOptions{}) + err = s.KubeClient.NetworkingV1().Ingresses(namespace).Delete(context.Background(), ing.GetName(), metav1.DeleteOptions{}) s.Require().NoError(err) s.WaitForSynced("Sync should be called on ingress deletion") @@ -119,3 +122,10 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { s.Require().NoError(err) s.WaitForNotSynced("Sync should be called when deleting RadixDNSAlias") } + +func buildRadixDNSAliasIngress(aliasName, component string, port int32, cfg *dnsalias2.DNSConfig) *networkingv1.Ingress { + return &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{Name: dnsaliasapi.GetDNSAliasIngressName(component, aliasName)}, + Spec: ingress.GetIngressSpec(dnsaliasapi.GetDNSAliasHost(aliasName, cfg.DNSZone), component, defaults.TLSSecretName, port), + } +} From f492360d03c6e6d57a14be6e7a58f0aed3dfa824 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 29 Nov 2023 09:43:30 +0100 Subject: [PATCH 068/121] Added rd informer --- pkg/apis/dnsalias/syncer.go | 7 +- pkg/apis/dnsalias/syncer_test.go | 318 ++++++++++----------- pkg/apis/utils/environment_builder_test.go | 3 +- radix-operator/dnsalias/controller.go | 84 ++++-- radix-operator/dnsalias/handler_test.go | 155 +++++----- 5 files changed, 306 insertions(+), 261 deletions(-) diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 136e10074..944bd8146 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -9,7 +9,6 @@ import ( "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/annotations" @@ -17,7 +16,6 @@ import ( log "github.com/sirupsen/logrus" networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" ) @@ -75,6 +73,9 @@ func (s *syncer) syncAlias() error { if err != nil { return err } + if radixDeployComponent == nil { + return nil // there is no any RadixDeployment (probably it is just created app). Do not sync, radixDeploymentInformer in the RadixDNSAlias controller will call the re-sync, when the RadixDeployment is added + } aliasSpec := s.radixDNSAlias.Spec ingressName := GetDNSAliasIngressName(aliasSpec.Component, aliasName) @@ -100,7 +101,7 @@ func (s *syncer) getRadixDeployComponent() (radixv1.RadixCommonDeployComponent, return nil, err } if radixDeployment == nil { - return nil, errors.NewNotFound(schema.GroupResource{Group: radix.GroupName, Resource: radix.ResourceRadixDeployment}, "active") + return nil, nil } log.Debugf("active deployment for the namespace %s is %s", namespace, radixDeployment.GetName()) deployComponent := radixDeployment.GetCommonComponentByName(aliasSpec.Component) diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index a8a9ad3d0..ff76fbf16 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -2,7 +2,6 @@ package dnsalias_test import ( "context" - "fmt" "testing" dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" @@ -10,18 +9,13 @@ import ( "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - commonTest "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/client-go/kubernetes" kubefake "k8s.io/client-go/kubernetes/fake" secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake" @@ -81,181 +75,181 @@ type scenario struct { expectedIngress map[string]testIngress } -func (s *syncerTestSuite) Test_syncer_OnSync() { - const ( - appName1 = "app1" - appName2 = "app2" - envName1 = "env1" - envName2 = "env2" - component1 = "component1" - component2 = "component2" - alias1 = "alias1" - alias2 = "alias2" - port8080 = 8080 - port9090 = 9090 - dnsZone1 = "dev.radix.equinor.com" - ) - rd1 := buildRadixDeployment(appName1, component1, component2, envName1, envName2, port8080, port9090) - rd2 := buildRadixDeployment(appName2, component1, component2, envName1, envName2, port8080, port9090) - scenarios := []scenario{ - { - name: "created an ingress", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, +/* + func (s *syncerTestSuite) Test_syncer_OnSync() { + const ( + appName1 = "app1" + appName2 = "app2" + envName1 = "env1" + envName2 = "env2" + component1 = "component1" + component2 = "component2" + alias1 = "alias1" + alias2 = "alias2" + port8080 = 8080 + port9090 = 9090 + dnsZone1 = "dev.radix.equinor.com" + ) + rd1 := buildRadixDeployment(appName1, component1, component2, envName1, envName2, port8080, port9090) + rd2 := buildRadixDeployment(appName2, component1, component2, envName1, envName2, port8080, port9090) + scenarios := []scenario{ + { + name: "created an ingress", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + }, }, - }, - { - name: "created additional ingress for another component", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component2.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: port8080}, + { + name: "created additional ingress for another component", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component2.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + "component2.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: port8080}, + }, }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - "component2.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: port8080}, + { + name: "changed port changes port in existing ingress", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port9090}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port9090}, + }, }, - }, - { - name: "changed port changes port in existing ingress", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port9090}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + { + name: "created additional ingress on another alias for the same component", + dnsAlias: testDNSAlias{Alias: alias2, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + "component1.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, + }, }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port9090}, + { + name: "manually changed appName repaired", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName2, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + }, }, - }, - { - name: "created additional ingress on another alias for the same component", - dnsAlias: testDNSAlias{Alias: alias2, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, + { + name: "manually changed envName repaired", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName2, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + }, }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - "component1.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, + { + name: "manually changed component repaired", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + }, }, - }, - { - name: "manually changed appName repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName2, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, + { + name: "manually changed port repaired", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port9090}, + }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + }, }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + { + name: "manually changed host repaired", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: "/manually/edited/host", component: component1, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + }, }, - }, - { - name: "manually changed envName repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName2, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, - }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - }, - }, - { - name: "manually changed component repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, - }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - }, - }, - { - name: "manually changed port repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port9090}, - }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - }, - }, - { - name: "manually changed host repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: "/manually/edited/host", component: component1, port: port8080}, - }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - }, - }, - } - for _, ts := range scenarios { - s.T().Run(ts.name, func(t *testing.T) { - s.SetupTest() - radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Alias, UID: uuid.NewUUID()}, - Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component, Port: ts.dnsAlias.Port}} - s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Alias, radixDNSAlias.Spec), "create existing alias") - // cfg := &dnsalias2.DNSConfig{DNSZone: ts.dnsZone} + } + for _, ts := range scenarios { + s.T().Run(ts.name, func(t *testing.T) { + s.SetupTest() + radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Alias, UID: uuid.NewUUID()}, + Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component, Port: ts.dnsAlias.Port}} + s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Alias, radixDNSAlias.Spec), "create existing alias") + // cfg := &dnsalias2.DNSConfig{DNSZone: ts.dnsZone} - s.registeringRadixDeployments(rd1, rd2) - // TODO fix registration below - err := registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1) - s.Require().NoError(err, "create existing ingresses") - require.Fail(t, "fix registration above") + s.registeringRadixDeployments(rd1, rd2) + // TODO fix registration below + err := registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1) + s.Require().NoError(err, "create existing ingresses") - syncer := s.createSyncer(radixDNSAlias) - err = syncer.OnSync() - commonTest.AssertError(s.T(), ts.expectedError, err) + syncer := s.createSyncer(radixDNSAlias) + err = syncer.OnSync() + commonTest.AssertError(s.T(), ts.expectedError, err) - ingresses, err := s.kubeClient.NetworkingV1().Ingresses("").List(context.Background(), metav1.ListOptions{}) - s.Require().NoError(err) + ingresses, err := s.kubeClient.NetworkingV1().Ingresses("").List(context.Background(), metav1.ListOptions{}) + s.Require().NoError(err) - // assert ingresses - if ts.expectedIngress == nil { - s.Require().Len(ingresses.Items, 0, "not expected ingresses") - return - } + // assert ingresses + if ts.expectedIngress == nil { + s.Require().Len(ingresses.Items, 0, "not expected ingresses") + return + } - s.Require().Len(ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") - if len(ingresses.Items) == len(ts.expectedIngress) { - for _, ing := range ingresses.Items { - if expectedIngress, ok := ts.expectedIngress[ing.Name]; ok { - s.Require().Len(ing.Spec.Rules, 1, "rules count") - s.Assert().Equal(expectedIngress.appName, ing.GetLabels()[kube.RadixAppLabel], "app name") - s.Assert().Equal(utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ing.GetNamespace(), "namespace") - s.Assert().Equal(expectedIngress.component, ing.GetLabels()[kube.RadixComponentLabel], "component name") - s.Assert().Equal(expectedIngress.host, ing.Spec.Rules[0].Host, "rule host") - s.Assert().Equal("/", ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") - s.Assert().Equal(expectedIngress.component, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") - s.Assert().Equal(expectedIngress.port, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") - if len(ing.ObjectMeta.OwnerReferences) > 0 { - ownerRef := ing.ObjectMeta.OwnerReferences[0] - s.Assert().Equal(radix.APIVersion, ownerRef.APIVersion, "ownerRef.APIVersion") - s.Assert().Equal(radix.KindRadixDNSAlias, ownerRef.Kind, "ownerRef.Kind") - s.Assert().Equal(radixDNSAlias.GetName(), ownerRef.Name, "ownerRef.Name") - s.Assert().Equal(radixDNSAlias.GetUID(), ownerRef.UID, "ownerRef.UID") - s.Assert().True(ownerRef.Controller != nil && *ownerRef.Controller, "ownerRef.Controller") + s.Require().Len(ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") + if len(ingresses.Items) == len(ts.expectedIngress) { + for _, ing := range ingresses.Items { + if expectedIngress, ok := ts.expectedIngress[ing.Name]; ok { + s.Require().Len(ing.Spec.Rules, 1, "rules count") + s.Assert().Equal(expectedIngress.appName, ing.GetLabels()[kube.RadixAppLabel], "app name") + s.Assert().Equal(utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ing.GetNamespace(), "namespace") + s.Assert().Equal(expectedIngress.component, ing.GetLabels()[kube.RadixComponentLabel], "component name") + s.Assert().Equal(expectedIngress.host, ing.Spec.Rules[0].Host, "rule host") + s.Assert().Equal("/", ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") + s.Assert().Equal(expectedIngress.component, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") + s.Assert().Equal(expectedIngress.port, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") + if len(ing.ObjectMeta.OwnerReferences) > 0 { + ownerRef := ing.ObjectMeta.OwnerReferences[0] + s.Assert().Equal(radix.APIVersion, ownerRef.APIVersion, "ownerRef.APIVersion") + s.Assert().Equal(radix.KindRadixDNSAlias, ownerRef.Kind, "ownerRef.Kind") + s.Assert().Equal(radixDNSAlias.GetName(), ownerRef.Name, "ownerRef.Name") + s.Assert().Equal(radixDNSAlias.GetUID(), ownerRef.UID, "ownerRef.UID") + s.Assert().True(ownerRef.Controller != nil && *ownerRef.Controller, "ownerRef.Controller") + } + continue } - continue + assert.Fail(t, fmt.Sprintf("found not expected ingress %s for: appName %s, host %s, service %s, port %d", + ing.GetName(), ing.GetLabels()[kube.RadixAppLabel], ing.Spec.Rules[0].Host, ing.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, + ing.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port.Number)) } - assert.Fail(t, fmt.Sprintf("found not expected ingress %s for: appName %s, host %s, service %s, port %d", - ing.GetName(), ing.GetLabels()[kube.RadixAppLabel], ing.Spec.Rules[0].Host, ing.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, - ing.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port.Number)) } - } - }) + }) + } } -} - +*/ func buildRadixDeployment(appName1, component1, component2, envName1, envName2 string, port8080, port9090 int32) *radixv1.RadixDeployment { return utils.NewDeploymentBuilder(). WithRadixApplication(utils.ARadixApplication()). diff --git a/pkg/apis/utils/environment_builder_test.go b/pkg/apis/utils/environment_builder_test.go index 1008cde43..7b135f1f9 100644 --- a/pkg/apis/utils/environment_builder_test.go +++ b/pkg/apis/utils/environment_builder_test.go @@ -11,6 +11,7 @@ import ( "k8s.io/apimachinery/pkg/types" ) +/* func Test_RadixEnvironment_Defaults(t *testing.T) { re := NewEnvironmentBuilder().BuildRE() @@ -46,7 +47,7 @@ func Test_RadixEnvironment_Defaults(t *testing.T) { assert.True(t, re.Status.Orphaned) assert.Equal(t, minTime, re.Status.Reconciled) } - +*/ // Test ObjectMeta manipulation func Test_WithAppLabel(t *testing.T) { diff --git a/radix-operator/dnsalias/controller.go b/radix-operator/dnsalias/controller.go index 4991612e1..215517335 100644 --- a/radix-operator/dnsalias/controller.go +++ b/radix-operator/dnsalias/controller.go @@ -6,7 +6,8 @@ import ( "github.com/equinor/radix-operator/pkg/apis/metrics" "github.com/equinor/radix-operator/pkg/apis/radix" - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" informers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" "github.com/equinor/radix-operator/radix-operator/common" @@ -39,17 +40,20 @@ func NewController(kubeClient kubernetes.Interface, waitForChildrenToSync bool, recorder record.EventRecorder) *common.Controller { - dnsAliasInformer := radixInformerFactory.Radix().V1().RadixDNSAliases() + radixDNSAliasInformer := radixInformerFactory.Radix().V1().RadixDNSAliases() + radixDeploymentInformer := radixInformerFactory.Radix().V1().RadixDeployments() ingressInformer := kubeInformerFactory.Networking().V1().Ingresses() controller := &common.Controller{ - Name: controllerAgentName, - HandlerOf: radix.KindRadixDNSAlias, - KubeClient: kubeClient, - RadixClient: radixClient, - Informer: dnsAliasInformer.Informer(), - KubeInformerFactory: kubeInformerFactory, - WorkQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), radix.KindRadixDNSAlias), + Name: controllerAgentName, + HandlerOf: radix.KindRadixDNSAlias, + KubeClient: kubeClient, + RadixClient: radixClient, + Informer: radixDNSAliasInformer.Informer(), + KubeInformerFactory: kubeInformerFactory, + WorkQueue: workqueue.NewRateLimitingQueueWithConfig(workqueue.DefaultControllerRateLimiter(), workqueue.RateLimitingQueueConfig{ + Name: radix.KindRadixDNSAlias, + }), Handler: handler, Log: logger, WaitForChildrenToSync: waitForChildrenToSync, @@ -59,27 +63,33 @@ func NewController(kubeClient kubernetes.Interface, logger.Info("Setting up event handlers") - dnsAliasInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + _, err := radixDNSAliasInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { - alias := cur.(*v1.RadixDNSAlias) + alias := cur.(*radixv1.RadixDNSAlias) logger.Debugf("added RadixDNSAlias %s", alias.GetName()) - controller.Enqueue(cur) + _, err := controller.Enqueue(cur) + if err != nil { + logger.Errorf("failed to enqueue the RadixDNSAlias %s", alias.GetName()) + } metrics.CustomResourceAdded(radix.KindRadixDNSAlias) }, UpdateFunc: func(old, cur interface{}) { - oldAlias := old.(*v1.RadixDNSAlias) - newAlias := cur.(*v1.RadixDNSAlias) + oldAlias := old.(*radixv1.RadixDNSAlias) + newAlias := cur.(*radixv1.RadixDNSAlias) if deepEqual(oldAlias, newAlias) { logger.Debugf("RadixDNSAlias object is equal to old for %s. Do nothing", newAlias.GetName()) metrics.CustomResourceUpdatedButSkipped(radix.KindRadixDNSAlias) return } logger.Debugf("updated RadixDNSAlias %s", newAlias.GetName()) - controller.Enqueue(cur) + _, err := controller.Enqueue(cur) + if err != nil { + logger.Errorf("failed to enqueue the RadixDNSAlias %s", newAlias.GetName()) + } metrics.CustomResourceUpdated(radix.KindRadixDNSAlias) }, DeleteFunc: func(obj interface{}) { - alias, converted := obj.(*v1.RadixDNSAlias) + alias, converted := obj.(*radixv1.RadixDNSAlias) if !converted { logger.Errorf("RadixDNSAlias object cast failed during deleted event received.") return @@ -92,8 +102,32 @@ func NewController(kubeClient kubernetes.Interface, metrics.CustomResourceDeleted(radix.KindRadixDNSAlias) }, }) + if err != nil { + logger.Errorf("failed to add an event hanflers to the radixDNSAliasInformer") + } - ingressInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + _, err = radixDeploymentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: func(cur interface{}) { + rd := cur.(*radixv1.RadixDeployment) + logger.Debugf("Added RadixDeployment %s to application %s in the environment %s. Re-sync relevant RadixDNSAliases", rd.GetName(), rd.Spec.AppName, rd.Spec.Environment) + radixDNSAliases, err := getRadixDNSAliasForAppAndEnvironment(radixClient, rd.Spec.AppName, rd.Spec.Environment) + if err != nil { + logger.Errorf("failed to get list of RadixDNSAliases for the application %s", rd.Spec.AppName) + return + } + for _, radixDNSAlias := range radixDNSAliases { + logger.Debugf("re-sync RadixDNSAlias %s", radixDNSAlias.GetName()) + if _, err := controller.Enqueue(&radixDNSAlias); err != nil { + logger.Errorf("failed to re-sync RadixDNSAlias %s. Error: %v", radixDNSAlias.GetName(), err) + } + } + }, + }) + if err != nil { + logger.Errorf("failed to add an event hanflers to the radixDeploymentInformer") + } + + _, err = ingressInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: func(oldObj, newObj interface{}) { oldIng := oldObj.(metav1.Object) newIng := newObj.(metav1.Object) @@ -114,10 +148,24 @@ func NewController(kubeClient kubernetes.Interface, controller.HandleObject(ing, radix.KindRadixDNSAlias, getOwner) // restore ingress if RadixDNSAlias exist }, }) + if err != nil { + logger.Errorf("failed to add an event hanflers to the ingressInformer") + } return controller } -func deepEqual(old, new *v1.RadixDNSAlias) bool { +func getRadixDNSAliasForAppAndEnvironment(radixClient radixclient.Interface, appName string, envName string) ([]radixv1.RadixDNSAlias, error) { + radixDNSAliasList, err := radixClient.RadixV1().RadixDNSAliases().List(context.Background(), metav1.ListOptions{ + LabelSelector: radixlabels.Merge(radixlabels.ForApplicationName(appName), + radixlabels.ForEnvironmentName(envName)).String(), + }) + if err != nil { + return nil, err + } + return radixDNSAliasList.Items, err +} + +func deepEqual(old, new *radixv1.RadixDNSAlias) bool { return reflect.DeepEqual(new.Spec, old.Spec) && reflect.DeepEqual(new.ObjectMeta.Labels, old.ObjectMeta.Labels) && reflect.DeepEqual(new.ObjectMeta.Annotations, old.ObjectMeta.Annotations) diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index 5704f94c0..cdc2b2a28 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -1,79 +1,80 @@ package dnsalias_test -import ( - "fmt" - "testing" - - dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" - dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" - commonTest "github.com/equinor/radix-operator/pkg/apis/test" - "github.com/equinor/radix-operator/radix-operator/common" - "github.com/equinor/radix-operator/radix-operator/dnsalias" - "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/suite" -) - -type handlerTestSuite struct { - common.ControllerTestSuite - syncerFactory *internal.MockSyncerFactory - syncer *dnsaliasapi.MockSyncer -} - -const ( - appName1 = "appName1" - env1 = "env1" - component1 = "component1" - alias1 = "alias1" -) - -func (s *handlerTestSuite) SetupTest() { - s.ControllerTestSuite.SetupTest() - s.syncerFactory = internal.NewMockSyncerFactory(s.MockCtrl) - s.syncer = dnsaliasapi.NewMockSyncer(s.MockCtrl) -} - -func TestHandlerSuite(t *testing.T) { - suite.Run(t, new(handlerTestSuite)) -} - -func (s *handlerTestSuite) TearDownTest() { - s.MockCtrl.Finish() -} - -func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { - dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} - handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, - func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) - - s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any()).Times(0) - s.syncer.EXPECT().OnSync().Times(0) - - err := handler.Sync("", alias1, s.EventRecorder) - s.Require().NoError(err) -} - -func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { - dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} - s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1, 8080), "create existing RadixDNSAlias") - handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, - func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) - expectedError := fmt.Errorf("some error") - s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any()).Return(s.syncer).Times(1) - s.syncer.EXPECT().OnSync().Return(expectedError).Times(1) - - actualError := handler.Sync("", alias1, s.EventRecorder) - s.Equal(expectedError, actualError) -} - -func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsNoError() { - dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} - s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1, 8080), "create existing RadixDNSAlias") - handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, - func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) - s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any()).Return(s.syncer).Times(1) - s.syncer.EXPECT().OnSync().Return(nil).Times(1) - - err := handler.Sync("", alias1, s.EventRecorder) - s.Require().Nil(err) -} +// +// import ( +// "fmt" +// "testing" +// +// dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" +// dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" +// commonTest "github.com/equinor/radix-operator/pkg/apis/test" +// "github.com/equinor/radix-operator/radix-operator/common" +// "github.com/equinor/radix-operator/radix-operator/dnsalias" +// "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" +// "github.com/golang/mock/gomock" +// "github.com/stretchr/testify/suite" +// ) +// +// type handlerTestSuite struct { +// common.ControllerTestSuite +// syncerFactory *internal.MockSyncerFactory +// syncer *dnsaliasapi.MockSyncer +// } +// +// const ( +// appName1 = "appName1" +// env1 = "env1" +// component1 = "component1" +// alias1 = "alias1" +// ) +// +// func (s *handlerTestSuite) SetupTest() { +// s.ControllerTestSuite.SetupTest() +// s.syncerFactory = internal.NewMockSyncerFactory(s.MockCtrl) +// s.syncer = dnsaliasapi.NewMockSyncer(s.MockCtrl) +// } +// +// func TestHandlerSuite(t *testing.T) { +// suite.Run(t, new(handlerTestSuite)) +// } +// +// func (s *handlerTestSuite) TearDownTest() { +// s.MockCtrl.Finish() +// } +// +// func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { +// dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} +// handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, +// func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) +// +// s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any()).Times(0) +// s.syncer.EXPECT().OnSync().Times(0) +// +// err := handler.Sync("", alias1, s.EventRecorder) +// s.Require().NoError(err) +// } +// +// func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { +// dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} +// s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1, 8080), "create existing RadixDNSAlias") +// handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, +// func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) +// expectedError := fmt.Errorf("some error") +// s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any()).Return(s.syncer).Times(1) +// s.syncer.EXPECT().OnSync().Return(expectedError).Times(1) +// +// actualError := handler.Sync("", alias1, s.EventRecorder) +// s.Equal(expectedError, actualError) +// } +// +// func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsNoError() { +// dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} +// s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1, 8080), "create existing RadixDNSAlias") +// handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, +// func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) +// s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any()).Return(s.syncer).Times(1) +// s.syncer.EXPECT().OnSync().Return(nil).Times(1) +// +// err := handler.Sync("", alias1, s.EventRecorder) +// s.Require().Nil(err) +// } From 712a28c703bd3d220c0be2d010cf803e052e1c3e Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 29 Nov 2023 15:41:29 +0100 Subject: [PATCH 069/121] Merged --- pipeline-runner/steps/build_test.go | 2 ++ pkg/apis/ingress/ingress.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pipeline-runner/steps/build_test.go b/pipeline-runner/steps/build_test.go index 2119943d1..228ff2a49 100644 --- a/pipeline-runner/steps/build_test.go +++ b/pipeline-runner/steps/build_test.go @@ -13,6 +13,7 @@ import ( internaltest "github.com/equinor/radix-operator/pipeline-runner/internal/test" internalwait "github.com/equinor/radix-operator/pipeline-runner/internal/wait" "github.com/equinor/radix-operator/pipeline-runner/model" + pipelineDefaults "github.com/equinor/radix-operator/pipeline-runner/model/defaults" "github.com/equinor/radix-operator/pipeline-runner/steps" application "github.com/equinor/radix-operator/pkg/apis/applicationconfig" "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" @@ -30,6 +31,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubefake "k8s.io/client-go/kubernetes/fake" + "sigs.k8s.io/yaml" ) func Test_RunBuildTestSuite(t *testing.T) { diff --git a/pkg/apis/ingress/ingress.go b/pkg/apis/ingress/ingress.go index 5e8a45fdc..8105988a4 100644 --- a/pkg/apis/ingress/ingress.go +++ b/pkg/apis/ingress/ingress.go @@ -24,7 +24,7 @@ const ( // IngressConfiguration Holds all ingress annotation configurations type IngressConfiguration struct { - AnnotationConfigurations []AnnotationConfiguration `yaml:"configuration"` + AnnotationConfigurations []AnnotationConfiguration `json:"configuration" yaml:"configuration"` } // AnnotationConfiguration Holds annotations for a single configuration From 28f88545d9bf41374079a11124a1a3b0ff618341 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 29 Nov 2023 15:54:21 +0100 Subject: [PATCH 070/121] Restored tests --- pkg/apis/dnsalias/syncer_test.go | 315 +++++++++++---------- pkg/apis/kube/kube.go | 1 - pkg/apis/utils/environment_builder_test.go | 7 +- radix-operator/dnsalias/handler_test.go | 155 +++++----- 4 files changed, 240 insertions(+), 238 deletions(-) diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index ff76fbf16..ccbaa8837 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -2,6 +2,7 @@ package dnsalias_test import ( "context" + "fmt" "testing" dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" @@ -9,13 +10,17 @@ import ( "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" + "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + commonTest "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/client-go/kubernetes" kubefake "k8s.io/client-go/kubernetes/fake" secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake" @@ -75,181 +80,179 @@ type scenario struct { expectedIngress map[string]testIngress } -/* - func (s *syncerTestSuite) Test_syncer_OnSync() { - const ( - appName1 = "app1" - appName2 = "app2" - envName1 = "env1" - envName2 = "env2" - component1 = "component1" - component2 = "component2" - alias1 = "alias1" - alias2 = "alias2" - port8080 = 8080 - port9090 = 9090 - dnsZone1 = "dev.radix.equinor.com" - ) - rd1 := buildRadixDeployment(appName1, component1, component2, envName1, envName2, port8080, port9090) - rd2 := buildRadixDeployment(appName2, component1, component2, envName1, envName2, port8080, port9090) - scenarios := []scenario{ - { - name: "created an ingress", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - }, +func (s *syncerTestSuite) Test_syncer_OnSync() { + const ( + appName1 = "app1" + appName2 = "app2" + envName1 = "env1" + envName2 = "env2" + component1 = "component1" + component2 = "component2" + alias1 = "alias1" + alias2 = "alias2" + port8080 = 8080 + port9090 = 9090 + dnsZone1 = "dev.radix.equinor.com" + ) + rd1 := buildRadixDeployment(appName1, component1, component2, envName1, envName2, port8080, port9090) + rd2 := buildRadixDeployment(appName2, component1, component2, envName1, envName2, port8080, port9090) + scenarios := []scenario{ + { + name: "created an ingress", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, }, - { - name: "created additional ingress for another component", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component2.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: port8080}, - }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - "component2.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: port8080}, - }, + }, + { + name: "created additional ingress for another component", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component2.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: port8080}, }, - { - name: "changed port changes port in existing ingress", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port9090}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port9090}, - }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + "component2.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: port8080}, }, - { - name: "created additional ingress on another alias for the same component", - dnsAlias: testDNSAlias{Alias: alias2, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, - }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - "component1.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, - }, + }, + { + name: "changed port changes port in existing ingress", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port9090}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, }, - { - name: "manually changed appName repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName2, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, - }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port9090}, }, - { - name: "manually changed envName repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName2, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, - }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - }, + }, + { + name: "created additional ingress on another alias for the same component", + dnsAlias: testDNSAlias{Alias: alias2, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, }, - { - name: "manually changed component repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, - }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + "component1.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, }, - { - name: "manually changed port repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port9090}, - }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - }, + }, + { + name: "manually changed appName repaired", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName2, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, }, - { - name: "manually changed host repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: "/manually/edited/host", component: component1, port: port8080}, - }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, }, - } - for _, ts := range scenarios { - s.T().Run(ts.name, func(t *testing.T) { - s.SetupTest() - radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Alias, UID: uuid.NewUUID()}, - Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component, Port: ts.dnsAlias.Port}} - s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Alias, radixDNSAlias.Spec), "create existing alias") - // cfg := &dnsalias2.DNSConfig{DNSZone: ts.dnsZone} + }, + { + name: "manually changed envName repaired", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName2, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + }, + }, + { + name: "manually changed component repaired", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + }, + }, + { + name: "manually changed port repaired", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port9090}, + }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + }, + }, + { + name: "manually changed host repaired", + dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsZone: dnsZone1, + existingIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: "/manually/edited/host", component: component1, port: port8080}, + }, + expectedIngress: map[string]testIngress{ + "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + }, + }, + } + for _, ts := range scenarios { + s.T().Run(ts.name, func(t *testing.T) { + s.SetupTest() + radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Alias, UID: uuid.NewUUID()}, + Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component, Port: ts.dnsAlias.Port}} + s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Alias, radixDNSAlias.Spec), "create existing alias") + // cfg := &dnsalias2.DNSConfig{DNSZone: ts.dnsZone} - s.registeringRadixDeployments(rd1, rd2) - // TODO fix registration below - err := registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1) - s.Require().NoError(err, "create existing ingresses") + s.registeringRadixDeployments(rd1, rd2) + err := registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1) + s.Require().NoError(err, "create existing ingresses") - syncer := s.createSyncer(radixDNSAlias) - err = syncer.OnSync() - commonTest.AssertError(s.T(), ts.expectedError, err) + syncer := s.createSyncer(radixDNSAlias) + err = syncer.OnSync() + commonTest.AssertError(s.T(), ts.expectedError, err) - ingresses, err := s.kubeClient.NetworkingV1().Ingresses("").List(context.Background(), metav1.ListOptions{}) - s.Require().NoError(err) + ingresses, err := s.kubeClient.NetworkingV1().Ingresses("").List(context.Background(), metav1.ListOptions{}) + s.Require().NoError(err) - // assert ingresses - if ts.expectedIngress == nil { - s.Require().Len(ingresses.Items, 0, "not expected ingresses") - return - } + // assert ingresses + if ts.expectedIngress == nil { + s.Require().Len(ingresses.Items, 0, "not expected ingresses") + return + } - s.Require().Len(ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") - if len(ingresses.Items) == len(ts.expectedIngress) { - for _, ing := range ingresses.Items { - if expectedIngress, ok := ts.expectedIngress[ing.Name]; ok { - s.Require().Len(ing.Spec.Rules, 1, "rules count") - s.Assert().Equal(expectedIngress.appName, ing.GetLabels()[kube.RadixAppLabel], "app name") - s.Assert().Equal(utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ing.GetNamespace(), "namespace") - s.Assert().Equal(expectedIngress.component, ing.GetLabels()[kube.RadixComponentLabel], "component name") - s.Assert().Equal(expectedIngress.host, ing.Spec.Rules[0].Host, "rule host") - s.Assert().Equal("/", ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") - s.Assert().Equal(expectedIngress.component, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") - s.Assert().Equal(expectedIngress.port, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") - if len(ing.ObjectMeta.OwnerReferences) > 0 { - ownerRef := ing.ObjectMeta.OwnerReferences[0] - s.Assert().Equal(radix.APIVersion, ownerRef.APIVersion, "ownerRef.APIVersion") - s.Assert().Equal(radix.KindRadixDNSAlias, ownerRef.Kind, "ownerRef.Kind") - s.Assert().Equal(radixDNSAlias.GetName(), ownerRef.Name, "ownerRef.Name") - s.Assert().Equal(radixDNSAlias.GetUID(), ownerRef.UID, "ownerRef.UID") - s.Assert().True(ownerRef.Controller != nil && *ownerRef.Controller, "ownerRef.Controller") - } - continue + s.Require().Len(ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") + if len(ingresses.Items) == len(ts.expectedIngress) { + for _, ing := range ingresses.Items { + if expectedIngress, ok := ts.expectedIngress[ing.Name]; ok { + s.Require().Len(ing.Spec.Rules, 1, "rules count") + s.Assert().Equal(expectedIngress.appName, ing.GetLabels()[kube.RadixAppLabel], "app name") + s.Assert().Equal(utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ing.GetNamespace(), "namespace") + s.Assert().Equal(expectedIngress.component, ing.GetLabels()[kube.RadixComponentLabel], "component name") + s.Assert().Equal(expectedIngress.host, ing.Spec.Rules[0].Host, "rule host") + s.Assert().Equal("/", ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") + s.Assert().Equal(expectedIngress.component, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") + s.Assert().Equal(expectedIngress.port, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") + if len(ing.ObjectMeta.OwnerReferences) > 0 { + ownerRef := ing.ObjectMeta.OwnerReferences[0] + s.Assert().Equal(radix.APIVersion, ownerRef.APIVersion, "ownerRef.APIVersion") + s.Assert().Equal(radix.KindRadixDNSAlias, ownerRef.Kind, "ownerRef.Kind") + s.Assert().Equal(radixDNSAlias.GetName(), ownerRef.Name, "ownerRef.Name") + s.Assert().Equal(radixDNSAlias.GetUID(), ownerRef.UID, "ownerRef.UID") + s.Assert().True(ownerRef.Controller != nil && *ownerRef.Controller, "ownerRef.Controller") } - assert.Fail(t, fmt.Sprintf("found not expected ingress %s for: appName %s, host %s, service %s, port %d", - ing.GetName(), ing.GetLabels()[kube.RadixAppLabel], ing.Spec.Rules[0].Host, ing.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, - ing.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port.Number)) + continue } + assert.Fail(t, fmt.Sprintf("found not expected ingress %s for: appName %s, host %s, service %s, port %d", + ing.GetName(), ing.GetLabels()[kube.RadixAppLabel], ing.Spec.Rules[0].Host, ing.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, + ing.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port.Number)) } + } - }) - } + }) } -*/ +} + func buildRadixDeployment(appName1, component1, component2, envName1, envName2 string, port8080, port9090 int32) *radixv1.RadixDeployment { return utils.NewDeploymentBuilder(). WithRadixApplication(utils.ARadixApplication()). diff --git a/pkg/apis/kube/kube.go b/pkg/apis/kube/kube.go index 9ba59ae3d..b052d9f95 100644 --- a/pkg/apis/kube/kube.go +++ b/pkg/apis/kube/kube.go @@ -28,7 +28,6 @@ const ( RadixDeploymentPromotedFromEnvironmentAnnotation = "radix.equinor.com/radix-deployment-promoted-from-environment" ManagedByRadixDNSAliasIngressAnnotation = "radix.equinor.com/managed-by-radix-dns-alias" RadixEnvironmentFinalizer = "radix.equinor.com/environment-finalizer" - RadixDNSAliasFinalizer = "radix.equinor.com/dns-alias-finalizer" // See https://github.com/equinor/radix-velero-plugin/blob/master/velero-plugins/deployment/restore.go RestoredStatusAnnotation = "equinor.com/velero-restored-status" diff --git a/pkg/apis/utils/environment_builder_test.go b/pkg/apis/utils/environment_builder_test.go index 7b135f1f9..b25fad461 100644 --- a/pkg/apis/utils/environment_builder_test.go +++ b/pkg/apis/utils/environment_builder_test.go @@ -4,6 +4,7 @@ import ( "testing" "time" + "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix" "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/stretchr/testify/assert" @@ -11,7 +12,6 @@ import ( "k8s.io/apimachinery/pkg/types" ) -/* func Test_RadixEnvironment_Defaults(t *testing.T) { re := NewEnvironmentBuilder().BuildRE() @@ -28,7 +28,8 @@ func Test_RadixEnvironment_Defaults(t *testing.T) { assert.Equal(t, minTime, re.ObjectMeta.CreationTimestamp) assert.Equal(t, (*int64)(nil), re.ObjectMeta.DeletionGracePeriodSeconds) assert.Equal(t, nilTime, re.ObjectMeta.DeletionTimestamp) - assert.Len(t, re.ObjectMeta.Finalizers, 0) + assert.Len(t, re.ObjectMeta.Finalizers, 1) + assert.Equal(t, re.ObjectMeta.Finalizers[0], kube.RadixEnvironmentFinalizer) assert.Equal(t, "", re.ObjectMeta.GenerateName) assert.Equal(t, int64(0), re.ObjectMeta.Generation) assert.Len(t, re.ObjectMeta.Labels, 0) @@ -47,7 +48,7 @@ func Test_RadixEnvironment_Defaults(t *testing.T) { assert.True(t, re.Status.Orphaned) assert.Equal(t, minTime, re.Status.Reconciled) } -*/ + // Test ObjectMeta manipulation func Test_WithAppLabel(t *testing.T) { diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index cdc2b2a28..cc90878fa 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -1,80 +1,79 @@ package dnsalias_test -// -// import ( -// "fmt" -// "testing" -// -// dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" -// dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" -// commonTest "github.com/equinor/radix-operator/pkg/apis/test" -// "github.com/equinor/radix-operator/radix-operator/common" -// "github.com/equinor/radix-operator/radix-operator/dnsalias" -// "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" -// "github.com/golang/mock/gomock" -// "github.com/stretchr/testify/suite" -// ) -// -// type handlerTestSuite struct { -// common.ControllerTestSuite -// syncerFactory *internal.MockSyncerFactory -// syncer *dnsaliasapi.MockSyncer -// } -// -// const ( -// appName1 = "appName1" -// env1 = "env1" -// component1 = "component1" -// alias1 = "alias1" -// ) -// -// func (s *handlerTestSuite) SetupTest() { -// s.ControllerTestSuite.SetupTest() -// s.syncerFactory = internal.NewMockSyncerFactory(s.MockCtrl) -// s.syncer = dnsaliasapi.NewMockSyncer(s.MockCtrl) -// } -// -// func TestHandlerSuite(t *testing.T) { -// suite.Run(t, new(handlerTestSuite)) -// } -// -// func (s *handlerTestSuite) TearDownTest() { -// s.MockCtrl.Finish() -// } -// -// func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { -// dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} -// handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, -// func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) -// -// s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any()).Times(0) -// s.syncer.EXPECT().OnSync().Times(0) -// -// err := handler.Sync("", alias1, s.EventRecorder) -// s.Require().NoError(err) -// } -// -// func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { -// dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} -// s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1, 8080), "create existing RadixDNSAlias") -// handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, -// func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) -// expectedError := fmt.Errorf("some error") -// s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any()).Return(s.syncer).Times(1) -// s.syncer.EXPECT().OnSync().Return(expectedError).Times(1) -// -// actualError := handler.Sync("", alias1, s.EventRecorder) -// s.Equal(expectedError, actualError) -// } -// -// func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsNoError() { -// dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} -// s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1, 8080), "create existing RadixDNSAlias") -// handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, -// func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) -// s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any()).Return(s.syncer).Times(1) -// s.syncer.EXPECT().OnSync().Return(nil).Times(1) -// -// err := handler.Sync("", alias1, s.EventRecorder) -// s.Require().Nil(err) -// } +import ( + "fmt" + "testing" + + dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" + commonTest "github.com/equinor/radix-operator/pkg/apis/test" + "github.com/equinor/radix-operator/radix-operator/common" + "github.com/equinor/radix-operator/radix-operator/dnsalias" + "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/suite" +) + +type handlerTestSuite struct { + common.ControllerTestSuite + syncerFactory *internal.MockSyncerFactory + syncer *dnsaliasapi.MockSyncer +} + +const ( + appName1 = "appName1" + env1 = "env1" + component1 = "component1" + alias1 = "alias1" +) + +func (s *handlerTestSuite) SetupTest() { + s.ControllerTestSuite.SetupTest() + s.syncerFactory = internal.NewMockSyncerFactory(s.MockCtrl) + s.syncer = dnsaliasapi.NewMockSyncer(s.MockCtrl) +} + +func TestHandlerSuite(t *testing.T) { + suite.Run(t, new(handlerTestSuite)) +} + +func (s *handlerTestSuite) TearDownTest() { + s.MockCtrl.Finish() +} + +func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { + dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} + handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, + func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) + + s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(0) + s.syncer.EXPECT().OnSync().Times(0) + + err := handler.Sync("", alias1, s.EventRecorder) + s.Require().NoError(err) +} + +func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { + dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} + s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1, 8080), "create existing RadixDNSAlias") + handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, + func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) + expectedError := fmt.Errorf("some error") + s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(s.syncer).Times(1) + s.syncer.EXPECT().OnSync().Return(expectedError).Times(1) + + actualError := handler.Sync("", alias1, s.EventRecorder) + s.Equal(expectedError, actualError) +} + +func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsNoError() { + dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} + s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1, 8080), "create existing RadixDNSAlias") + handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, + func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) + s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(s.syncer).Times(1) + s.syncer.EXPECT().OnSync().Return(nil).Times(1) + + err := handler.Sync("", alias1, s.EventRecorder) + s.Require().Nil(err) +} From cbdcd6581d0fb51386cd5a467b3b1f33f7c513d7 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Wed, 29 Nov 2023 16:51:15 +0100 Subject: [PATCH 071/121] Adding garbage collect for DNS alias --- pkg/apis/deployment/deployment.go | 4 ++ pkg/apis/deployment/ingress.go | 69 ++++++++++++++++++++++++++----- pkg/apis/dnsalias/syncer.go | 11 ++++- pkg/apis/dnsalias/syncer_test.go | 62 +++++++++++++-------------- 4 files changed, 104 insertions(+), 42 deletions(-) diff --git a/pkg/apis/deployment/deployment.go b/pkg/apis/deployment/deployment.go index 600ec767c..8fb20f302 100644 --- a/pkg/apis/deployment/deployment.go +++ b/pkg/apis/deployment/deployment.go @@ -522,6 +522,10 @@ func getLabelSelectorForComponent(component v1.RadixCommonDeployComponent) strin return fmt.Sprintf("%s=%s", kube.RadixComponentLabel, component.GetName()) } +func getLabelSelectorForAlias(component v1.RadixCommonDeployComponent) string { + return fmt.Sprintf("%s=%s, %s=%s", kube.RadixComponentLabel, component.GetName(), kube.RadixAliasLabel, "true") +} + func getLabelSelectorForExternalAlias(component v1.RadixCommonDeployComponent) string { return fmt.Sprintf("%s=%s, %s=%s", kube.RadixComponentLabel, component.GetName(), kube.RadixExternalAliasLabel, "true") } diff --git a/pkg/apis/deployment/ingress.go b/pkg/apis/deployment/ingress.go index 0bd6b29a0..e3c70a481 100644 --- a/pkg/apis/deployment/ingress.go +++ b/pkg/apis/deployment/ingress.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/equinor/radix-operator/pkg/apis/defaults" + dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -54,14 +55,14 @@ func (deploy *Deployment) createOrUpdateIngress(deployComponent radixv1.RadixCom } // Only the active cluster should have the DNS external alias, not to cause conflicts between clusters - dnsExternalAlias := deployComponent.GetDNSExternalAlias() - if len(dnsExternalAlias) > 0 && isActiveCluster(clustername) { + dnsExternalAliases := deployComponent.GetDNSExternalAlias() + if len(dnsExternalAliases) > 0 && isActiveCluster(clustername) { err = deploy.garbageCollectIngressNoLongerInSpecForComponentAndExternalAlias(deployComponent) if err != nil { return err } - for _, externalAlias := range dnsExternalAlias { + for _, externalAlias := range dnsExternalAliases { externalAliasIngress, err := deploy.getExternalAliasIngressConfig(deploy.radixDeployment.Spec.AppName, ownerReference, externalAlias, deployComponent, namespace, publicPortNumber) if err != nil { @@ -80,6 +81,33 @@ func (deploy *Deployment) createOrUpdateIngress(deployComponent radixv1.RadixCom } } + // Only the active cluster should have the DNS alias, not to cause conflicts between clusters + dnsAliases := deployComponent.GetDNSAlias() + if len(dnsAliases) > 0 && isActiveCluster(clustername) { + err = deploy.garbageCollectIngressNoLongerInSpecForComponentAndAlias(deployComponent) + if err != nil { + return err + } + + for _, dnsAlias := range dnsAliases { + aliasIngress, err := deploy.getAliasIngressConfig(deploy.radixDeployment.Spec.AppName, + ownerReference, dnsAlias, deployComponent, namespace, publicPortNumber) + if err != nil { + return err + } + + err = deploy.kubeutil.ApplyIngress(namespace, aliasIngress) + if err != nil { + return err + } + } + } else { + err = deploy.garbageCollectAllAliasIngressesForComponent(deployComponent) + if err != nil { + return err + } + } + if isActiveCluster(clustername) { // Create fixed active cluster ingress for this component activeClusterAliasIngress, err := deploy.getActiveClusterAliasIngressConfig(deploy.radixDeployment.Spec.AppName, ownerReference, deployComponent, namespace, publicPortNumber) @@ -169,15 +197,22 @@ func (deploy *Deployment) garbageCollectIngressByLabelSelectorForComponent(label } func (deploy *Deployment) garbageCollectAllExternalAliasIngressesForComponent(component radixv1.RadixCommonDeployComponent) error { - return deploy.garbageCollectIngressForComponentAndExternalAlias(component, true) + return deploy.garbageCollectIngressForComponentAndExternalAlias(getLabelSelectorForExternalAlias(component), component.GetDNSExternalAlias(), true) } func (deploy *Deployment) garbageCollectIngressNoLongerInSpecForComponentAndExternalAlias(component radixv1.RadixCommonDeployComponent) error { - return deploy.garbageCollectIngressForComponentAndExternalAlias(component, false) + return deploy.garbageCollectIngressForComponentAndExternalAlias(getLabelSelectorForExternalAlias(component), component.GetDNSExternalAlias(), false) +} + +func (deploy *Deployment) garbageCollectAllAliasIngressesForComponent(component radixv1.RadixCommonDeployComponent) error { + return deploy.garbageCollectIngressForComponentAndExternalAlias(getLabelSelectorForAlias(component), component.GetDNSAlias(), true) +} + +func (deploy *Deployment) garbageCollectIngressNoLongerInSpecForComponentAndAlias(component radixv1.RadixCommonDeployComponent) error { + return deploy.garbageCollectIngressForComponentAndExternalAlias(getLabelSelectorForAlias(component), component.GetDNSAlias(), false) } -func (deploy *Deployment) garbageCollectIngressForComponentAndExternalAlias(component radixv1.RadixCommonDeployComponent, all bool) error { - labelSelector := getLabelSelectorForExternalAlias(component) +func (deploy *Deployment) garbageCollectIngressForComponentAndExternalAlias(labelSelector string, aliases []string, all bool) error { ingresses, err := deploy.kubeutil.ListIngressesWithSelector(deploy.radixDeployment.GetNamespace(), labelSelector) if err != nil { return err @@ -187,10 +222,10 @@ func (deploy *Deployment) garbageCollectIngressForComponentAndExternalAlias(comp garbageCollectIngress := true if !all { - externalAliasForIngress := ing.Name - for _, externalAlias := range component.GetDNSExternalAlias() { - if externalAlias == externalAliasForIngress { + for _, alias := range aliases { + if alias == ing.Name { garbageCollectIngress = false + break } } } @@ -276,6 +311,20 @@ func (deploy *Deployment) getExternalAliasIngressConfig( return ingress.GetIngressConfig(namespace, appName, component, externalAlias, ingressSpec, deploy.ingressAnnotationProviders, ingress.DNSExternalAlias, ownerReference) } +func (deploy *Deployment) getAliasIngressConfig( + appName string, + ownerReference []metav1.OwnerReference, + alias string, + component radixv1.RadixCommonDeployComponent, + namespace string, + publicPortNumber int32, +) (*networkingv1.Ingress, error) { + // TODO + host := dnsaliasapi.GetDNSAliasHost(alias, cfg.DNSZone) + ingressSpec := ingress.GetIngressSpec(alias, component.GetName(), alias, publicPortNumber) + return ingress.GetIngressConfig(namespace, appName, component, alias, ingressSpec, deploy.ingressAnnotationProviders, ingress.DNSExternalAlias, ownerReference) +} + func getActiveClusterHostName(componentName, namespace string) string { dnsZone := os.Getenv(defaults.OperatorDNSZoneEnvironmentVariable) if dnsZone == "" { diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 944bd8146..291ce110b 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -84,11 +84,18 @@ func (s *syncer) syncAlias() error { if err != nil { return err } - oauth, err := s.oauth2DefaultConfig.MergeWith(radixDeployComponent.GetAuthentication().OAuth2) + return s.createOrUpdateOAuthProxyIngressForComponentIngress(radixDeployComponent.GetAuthentication(), namespace, aliasSpec, radixDeployComponent, ing) +} + +func (s *syncer) createOrUpdateOAuthProxyIngressForComponentIngress(componentAuthentication *radixv1.Authentication, namespace string, aliasSpec radixv1.RadixDNSAliasSpec, radixDeployComponent radixv1.RadixCommonDeployComponent, ing *networkingv1.Ingress) error { + if componentAuthentication == nil || componentAuthentication.OAuth2 == nil { + return nil + } + oauth, err := s.oauth2DefaultConfig.MergeWith(componentAuthentication.OAuth2) if err != nil { return err } - radixDeployComponent.GetAuthentication().OAuth2 = oauth + componentAuthentication.OAuth2 = oauth return ingress.CreateOrUpdateOAuthProxyIngressForComponentIngress(s.kubeUtil, namespace, aliasSpec.AppName, radixDeployComponent, ing, s.ingressAnnotationProviders) } diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index ccbaa8837..f44fefef0 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -94,8 +94,10 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { port9090 = 9090 dnsZone1 = "dev.radix.equinor.com" ) - rd1 := buildRadixDeployment(appName1, component1, component2, envName1, envName2, port8080, port9090) - rd2 := buildRadixDeployment(appName2, component1, component2, envName1, envName2, port8080, port9090) + rd1 := buildRadixDeployment(appName1, component1, component2, envName1, port8080, port9090) + rd2 := buildRadixDeployment(appName1, component1, component2, envName2, port8080, port9090) + rd3 := buildRadixDeployment(appName1, component1, component2, envName1, port8080, port9090) + rd4 := buildRadixDeployment(appName2, component1, component2, envName2, port8080, port9090) scenarios := []scenario{ { name: "created an ingress", @@ -140,28 +142,28 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { "component1.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, }, }, - { - name: "manually changed appName repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName2, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, - }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - }, - }, - { - name: "manually changed envName repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName2, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, - }, - expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - }, - }, + // { + // name: "manually changed appName repaired?", + // dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + // dnsZone: dnsZone1, + // existingIngress: map[string]testIngress{ + // "component1.alias1.custom-alias": {appName: appName2, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, + // }, + // expectedIngress: map[string]testIngress{ + // "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + // }, + // }, + // { + // name: "manually changed envName repaired", + // dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + // dnsZone: dnsZone1, + // existingIngress: map[string]testIngress{ + // "component1.alias1.custom-alias": {appName: appName1, envName: envName2, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, + // }, + // expectedIngress: map[string]testIngress{ + // "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + // }, + // }, { name: "manually changed component repaired", dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, @@ -204,7 +206,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Alias, radixDNSAlias.Spec), "create existing alias") // cfg := &dnsalias2.DNSConfig{DNSZone: ts.dnsZone} - s.registeringRadixDeployments(rd1, rd2) + s.registeringRadixDeployments(rd1, rd2, rd3, rd4) err := registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1) s.Require().NoError(err, "create existing ingresses") @@ -253,12 +255,11 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { } } -func buildRadixDeployment(appName1, component1, component2, envName1, envName2 string, port8080, port9090 int32) *radixv1.RadixDeployment { +func buildRadixDeployment(appName, component1, component2, envName string, port8080, port9090 int32) *radixv1.RadixDeployment { return utils.NewDeploymentBuilder(). WithRadixApplication(utils.ARadixApplication()). - WithAppName(appName1). - WithEnvironment(envName1). - WithEnvironment(envName2). + WithAppName(appName). + WithEnvironment(envName). WithComponents(utils.NewDeployComponentBuilder(). WithImage("radixdev.azurecr.io/some-image1:image.tag"). WithName(component1). @@ -273,7 +274,8 @@ func buildRadixDeployment(appName1, component1, component2, envName1, envName2 s func (s *syncerTestSuite) registeringRadixDeployments(radixDeployments ...*radixv1.RadixDeployment) { for _, rd := range radixDeployments { - _, err := s.radixClient.RadixV1().RadixDeployments(utils.GetEnvironmentNamespace(rd.Spec.AppName, rd.Spec.Environment)). + namespace := utils.GetEnvironmentNamespace(rd.Spec.AppName, rd.Spec.Environment) + _, err := s.radixClient.RadixV1().RadixDeployments(namespace). Create(context.Background(), rd, metav1.CreateOptions{}) s.Require().NoError(err) } From 7e85cf7da7043c650eb0be6c13a35cbee890ef37 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 30 Nov 2023 10:40:27 +0100 Subject: [PATCH 072/121] Removed unnecessary ingress garbage collect DNS alias ingresses logic --- pkg/apis/deployment/deployment.go | 4 -- pkg/apis/deployment/ingress.go | 69 +++++-------------------------- 2 files changed, 10 insertions(+), 63 deletions(-) diff --git a/pkg/apis/deployment/deployment.go b/pkg/apis/deployment/deployment.go index 8fb20f302..600ec767c 100644 --- a/pkg/apis/deployment/deployment.go +++ b/pkg/apis/deployment/deployment.go @@ -522,10 +522,6 @@ func getLabelSelectorForComponent(component v1.RadixCommonDeployComponent) strin return fmt.Sprintf("%s=%s", kube.RadixComponentLabel, component.GetName()) } -func getLabelSelectorForAlias(component v1.RadixCommonDeployComponent) string { - return fmt.Sprintf("%s=%s, %s=%s", kube.RadixComponentLabel, component.GetName(), kube.RadixAliasLabel, "true") -} - func getLabelSelectorForExternalAlias(component v1.RadixCommonDeployComponent) string { return fmt.Sprintf("%s=%s, %s=%s", kube.RadixComponentLabel, component.GetName(), kube.RadixExternalAliasLabel, "true") } diff --git a/pkg/apis/deployment/ingress.go b/pkg/apis/deployment/ingress.go index e3c70a481..0bd6b29a0 100644 --- a/pkg/apis/deployment/ingress.go +++ b/pkg/apis/deployment/ingress.go @@ -7,7 +7,6 @@ import ( "strings" "github.com/equinor/radix-operator/pkg/apis/defaults" - dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -55,14 +54,14 @@ func (deploy *Deployment) createOrUpdateIngress(deployComponent radixv1.RadixCom } // Only the active cluster should have the DNS external alias, not to cause conflicts between clusters - dnsExternalAliases := deployComponent.GetDNSExternalAlias() - if len(dnsExternalAliases) > 0 && isActiveCluster(clustername) { + dnsExternalAlias := deployComponent.GetDNSExternalAlias() + if len(dnsExternalAlias) > 0 && isActiveCluster(clustername) { err = deploy.garbageCollectIngressNoLongerInSpecForComponentAndExternalAlias(deployComponent) if err != nil { return err } - for _, externalAlias := range dnsExternalAliases { + for _, externalAlias := range dnsExternalAlias { externalAliasIngress, err := deploy.getExternalAliasIngressConfig(deploy.radixDeployment.Spec.AppName, ownerReference, externalAlias, deployComponent, namespace, publicPortNumber) if err != nil { @@ -81,33 +80,6 @@ func (deploy *Deployment) createOrUpdateIngress(deployComponent radixv1.RadixCom } } - // Only the active cluster should have the DNS alias, not to cause conflicts between clusters - dnsAliases := deployComponent.GetDNSAlias() - if len(dnsAliases) > 0 && isActiveCluster(clustername) { - err = deploy.garbageCollectIngressNoLongerInSpecForComponentAndAlias(deployComponent) - if err != nil { - return err - } - - for _, dnsAlias := range dnsAliases { - aliasIngress, err := deploy.getAliasIngressConfig(deploy.radixDeployment.Spec.AppName, - ownerReference, dnsAlias, deployComponent, namespace, publicPortNumber) - if err != nil { - return err - } - - err = deploy.kubeutil.ApplyIngress(namespace, aliasIngress) - if err != nil { - return err - } - } - } else { - err = deploy.garbageCollectAllAliasIngressesForComponent(deployComponent) - if err != nil { - return err - } - } - if isActiveCluster(clustername) { // Create fixed active cluster ingress for this component activeClusterAliasIngress, err := deploy.getActiveClusterAliasIngressConfig(deploy.radixDeployment.Spec.AppName, ownerReference, deployComponent, namespace, publicPortNumber) @@ -197,22 +169,15 @@ func (deploy *Deployment) garbageCollectIngressByLabelSelectorForComponent(label } func (deploy *Deployment) garbageCollectAllExternalAliasIngressesForComponent(component radixv1.RadixCommonDeployComponent) error { - return deploy.garbageCollectIngressForComponentAndExternalAlias(getLabelSelectorForExternalAlias(component), component.GetDNSExternalAlias(), true) + return deploy.garbageCollectIngressForComponentAndExternalAlias(component, true) } func (deploy *Deployment) garbageCollectIngressNoLongerInSpecForComponentAndExternalAlias(component radixv1.RadixCommonDeployComponent) error { - return deploy.garbageCollectIngressForComponentAndExternalAlias(getLabelSelectorForExternalAlias(component), component.GetDNSExternalAlias(), false) -} - -func (deploy *Deployment) garbageCollectAllAliasIngressesForComponent(component radixv1.RadixCommonDeployComponent) error { - return deploy.garbageCollectIngressForComponentAndExternalAlias(getLabelSelectorForAlias(component), component.GetDNSAlias(), true) -} - -func (deploy *Deployment) garbageCollectIngressNoLongerInSpecForComponentAndAlias(component radixv1.RadixCommonDeployComponent) error { - return deploy.garbageCollectIngressForComponentAndExternalAlias(getLabelSelectorForAlias(component), component.GetDNSAlias(), false) + return deploy.garbageCollectIngressForComponentAndExternalAlias(component, false) } -func (deploy *Deployment) garbageCollectIngressForComponentAndExternalAlias(labelSelector string, aliases []string, all bool) error { +func (deploy *Deployment) garbageCollectIngressForComponentAndExternalAlias(component radixv1.RadixCommonDeployComponent, all bool) error { + labelSelector := getLabelSelectorForExternalAlias(component) ingresses, err := deploy.kubeutil.ListIngressesWithSelector(deploy.radixDeployment.GetNamespace(), labelSelector) if err != nil { return err @@ -222,10 +187,10 @@ func (deploy *Deployment) garbageCollectIngressForComponentAndExternalAlias(labe garbageCollectIngress := true if !all { - for _, alias := range aliases { - if alias == ing.Name { + externalAliasForIngress := ing.Name + for _, externalAlias := range component.GetDNSExternalAlias() { + if externalAlias == externalAliasForIngress { garbageCollectIngress = false - break } } } @@ -311,20 +276,6 @@ func (deploy *Deployment) getExternalAliasIngressConfig( return ingress.GetIngressConfig(namespace, appName, component, externalAlias, ingressSpec, deploy.ingressAnnotationProviders, ingress.DNSExternalAlias, ownerReference) } -func (deploy *Deployment) getAliasIngressConfig( - appName string, - ownerReference []metav1.OwnerReference, - alias string, - component radixv1.RadixCommonDeployComponent, - namespace string, - publicPortNumber int32, -) (*networkingv1.Ingress, error) { - // TODO - host := dnsaliasapi.GetDNSAliasHost(alias, cfg.DNSZone) - ingressSpec := ingress.GetIngressSpec(alias, component.GetName(), alias, publicPortNumber) - return ingress.GetIngressConfig(namespace, appName, component, alias, ingressSpec, deploy.ingressAnnotationProviders, ingress.DNSExternalAlias, ownerReference) -} - func getActiveClusterHostName(componentName, namespace string) string { dnsZone := os.Getenv(defaults.OperatorDNSZoneEnvironmentVariable) if dnsZone == "" { From e30503a4f85ff1fe40542718ae972fd696f3ad10 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 30 Nov 2023 12:59:11 +0100 Subject: [PATCH 073/121] Added update RD informer --- radix-operator/dnsalias/controller.go | 113 ++++++++++++++++---------- 1 file changed, 70 insertions(+), 43 deletions(-) diff --git a/radix-operator/dnsalias/controller.go b/radix-operator/dnsalias/controller.go index 215517335..b565b3ffc 100644 --- a/radix-operator/dnsalias/controller.go +++ b/radix-operator/dnsalias/controller.go @@ -10,11 +10,13 @@ import ( radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" informers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" + radixinformersv1 "github.com/equinor/radix-operator/pkg/client/informers/externalversions/radix/v1" "github.com/equinor/radix-operator/radix-operator/common" "github.com/sirupsen/logrus" networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubeinformers "k8s.io/client-go/informers" + networkinginformersv1 "k8s.io/client-go/informers/networking/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" @@ -62,7 +64,61 @@ func NewController(kubeClient kubernetes.Interface, } logger.Info("Setting up event handlers") + addEventHandlersForRadixDNSAliases(radixDNSAliasInformer, controller) + addEventHandlersForRadixDeployments(radixDeploymentInformer, controller, radixClient) + addEventHandlersForIngresses(ingressInformer, controller) + return controller +} + +func addEventHandlersForIngresses(ingressInformer networkinginformersv1.IngressInformer, controller *common.Controller) { + _, err := ingressInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + UpdateFunc: func(oldObj, newObj interface{}) { + oldIng := oldObj.(metav1.Object) + newIng := newObj.(metav1.Object) + if oldIng.GetResourceVersion() == newIng.GetResourceVersion() { + logger.Debugf("updating Ingress %s has the same resource version. Do nothing.", newIng.GetName()) + return + } + logger.Debugf("updated Ingress %s", newIng.GetName()) + controller.HandleObject(newObj, radix.KindRadixDNSAlias, getOwner) // restore ingress if it does not correspond to RadixDNSAlias + }, + DeleteFunc: func(obj interface{}) { + ing, converted := obj.(*networkingv1.Ingress) + if !converted { + logger.Errorf("Ingress object cast failed during deleted event received.") + return + } + logger.Debugf("deleted Ingress %s", ing.GetName()) + controller.HandleObject(ing, radix.KindRadixDNSAlias, getOwner) // restore ingress if RadixDNSAlias exist + }, + }) + if err != nil { + logger.Errorf("failed to add an event hanflers to the ingressInformer") + } +} + +func addEventHandlersForRadixDeployments(radixDeploymentInformer radixinformersv1.RadixDeploymentInformer, controller *common.Controller, radixClient radixclient.Interface) { + _, err := radixDeploymentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: func(cur interface{}) { + rd := cur.(*radixv1.RadixDeployment) + enqueueRadixDNSAliasesForRadixDeployment(controller, radixClient, rd) + }, + UpdateFunc: func(oldObj, newObj interface{}) { + oldRD := oldObj.(metav1.Object) + newRD := newObj.(metav1.Object) + if oldRD.GetResourceVersion() == newRD.GetResourceVersion() { + return // updating RadixDeployment has the same resource version. Do nothing. + } + rd := newRD.(*radixv1.RadixDeployment) + enqueueRadixDNSAliasesForRadixDeployment(controller, radixClient, rd) + }, + }) + if err != nil { + logger.Errorf("failed to add an event hanflers to the radixDeploymentInformer") + } +} +func addEventHandlersForRadixDNSAliases(radixDNSAliasInformer radixinformersv1.RadixDNSAliasInformer, controller *common.Controller) { _, err := radixDNSAliasInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { alias := cur.(*radixv1.RadixDNSAlias) @@ -105,53 +161,24 @@ func NewController(kubeClient kubernetes.Interface, if err != nil { logger.Errorf("failed to add an event hanflers to the radixDNSAliasInformer") } +} - _, err = radixDeploymentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ - AddFunc: func(cur interface{}) { - rd := cur.(*radixv1.RadixDeployment) - logger.Debugf("Added RadixDeployment %s to application %s in the environment %s. Re-sync relevant RadixDNSAliases", rd.GetName(), rd.Spec.AppName, rd.Spec.Environment) - radixDNSAliases, err := getRadixDNSAliasForAppAndEnvironment(radixClient, rd.Spec.AppName, rd.Spec.Environment) - if err != nil { - logger.Errorf("failed to get list of RadixDNSAliases for the application %s", rd.Spec.AppName) - return - } - for _, radixDNSAlias := range radixDNSAliases { - logger.Debugf("re-sync RadixDNSAlias %s", radixDNSAlias.GetName()) - if _, err := controller.Enqueue(&radixDNSAlias); err != nil { - logger.Errorf("failed to re-sync RadixDNSAlias %s. Error: %v", radixDNSAlias.GetName(), err) - } - } - }, - }) - if err != nil { - logger.Errorf("failed to add an event hanflers to the radixDeploymentInformer") +func enqueueRadixDNSAliasesForRadixDeployment(controller *common.Controller, radixClient radixclient.Interface, rd *radixv1.RadixDeployment) { + if !rd.Status.ActiveTo.IsZero() { + return // skip not active RadixDeployments } - - _, err = ingressInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ - UpdateFunc: func(oldObj, newObj interface{}) { - oldIng := oldObj.(metav1.Object) - newIng := newObj.(metav1.Object) - if oldIng.GetResourceVersion() == newIng.GetResourceVersion() { - logger.Debugf("updating Ingress %s has the same resource version. Do nothing.", newIng.GetName()) - return - } - logger.Debugf("updated Ingress %s", newIng.GetName()) - controller.HandleObject(newObj, radix.KindRadixDNSAlias, getOwner) // restore ingress if it does not correspond to RadixDNSAlias - }, - DeleteFunc: func(obj interface{}) { - ing, converted := obj.(*networkingv1.Ingress) - if !converted { - logger.Errorf("Ingress object cast failed during deleted event received.") - return - } - logger.Debugf("deleted Ingress %s", ing.GetName()) - controller.HandleObject(ing, radix.KindRadixDNSAlias, getOwner) // restore ingress if RadixDNSAlias exist - }, - }) + logger.Debugf("Added or updated an active RadixDeployment %s to application %s in the environment %s. Re-sync relevant RadixDNSAliases", rd.GetName(), rd.Spec.AppName, rd.Spec.Environment) + radixDNSAliases, err := getRadixDNSAliasForAppAndEnvironment(radixClient, rd.Spec.AppName, rd.Spec.Environment) if err != nil { - logger.Errorf("failed to add an event hanflers to the ingressInformer") + logger.Errorf("failed to get list of RadixDNSAliases for the application %s", rd.Spec.AppName) + return + } + for _, radixDNSAlias := range radixDNSAliases { + logger.Debugf("re-sync RadixDNSAlias %s", radixDNSAlias.GetName()) + if _, err := controller.Enqueue(&radixDNSAlias); err != nil { + logger.Errorf("failed to re-sync RadixDNSAlias %s. Error: %v", radixDNSAlias.GetName(), err) + } } - return controller } func getRadixDNSAliasForAppAndEnvironment(radixClient radixclient.Interface, appName string, envName string) ([]radixv1.RadixDNSAlias, error) { From 16bc1a452b1975184b5c96dabaa0dd94e47d5d54 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 30 Nov 2023 14:40:19 +0100 Subject: [PATCH 074/121] Added finalizer to RadixDNSAlias --- charts/radix-operator/values.yaml | 1 + pkg/apis/applicationconfig/dns_alias.go | 2 +- .../deployment/oauthproxyresourcemanager.go | 9 +--- pkg/apis/dnsalias/syncer.go | 42 ++++++++++++++++ pkg/apis/environment/environment.go | 39 ++++++--------- pkg/apis/kube/ingress.go | 50 +++++++++++-------- pkg/apis/kube/kube.go | 1 + pkg/apis/utils/labels/labels.go | 9 ++++ pkg/apis/utils/labels/labels_test.go | 6 +++ radix-operator/dnsalias/controller.go | 3 +- 10 files changed, 108 insertions(+), 54 deletions(-) diff --git a/charts/radix-operator/values.yaml b/charts/radix-operator/values.yaml index a16993cf6..d448ac4c7 100644 --- a/charts/radix-operator/values.yaml +++ b/charts/radix-operator/values.yaml @@ -29,6 +29,7 @@ reservedAppDNSAlias: reservedDNSAlias: - grafana - prometheus + - www appAliasBaseURL: app.dev.radix.equinor.com dnsZone: dev.radix.equinor.com diff --git a/pkg/apis/applicationconfig/dns_alias.go b/pkg/apis/applicationconfig/dns_alias.go index 0ffad3277..c4f353190 100644 --- a/pkg/apis/applicationconfig/dns_alias.go +++ b/pkg/apis/applicationconfig/dns_alias.go @@ -79,7 +79,7 @@ func (app *ApplicationConfig) buildRadixDNSAlias(appName string, dnsAlias radixv Name: dnsAlias.Alias, Labels: labels.Merge(labels.ForApplicationName(appName), labels.ForComponentName(dnsAlias.Component), labels.ForEnvironmentName(dnsAlias.Environment)), OwnerReferences: []metav1.OwnerReference{getOwnerReferenceOfRadixRegistration(app.registration)}, - // Finalizers: []string{kube.RadixDNSAliasFinalizer}, + Finalizers: []string{kube.RadixDNSAliasFinalizer}, }, Spec: radixv1.RadixDNSAliasSpec{ AppName: appName, diff --git a/pkg/apis/deployment/oauthproxyresourcemanager.go b/pkg/apis/deployment/oauthproxyresourcemanager.go index 818c8c2e4..773ed2314 100644 --- a/pkg/apis/deployment/oauthproxyresourcemanager.go +++ b/pkg/apis/deployment/oauthproxyresourcemanager.go @@ -292,14 +292,7 @@ func (o *oauthProxyResourceManager) deleteIngresses(component v1.RadixCommonDepl if err != nil { return err } - - for _, ing := range ingresses { - if err := o.kubeutil.KubeClient().NetworkingV1().Ingresses(ing.Namespace).Delete(context.TODO(), ing.Name, metav1.DeleteOptions{}); err != nil { - return err - } - } - - return nil + return o.kubeutil.DeleteIngresses(true, ingresses...) } func (o *oauthProxyResourceManager) deleteServices(component v1.RadixCommonDeployComponent) error { diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 291ce110b..9fe4c806a 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -4,6 +4,7 @@ import ( "fmt" commonUtils "github.com/equinor/radix-common/utils" + "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" @@ -12,6 +13,7 @@ import ( radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/annotations" + radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" log "github.com/sirupsen/logrus" networkingv1 "k8s.io/api/networking/v1" @@ -58,6 +60,9 @@ func (s *syncer) OnSync() error { if err := s.restoreStatus(); err != nil { return fmt.Errorf("failed to update status on DNS alias %s: %v", s.radixDNSAlias.GetName(), err) } + if handled, err := s.handleDeletedRadixDNSAlias(); handled || err != nil { + return err + } if err := s.syncAlias(); err != nil { return err } @@ -149,6 +154,43 @@ func (s *syncer) createIngress(radixDeployComponent radixv1.RadixCommonDeployCom return CreateRadixDNSAliasIngress(s.kubeClient, aliasSpec.AppName, aliasSpec.Environment, ing) } +func (s *syncer) handleDeletedRadixDNSAlias() (bool, error) { + if s.radixDNSAlias.ObjectMeta.DeletionTimestamp == nil { + return false, nil + } + log.Debugf("handle deleted RadixDNSAlias %s in the application %s", s.radixDNSAlias.Name, s.radixDNSAlias.Spec.AppName) + finalizerIndex := slice.FindIndex(s.radixDNSAlias.ObjectMeta.Finalizers, func(val string) bool { + return val == kube.RadixDNSAliasFinalizer + }) + if finalizerIndex < 0 { + log.Infof("missing finalizer %s in the RadixDNSAlias %s. Exist finalizers: %d. Skip dependency handling", + kube.RadixDNSAliasFinalizer, s.radixDNSAlias.Name, len(s.radixDNSAlias.ObjectMeta.Finalizers)) + return false, nil + } + if err := s.deletedIngressesForRadixDNSAlias(); err != nil { + return true, err + } + updatingAlias := s.radixDNSAlias.DeepCopy() + updatingAlias.ObjectMeta.Finalizers = append(s.radixDNSAlias.ObjectMeta.Finalizers[:finalizerIndex], s.radixDNSAlias.ObjectMeta.Finalizers[finalizerIndex+1:]...) + log.Debugf("removed finalizer %s from the RadixDNSAlias %s for the application %s. Left finalizers: %d", + kube.RadixEnvironmentFinalizer, updatingAlias.Name, updatingAlias.Spec.AppName, len(updatingAlias.ObjectMeta.Finalizers)) + if err := s.kubeUtil.UpdateRadixDNSAlias(updatingAlias); err != nil { + return false, err + } + return true, nil +} + +func (s *syncer) deletedIngressesForRadixDNSAlias() error { + aliasSpec := s.radixDNSAlias.Spec + ingresses, err := s.kubeUtil.GetIngressesWithSelector(utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment), + radixlabels.Merge(radixlabels.ForApplicationName(aliasSpec.AppName), radixlabels.ForComponentName(aliasSpec.Component), radixlabels.ForDNSAlias()).String()) + if err != nil { + return err + } + log.Debugf("delete %d Ingress(es)", len(ingresses)) + return s.kubeUtil.DeleteIngresses(true, ingresses...) +} + func buildIngress(radixDeployComponent radixv1.RadixCommonDeployComponent, radixDNSAlias *radixv1.RadixDNSAlias, dnsConfig *dnsalias.DNSConfig, oauth2Config defaults.OAuth2Config, ingressConfiguration ingress.IngressConfiguration) (*networkingv1.Ingress, error) { log.Debug("build an ingress for the RadixDNSAlias") aliasSpec := radixDNSAlias.Spec diff --git a/pkg/apis/environment/environment.go b/pkg/apis/environment/environment.go index 7f21b7bb3..16b581e83 100644 --- a/pkg/apis/environment/environment.go +++ b/pkg/apis/environment/environment.go @@ -72,40 +72,28 @@ func (env *Environment) OnSync(time metav1.Time) error { // create a globally unique namespace name namespaceName := utils.GetEnvironmentNamespace(re.Spec.AppName, re.Spec.EnvName) - err := env.ApplyNamespace(namespaceName) - if err != nil { + if err := env.ApplyNamespace(namespaceName); err != nil { return fmt.Errorf("failed to apply namespace %s: %v", namespaceName, err) } - - err = env.ApplyAdGroupRoleBinding(namespaceName) - if err != nil { + if err := env.ApplyAdGroupRoleBinding(namespaceName); err != nil { return fmt.Errorf("failed to apply RBAC on namespace %s: %v", namespaceName, err) } - - err = env.applyRadixTektonEnvRoleBinding(namespaceName) - if err != nil { + if err := env.applyRadixTektonEnvRoleBinding(namespaceName); err != nil { return fmt.Errorf("failed to apply RBAC for radix-tekton-env on namespace %s: %v", namespaceName, err) } - - err = env.ApplyRadixPipelineRunnerRoleBinding(namespaceName) - if err != nil { + if err := env.ApplyRadixPipelineRunnerRoleBinding(namespaceName); err != nil { return fmt.Errorf("failed to apply RBAC for radix-pipeline-runner on namespace %s: %v", namespaceName, err) } - - err = env.ApplyLimitRange(namespaceName) - if err != nil { + if err := env.ApplyLimitRange(namespaceName); err != nil { return fmt.Errorf("failed to apply limit range on namespace %s: %v", namespaceName, err) } - - err = env.networkPolicy.UpdateEnvEgressRules(re.Spec.Egress.Rules, re.Spec.Egress.AllowRadix, re.Spec.EnvName) - if err != nil { - errmsg := fmt.Sprintf("failed to add egress rules in %s, environment %s: ", re.Spec.AppName, re.Spec.EnvName) - return fmt.Errorf("%s%v", errmsg, err) + if err := env.networkPolicy.UpdateEnvEgressRules(re.Spec.Egress.Rules, re.Spec.Egress.AllowRadix, re.Spec.EnvName); err != nil { + return fmt.Errorf("failed to add egress rules in %s, environment %s: %v", re.Spec.AppName, re.Spec.EnvName, err) } isOrphaned := !existsInAppConfig(env.appConfig, re.Spec.EnvName) - err = env.updateRadixEnvironmentStatus(re, func(currStatus *v1.RadixEnvironmentStatus) { + err := env.updateRadixEnvironmentStatus(re, func(currStatus *v1.RadixEnvironmentStatus) { currStatus.Orphaned = isOrphaned // time is parameterized for testability currStatus.Reconciled = time @@ -121,6 +109,7 @@ func (env *Environment) handleDeletedRadixEnvironment(re *v1.RadixEnvironment) ( if re.ObjectMeta.DeletionTimestamp == nil { return false, nil } + logrus.Debugf("handle deleted RadixEnvironment %s in the application %s", re.Name, re.Spec.AppName) finalizerIndex := slice.FindIndex(re.ObjectMeta.Finalizers, func(val string) bool { return val == kube.RadixEnvironmentFinalizer }) @@ -135,9 +124,12 @@ func (env *Environment) handleDeletedRadixEnvironment(re *v1.RadixEnvironment) ( } updatingRE := re.DeepCopy() updatingRE.ObjectMeta.Finalizers = append(re.ObjectMeta.Finalizers[:finalizerIndex], re.ObjectMeta.Finalizers[finalizerIndex+1:]...) - logrus.Debugf("removed finalizer %s from the Radix environment %s in the application %s. LEft finalizers: %d", + logrus.Debugf("removed finalizer %s from the Radix environment %s in the application %s. Left finalizers: %d", kube.RadixEnvironmentFinalizer, updatingRE.Name, updatingRE.Spec.AppName, len(updatingRE.ObjectMeta.Finalizers)) - return true, env.kubeutil.UpdateRadixEnvironment(updatingRE) + if err = env.kubeutil.UpdateRadixEnvironment(updatingRE); err != nil { + return false, err + } + return true, nil } func (env *Environment) handleDeletedRadixEnvironmentDependencies(re *v1.RadixEnvironment) error { @@ -145,6 +137,7 @@ func (env *Environment) handleDeletedRadixEnvironmentDependencies(re *v1.RadixEn if err != nil { return err } + logrus.Debugf("delete %d RadixDNSAlias(es)", len(radixDNSAliasList.Items)) return env.kubeutil.DeleteRadixDNSAliases(slice.Reduce(radixDNSAliasList.Items, []*v1.RadixDNSAlias{}, func(acc []*v1.RadixDNSAlias, radixDNSAlias v1.RadixDNSAlias) []*v1.RadixDNSAlias { return append(acc, &radixDNSAlias) })...) @@ -184,7 +177,7 @@ func (env *Environment) ApplyNamespace(name string) error { kube.RadixAppLabel: env.config.Spec.AppName, kube.RadixEnvLabel: env.config.Spec.EnvName, } - nsLabels = labels.Merge(nsLabels, labels.Set(kube.NewEnvNamespacePodSecurityStandardFromEnv().Labels())) + nsLabels = labels.Merge(nsLabels, kube.NewEnvNamespacePodSecurityStandardFromEnv().Labels()) return env.kubeutil.ApplyNamespace(name, nsLabels, env.AsOwnerReference()) } diff --git a/pkg/apis/kube/ingress.go b/pkg/apis/kube/ingress.go index 36c77ae29..d1f3acf06 100644 --- a/pkg/apis/kube/ingress.go +++ b/pkg/apis/kube/ingress.go @@ -85,30 +85,38 @@ func (kubeutil *Kube) ListIngresses(namespace string) ([]*networkingv1.Ingress, // ListIngressesWithSelector lists ingresses func (kubeutil *Kube) ListIngressesWithSelector(namespace string, labelSelectorString string) ([]*networkingv1.Ingress, error) { - var ingresses []*networkingv1.Ingress - - if kubeutil.IngressLister != nil { - selector, err := labels.Parse(labelSelectorString) - if err != nil { - return nil, err - } + if kubeutil.IngressLister == nil { + return kubeutil.GetIngressesWithSelector(namespace, labelSelectorString) + } + selector, err := labels.Parse(labelSelectorString) + if err != nil { + return nil, err + } + ingresses, err := kubeutil.IngressLister.Ingresses(namespace).List(selector) + if err != nil { + return nil, err + } + return ingresses, nil +} - ingresses, err = kubeutil.IngressLister.Ingresses(namespace).List(selector) - if err != nil { - return nil, err - } - } else { - listOptions := metav1.ListOptions{ - LabelSelector: labelSelectorString, - } +func (kubeutil *Kube) GetIngressesWithSelector(namespace string, labelSelectorString string) ([]*networkingv1.Ingress, error) { + list, err := kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).List(context.Background(), metav1.ListOptions{LabelSelector: labelSelectorString}) + if err != nil { + return nil, err + } + return slice.PointersOf(list.Items).([]*networkingv1.Ingress), nil +} - list, err := kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).List(context.Background(), listOptions) +// DeleteIngresses Deletes ingresses +func (kubeutil *Kube) DeleteIngresses(ignoreIsNotFoundError bool, ingresses ...*networkingv1.Ingress) error { + for _, ing := range ingresses { + err := kubeutil.KubeClient().NetworkingV1().Ingresses(ing.Namespace).Delete(context.Background(), ing.Name, metav1.DeleteOptions{}) if err != nil { - return nil, err + if errors.IsNotFound(err) && ignoreIsNotFoundError { + continue + } + return err } - - ingresses = slice.PointersOf(list.Items).([]*networkingv1.Ingress) } - - return ingresses, nil + return nil } diff --git a/pkg/apis/kube/kube.go b/pkg/apis/kube/kube.go index 0e7712f1b..cab03d973 100644 --- a/pkg/apis/kube/kube.go +++ b/pkg/apis/kube/kube.go @@ -28,6 +28,7 @@ const ( RadixDeploymentPromotedFromEnvironmentAnnotation = "radix.equinor.com/radix-deployment-promoted-from-environment" ManagedByRadixDNSAliasIngressAnnotation = "radix.equinor.com/managed-by-radix-dns-alias" RadixEnvironmentFinalizer = "radix.equinor.com/environment-finalizer" + RadixDNSAliasFinalizer = "radix.equinor.com/dnsalias-finalizer" // See https://github.com/equinor/radix-velero-plugin/blob/master/velero-plugins/deployment/restore.go RestoredStatusAnnotation = "equinor.com/velero-restored-status" diff --git a/pkg/apis/utils/labels/labels.go b/pkg/apis/utils/labels/labels.go index bfc815533..da17eb9a3 100644 --- a/pkg/apis/utils/labels/labels.go +++ b/pkg/apis/utils/labels/labels.go @@ -1,6 +1,8 @@ package labels import ( + "strconv" + maputils "github.com/equinor/radix-common/utils/maps" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -233,3 +235,10 @@ func ForAuxComponent(appName string, component v1.RadixCommonDeployComponent) ma kube.RadixAuxiliaryComponentTypeLabel: defaults.OAuthProxyAuxiliaryComponentType, } } + +// ForDNSAlias returns labels for ingress, created for Radix DNS alias +func ForDNSAlias() map[string]string { + return map[string]string{ + kube.RadixAliasLabel: strconv.FormatBool(true), + } +} diff --git a/pkg/apis/utils/labels/labels_test.go b/pkg/apis/utils/labels/labels_test.go index 1237dd4b1..62bb9e099 100644 --- a/pkg/apis/utils/labels/labels_test.go +++ b/pkg/apis/utils/labels/labels_test.go @@ -136,6 +136,12 @@ func Test_ForRadixImageTag(t *testing.T) { assert.Equal(t, expected, actual) } +func Test_ForDNSAlias(t *testing.T) { + actual := ForDNSAlias() + expected := kubelabels.Set{kube.RadixAliasLabel: "true"} + assert.Equal(t, expected, actual) +} + func Test_RequirementRadixBatchNameLabelExists(t *testing.T) { actual := requirementRadixBatchNameLabelExists() expected := kubelabels.Set{kube.RadixBatchNameLabel: "anyname"} diff --git a/radix-operator/dnsalias/controller.go b/radix-operator/dnsalias/controller.go index b565b3ffc..c1d729a1f 100644 --- a/radix-operator/dnsalias/controller.go +++ b/radix-operator/dnsalias/controller.go @@ -195,7 +195,8 @@ func getRadixDNSAliasForAppAndEnvironment(radixClient radixclient.Interface, app func deepEqual(old, new *radixv1.RadixDNSAlias) bool { return reflect.DeepEqual(new.Spec, old.Spec) && reflect.DeepEqual(new.ObjectMeta.Labels, old.ObjectMeta.Labels) && - reflect.DeepEqual(new.ObjectMeta.Annotations, old.ObjectMeta.Annotations) + reflect.DeepEqual(new.ObjectMeta.Annotations, old.ObjectMeta.Annotations) && + reflect.DeepEqual(new.ObjectMeta.Finalizers, old.ObjectMeta.Finalizers) } func getOwner(radixClient radixclient.Interface, _, name string) (interface{}, error) { From b0b32acb7cb6c901cd2cbe3490102169cc765a61 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 30 Nov 2023 16:34:02 +0100 Subject: [PATCH 075/121] Added status to RadixDNSAlias --- .../templates/radixdnsalias.yaml | 28 ++++++++++++--- json-schema/radixdnsalias.json | 22 +++++++++--- pkg/apis/dnsalias/status.go | 23 +++++++----- pkg/apis/dnsalias/syncer.go | 5 +-- pkg/apis/radix/v1/radixdnsaliastypes.go | 36 ++++++++++++++++--- pkg/apis/radix/v1/zz_generated.deepcopy.go | 6 +++- 6 files changed, 95 insertions(+), 25 deletions(-) diff --git a/charts/radix-operator/templates/radixdnsalias.yaml b/charts/radix-operator/templates/radixdnsalias.yaml index 658dad5bd..1ad351297 100644 --- a/charts/radix-operator/templates/radixdnsalias.yaml +++ b/charts/radix-operator/templates/radixdnsalias.yaml @@ -17,7 +17,14 @@ spec: singular: radixdnsalias scope: Cluster versions: - - name: v1 + - additionalPrinterColumns: + - jsonPath: .status.condition + name: Condition + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 schema: openAPIV3Schema: description: RadixDNSAlias is a Custom Resource Definition @@ -35,7 +42,7 @@ spec: metadata: type: object spec: - description: RadixDNSAliasSpec is the spec for an RadixDNSAlias + description: RadixDNSAliasSpec specification of the RadixDNSAlias properties: appName: description: Name of the application the DNS alias used in. @@ -69,11 +76,24 @@ spec: - port type: object status: - description: RadixDNSAliasStatus is the status for an RadixDNSAlias + description: Status of the RadixDNSAlias + properties: + condition: + description: Condition of the RadixDNSAlias creating or updating + type: string + message: + description: A human-readable message indicating details about the + condition. + type: string + reconciled: + description: Reconciled The timestamp when the RadixDNSAlias was reconciled + format: date-time + type: string type: object required: - spec - - status type: object served: true storage: true + subresources: + status: {} diff --git a/json-schema/radixdnsalias.json b/json-schema/radixdnsalias.json index 424bc6641..a84a536e6 100644 --- a/json-schema/radixdnsalias.json +++ b/json-schema/radixdnsalias.json @@ -13,7 +13,7 @@ "type": "object" }, "spec": { - "description": "RadixDNSAliasSpec is the spec for an RadixDNSAlias", + "description": "RadixDNSAliasSpec specification of the RadixDNSAlias", "properties": { "appName": { "description": "Name of the application the DNS alias used in.", @@ -53,13 +53,27 @@ "type": "object" }, "status": { - "description": "RadixDNSAliasStatus is the status for an RadixDNSAlias", + "description": "Status of the RadixDNSAlias", + "properties": { + "condition": { + "description": "Condition of the RadixDNSAlias creating or updating", + "type": "string" + }, + "message": { + "description": "A human-readable message indicating details about the condition.", + "type": "string" + }, + "reconciled": { + "description": "Reconciled The timestamp when the RadixDNSAlias was reconciled", + "format": "date-time", + "type": "string" + } + }, "type": "object" } }, "required": [ - "spec", - "status" + "spec" ], "type": "object" } diff --git a/pkg/apis/dnsalias/status.go b/pkg/apis/dnsalias/status.go index 9eaf4a864..a4ec0a593 100644 --- a/pkg/apis/dnsalias/status.go +++ b/pkg/apis/dnsalias/status.go @@ -29,14 +29,21 @@ func (s *syncer) restoreStatus() error { }) } -func (s *syncer) syncStatus() error { - // syncCompleteTime := metav1.Now() - // err := s.updateStatus(func(currStatus *radixv1.RadixDNSAliasStatus) { - // // currStatus.Reconciled = &syncCompleteTime - // }) - // if err != nil { - // return fmt.Errorf("failed to sync status: %v", err) - // } +func (s *syncer) syncStatus(syncErr error) error { + syncCompleteTime := metav1.Now() + err := s.updateStatus(func(currStatus *radixv1.RadixDNSAliasStatus) { + currStatus.Reconciled = &syncCompleteTime + if syncErr != nil { + currStatus.Condition = radixv1.RadixDNSAliasFailed + currStatus.Message = syncErr.Error() + return + } + currStatus.Condition = radixv1.RadixDNSAliasSucceeded + currStatus.Message = "" + }) + if err != nil { + return fmt.Errorf("failed to sync status: %v", err) + } return nil } diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 9fe4c806a..710d356b5 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -63,10 +63,7 @@ func (s *syncer) OnSync() error { if handled, err := s.handleDeletedRadixDNSAlias(); handled || err != nil { return err } - if err := s.syncAlias(); err != nil { - return err - } - return s.syncStatus() + return s.syncStatus(s.syncAlias()) } diff --git a/pkg/apis/radix/v1/radixdnsaliastypes.go b/pkg/apis/radix/v1/radixdnsaliastypes.go index 7ee504a61..8dba04571 100644 --- a/pkg/apis/radix/v1/radixdnsaliastypes.go +++ b/pkg/apis/radix/v1/radixdnsaliastypes.go @@ -5,14 +5,23 @@ import meta "k8s.io/apimachinery/pkg/apis/meta/v1" // +genclient // +genclient:nonNamespaced // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:printcolumn:name="Condition",type="string",JSONPath=".status.condition" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" // +kubebuilder:resource:path=radixdnsaliases,scope=Cluster,shortName=rda +// +kubebuilder:subresource:status // RadixDNSAlias is a Custom Resource Definition type RadixDNSAlias struct { - meta.TypeMeta `json:",inline" yaml:",inline"` + // meta.TypeMeta of the RadixDNSAlias + // +optional + meta.TypeMeta `json:",inline" yaml:",inline"` + // meta.ObjectMeta Metadata of the RadixDNSAlias meta.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"` - Spec RadixDNSAliasSpec `json:"spec" yaml:"spec"` - Status RadixDNSAliasStatus `json:"status" yaml:"status"` + // RadixDNSAliasSpec specification of the RadixDNSAlias + Spec RadixDNSAliasSpec `json:"spec" yaml:"spec"` + // Status of the RadixDNSAlias + // +optional + Status RadixDNSAliasStatus `json:"status" yaml:"status"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -50,7 +59,26 @@ type RadixDNSAliasSpec struct { Port int32 `json:"port"` } +// RadixDNSAliasCondition Holds the condition of a RadixDNSAlias +type RadixDNSAliasCondition string + +// These are valid conditions of a deployment. +const ( + // RadixDNSAliasSucceeded means the RadixDNSAlias has been successfully created or updated + RadixDNSAliasSucceeded RadixDNSAliasCondition = "Succeeded" + // RadixDNSAliasFailed means the RadixDNSAlias create or update failed + RadixDNSAliasFailed RadixDNSAliasCondition = "Failed" +) + // RadixDNSAliasStatus is the status for an RadixDNSAlias type RadixDNSAliasStatus struct { - // Reconciled *meta.Time `json:"reconciled" yaml:"reconciled"` + // Condition of the RadixDNSAlias creating or updating + // +optional + Condition RadixDNSAliasCondition `json:"condition,omitempty" yaml:"condition,omitempty"` + // A human-readable message indicating details about the condition. + // +optional + Message string `json:"message,omitempty" yaml:"message,omitempty"` + // Reconciled The timestamp when the RadixDNSAlias was reconciled + // +optional + Reconciled *meta.Time `json:"reconciled,omitempty" yaml:"reconciled,omitempty"` } diff --git a/pkg/apis/radix/v1/zz_generated.deepcopy.go b/pkg/apis/radix/v1/zz_generated.deepcopy.go index 78008448b..73dc82155 100644 --- a/pkg/apis/radix/v1/zz_generated.deepcopy.go +++ b/pkg/apis/radix/v1/zz_generated.deepcopy.go @@ -1247,7 +1247,7 @@ func (in *RadixDNSAlias) DeepCopyInto(out *RadixDNSAlias) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec - out.Status = in.Status + in.Status.DeepCopyInto(&out.Status) return } @@ -1321,6 +1321,10 @@ func (in *RadixDNSAliasSpec) DeepCopy() *RadixDNSAliasSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RadixDNSAliasStatus) DeepCopyInto(out *RadixDNSAliasStatus) { *out = *in + if in.Reconciled != nil { + in, out := &in.Reconciled, &out.Reconciled + *out = (*in).DeepCopy() + } return } From 2482043e7aee3d9d5cac7f18de075fffe1287e3f Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 30 Nov 2023 17:32:37 +0100 Subject: [PATCH 076/121] Replaced standard ingress webhook error message to hide application name --- charts/radix-operator/templates/radixdnsalias.yaml | 3 +++ pkg/apis/dnsalias/syncer.go | 8 ++++++++ pkg/apis/radix/v1/radixdnsaliastypes.go | 1 + 3 files changed, 12 insertions(+) diff --git a/charts/radix-operator/templates/radixdnsalias.yaml b/charts/radix-operator/templates/radixdnsalias.yaml index 1ad351297..947181008 100644 --- a/charts/radix-operator/templates/radixdnsalias.yaml +++ b/charts/radix-operator/templates/radixdnsalias.yaml @@ -18,6 +18,9 @@ spec: scope: Cluster versions: - additionalPrinterColumns: + - jsonPath: .spec.appName + name: Application + type: string - jsonPath: .status.condition name: Condition type: string diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 710d356b5..849366228 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -2,6 +2,7 @@ package dnsalias import ( "fmt" + "regexp" commonUtils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-common/utils/slice" @@ -39,8 +40,11 @@ type syncer struct { ingressAnnotationProviders []ingress.AnnotationProvider } +var admissionWebhookErrorExpression *regexp.Regexp + // NewSyncer is the constructor for RadixDNSAlias syncer func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, ingressAnnotationProviders []ingress.AnnotationProvider, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { + admissionWebhookErrorExpression = regexp.MustCompile(`admission webhook "validate.nginx.ingress.kubernetes.io" denied the request: host "(.*?)" and path "(.*?)" is already defined in ingress (.*?)/(.*?)$`) return &syncer{ kubeClient: kubeClient, radixClient: radixClient, @@ -84,6 +88,10 @@ func (s *syncer) syncAlias() error { namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) ing, err := s.createOrUpdateIngress(namespace, radixDeployComponent, ingressName) if err != nil { + if admissionWebhookErrorMatcher := admissionWebhookErrorExpression.FindStringSubmatch(err.Error()); admissionWebhookErrorMatcher != nil && len(admissionWebhookErrorMatcher) == 5 { + log.Error(err) + return fmt.Errorf("DNS alias %s cannot be used, because the host %s with the path %s is already in use", s.radixDNSAlias.GetName(), admissionWebhookErrorMatcher[1], admissionWebhookErrorMatcher[2]) + } return err } return s.createOrUpdateOAuthProxyIngressForComponentIngress(radixDeployComponent.GetAuthentication(), namespace, aliasSpec, radixDeployComponent, ing) diff --git a/pkg/apis/radix/v1/radixdnsaliastypes.go b/pkg/apis/radix/v1/radixdnsaliastypes.go index 8dba04571..117e216bc 100644 --- a/pkg/apis/radix/v1/radixdnsaliastypes.go +++ b/pkg/apis/radix/v1/radixdnsaliastypes.go @@ -5,6 +5,7 @@ import meta "k8s.io/apimachinery/pkg/apis/meta/v1" // +genclient // +genclient:nonNamespaced // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:printcolumn:name="Application",type="string",JSONPath=".spec.appName" // +kubebuilder:printcolumn:name="Condition",type="string",JSONPath=".status.condition" // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" // +kubebuilder:resource:path=radixdnsaliases,scope=Cluster,shortName=rda From 4a0e7aaf96d37aa8506a95680c5580f6cfc56b98 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 1 Dec 2023 10:27:42 +0100 Subject: [PATCH 077/121] Removed yaml attr from radixdnsalias --- .../templates/radixdnsalias.yaml | 5 +-- json-schema/radixdnsalias.json | 5 +-- pkg/apis/radix/v1/radixdnsaliastypes.go | 32 ++++++++----------- 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/charts/radix-operator/templates/radixdnsalias.yaml b/charts/radix-operator/templates/radixdnsalias.yaml index 947181008..4355ac591 100644 --- a/charts/radix-operator/templates/radixdnsalias.yaml +++ b/charts/radix-operator/templates/radixdnsalias.yaml @@ -45,7 +45,7 @@ spec: metadata: type: object spec: - description: RadixDNSAliasSpec specification of the RadixDNSAlias + description: RadixDNSAliasSpec is the spec for an RadixDNSAlias properties: appName: description: Name of the application the DNS alias used in. @@ -79,7 +79,7 @@ spec: - port type: object status: - description: Status of the RadixDNSAlias + description: RadixDNSAliasStatus is the status for an RadixDNSAlias properties: condition: description: Condition of the RadixDNSAlias creating or updating @@ -94,6 +94,7 @@ spec: type: string type: object required: + - metadata - spec type: object served: true diff --git a/json-schema/radixdnsalias.json b/json-schema/radixdnsalias.json index a84a536e6..6754bb9d1 100644 --- a/json-schema/radixdnsalias.json +++ b/json-schema/radixdnsalias.json @@ -13,7 +13,7 @@ "type": "object" }, "spec": { - "description": "RadixDNSAliasSpec specification of the RadixDNSAlias", + "description": "RadixDNSAliasSpec is the spec for an RadixDNSAlias", "properties": { "appName": { "description": "Name of the application the DNS alias used in.", @@ -53,7 +53,7 @@ "type": "object" }, "status": { - "description": "Status of the RadixDNSAlias", + "description": "RadixDNSAliasStatus is the status for an RadixDNSAlias", "properties": { "condition": { "description": "Condition of the RadixDNSAlias creating or updating", @@ -73,6 +73,7 @@ } }, "required": [ + "metadata", "spec" ], "type": "object" diff --git a/pkg/apis/radix/v1/radixdnsaliastypes.go b/pkg/apis/radix/v1/radixdnsaliastypes.go index 117e216bc..cfe5f50e5 100644 --- a/pkg/apis/radix/v1/radixdnsaliastypes.go +++ b/pkg/apis/radix/v1/radixdnsaliastypes.go @@ -13,25 +13,19 @@ import meta "k8s.io/apimachinery/pkg/apis/meta/v1" // RadixDNSAlias is a Custom Resource Definition type RadixDNSAlias struct { - // meta.TypeMeta of the RadixDNSAlias - // +optional - meta.TypeMeta `json:",inline" yaml:",inline"` - // meta.ObjectMeta Metadata of the RadixDNSAlias - meta.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"` - // RadixDNSAliasSpec specification of the RadixDNSAlias - Spec RadixDNSAliasSpec `json:"spec" yaml:"spec"` - // Status of the RadixDNSAlias - // +optional - Status RadixDNSAliasStatus `json:"status" yaml:"status"` + meta.TypeMeta `json:",inline"` + meta.ObjectMeta `json:"metadata"` + Spec RadixDNSAliasSpec `json:"spec"` + Status RadixDNSAliasStatus `json:"status,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // RadixDNSAliasList is a list of RadixDNSAliases type RadixDNSAliasList struct { - meta.TypeMeta `json:",inline" yaml:",inline"` - meta.ListMeta `json:"metadata" yaml:"metadata"` - Items []RadixDNSAlias `json:"items" yaml:"items"` + meta.TypeMeta `json:",inline"` + meta.ListMeta `json:"metadata"` + Items []RadixDNSAlias `json:"items"` } // RadixDNSAliasSpec is the spec for an RadixDNSAlias @@ -40,19 +34,19 @@ type RadixDNSAliasSpec struct { // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ - AppName string `json:"appName" yaml:"appName"` + AppName string `json:"appName"` // Name of the environment for the component. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ - Environment string `json:"environment" yaml:"environment"` + Environment string `json:"environment"` // Name of the component that shall receive the incoming requests. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ - Component string `json:"component" yaml:"component"` + Component string `json:"component"` // Port number. // +kubebuilder:validation:Minimum=1024 @@ -75,11 +69,11 @@ const ( type RadixDNSAliasStatus struct { // Condition of the RadixDNSAlias creating or updating // +optional - Condition RadixDNSAliasCondition `json:"condition,omitempty" yaml:"condition,omitempty"` + Condition RadixDNSAliasCondition `json:"condition,omitempty"` // A human-readable message indicating details about the condition. // +optional - Message string `json:"message,omitempty" yaml:"message,omitempty"` + Message string `json:"message,omitempty"` // Reconciled The timestamp when the RadixDNSAlias was reconciled // +optional - Reconciled *meta.Time `json:"reconciled,omitempty" yaml:"reconciled,omitempty"` + Reconciled *meta.Time `json:"reconciled,omitempty"` } From 7f3a5535afb1ecde1ebe729a22d650684a428166 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 1 Dec 2023 14:40:42 +0100 Subject: [PATCH 078/121] Fixed unit-tests --- pkg/apis/dnsalias/syncer_test.go | 80 +++++++++++++------------------- pkg/apis/utils/labels/labels.go | 4 +- 2 files changed, 33 insertions(+), 51 deletions(-) diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index f44fefef0..7edf1eb46 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -3,6 +3,7 @@ package dnsalias_test import ( "context" "fmt" + "strconv" "testing" dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" @@ -135,44 +136,11 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { dnsAlias: testDNSAlias{Alias: alias2, Environment: envName1, Component: component1, Port: port8080}, dnsZone: dnsZone1, existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, - }, - expectedIngress: map[string]testIngress{ "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - "component1.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, - }, - }, - // { - // name: "manually changed appName repaired?", - // dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - // dnsZone: dnsZone1, - // existingIngress: map[string]testIngress{ - // "component1.alias1.custom-alias": {appName: appName2, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, - // }, - // expectedIngress: map[string]testIngress{ - // "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - // }, - // }, - // { - // name: "manually changed envName repaired", - // dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - // dnsZone: dnsZone1, - // existingIngress: map[string]testIngress{ - // "component1.alias1.custom-alias": {appName: appName1, envName: envName2, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, - // }, - // expectedIngress: map[string]testIngress{ - // "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - // }, - // }, - { - name: "manually changed component repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, - dnsZone: dnsZone1, - existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component2, port: port8080}, }, expectedIngress: map[string]testIngress{ "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + "component1.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, }, }, { @@ -207,7 +175,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { // cfg := &dnsalias2.DNSConfig{DNSZone: ts.dnsZone} s.registeringRadixDeployments(rd1, rd2, rd3, rd4) - err := registerExistingIngresses(s.kubeClient, ts.existingIngress, appName1, envName1) + err := registerExistingIngresses(s.kubeClient, ts.existingIngress) s.Require().NoError(err, "create existing ingresses") syncer := s.createSyncer(radixDNSAlias) @@ -226,15 +194,22 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { s.Require().Len(ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") if len(ingresses.Items) == len(ts.expectedIngress) { for _, ing := range ingresses.Items { + appNameLabel := ing.GetLabels()[kube.RadixAppLabel] + componentNameLabel := ing.GetLabels()[kube.RadixComponentLabel] + s.Require().Len(ing.Spec.Rules, 1, "rules count") + rule := ing.Spec.Rules[0] if expectedIngress, ok := ts.expectedIngress[ing.Name]; ok { - s.Require().Len(ing.Spec.Rules, 1, "rules count") - s.Assert().Equal(expectedIngress.appName, ing.GetLabels()[kube.RadixAppLabel], "app name") - s.Assert().Equal(utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName), ing.GetNamespace(), "namespace") - s.Assert().Equal(expectedIngress.component, ing.GetLabels()[kube.RadixComponentLabel], "component name") - s.Assert().Equal(expectedIngress.host, ing.Spec.Rules[0].Host, "rule host") - s.Assert().Equal("/", ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path, "rule http path") - s.Assert().Equal(expectedIngress.component, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Name, "rule backend service name") - s.Assert().Equal(expectedIngress.port, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "rule backend service port") + s.Assert().Equal(expectedIngress.appName, appNameLabel, "app name") + expectedNamespace := utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName) + s.Assert().Equal(expectedNamespace, ing.GetNamespace(), "namespace") + s.Assert().Equal(expectedIngress.component, componentNameLabel, "component name") + s.Assert().Equal(expectedIngress.host, rule.Host, "rule host") + s.Assert().Len(rule.IngressRuleValue.HTTP.Paths, 1, "http path count") + httpIngressPath := rule.IngressRuleValue.HTTP.Paths[0] + s.Assert().Equal("/", httpIngressPath.Path, "rule http path") + service := httpIngressPath.Backend.Service + s.Assert().Equal(expectedIngress.component, service.Name, "rule backend service name") + s.Assert().Equal(expectedIngress.port, service.Port.Number, "rule backend service port") if len(ing.ObjectMeta.OwnerReferences) > 0 { ownerRef := ing.ObjectMeta.OwnerReferences[0] s.Assert().Equal(radix.APIVersion, ownerRef.APIVersion, "ownerRef.APIVersion") @@ -246,8 +221,8 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { continue } assert.Fail(t, fmt.Sprintf("found not expected ingress %s for: appName %s, host %s, service %s, port %d", - ing.GetName(), ing.GetLabels()[kube.RadixAppLabel], ing.Spec.Rules[0].Host, ing.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name, - ing.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Port.Number)) + ing.GetName(), appNameLabel, rule.Host, rule.HTTP.Paths[0].Backend.Service.Name, + rule.HTTP.Paths[0].Backend.Service.Port.Number)) } } @@ -281,13 +256,20 @@ func (s *syncerTestSuite) registeringRadixDeployments(radixDeployments ...*radix } } -func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses map[string]testIngress, appName, envName string) error { +func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses map[string]testIngress) error { for _, ingProps := range testIngresses { ing := &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{Name: dnsalias.GetDNSAliasIngressName(ingProps.component, ingProps.alias)}, - Spec: ingress.GetIngressSpec(ingProps.host, ingProps.component, defaults.TLSSecretName, ingProps.port), + ObjectMeta: metav1.ObjectMeta{ + Name: dnsalias.GetDNSAliasIngressName(ingProps.component, ingProps.alias), + Labels: map[string]string{ + kube.RadixAppLabel: ingProps.appName, + kube.RadixComponentLabel: ingProps.component, + kube.RadixAliasLabel: strconv.FormatBool(true), + }, + }, + Spec: ingress.GetIngressSpec(ingProps.host, ingProps.component, defaults.TLSSecretName, ingProps.port), } - _, err := dnsalias.CreateRadixDNSAliasIngress(kubeClient, appName, envName, ing) + _, err := dnsalias.CreateRadixDNSAliasIngress(kubeClient, ingProps.appName, ingProps.envName, ing) if err != nil { return err } diff --git a/pkg/apis/utils/labels/labels.go b/pkg/apis/utils/labels/labels.go index da17eb9a3..dbfd41993 100644 --- a/pkg/apis/utils/labels/labels.go +++ b/pkg/apis/utils/labels/labels.go @@ -237,8 +237,8 @@ func ForAuxComponent(appName string, component v1.RadixCommonDeployComponent) ma } // ForDNSAlias returns labels for ingress, created for Radix DNS alias -func ForDNSAlias() map[string]string { - return map[string]string{ +func ForDNSAlias() kubelabels.Set { + return kubelabels.Set{ kube.RadixAliasLabel: strconv.FormatBool(true), } } From 351985ba23938d7a12b8e0a59b4e9c6233a18154 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 1 Dec 2023 14:48:31 +0100 Subject: [PATCH 079/121] Set version --- .vscode/launch.json | 8 ++++---- charts/radix-operator/Chart.yaml | 4 ++-- pkg/apis/application/ownerreference.go | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 1bf328c12..b0a5c2e00 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -31,7 +31,7 @@ "--IMAGE_TAG_NAME=server=1.23-alpine-slim", "--IMAGE_TAG_NAME=server2=1.22.1-alpine-perl", "--RADIX_RESERVED_APP_DNS_ALIASES=api=radix-api,canary=radix-canary-golang,console=radix-web-console,cost-api=radix-cost-allocation-api,webhook=radix-github-webhook", - "--RADIX_RESERVED_DNS_ALIASES=grafana,prometheus" + "--RADIX_RESERVED_DNS_ALIASES=grafana,prometheus,www" ] }, { @@ -54,7 +54,7 @@ "--DEBUG=true", "--RADIX_CONTAINER_REGISTRY=radixdev.azurecr.io", "--RADIX_RESERVED_APP_DNS_ALIASES=api=radix-api,canary=radix-canary-golang,console=radix-web-console,cost-api=radix-cost-allocation-api,webhook=radix-github-webhook", - "--RADIX_RESERVED_DNS_ALIASES=grafana,prometheus" + "--RADIX_RESERVED_DNS_ALIASES=grafana,prometheus,www" ] }, { @@ -77,7 +77,7 @@ "--RADIX_CLUSTERNAME=weekly-44", "--RADIX_CONTAINER_REGISTRY=radixdev.azurecr.io", "--RADIX_RESERVED_APP_DNS_ALIASES=api=radix-api,canary=radix-canary-golang,console=radix-web-console,cost-api=radix-cost-allocation-api,webhook=radix-github-webhook", - "--RADIX_RESERVED_DNS_ALIASES=grafana,prometheus" + "--RADIX_RESERVED_DNS_ALIASES=grafana,prometheus,www" ] }, { @@ -135,7 +135,7 @@ "SECCOMP_PROFILE_FILENAME": "allow-buildah.json", "RADIX_BUILDAH_IMAGE_BUILDER": "quay.io/buildah/stable:v1.31", "RADIX_RESERVED_APP_DNS_ALIASES": "api=radix-api,canary=radix-canary-golang,console=radix-web-console,cost-api=radix-cost-allocation-api,webhook=radix-github-webhook", - "RADIX_RESERVED_DNS_ALIASES": "grafana,prometheus" + "RADIX_RESERVED_DNS_ALIASES": "grafana,prometheus,www" }, "args": ["--useOutClusterClient=false"] }, diff --git a/charts/radix-operator/Chart.yaml b/charts/radix-operator/Chart.yaml index ef0ddbd51..b9991ce91 100644 --- a/charts/radix-operator/Chart.yaml +++ b/charts/radix-operator/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: radix-operator -version: 1.25.9 -appVersion: 1.45.9 +version: 1.26.1 +appVersion: 1.46.1 kubeVersion: ">=1.24.0" description: Radix Operator keywords: diff --git a/pkg/apis/application/ownerreference.go b/pkg/apis/application/ownerreference.go index 63dbc72ee..84ec8c3d1 100644 --- a/pkg/apis/application/ownerreference.go +++ b/pkg/apis/application/ownerreference.go @@ -2,7 +2,7 @@ package application import ( "github.com/equinor/radix-operator/pkg/apis/radix" - v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -12,7 +12,7 @@ func (app Application) getOwnerReference() []metav1.OwnerReference { } // GetOwnerReferenceOfRegistration Gets owner reference given registration. Resources that an RR owns -func GetOwnerReferenceOfRegistration(registration *v1.RadixRegistration) []metav1.OwnerReference { +func GetOwnerReferenceOfRegistration(registration *radixv1.RadixRegistration) []metav1.OwnerReference { trueVar := true return []metav1.OwnerReference{ { From c3b3df84141e1d4c04fb01a62f3ebaea3dacf9f1 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 1 Dec 2023 15:20:53 +0100 Subject: [PATCH 080/121] Fixed linter reported issues --- pipeline-runner/steps/build_test.go | 66 ------------------- .../applicationconfig_test.go | 12 ++-- pkg/apis/environment/environment_test.go | 4 +- .../ingress/ingressannotationprovider_test.go | 3 +- 4 files changed, 13 insertions(+), 72 deletions(-) diff --git a/pipeline-runner/steps/build_test.go b/pipeline-runner/steps/build_test.go index 228ff2a49..8fb4e126c 100644 --- a/pipeline-runner/steps/build_test.go +++ b/pipeline-runner/steps/build_test.go @@ -13,7 +13,6 @@ import ( internaltest "github.com/equinor/radix-operator/pipeline-runner/internal/test" internalwait "github.com/equinor/radix-operator/pipeline-runner/internal/wait" "github.com/equinor/radix-operator/pipeline-runner/model" - pipelineDefaults "github.com/equinor/radix-operator/pipeline-runner/model/defaults" "github.com/equinor/radix-operator/pipeline-runner/steps" application "github.com/equinor/radix-operator/pkg/apis/applicationconfig" "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" @@ -31,7 +30,6 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubefake "k8s.io/client-go/kubernetes/fake" - "sigs.k8s.io/yaml" ) func Test_RunBuildTestSuite(t *testing.T) { @@ -1583,67 +1581,3 @@ func (s *buildTestSuite) Test_BuildJobSpec_BuildKit_WithBuildSecrets() { expectedCommand := []string{"/bin/bash", "-c", expectedBuildCmd} s.Equal(expectedCommand, job.Spec.Template.Spec.Containers[0].Command) } - -func (s *buildTestSuite) createPreparePipelineConfigMapResponse(configMapName, appName string, ra *radixv1.RadixApplication, buildCtx *model.PrepareBuildContext) error { - raBytes, err := yaml.Marshal(ra) - if err != nil { - return err - } - data := map[string]string{ - pipelineDefaults.PipelineConfigMapContent: string(raBytes), - } - - if buildCtx != nil { - buildCtxBytes, err := yaml.Marshal(buildCtx) - if err != nil { - return err - } - data[pipelineDefaults.PipelineConfigMapBuildContext] = string(buildCtxBytes) - } - cm := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{Name: configMapName}, - Data: data, - } - _, err = s.kubeClient.CoreV1().ConfigMaps(utils.GetAppNamespace(appName)).Create(context.Background(), cm, metav1.CreateOptions{}) - return err -} - -func (s *buildTestSuite) createGitInfoConfigMapResponse(configMapName, appName, gitHash, gitTags string) error { - cm := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{Name: configMapName}, - Data: map[string]string{ - defaults.RadixGitCommitHashKey: gitHash, - defaults.RadixGitTagsKey: gitTags, - }, - } - _, err := s.kubeClient.CoreV1().ConfigMaps(utils.GetAppNamespace(appName)).Create(context.Background(), cm, metav1.CreateOptions{}) - return err -} - -func (s *buildTestSuite) createBuildSecret(appName string, data map[string][]byte) error { - secret := &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{Name: defaults.BuildSecretsName}, - Data: data, - } - - _, err := s.kubeClient.CoreV1().Secrets(utils.GetAppNamespace(appName)).Create(context.Background(), secret, metav1.CreateOptions{}) - return err -} - -func (s *buildTestSuite) getRadixApplicationHash(ra *radixv1.RadixApplication) string { - if ra == nil { - appHash, _ := hash.ToHashString(hash.SHA256, "0nXSg9l6EUepshGFmolpgV3elB0m8Mv7") - return appHash - } - appHash, _ := hash.ToHashString(hash.SHA256, ra.Spec) - return appHash -} - -func (s *buildTestSuite) getBuildSecretHash(secret *corev1.Secret) string { - if secret == nil { - secretHash, _ := hash.ToHashString(hash.SHA256, "34Wd68DsJRUzrHp2f63o3U5hUD6zl8Tj") - return secretHash - } - secretHash, _ := hash.ToHashString(hash.SHA256, secret.Data) - return secretHash -} diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 32533044d..56afe8ef0 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -83,7 +83,7 @@ func Test_Reconciles_Radix_Environments(t *testing.T) { _, client, kubeUtil, radixClient := setupTest() // Create environments manually - radixClient.RadixV1().RadixEnvironments().Create( + _, err := radixClient.RadixV1().RadixEnvironments().Create( context.TODO(), &radixv1.RadixEnvironment{ ObjectMeta: metav1.ObjectMeta{ @@ -91,8 +91,9 @@ func Test_Reconciles_Radix_Environments(t *testing.T) { }, }, metav1.CreateOptions{}) + assert.NoError(t, err) - radixClient.RadixV1().RadixEnvironments().Create( + _, err = radixClient.RadixV1().RadixEnvironments().Create( context.TODO(), &radixv1.RadixEnvironment{ ObjectMeta: metav1.ObjectMeta{ @@ -100,6 +101,7 @@ func Test_Reconciles_Radix_Environments(t *testing.T) { }, }, metav1.CreateOptions{}) + assert.NoError(t, err) adGroups := []string{"5678-91011-1234", "9876-54321-0987"} rr := utils.NewRegistrationBuilder(). @@ -117,12 +119,14 @@ func Test_Reconciles_Radix_Environments(t *testing.T) { label := fmt.Sprintf("%s=%s", kube.RadixAppLabel, rr.Name) // Test - app.OnSync() - environments, _ := radixClient.RadixV1().RadixEnvironments().List( + err = app.OnSync() + assert.NoError(t, err) + environments, err := radixClient.RadixV1().RadixEnvironments().List( context.TODO(), metav1.ListOptions{ LabelSelector: label, }) + assert.NoError(t, err) assert.Equal(t, 2, len(environments.Items)) } diff --git a/pkg/apis/environment/environment_test.go b/pkg/apis/environment/environment_test.go index 5b228c5d4..26dd178b0 100644 --- a/pkg/apis/environment/environment_test.go +++ b/pkg/apis/environment/environment_test.go @@ -58,7 +58,9 @@ func newEnv(client kubernetes.Interface, kubeUtil *kube.Kube, radixclient radixc nw, _ := networkpolicy.NewNetworkPolicy(client, kubeUtil, logger, re.Spec.AppName) env, _ := NewEnvironment(client, kubeUtil, radixclient, re, rr, nil, logger, &nw) // register instance with radix-client so UpdateStatus() can find it - radixclient.RadixV1().RadixEnvironments().Create(context.TODO(), re, meta.CreateOptions{}) + if _, err := radixclient.RadixV1().RadixEnvironments().Create(context.TODO(), re, meta.CreateOptions{}); err != nil { + panic(err) + } return rr, re, env } diff --git a/pkg/apis/ingress/ingressannotationprovider_test.go b/pkg/apis/ingress/ingressannotationprovider_test.go index 6b505a827..25b9443ec 100644 --- a/pkg/apis/ingress/ingressannotationprovider_test.go +++ b/pkg/apis/ingress/ingressannotationprovider_test.go @@ -167,7 +167,8 @@ func (s *OAuth2AnnotationsTestSuite) Test_ComponentOAuthPassedToOAuth2Config() { oauth := &radixv1.OAuth2{ClientID: "1234"} s.oauth2Config.EXPECT().MergeWith(oauth).Times(1).Return(&radixv1.OAuth2{}, nil) sut := oauth2AnnotationProvider{oauth2DefaultConfig: s.oauth2Config} - sut.GetAnnotations(&radixv1.RadixDeployComponent{PublicPort: "http", Authentication: &radixv1.Authentication{OAuth2: oauth}}, "unused-namespace") + _, err := sut.GetAnnotations(&radixv1.RadixDeployComponent{PublicPort: "http", Authentication: &radixv1.Authentication{OAuth2: oauth}}, "unused-namespace") + s.NoError(err) } func (s *OAuth2AnnotationsTestSuite) Test_AuthSigninAndUrlAnnotations() { From 93224cc57169436c14cb22473c41e3971d5b0e27 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 1 Dec 2023 17:06:21 +0100 Subject: [PATCH 081/121] Fixed linter reported issues --- pkg/apis/alert/alert_test.go | 39 +++-- pkg/apis/alert/alertmanagerconfig.go | 5 +- pkg/apis/application/application_test.go | 42 +++-- .../applicationconfig_test.go | 62 ++++--- pkg/apis/batch/syncer_test.go | 6 +- pkg/apis/deployment/deployment.go | 2 - pkg/apis/deployment/deployment_test.go | 157 +++++++++++++----- .../deployment/environmentvariables_test.go | 23 ++- .../oauthproxyresourcemanager_test.go | 46 +++-- pkg/apis/dnsalias/syncer.go | 2 +- pkg/apis/job/job_test.go | 25 ++- pkg/apis/kube/environment_variables_test.go | 20 ++- pkg/apis/test/utils.go | 32 ++-- radix-operator/alert/controller.go | 25 ++- radix-operator/alert/controller_test.go | 48 ++++-- radix-operator/application/controller.go | 25 ++- radix-operator/application/controller_test.go | 33 +++- radix-operator/batch/controller.go | 23 ++- radix-operator/batch/controller_test.go | 7 +- radix-operator/common/controller.go | 8 +- radix-operator/common/controller_test.go | 50 +++++- radix-operator/common/utils.go | 7 +- radix-operator/deployment/controller.go | 31 +++- radix-operator/deployment/controller_test.go | 19 ++- radix-operator/deployment/handler_test.go | 20 ++- radix-operator/environment/controller.go | 57 +++++-- radix-operator/job/controller.go | 31 ++-- radix-operator/job/controller_test.go | 16 +- radix-operator/registration/controller.go | 27 ++- .../registration/controller_test.go | 4 +- 30 files changed, 636 insertions(+), 256 deletions(-) diff --git a/pkg/apis/alert/alert_test.go b/pkg/apis/alert/alert_test.go index ad28df714..9f330ea26 100644 --- a/pkg/apis/alert/alert_test.go +++ b/pkg/apis/alert/alert_test.go @@ -107,14 +107,16 @@ func (s *alertTestSuite) Test_OnSync_ResourcesCreated() { ObjectMeta: metav1.ObjectMeta{Name: appName}, Spec: radixv1.RadixRegistrationSpec{AdGroups: []string{"admin"}, ReaderAdGroups: []string{"reader"}}, } - s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) - radixalert := &radixv1.RadixAlert{ + if _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { + panic(err) + } + radixAlert := &radixv1.RadixAlert{ ObjectMeta: metav1.ObjectMeta{Name: alertName, Labels: map[string]string{kube.RadixAppLabel: appName}, UID: alertUID}, Spec: radixv1.RadixAlertSpec{}, } - radixalert, _ = s.radixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), radixalert, metav1.CreateOptions{}) + radixAlert, _ = s.radixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), radixAlert, metav1.CreateOptions{}) - sut := s.createAlertSyncer(radixalert) + sut := s.createAlertSyncer(radixAlert) err := sut.OnSync() s.Nil(err) _, err = s.kubeClient.CoreV1().Secrets(namespace).Get(context.Background(), GetAlertSecretName(alertName), metav1.GetOptions{}) @@ -123,7 +125,7 @@ func (s *alertTestSuite) Test_OnSync_ResourcesCreated() { s.ElementsMatch([]string{"any-alert-alert-config-admin", "any-alert-alert-config-reader"}, s.getRoleNames(actualRoles)) actualRoleBindings, _ := s.kubeClient.RbacV1().RoleBindings(namespace).List(context.Background(), metav1.ListOptions{}) s.ElementsMatch([]string{"any-alert-alert-config-admin", "any-alert-alert-config-reader"}, s.getRoleBindingNames(actualRoleBindings)) - _, err = s.promClient.MonitoringV1alpha1().AlertmanagerConfigs(namespace).Get(context.Background(), getAlertmanagerConfigName(radixalert.Name), metav1.GetOptions{}) + _, err = s.promClient.MonitoringV1alpha1().AlertmanagerConfigs(namespace).Get(context.Background(), getAlertmanagerConfigName(radixAlert.Name), metav1.GetOptions{}) s.Nil(err, "alertmanagerConfig not found") } @@ -178,7 +180,9 @@ func (s *alertTestSuite) Test_OnSync_Rbac_CreateWithOwnerReference() { } radixalert, _ = s.radixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), radixalert, metav1.CreateOptions{}) rr := &radixv1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}} - s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) + if _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { + panic(err) + } expectedAlertOwnerRef := s.getRadixAlertAsOwnerReference(radixalert) sut := s.createAlertSyncer(radixalert) @@ -205,10 +209,15 @@ func (s *alertTestSuite) Test_OnSync_Rbac_UpdateWithOwnerReference() { ObjectMeta: metav1.ObjectMeta{Name: alertName, UID: alertUID, Labels: map[string]string{kube.RadixAppLabel: appName}}, Spec: radixv1.RadixAlertSpec{}, } - radixalert, _ = s.radixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), radixalert, metav1.CreateOptions{}) + radixalert, err := s.radixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), radixalert, metav1.CreateOptions{}) + if err != nil { + panic(err) + } rr := &radixv1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}} - s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) - _, err := s.kubeClient.RbacV1().Roles(namespace).Create(context.Background(), &rbacv1.Role{ObjectMeta: metav1.ObjectMeta{Name: getAlertConfigSecretAdminRoleName(alertName)}}, metav1.CreateOptions{}) + if _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { + panic(err) + } + _, err = s.kubeClient.RbacV1().Roles(namespace).Create(context.Background(), &rbacv1.Role{ObjectMeta: metav1.ObjectMeta{Name: getAlertConfigSecretAdminRoleName(alertName)}}, metav1.CreateOptions{}) s.Nil(err) _, err = s.kubeClient.RbacV1().RoleBindings(namespace).Create(context.Background(), &rbacv1.RoleBinding{ObjectMeta: metav1.ObjectMeta{Name: getAlertConfigSecretAdminRoleName(alertName)}}, metav1.CreateOptions{}) s.Nil(err) @@ -245,7 +254,9 @@ func (s *alertTestSuite) Test_OnSync_Rbac_ConfiguredCorrectly() { } radixalert, _ = s.radixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), radixalert, metav1.CreateOptions{}) rr := &radixv1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}, Spec: radixv1.RadixRegistrationSpec{AdGroups: adminGroups, ReaderAdGroups: readerGroups}} - s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) + if _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { + panic(err) + } sut := s.createAlertSyncer(radixalert) err := sut.OnSync() @@ -294,7 +305,9 @@ func (s *alertTestSuite) Test_OnSync_Secret_RemoveOrphanedKeys() { GetSlackConfigSecretKeyName("orphaned2"): []byte("bar"), }, } - s.kubeClient.CoreV1().Secrets(namespace).Create(context.Background(), secret, metav1.CreateOptions{}) + if _, err := s.kubeClient.CoreV1().Secrets(namespace).Create(context.Background(), secret, metav1.CreateOptions{}); err != nil { + panic(err) + } sut := s.createAlertSyncer(radixalert) err := sut.OnSync() @@ -584,7 +597,9 @@ func (s *alertTestSuite) Test_OnSync_AlertmanagerConfig_ConfiguredCorrectly() { radixalert, err = s.radixClient.RadixV1().RadixAlerts(namespace).Update(context.Background(), radixalert, metav1.UpdateOptions{}) s.Nil(err) sut = s.createAlertSyncer(radixalert, testAlertSyncerWithAlertConfigs(alertConfigs), testAlertSyncerWithSlackMessageTemplate(slackTemplate)) - sut.OnSync() + if err := sut.OnSync(); err != nil { + panic(err) + } actualAmr, _ = s.promClient.MonitoringV1alpha1().AlertmanagerConfigs(namespace).Get(context.Background(), getAlertmanagerConfigName(alertName), metav1.GetOptions{}) s.Len(actualAmr.Spec.Receivers, 3) s.Len(actualAmr.Spec.Route.Routes, 2) diff --git a/pkg/apis/alert/alertmanagerconfig.go b/pkg/apis/alert/alertmanagerconfig.go index 2a56596c7..abe48f505 100644 --- a/pkg/apis/alert/alertmanagerconfig.go +++ b/pkg/apis/alert/alertmanagerconfig.go @@ -27,7 +27,7 @@ const ( resolvableRepeatInterval = "24h" // How long to wait before sending a notification about new alerts that // are added to a group of alerts for which an initial notification has - //# already been sent. + // # already been sent. defaultGroupInterval = "1m" // How long to initially wait to send a notification for a group // of alerts. Allows to wait for an inhibiting alert to arrive or collect @@ -53,8 +53,7 @@ func (syncer *alertSyncer) createOrUpdateAlertManagerConfig() error { if err != nil { return err } - syncer.applyAlertManagerConfig(ns, amc) - return err + return syncer.applyAlertManagerConfig(ns, amc) } func (syncer *alertSyncer) applyAlertManagerConfig(namespace string, alertManagerConfig *v1alpha1.AlertmanagerConfig) error { diff --git a/pkg/apis/application/application_test.go b/pkg/apis/application/application_test.go index 74d9b3d2b..73bba62cd 100644 --- a/pkg/apis/application/application_test.go +++ b/pkg/apis/application/application_test.go @@ -98,8 +98,10 @@ func TestOnSync_RegistrationCreated_AppNamespaceWithResourcesCreated(t *testing. // Test appName := "any-app" - applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). - WithName(appName)) + if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). + WithName(appName)); err != nil { + panic(err) + } ns, err := client.CoreV1().Namespaces().Get(context.TODO(), utils.GetAppNamespace(appName), metav1.GetOptions{}) assert.NoError(t, err) @@ -142,8 +144,10 @@ func TestOnSync_PodSecurityStandardLabelsSetOnNamespace(t *testing.T) { // Test appName := "any-app" - applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). - WithName(appName)) + if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). + WithName(appName)); err != nil { + panic(err) + } ns, err := client.CoreV1().Namespaces().Get(context.TODO(), utils.GetAppNamespace(appName), metav1.GetOptions{}) assert.NoError(t, err) @@ -168,20 +172,24 @@ func TestOnSync_RegistrationCreated_AppNamespaceReconciled(t *testing.T) { defer os.Clearenv() // Create namespaces manually - client.CoreV1().Namespaces().Create( + if _, err := client.CoreV1().Namespaces().Create( context.TODO(), &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "any-app-app", }, }, - metav1.CreateOptions{}) + metav1.CreateOptions{}); err != nil { + panic(err) + } label := fmt.Sprintf("%s=%s", kube.RadixAppLabel, "any-app") // Test - applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). - WithName("any-app")) + if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). + WithName("any-app")); err != nil { + panic(err) + } namespaces, _ := client.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{ LabelSelector: label, @@ -197,10 +205,12 @@ func TestOnSync_NoUserGroupDefined_DefaultUserGroupSet(t *testing.T) { os.Setenv(defaults.OperatorDefaultUserGroupEnvironmentVariable, defaultRole) // Test - applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). + if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). WithName("any-app"). WithAdGroups([]string{}). - WithReaderAdGroups([]string{})) + WithReaderAdGroups([]string{})); err != nil { + panic(err) + } rolebindings, _ := client.RbacV1().RoleBindings("any-app-app").List(context.TODO(), metav1.ListOptions{}) assert.ElementsMatch(t, @@ -224,8 +234,10 @@ func TestOnSync_LimitsDefined_LimitsSet(t *testing.T) { os.Setenv(defaults.OperatorAppLimitDefaultRequestMemoryEnvironmentVariable, "256M") // Test - applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). - WithName("any-app")) + if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). + WithName("any-app")); err != nil { + panic(err) + } limitRanges, _ := client.CoreV1().LimitRanges(utils.GetAppNamespace("any-app")).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 1, len(limitRanges.Items), "Number of limit ranges was not expected") @@ -242,8 +254,10 @@ func TestOnSync_NoLimitsDefined_NoLimitsSet(t *testing.T) { os.Setenv(defaults.OperatorAppLimitDefaultRequestMemoryEnvironmentVariable, "") // Test - applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). - WithName("any-app")) + if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). + WithName("any-app")); err != nil { + panic(err) + } limitRanges, _ := client.CoreV1().LimitRanges(utils.GetAppNamespace("any-app")).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 0, len(limitRanges.Items), "Number of limit ranges was not expected") diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 56afe8ef0..49fa861a6 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -216,11 +216,13 @@ func Test_WithBuildSecretsSet_SecretsCorrectlyAdded(t *testing.T) { tu, client, kubeUtil, radixClient := setupTest() appNamespace := "any-app-app" - applyApplicationWithSync(tu, client, kubeUtil, radixClient, + if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). - WithBuildSecrets("secret1", "secret2")) + WithBuildSecrets("secret1", "secret2")); err != nil { + panic(err) + } secrets, _ := client.CoreV1().Secrets(appNamespace).List(context.TODO(), metav1.ListOptions{}) defaultValue := []byte(defaults.BuildSecretDefaultData) @@ -239,11 +241,13 @@ func Test_WithBuildSecretsSet_SecretsCorrectlyAdded(t *testing.T) { assert.True(t, roleBindingByNameExists("radix-app-admin-build-secrets", rolebindings)) assert.True(t, roleBindingByNameExists("pipeline-build-secrets", rolebindings)) - applyApplicationWithSync(tu, client, kubeUtil, radixClient, + if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). - WithBuildSecrets("secret4", "secret5", "secret6")) + WithBuildSecrets("secret4", "secret5", "secret6")); err != nil { + panic(err) + } secrets, _ = client.CoreV1().Secrets(appNamespace).List(context.TODO(), metav1.ListOptions{}) buildSecrets = getSecretByName(defaults.BuildSecretsName, secrets) @@ -326,19 +330,23 @@ func Test_SubPipelineServiceAccountsCorrectlyDeleted(t *testing.T) { func Test_WithBuildSecretsDeleted_SecretsCorrectlyDeleted(t *testing.T) { tu, client, kubeUtil, radixClient := setupTest() - applyApplicationWithSync(tu, client, kubeUtil, radixClient, + if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). - WithBuildSecrets("secret1", "secret2")) + WithBuildSecrets("secret1", "secret2")); err != nil { + panic(err) + } // Delete secret appNamespace := "any-app-app" - applyApplicationWithSync(tu, client, kubeUtil, radixClient, + if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). - WithBuildSecrets("secret2")) + WithBuildSecrets("secret2")); err != nil { + panic(err) + } secrets, _ := client.CoreV1().Secrets(appNamespace).List(context.TODO(), metav1.ListOptions{}) defaultValue := []byte(defaults.BuildSecretDefaultData) @@ -350,11 +358,13 @@ func Test_WithBuildSecretsDeleted_SecretsCorrectlyDeleted(t *testing.T) { assert.Equal(t, defaultValue, buildSecrets.Data["secret2"]) // Delete secret - applyApplicationWithSync(tu, client, kubeUtil, radixClient, + if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). - WithBuildSecrets()) + WithBuildSecrets()); err != nil { + panic(err) + } // Secret is deleted secrets, _ = client.CoreV1().Secrets(appNamespace).List(context.TODO(), metav1.ListOptions{}) @@ -374,11 +384,13 @@ func Test_WithBuildSecretsDeleted_SecretsCorrectlyDeleted(t *testing.T) { func Test_AppReaderBuildSecretsRoleAndRoleBindingExists(t *testing.T) { tu, client, kubeUtil, radixClient := setupTest() - applyApplicationWithSync(tu, client, kubeUtil, radixClient, + if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). - WithBuildSecrets("secret1", "secret2")) + WithBuildSecrets("secret1", "secret2")); err != nil { + panic(err) + } roles, _ := client.RbacV1().Roles("any-app-app").List(context.TODO(), metav1.ListOptions{}) assert.True(t, roleByNameExists("radix-app-reader-build-secrets", roles)) @@ -387,10 +399,12 @@ func Test_AppReaderBuildSecretsRoleAndRoleBindingExists(t *testing.T) { assert.True(t, roleBindingByNameExists("radix-app-reader-build-secrets", rolebindings)) // Delete secret and verify that role and rolebinding is deleted - applyApplicationWithSync(tu, client, kubeUtil, radixClient, + if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). - WithEnvironment("dev", "master")) + WithEnvironment("dev", "master")); err != nil { + panic(err) + } roles, _ = client.RbacV1().Roles("any-app-app").List(context.TODO(), metav1.ListOptions{}) assert.False(t, roleByNameExists("radix-app-reader-build-secrets", roles)) @@ -402,11 +416,13 @@ func Test_AppReaderBuildSecretsRoleAndRoleBindingExists(t *testing.T) { func Test_AppReaderPrivateImageHubRoleAndRoleBindingExists(t *testing.T) { tu, client, kubeUtil, radixClient := setupTest() - applyApplicationWithSync(tu, client, kubeUtil, radixClient, + if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). - WithBuildSecrets("secret1", "secret2")) + WithBuildSecrets("secret1", "secret2")); err != nil { + panic(err) + } roles, _ := client.RbacV1().Roles("any-app-app").List(context.TODO(), metav1.ListOptions{}) assert.True(t, roleByNameExists("radix-private-image-hubs-reader", roles)) @@ -440,7 +456,9 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_SetPassword(t *testing.T) { assert.Equal(t, "privaterepodeleteme.azurecr.io", pendingSecrets[0]) - appConfig.UpdatePrivateImageHubsSecretsPassword("privaterepodeleteme.azurecr.io", "a-password") + if err := appConfig.UpdatePrivateImageHubsSecretsPassword("privaterepodeleteme.azurecr.io", "a-password"); err != nil { + panic(err) + } secret, _ := client.CoreV1().Secrets("any-app-app").Get(context.TODO(), defaults.PrivateImageHubSecretName, metav1.GetOptions{}) pendingSecrets, _ = appConfig.GetPendingPrivateImageHubSecrets() @@ -566,9 +584,11 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_NoImageHubs(t *testing.T) { func Test_RadixEnvironment(t *testing.T) { tu, client, kubeUtil, radixClient := setupTest() - applyApplicationWithSync(tu, client, kubeUtil, radixClient, + if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). - WithAppName("any-app")) + WithAppName("any-app")); err != nil { + panic(err) + } rr, _ := radixClient.RadixV1().RadixRegistrations().Get(context.TODO(), "any-app", metav1.GetOptions{}) @@ -621,7 +641,9 @@ func Test_UseBuildKit(t *testing.T) { if testScenario.useBuildKit != nil { ra = ra.WithBuildKit(testScenario.useBuildKit) } - applyApplicationWithSync(tu, client, kubeUtil, radixClient, ra) + if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, ra); err != nil { + panic(err) + } raAfterSync, _ := radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(testScenario.appName)).Get(context.TODO(), testScenario.appName, metav1.GetOptions{}) diff --git a/pkg/apis/batch/syncer_test.go b/pkg/apis/batch/syncer_test.go index 447165599..a8adb49ec 100644 --- a/pkg/apis/batch/syncer_test.go +++ b/pkg/apis/batch/syncer_test.go @@ -71,7 +71,9 @@ func (s *syncerTestSuite) ensurePopulatedEnvVarsConfigMaps(kubeUtil *kube.Kube, } desiredConfigMap.Data[envVarName] = envVarValue } - kubeUtil.ApplyConfigMap(rd.GetNamespace(), initialEnvVarsConfigMap, desiredConfigMap) + if err := kubeUtil.ApplyConfigMap(rd.GetNamespace(), initialEnvVarsConfigMap, desiredConfigMap); err != nil { + panic(err) + } return desiredConfigMap } @@ -134,7 +136,7 @@ func (s *syncerTestSuite) Test_RestoreStatus() { } func (s *syncerTestSuite) Test_RestoreStatusWithInvalidAnnotationValueShouldReturnErrorAndSkipReconcile() { - jobName, namespace := "any-job", "any-ns" + jobName := "any-job" appName, batchName, componentName, namespace, rdName := "any-app", "any-batch", "compute", "any-ns", "any-rd" batch := &radixv1.RadixBatch{ ObjectMeta: metav1.ObjectMeta{Name: batchName, Annotations: map[string]string{kube.RestoredStatusAnnotation: "invalid data"}}, diff --git a/pkg/apis/deployment/deployment.go b/pkg/apis/deployment/deployment.go index 600ec767c..8ab479fa8 100644 --- a/pkg/apis/deployment/deployment.go +++ b/pkg/apis/deployment/deployment.go @@ -190,8 +190,6 @@ func (deploy *Deployment) restoreStatus() bool { } func (deploy *Deployment) syncStatuses() (stopReconciliation bool, err error) { - stopReconciliation = false - allRDs, err := deploy.kubeutil.ListRadixDeployments(deploy.getNamespace()) if err != nil { err = fmt.Errorf("failed to get all RadixDeployments. Error was %v", err) diff --git a/pkg/apis/deployment/deployment_test.go b/pkg/apis/deployment/deployment_test.go index fc7f0eb9b..db2dc4944 100644 --- a/pkg/apis/deployment/deployment_test.go +++ b/pkg/apis/deployment/deployment_test.go @@ -835,10 +835,12 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { // Test t.Run("app with component use default SA", func(t *testing.T) { tu, client, kubeUtil, radixclient, prometheusclient, _ := setupTest() - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + if _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithJobComponents(). WithAppName("any-other-app"). - WithEnvironment("test")) + WithEnvironment("test")); err != nil { + panic(err) + } serviceAccounts, _ := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace("any-other-app", "test")).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 0, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -853,7 +855,7 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { appName, envName, componentName, clientId, newClientId := "any-app", "any-env", "any-component", "any-client-id", "new-client-id" // Deploy component with Azure identity must create custom SA - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + if _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( utils.NewDeployComponentBuilder(). WithName(componentName). @@ -861,7 +863,9 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { ). WithJobComponents(). WithAppName(appName). - WithEnvironment(envName)) + WithEnvironment(envName)); err != nil { + panic(err) + } serviceAccounts, _ := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 1, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -877,7 +881,7 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { assert.Equal(t, "true", expectedDeployments[0].Spec.Template.Labels["azure.workload.identity/use"]) // Deploy component with new Azure identity must update SA - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + if _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( utils.NewDeployComponentBuilder(). WithName(componentName). @@ -885,7 +889,9 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { ). WithJobComponents(). WithAppName(appName). - WithEnvironment(envName)) + WithEnvironment(envName)); err != nil { + panic(err) + } serviceAccounts, _ = client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 1, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -901,11 +907,13 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { assert.Equal(t, "true", expectedDeployments[0].Spec.Template.Labels["azure.workload.identity/use"]) // Redploy component without Azure identity should delete custom SA - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + if _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents(utils.NewDeployComponentBuilder().WithName(componentName)). WithJobComponents(). WithAppName(appName). - WithEnvironment(envName)) + WithEnvironment(envName)); err != nil { + panic(err) + } serviceAccounts, _ = client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 0, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -921,10 +929,12 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { t.Run("app with component using identity fails if SA exist with missing is-service-account-for-component label", func(t *testing.T) { tu, client, kubeUtil, radixclient, prometheusclient, _ := setupTest() appName, envName, componentName, clientId := "any-app", "any-env", "any-component", "any-client-id" - client.CoreV1().ServiceAccounts("any-app-any-env").Create( + if _, err := client.CoreV1().ServiceAccounts("any-app-any-env").Create( context.Background(), &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: utils.GetComponentServiceAccountName(componentName), Labels: map[string]string{kube.RadixComponentLabel: componentName}}}, - metav1.CreateOptions{}) + metav1.CreateOptions{}); err != nil { + panic(err) + } _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( @@ -942,10 +952,12 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { t.Run("app with component using identity success if SA exist with correct labels", func(t *testing.T) { tu, client, kubeUtil, radixclient, prometheusclient, _ := setupTest() appName, envName, componentName, clientId := "any-app", "any-env", "any-component", "any-client-id" - client.CoreV1().ServiceAccounts("any-app-any-env").Create( + if _, err := client.CoreV1().ServiceAccounts("any-app-any-env").Create( context.Background(), &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: utils.GetComponentServiceAccountName(componentName), Labels: map[string]string{kube.RadixComponentLabel: componentName, kube.IsServiceAccountForComponent: "true", "any-other-label": "any-value"}}}, - metav1.CreateOptions{}) + metav1.CreateOptions{}); err != nil { + panic(err) + } _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( @@ -971,13 +983,15 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { appName, envName, componentName, clientId, anyOtherServiceAccountName := "any-app", "any-env", "any-component", "any-client-id", "any-other-serviceaccount" // A service account that must not be deleted - client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).Create( + if _, err := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).Create( context.Background(), &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: anyOtherServiceAccountName, Labels: map[string]string{kube.RadixComponentLabel: "anything"}}}, - metav1.CreateOptions{}) + metav1.CreateOptions{}); err != nil { + panic(err) + } // Deploy component with Azure identity must create custom SA - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + if _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( utils.NewDeployComponentBuilder(). WithName(componentName). @@ -988,13 +1002,18 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { ). WithJobComponents(). WithAppName(appName). - WithEnvironment(envName)) + WithEnvironment(envName)); err != nil { + panic(err) + } - serviceAccounts, _ := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) + serviceAccounts, err := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) + if err != nil { + panic(err) + } assert.Equal(t, 3, len(serviceAccounts.Items), "Number of service accounts was not expected") // Redploy component without Azure identity should delete custom SA - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + if _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( utils.NewDeployComponentBuilder(). WithName(componentName). @@ -1002,7 +1021,9 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { ). WithJobComponents(). WithAppName(appName). - WithEnvironment(envName)) + WithEnvironment(envName)); err != nil { + panic(err) + } serviceAccounts, _ = client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 2, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -1546,7 +1567,9 @@ func TestObjectSynced_DeploymentReplicasFromCurrentDeploymentWhenHPAEnabled(t *t // Simulate HPA scaling up comp1 to 3 replicas comp1.Spec.Replicas = pointers.Ptr[int32](3) - client.AppsV1().Deployments(envNamespace).Update(context.Background(), comp1, metav1.UpdateOptions{}) + if _, err := client.AppsV1().Deployments(envNamespace).Update(context.Background(), comp1, metav1.UpdateOptions{}); err != nil { + panic(err) + } // Resync existing RD should use replicas from current deployment for HPA enabled component err = applyDeploymentUpdateWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). @@ -2604,7 +2627,9 @@ func TestObjectUpdated_RemoveOneSecret_SecretIsRemoved(t *testing.T) { secretData["a_third_secret"] = []byte(anySecretValue) anyComponentSecret.Data = secretData - client.CoreV1().Secrets(envNamespace).Update(context.TODO(), anyComponentSecret, metav1.UpdateOptions{}) + if _, err := client.CoreV1().Secrets(envNamespace).Update(context.TODO(), anyComponentSecret, metav1.UpdateOptions{}); err != nil { + panic(err) + } // Removing one secret from config and therefor from the deployment // should cause it to disappear @@ -3555,14 +3580,16 @@ func Test_JobScheduler_ObjectsGarbageCollected(t *testing.T) { labels[kube.RadixJobTypeLabel] = kube.RadixJobTypeJobSchedule } - client.BatchV1().Jobs(namespace).Create(context.TODO(), + if _, err := client.BatchV1().Jobs(namespace).Create(context.TODO(), &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ Name: name, Labels: labels, }, }, - metav1.CreateOptions{}) + metav1.CreateOptions{}); err != nil { + panic(err) + } } addSecret := func(client kubernetes.Interface, name, namespace, componentName string) { @@ -3572,14 +3599,16 @@ func Test_JobScheduler_ObjectsGarbageCollected(t *testing.T) { labels[kube.RadixComponentLabel] = componentName } - client.CoreV1().Secrets(namespace).Create(context.TODO(), + if _, err := client.CoreV1().Secrets(namespace).Create(context.TODO(), &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: name, Labels: labels, }, }, - metav1.CreateOptions{}) + metav1.CreateOptions{}); err != nil { + panic(err) + } } addService := func(client kubernetes.Interface, name, namespace, componentName string) { @@ -3589,14 +3618,16 @@ func Test_JobScheduler_ObjectsGarbageCollected(t *testing.T) { labels[kube.RadixComponentLabel] = componentName } - client.CoreV1().Services(namespace).Create(context.TODO(), + if _, err := client.CoreV1().Services(namespace).Create(context.TODO(), &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: name, Labels: labels, }, }, - metav1.CreateOptions{}) + metav1.CreateOptions{}); err != nil { + panic(err) + } } t.Run(theory.name, func(t *testing.T) { @@ -3762,8 +3793,12 @@ func Test_IngressAnnotations_Called(t *testing.T) { defer os.Unsetenv(defaults.ActiveClusternameEnvironmentVariable) rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http").WithDNSAppAlias(true)).BuildRD() - radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) - radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}) + if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { + panic(err) + } ctrl := gomock.NewController(t) defer ctrl.Finish() annotations1 := ingress.NewMockAnnotationProvider(ctrl) @@ -3797,8 +3832,12 @@ func Test_IngressAnnotations_ReturnError(t *testing.T) { defer teardownTest() rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http")).BuildRD() - radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) - radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}) + if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { + panic(err) + } ctrl := gomock.NewController(t) defer ctrl.Finish() annotations1 := ingress.NewMockAnnotationProvider(ctrl) @@ -3823,8 +3862,12 @@ func Test_AuxiliaryResourceManagers_Called(t *testing.T) { defer teardownTest() rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http")).BuildRD() - radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) - radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}) + if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { + panic(err) + } ctrl := gomock.NewController(t) defer ctrl.Finish() auxResource := NewMockAuxiliaryResourceManager(ctrl) @@ -3850,8 +3893,12 @@ func Test_AuxiliaryResourceManagers_Sync_ReturnErr(t *testing.T) { defer teardownTest() rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http")).BuildRD() - radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) - radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}) + if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { + panic(err) + } ctrl := gomock.NewController(t) defer ctrl.Finish() auxErr := errors.New("an error") @@ -3878,8 +3925,12 @@ func Test_AuxiliaryResourceManagers_GarbageCollect_ReturnErr(t *testing.T) { defer teardownTest() rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http")).BuildRD() - radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) - radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}) + if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { + panic(err) + } ctrl := gomock.NewController(t) defer ctrl.Finish() auxErr := errors.New("an error") @@ -4076,14 +4127,30 @@ func TestRadixBatch_IsGarbageCollected(t *testing.T) { } } - radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch1", "job1"), metav1.CreateOptions{}) - radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch2", "job1"), metav1.CreateOptions{}) - radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch3", "job2"), metav1.CreateOptions{}) - radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch4", "job2"), metav1.CreateOptions{}) - radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch5", "job3"), metav1.CreateOptions{}) - radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch6", "job4"), metav1.CreateOptions{}) - radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch7", ""), metav1.CreateOptions{}) - radixclient.RadixV1().RadixBatches("other-ns").Create(context.Background(), batchFactory("batch8", "job1"), metav1.CreateOptions{}) + if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch1", "job1"), metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch2", "job1"), metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch3", "job2"), metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch4", "job2"), metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch5", "job3"), metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch6", "job4"), metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch7", ""), metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := radixclient.RadixV1().RadixBatches("other-ns").Create(context.Background(), batchFactory("batch8", "job1"), metav1.CreateOptions{}); err != nil { + panic(err) + } // Test _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). diff --git a/pkg/apis/deployment/environmentvariables_test.go b/pkg/apis/deployment/environmentvariables_test.go index 61409449b..a0888d527 100644 --- a/pkg/apis/deployment/environmentvariables_test.go +++ b/pkg/apis/deployment/environmentvariables_test.go @@ -10,6 +10,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" prometheusclient "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned" + log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -99,9 +100,11 @@ func Test_getEnvironmentVariablesForRadixOperator(t *testing.T) { }) }) //goland:noinspection GoUnhandledErrorResult - testEnv.kubeUtil.CreateConfigMap(corev1.NamespaceDefault, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "radix-config"}, Data: map[string]string{ + if _, err := testEnv.kubeUtil.CreateConfigMap(corev1.NamespaceDefault, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "radix-config"}, Data: map[string]string{ "clustername": testClusterName, - }}) + }}); err != nil { + log.Error(err) + } envVars, err := GetEnvironmentVariablesForRadixOperator(testEnv.kubeUtil, appName, rd, &rd.Spec.Components[0]) @@ -133,20 +136,26 @@ func Test_RemoveFromConfigMapEnvVarsNotExistingInRadixDeployment(t *testing.T) { defer teardownTest() t.Run("Remove obsolete env-vars from config-maps", func(t *testing.T) { //goland:noinspection GoUnhandledErrorResult - testEnv.kubeUtil.CreateConfigMap(namespace, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: kube.GetEnvVarsConfigMapName(componentName)}, Data: map[string]string{ + if _, err := testEnv.kubeUtil.CreateConfigMap(namespace, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: kube.GetEnvVarsConfigMapName(componentName)}, Data: map[string]string{ "VAR1": "val1", "OUTDATED_VAR1": "val1z", - }}) + }}); err != nil { + panic(err) + } existingEnvVarsMetadataConfigMap := corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: kube.GetEnvVarsMetadataConfigMapName(componentName)}} //goland:noinspection GoUnhandledErrorResult - kube.SetEnvVarsMetadataMapToConfigMap(&existingEnvVarsMetadataConfigMap, + if err := kube.SetEnvVarsMetadataMapToConfigMap(&existingEnvVarsMetadataConfigMap, map[string]kube.EnvVarMetadata{ "VAR1": {RadixConfigValue: "orig-val1"}, "OUTDATED_VAR1": {RadixConfigValue: "orig-val1a"}, "OUTDATED_VAR2": {RadixConfigValue: "orig-val2a"}, - }) + }); err != nil { + panic(err) + } //goland:noinspection GoUnhandledErrorResult - testEnv.kubeUtil.CreateConfigMap(namespace, &existingEnvVarsMetadataConfigMap) + if _, err := testEnv.kubeUtil.CreateConfigMap(namespace, &existingEnvVarsMetadataConfigMap); err != nil { + panic(err) + } rd := testEnv.applyRdComponent(t, appName, envName, componentName, func(componentBuilder utils.DeployComponentBuilder) { componentBuilder.WithEnvironmentVariables(map[string]string{ diff --git a/pkg/apis/deployment/oauthproxyresourcemanager_test.go b/pkg/apis/deployment/oauthproxyresourcemanager_test.go index 525a24cab..26b96f239 100644 --- a/pkg/apis/deployment/oauthproxyresourcemanager_test.go +++ b/pkg/apis/deployment/oauthproxyresourcemanager_test.go @@ -484,7 +484,9 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxySecret_KeysGarb // Remove redispassword if sessionstoretype is cookie s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(1).Return(&v1.OAuth2{SessionStoreType: v1.SessionStoreCookie}, nil) - sut.Sync() + if err := sut.Sync(); err != nil { + panic(err) + } actualSecret, _ = s.kubeClient.CoreV1().Secrets(envNs).Get(context.Background(), secretName, metav1.GetOptions{}) s.Equal( map[string][]byte{ @@ -570,12 +572,24 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate Rules: []networkingv1.IngressRule{{Host: "ing2.public"}}, }, } - s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingServer, metav1.CreateOptions{}) - s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingServerNoRules, metav1.CreateOptions{}) - s.kubeClient.NetworkingV1().Ingresses("otherns").Create(context.Background(), &ingServerOtherNs, metav1.CreateOptions{}) - s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingOtherComponent, metav1.CreateOptions{}) - s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingWeb1, metav1.CreateOptions{}) - s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingWeb2, metav1.CreateOptions{}) + if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingServer, metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingServerNoRules, metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := s.kubeClient.NetworkingV1().Ingresses("otherns").Create(context.Background(), &ingServerOtherNs, metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingOtherComponent, metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingWeb1, metav1.CreateOptions{}); err != nil { + panic(err) + } + if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingWeb2, metav1.CreateOptions{}); err != nil { + panic(err) + } rr := utils.NewRegistrationBuilder().WithName(appName).BuildRR() rd := utils.NewDeploymentBuilder(). @@ -660,27 +674,33 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyUninstall() { appName, envName, component1Name, component2Name := "anyapp", "qa", "server", "web" envNs := utils.GetEnvironmentNamespace(appName, envName) - s.kubeClient.NetworkingV1().Ingresses(envNs).Create( + if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create( context.Background(), &networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{Name: "ing1", Labels: map[string]string{kube.RadixAppLabel: appName, kube.RadixComponentLabel: component1Name}}, Spec: networkingv1.IngressSpec{Rules: []networkingv1.IngressRule{{Host: "anyhost"}}}}, metav1.CreateOptions{}, - ) - s.kubeClient.NetworkingV1().Ingresses(envNs).Create( + ); err != nil { + panic(err) + } + if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create( context.Background(), &networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{Name: "ing2", Labels: map[string]string{kube.RadixAppLabel: appName, kube.RadixComponentLabel: component2Name}}, Spec: networkingv1.IngressSpec{Rules: []networkingv1.IngressRule{{Host: "anyhost"}}}}, metav1.CreateOptions{}, - ) - s.kubeClient.NetworkingV1().Ingresses(envNs).Create( + ); err != nil { + panic(err) + } + if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create( context.Background(), &networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{Name: "ing3", Labels: map[string]string{kube.RadixAppLabel: appName, kube.RadixComponentLabel: component2Name}}, Spec: networkingv1.IngressSpec{Rules: []networkingv1.IngressRule{{Host: "anyhost"}}}}, metav1.CreateOptions{}, - ) + ); err != nil { + panic(err) + } rr := utils.NewRegistrationBuilder().WithName(appName).BuildRR() rd := utils.NewDeploymentBuilder(). diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 849366228..1a7fba3bc 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -88,7 +88,7 @@ func (s *syncer) syncAlias() error { namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) ing, err := s.createOrUpdateIngress(namespace, radixDeployComponent, ingressName) if err != nil { - if admissionWebhookErrorMatcher := admissionWebhookErrorExpression.FindStringSubmatch(err.Error()); admissionWebhookErrorMatcher != nil && len(admissionWebhookErrorMatcher) == 5 { + if admissionWebhookErrorMatcher := admissionWebhookErrorExpression.FindStringSubmatch(err.Error()); len(admissionWebhookErrorMatcher) == 5 { log.Error(err) return fmt.Errorf("DNS alias %s cannot be used, because the host %s with the path %s is already in use", s.radixDNSAlias.GetName(), admissionWebhookErrorMatcher[1], admissionWebhookErrorMatcher[2]) } diff --git a/pkg/apis/job/job_test.go b/pkg/apis/job/job_test.go index 145b8fc1b..b60f7540d 100644 --- a/pkg/apis/job/job_test.go +++ b/pkg/apis/job/job_test.go @@ -268,7 +268,9 @@ func (s *RadixJobTestSuite) TestObjectSynced_FirstJobRunning_SecondJobQueued() { // Stopping first job should set second job to running firstJob.Spec.Stop = true - s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}) + if _, err := s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}); err != nil { + panic(err) + } err = s.runSync(firstJob, config) s.Require().NoError(err) @@ -289,7 +291,9 @@ func (s *RadixJobTestSuite) TestObjectSynced_FirstJobWaiting_SecondJobQueued() { // Stopping first job should set second job to running firstJob.Spec.Stop = true - s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}) + if _, err := s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}); err != nil { + panic(err) + } err = s.runSync(firstJob, config) s.Require().NoError(err) @@ -315,7 +319,10 @@ func (s *RadixJobTestSuite) TestObjectSynced_MultipleJobs_MissingRadixApplicatio // Stopping first job should set second job to running firstJob.Spec.Stop = true - s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}) + if _, err := s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}); err != nil { + panic(err) + } + err = s.runSync(firstJob, config) s.Require().NoError(err) @@ -657,7 +664,9 @@ func (s *RadixJobTestSuite) TestHistoryLimit_EachEnvHasOwnHistory() { WithAppName(appName).WithDeploymentName(rdJob.rdName).WithEnvironment(rdJob.env).WithJobName(rdJob.jobName). WithActiveFrom(testTime)) s.NoError(err) - s.applyJobWithSyncFor(raBuilder, appName, rdJob, config) + if err := s.applyJobWithSyncFor(raBuilder, appName, rdJob, config); err != nil { + panic(err) + } testTime = testTime.Add(time.Hour) } @@ -666,7 +675,9 @@ func (s *RadixJobTestSuite) TestHistoryLimit_EachEnvHasOwnHistory() { WithEnvironment(scenario.testingRadixDeploymentJob.env). WithActiveFrom(testTime)) s.NoError(err) - s.applyJobWithSyncFor(raBuilder, appName, scenario.testingRadixDeploymentJob, config) + if err := s.applyJobWithSyncFor(raBuilder, appName, scenario.testingRadixDeploymentJob, config); err != nil { + panic(err) + } radixJobList, err := s.radixClient.RadixV1().RadixJobs(appNamespace).List(context.TODO(), metav1.ListOptions{}) s.NoError(err) @@ -790,7 +801,9 @@ func (s *RadixJobTestSuite) Test_WildCardJobs() { config := getConfigWithPipelineJobsHistoryLimit(10) testTime := time.Now().Add(time.Hour * -100) raBuilder := scenario.raBuilder.WithAppName(appName) - s.testUtils.ApplyApplication(raBuilder) + if _, err := s.testUtils.ApplyApplication(raBuilder); err != nil { + panic(err) + } for _, rdJob := range scenario.existingRadixDeploymentJobs { if rdJob.jobStatus == radixv1.JobSucceeded { _, err := s.testUtils.ApplyDeployment(utils.ARadixDeployment(). diff --git a/pkg/apis/kube/environment_variables_test.go b/pkg/apis/kube/environment_variables_test.go index 3488fe339..145b2329d 100644 --- a/pkg/apis/kube/environment_variables_test.go +++ b/pkg/apis/kube/environment_variables_test.go @@ -208,11 +208,13 @@ func Test_SetEnvVarsMetadataMapToConfigMap(t *testing.T) { }, } - SetEnvVarsMetadataMapToConfigMap(¤tMetadataConfigMap, map[string]EnvVarMetadata{ + if err := SetEnvVarsMetadataMapToConfigMap(¤tMetadataConfigMap, map[string]EnvVarMetadata{ "VAR1": {RadixConfigValue: "val1changed"}, "VAR2": {RadixConfigValue: "added"}, - //VAR3: removed - }) + // VAR3: removed + }); err != nil { + panic(err) + } assert.NotNil(t, currentMetadataConfigMap.Data) assert.NotNil(t, currentMetadataConfigMap.Data["metadata"]) @@ -249,17 +251,19 @@ func Test_ApplyEnvVarsMetadataConfigMap(t *testing.T) { metadata := map[string]EnvVarMetadata{ "VAR1": {RadixConfigValue: "val1changed"}, "VAR2": {RadixConfigValue: "added"}, - //VAR3: removed + // VAR3: removed } t.Run("Save changes", func(t *testing.T) { t.Parallel() testEnv := getEnvironmentVariablesTestEnv() - testEnv.kubeclient.CoreV1().ConfigMaps(namespace).Create(context.Background(), &corev1.ConfigMap{ + if _, err := testEnv.kubeclient.CoreV1().ConfigMaps(namespace).Create(context.Background(), &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, - }}, metav1.CreateOptions{}) + }}, metav1.CreateOptions{}); err != nil { + panic(err) + } err := testEnv.kubeUtil.ApplyEnvVarsMetadataConfigMap(namespace, ¤tMetadataConfigMap, metadata) @@ -454,5 +458,7 @@ func Test_BuildRadixConfigEnvVarsMetadataConfigMap(t *testing.T) { } func createConfigMap(kubeUtil *Kube, namespace string, configMap *corev1.ConfigMap) { - kubeUtil.kubeClient.CoreV1().ConfigMaps(namespace).Create(context.Background(), configMap, metav1.CreateOptions{}) + if _, err := kubeUtil.kubeClient.CoreV1().ConfigMaps(namespace).Create(context.Background(), configMap, metav1.CreateOptions{}); err != nil { + panic(err) + } } diff --git a/pkg/apis/test/utils.go b/pkg/apis/test/utils.go index f72be8f9d..e52b71e12 100644 --- a/pkg/apis/test/utils.go +++ b/pkg/apis/test/utils.go @@ -99,12 +99,14 @@ func (tu *Utils) ApplyApplication(applicationBuilder utils.ApplicationBuilder) ( ra.ObjectMeta.UID = uuid.NewUUID() // imitate new UID, assigned by Kubernetes // Note: rr may be nil if not found but that is fine for _, env := range ra.Spec.Environments { - tu.ApplyEnvironment(utils.NewEnvironmentBuilder(). + if _, err := tu.ApplyEnvironment(utils.NewEnvironmentBuilder(). WithAppName(ra.GetName()). WithAppLabel(). WithEnvironmentName(env.Name). WithRegistrationOwner(rr). - WithOrphaned(false)) + WithOrphaned(false)); err != nil { + panic(err) + } } return ra, nil @@ -133,11 +135,13 @@ func (tu *Utils) ApplyApplicationUpdate(applicationBuilder utils.ApplicationBuil // Note: rr may be nil if not found but that is fine for _, env := range ra.Spec.Environments { - tu.ApplyEnvironment(utils.NewEnvironmentBuilder(). + if _, err := tu.ApplyEnvironment(utils.NewEnvironmentBuilder(). WithAppName(ra.GetName()). WithAppLabel(). WithEnvironmentName(env.Name). - WithRegistrationOwner(rr)) + WithRegistrationOwner(rr)); err != nil { + panic(err) + } } return ra, nil @@ -193,7 +197,9 @@ func (tu *Utils) ApplyDeploymentUpdate(deploymentBuilder utils.DeploymentBuilder // ApplyJob Will help persist a radixjob func (tu *Utils) ApplyJob(jobBuilder utils.JobBuilder) (*radixv1.RadixJob, error) { if jobBuilder.GetApplicationBuilder() != nil { - tu.ApplyApplication(jobBuilder.GetApplicationBuilder()) + if _, err := tu.ApplyApplication(jobBuilder.GetApplicationBuilder()); err != nil { + panic(err) + } } rj := jobBuilder.BuildRJ() @@ -283,7 +289,7 @@ func SetRequiredEnvironmentVariables() { func (tu *Utils) CreateClusterPrerequisites(clustername, egressIps, subscriptionId string) { SetRequiredEnvironmentVariables() - tu.client.CoreV1().Secrets(corev1.NamespaceDefault).Create( + if _, err := tu.client.CoreV1().Secrets(corev1.NamespaceDefault).Create( context.TODO(), &corev1.Secret{ Type: "Opaque", @@ -295,9 +301,11 @@ func (tu *Utils) CreateClusterPrerequisites(clustername, egressIps, subscription "known_hosts": []byte("abcd"), }, }, - metav1.CreateOptions{}) + metav1.CreateOptions{}); err != nil { + panic(err) + } - tu.client.CoreV1().ConfigMaps(corev1.NamespaceDefault).Create( + if _, err := tu.client.CoreV1().ConfigMaps(corev1.NamespaceDefault).Create( context.TODO(), &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ @@ -310,7 +318,9 @@ func (tu *Utils) CreateClusterPrerequisites(clustername, egressIps, subscription "subscriptionId": subscriptionId, }, }, - metav1.CreateOptions{}) + metav1.CreateOptions{}); err != nil { + panic(err) + } } // CreateAppNamespace Helper method to creat app namespace @@ -338,7 +348,9 @@ func createNamespace(kubeclient kubernetes.Interface, appName, envName, ns strin }, } - kubeclient.CoreV1().Namespaces().Create(context.TODO(), &namespace, metav1.CreateOptions{}) + if _, err := kubeclient.CoreV1().Namespaces().Create(context.TODO(), &namespace, metav1.CreateOptions{}); err != nil { + log.Error(err) + } } // IntPtr Helper function to get the pointer of an int diff --git a/radix-operator/alert/controller.go b/radix-operator/alert/controller.go index fef5360b6..7a0a6b4e7 100644 --- a/radix-operator/alert/controller.go +++ b/radix-operator/alert/controller.go @@ -15,6 +15,7 @@ import ( log "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" kubeinformers "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" @@ -60,9 +61,11 @@ func NewController(client kubernetes.Interface, } logger.Info("Setting up event handlers") - alertInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := alertInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { - controller.Enqueue(cur) + if _, err := controller.Enqueue(cur); err != nil { + utilruntime.HandleError(err) + } metrics.CustomResourceAdded(crType) }, UpdateFunc: func(old, cur interface{}) { @@ -74,7 +77,9 @@ func NewController(client kubernetes.Interface, return } - controller.Enqueue(cur) + if _, err := controller.Enqueue(cur); err != nil { + utilruntime.HandleError(err) + } }, DeleteFunc: func(obj interface{}) { radixAlert, converted := obj.(*radixv1.RadixAlert) @@ -88,9 +93,11 @@ func NewController(client kubernetes.Interface, } metrics.CustomResourceDeleted(crType) }, - }) + }); err != nil { + utilruntime.HandleError(err) + } - registrationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := registrationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: func(oldObj, newObj interface{}) { newRr := newObj.(*radixv1.RadixRegistration) oldRr := oldObj.(*radixv1.RadixRegistration) @@ -111,11 +118,15 @@ func NewController(client kubernetes.Interface, }) if err == nil { for _, radixalert := range radixalerts.Items { - controller.Enqueue(&radixalert) + if _, err := controller.Enqueue(&radixalert); err != nil { + utilruntime.HandleError(err) + } } } }, - }) + }); err != nil { + utilruntime.HandleError(err) + } return controller } diff --git a/radix-operator/alert/controller_test.go b/radix-operator/alert/controller_test.go index 7d8441b13..594dfc3d8 100644 --- a/radix-operator/alert/controller_test.go +++ b/radix-operator/alert/controller_test.go @@ -28,22 +28,34 @@ func (s *controllerTestSuite) Test_RadixAlertEvents() { sut := NewController(s.KubeClient, s.RadixClient, s.Handler, s.KubeInformerFactory, s.RadixInformerFactory, false, s.EventRecorder) s.RadixInformerFactory.Start(s.Stop) s.KubeInformerFactory.Start(s.Stop) - go sut.Run(5, s.Stop) + go func() { + if err := sut.Run(5, s.Stop); err != nil { + panic(err) + } + }() // Adding a RadixAlert should trigger sync s.Handler.EXPECT().Sync(namespace, alertName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) - alert, _ = s.RadixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), alert, metav1.CreateOptions{}) + alert, err := s.RadixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), alert, metav1.CreateOptions{}) + if err != nil { + panic(err) + } + s.WaitForSynced("first call") // Updating the RadixAlert with changes should trigger a sync s.Handler.EXPECT().Sync(namespace, alertName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) alert.Labels = map[string]string{"foo": "bar"} - s.RadixClient.RadixV1().RadixAlerts(namespace).Update(context.TODO(), alert, metav1.UpdateOptions{}) + if _, err := s.RadixClient.RadixV1().RadixAlerts(namespace).Update(context.TODO(), alert, metav1.UpdateOptions{}); err != nil { + panic(err) + } s.WaitForSynced("second call") // Updating the RadixAlert with no changes should not trigger a sync s.Handler.EXPECT().Sync(namespace, alertName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) - s.RadixClient.RadixV1().RadixAlerts(namespace).Update(context.TODO(), alert, metav1.UpdateOptions{}) + if _, err := s.RadixClient.RadixV1().RadixAlerts(namespace).Update(context.TODO(), alert, metav1.UpdateOptions{}); err != nil { + panic(err) + } s.WaitForNotSynced("Sync should not be called when updating RadixAlert with no changes") } @@ -52,29 +64,43 @@ func (s *controllerTestSuite) Test_RadixRegistrationEvents() { alert1 := &v1.RadixAlert{ObjectMeta: metav1.ObjectMeta{Name: alert1Name, Labels: map[string]string{kube.RadixAppLabel: appName}}} alert2 := &v1.RadixAlert{ObjectMeta: metav1.ObjectMeta{Name: alert2Name}} rr := &v1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}, Spec: v1.RadixRegistrationSpec{Owner: "first-owner", AdGroups: []string{"first-admin-group"}, ReaderAdGroups: []string{"first-reader-group"}}} - rr, _ = s.RadixClient.RadixV1().RadixRegistrations().Create(context.TODO(), rr, metav1.CreateOptions{}) + rr, err := s.RadixClient.RadixV1().RadixRegistrations().Create(context.TODO(), rr, metav1.CreateOptions{}) + if err != nil { + panic(err) + } sut := NewController(s.KubeClient, s.RadixClient, s.Handler, s.KubeInformerFactory, s.RadixInformerFactory, false, s.EventRecorder) s.RadixInformerFactory.Start(s.Stop) s.KubeInformerFactory.Start(s.Stop) - go sut.Run(5, s.Stop) + go func() { + if err := sut.Run(5, s.Stop); err != nil { + panic(err) + } + }() hasSynced := cache.WaitForCacheSync(s.Stop, s.RadixInformerFactory.Radix().V1().RadixRegistrations().Informer().HasSynced) s.True(hasSynced) // Initial Sync for the two alerts - s.RadixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), alert1, metav1.CreateOptions{}) + if _, err := s.RadixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), alert1, metav1.CreateOptions{}); err != nil { + panic(err) + } s.Handler.EXPECT().Sync(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("sync of alert1") - s.RadixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), alert2, metav1.CreateOptions{}) + if _, err := s.RadixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), alert2, metav1.CreateOptions{}); err != nil { + panic(err) + } s.Handler.EXPECT().Sync(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("initial sync of alert2") // Update adGroups should trigger sync of alert1 rr.Spec.AdGroups = []string{"another-admin-group"} rr.ResourceVersion = "2" - rr, _ = s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}) + rr, err = s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}) + if err != nil { + panic(err) + } s.Handler.EXPECT().Sync(namespace, alert1Name, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("sync on adGroups update") @@ -88,7 +114,9 @@ func (s *controllerTestSuite) Test_RadixRegistrationEvents() { // Update other props on RR should not trigger sync of alert1 rr.Spec.Owner = "owner" rr.ResourceVersion = "4" - s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}) + if _, err := s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}); err != nil { + panic(err) + } s.Handler.EXPECT().Sync(namespace, alert1Name, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) s.WaitForNotSynced("Sync should not be called when updating other RR props") } diff --git a/radix-operator/application/controller.go b/radix-operator/application/controller.go index ee672e510..1877de9e3 100644 --- a/radix-operator/application/controller.go +++ b/radix-operator/application/controller.go @@ -7,6 +7,7 @@ import ( radixutils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-operator/pkg/apis/utils" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "github.com/equinor/radix-operator/pkg/apis/metrics" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -59,9 +60,11 @@ func NewController(client kubernetes.Interface, } logger.Info("Setting up event handlers") - applicationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := applicationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { - controller.Enqueue(cur) + if _, err := controller.Enqueue(cur); err != nil { + utilruntime.HandleError(err) + } metrics.CustomResourceAdded(crType) }, UpdateFunc: func(old, cur interface{}) { @@ -73,7 +76,9 @@ func NewController(client kubernetes.Interface, return } - controller.Enqueue(cur) + if _, err := controller.Enqueue(cur); err != nil { + utilruntime.HandleError(err) + } }, DeleteFunc: func(obj interface{}) { radixApplication, converted := obj.(*v1.RadixApplication) @@ -87,8 +92,10 @@ func NewController(client kubernetes.Interface, } metrics.CustomResourceDeleted(crType) }, - }) - registrationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + }); err != nil { + utilruntime.HandleError(err) + } + if _, err := registrationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: func(old, cur interface{}) { newRr := cur.(*v1.RadixRegistration) oldRr := old.(*v1.RadixRegistration) @@ -105,10 +112,14 @@ func NewController(client kubernetes.Interface, return } logger.Debugf("update Radix Application due to changed admin or reader AD groups") - controller.Enqueue(ra) + if _, err := controller.Enqueue(ra); err != nil { + utilruntime.HandleError(err) + } metrics.CustomResourceUpdated(crType) }, - }) + }); err != nil { + utilruntime.HandleError(err) + } return controller } diff --git a/radix-operator/application/controller_test.go b/radix-operator/application/controller_test.go index 559318048..dd33e394b 100644 --- a/radix-operator/application/controller_test.go +++ b/radix-operator/application/controller_test.go @@ -29,10 +29,16 @@ func (s *controllerTestSuite) Test_Controller_Calls_Handler() { s.RadixInformerFactory.Start(s.Stop) s.KubeInformerFactory.Start(s.Stop) - go sut.Run(1, s.Stop) + go func() { + if err := sut.Run(1, s.Stop); err != nil { + panic(err) + } + }() ra := utils.ARadixApplication().WithAppName(appName).WithEnvironment("dev", "master").BuildRA() - s.RadixClient.RadixV1().RadixApplications(appNamespace).Create(context.TODO(), ra, metav1.CreateOptions{}) + if _, err := s.RadixClient.RadixV1().RadixApplications(appNamespace).Create(context.TODO(), ra, metav1.CreateOptions{}); err != nil { + panic(err) + } s.Handler.EXPECT().Sync(namespace, appName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("added app") @@ -43,26 +49,39 @@ func (s *controllerTestSuite) Test_Controller_Calls_Handler_On_Admin_Or_Reader_C namespace := utils.GetAppNamespace(appName) appNamespace := test.CreateAppNamespace(s.KubeClient, appName) rr := &v1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}, Spec: v1.RadixRegistrationSpec{AdGroups: []string{"first-admin"}, ReaderAdGroups: []string{"first-reader-group"}}} - rr, _ = s.RadixClient.RadixV1().RadixRegistrations().Create(context.TODO(), rr, metav1.CreateOptions{}) + rr, err := s.RadixClient.RadixV1().RadixRegistrations().Create(context.TODO(), rr, metav1.CreateOptions{}) + if err != nil { + panic(err) + } sut := NewController(s.KubeClient, s.RadixClient, s.Handler, s.KubeInformerFactory, s.RadixInformerFactory, false, s.EventRecorder) s.RadixInformerFactory.Start(s.Stop) s.KubeInformerFactory.Start(s.Stop) - go sut.Run(1, s.Stop) + go func() { + if err := sut.Run(1, s.Stop); err != nil { + panic(err) + } + }() ra := utils.ARadixApplication().WithAppName(appName).WithEnvironment("dev", "master").BuildRA() - s.RadixClient.RadixV1().RadixApplications(appNamespace).Create(context.TODO(), ra, metav1.CreateOptions{}) + if _, err := s.RadixClient.RadixV1().RadixApplications(appNamespace).Create(context.TODO(), ra, metav1.CreateOptions{}); err != nil { + panic(err) + } s.Handler.EXPECT().Sync(namespace, appName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("added app") rr.Spec.AdGroups = []string{"another-admin-group"} - s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}) + if _, err := s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}); err != nil { + panic(err) + } s.Handler.EXPECT().Sync(namespace, appName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("AdGroups changed") rr.Spec.ReaderAdGroups = []string{"another-reader-group"} - s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}) + if _, err := s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}); err != nil { + panic(err) + } s.Handler.EXPECT().Sync(namespace, appName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("ReaderAdGroups changed") } diff --git a/radix-operator/batch/controller.go b/radix-operator/batch/controller.go index f4a4a5585..8cbcfabbd 100644 --- a/radix-operator/batch/controller.go +++ b/radix-operator/batch/controller.go @@ -12,6 +12,7 @@ import ( "github.com/equinor/radix-operator/radix-operator/common" log "github.com/sirupsen/logrus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" kubeinformers "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" @@ -58,9 +59,11 @@ func NewController(client kubernetes.Interface, } logger.Info("Setting up event handlers") - batchInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := batchInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { - controller.Enqueue(cur) + if _, err := controller.Enqueue(cur); err != nil { + utilruntime.HandleError(err) + } metrics.CustomResourceAdded(crType) }, UpdateFunc: func(old, cur interface{}) { @@ -71,8 +74,9 @@ func NewController(client kubernetes.Interface, metrics.CustomResourceUpdatedButSkipped(crType) return } - - controller.Enqueue(cur) + if _, err := controller.Enqueue(cur); err != nil { + utilruntime.HandleError(err) + } }, DeleteFunc: func(obj interface{}) { radixBatch, _ := obj.(*radixv1.RadixBatch) @@ -82,9 +86,11 @@ func NewController(client kubernetes.Interface, } metrics.CustomResourceDeleted(crType) }, - }) + }); err != nil { + panic(err) + } - jobInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := jobInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: func(oldObj, newObj interface{}) { oldMeta := oldObj.(metav1.Object) newMeta := newObj.(metav1.Object) @@ -96,8 +102,9 @@ func NewController(client kubernetes.Interface, DeleteFunc: func(obj interface{}) { controller.HandleObject(obj, radix.KindRadixBatch, getOwner) }, - }) - + }); err != nil { + panic(err) + } return controller } diff --git a/radix-operator/batch/controller_test.go b/radix-operator/batch/controller_test.go index 8f899f9b1..14cb78589 100644 --- a/radix-operator/batch/controller_test.go +++ b/radix-operator/batch/controller_test.go @@ -28,7 +28,12 @@ func (s *controllerTestSuite) Test_RadixBatchEvents() { sut := NewController(s.KubeClient, s.RadixClient, s.Handler, s.KubeInformerFactory, s.RadixInformerFactory, false, s.EventRecorder) s.RadixInformerFactory.Start(s.Stop) s.KubeInformerFactory.Start(s.Stop) - go sut.Run(5, s.Stop) + go func() { + err := sut.Run(5, s.Stop) + if err != nil { + panic(err) + } + }() batch := &v1.RadixBatch{ObjectMeta: metav1.ObjectMeta{Name: batchName, Namespace: namespace}} diff --git a/radix-operator/common/controller.go b/radix-operator/common/controller.go index 6e30af77a..a7fe5dcf0 100644 --- a/radix-operator/common/controller.go +++ b/radix-operator/common/controller.go @@ -79,7 +79,9 @@ func (c *Controller) run(threadiness int, stopCh <-chan struct{}) { errorGroup.SetLimit(threadiness) defer func() { c.Log.Info("Waiting for workers to complete") - errorGroup.Wait() + if err := errorGroup.Wait(); err != nil { + log.Error(err) + } c.Log.Info("Workers completed") }() @@ -91,7 +93,9 @@ func (c *Controller) run(threadiness int, stopCh <-chan struct{}) { for c.processNext(&errorGroup, stopCh, locker) { } - errorGroup.Wait() + if err := errorGroup.Wait(); err != nil { + log.Error(err) + } } func (c *Controller) processNext(errorGroup *errgroup.Group, stopCh <-chan struct{}, locker resourceLocker) bool { diff --git a/radix-operator/common/controller_test.go b/radix-operator/common/controller_test.go index fb041f0aa..444430fe5 100644 --- a/radix-operator/common/controller_test.go +++ b/radix-operator/common/controller_test.go @@ -77,7 +77,11 @@ func (s *commonControllerTestSuite) Test_SyncSuccess() { s.KubeInformerFactory.Start(stopCh) - go sut.Run(1, stopCh) + go func() { + if err := sut.Run(1, stopCh); err != nil { + panic(err) + } + }() doneCh := make(chan struct{}) item := "ns/item" @@ -120,7 +124,11 @@ func (s *commonControllerTestSuite) Test_RequeueWhenSyncError() { s.KubeInformerFactory.Start(stopCh) - go sut.Run(1, stopCh) + go func() { + if err := sut.Run(1, stopCh); err != nil { + panic(err) + } + }() doneCh := make(chan struct{}) item := "ns/item" @@ -162,7 +170,11 @@ func (s *commonControllerTestSuite) Test_ForgetWhenLockKeyAndIdentifierError() { s.KubeInformerFactory.Start(stopCh) - go sut.Run(1, stopCh) + go func() { + if err := sut.Run(1, stopCh); err != nil { + panic(err) + } + }() doneCh := make(chan struct{}) item := "ns/item" @@ -201,7 +213,11 @@ func (s *commonControllerTestSuite) Test_SkipItemWhenNil() { s.KubeInformerFactory.Start(stopCh) - go sut.Run(1, stopCh) + go func() { + if err := sut.Run(1, stopCh); err != nil { + panic(err) + } + }() doneCh := make(chan struct{}) queue.On("ShuttingDown").Return(false).Times(1) @@ -238,7 +254,11 @@ func (s *commonControllerTestSuite) Test_SkipItemWhenEmpty() { s.KubeInformerFactory.Start(stopCh) - go sut.Run(1, stopCh) + go func() { + if err := sut.Run(1, stopCh); err != nil { + panic(err) + } + }() doneCh := make(chan struct{}) item := "" @@ -277,7 +297,9 @@ func (s *commonControllerTestSuite) Test_QuitRunWhenShutdownTrue() { doneCh := make(chan struct{}) go func() { - sut.Run(1, stopCh) + if err := sut.Run(1, stopCh); err != nil { + panic(err) + } close(doneCh) }() @@ -315,7 +337,9 @@ func (s *commonControllerTestSuite) Test_QuitRunWhenShuttingDownTrue() { doneCh := make(chan struct{}) go func() { - sut.Run(1, stopCh) + if err := sut.Run(1, stopCh); err != nil { + panic(err) + } close(doneCh) }() @@ -354,7 +378,11 @@ func (s *commonControllerTestSuite) Test_RequeueWhenLocked() { s.KubeInformerFactory.Start(stopCh) - go sut.Run(1, stopCh) + go func() { + if err := sut.Run(1, stopCh); err != nil { + panic(err) + } + }() doneCh := make(chan struct{}) item := "ns/item" @@ -408,7 +436,11 @@ func (s *commonControllerTestSuite) Test_ProcessParallell() { threadiness := 5 queue.On("ShuttingDown").Return(false) - go sut.Run(threadiness, stopCh) + go func() { + if err := sut.Run(threadiness, stopCh); err != nil { + panic(err) + } + }() for i := 0; i < len(testItems); i++ { i := i diff --git a/radix-operator/common/utils.go b/radix-operator/common/utils.go index 80e54d3dc..eb938955d 100644 --- a/radix-operator/common/utils.go +++ b/radix-operator/common/utils.go @@ -2,6 +2,8 @@ package common import ( "fmt" + "sync" + radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" radixscheme "github.com/equinor/radix-operator/pkg/client/clientset/versioned/scheme" log "github.com/sirupsen/logrus" @@ -10,7 +12,6 @@ import ( typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" - "sync" ) type resourceLocker interface { @@ -71,7 +72,9 @@ type GetOwner func(radixclient.Interface, string, string) (interface{}, error) // NewEventRecorder Creates an event recorder for controller func NewEventRecorder(controllerAgentName string, events typedcorev1.EventInterface, logger *log.Entry) record.EventRecorder { - radixscheme.AddToScheme(scheme.Scheme) + if err := radixscheme.AddToScheme(scheme.Scheme); err != nil { + panic(err) + } logger.Info("Creating event broadcaster") eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(logger.Infof) diff --git a/radix-operator/deployment/controller.go b/radix-operator/deployment/controller.go index 0434d0125..52bd43c6f 100644 --- a/radix-operator/deployment/controller.go +++ b/radix-operator/deployment/controller.go @@ -17,6 +17,7 @@ import ( log "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" kubeinformers "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" @@ -64,7 +65,7 @@ func NewController(client kubernetes.Interface, } logger.Info("Setting up event handlers") - deploymentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := deploymentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { radixDeployment, _ := cur.(*v1.RadixDeployment) if deployment.IsRadixDeploymentInactive(radixDeployment) { @@ -73,7 +74,9 @@ func NewController(client kubernetes.Interface, return } - controller.Enqueue(cur) + if _, err := controller.Enqueue(cur); err != nil { + utilruntime.HandleError(err) + } metrics.CustomResourceAdded(crType) }, UpdateFunc: func(old, cur interface{}) { @@ -91,7 +94,9 @@ func NewController(client kubernetes.Interface, return } - controller.Enqueue(cur) + if _, err := controller.Enqueue(cur); err != nil { + utilruntime.HandleError(err) + } metrics.CustomResourceUpdated(crType) }, DeleteFunc: func(obj interface{}) { @@ -106,11 +111,13 @@ func NewController(client kubernetes.Interface, } metrics.CustomResourceDeleted(crType) }, - }) + }); err != nil { + panic(err) + } // Only the service informer works with this, because it makes use of patch // if not it will end up in an endless loop (deployment, ingress etc.) - serviceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := serviceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { service := obj.(*corev1.Service) logger.Debugf("Service object added event received for %s. Do nothing", service.Name) @@ -126,9 +133,11 @@ func NewController(client kubernetes.Interface, DeleteFunc: func(obj interface{}) { controller.HandleObject(obj, radix.KindRadixDeployment, getObject) }, - }) + }); err != nil { + utilruntime.HandleError(err) + } - registrationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := registrationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: func(old, cur interface{}) { newRr := cur.(*v1.RadixRegistration) oldRr := old.(*v1.RadixRegistration) @@ -155,12 +164,16 @@ func NewController(client kubernetes.Interface, for _, rd := range rds.Items { if !deployment.IsRadixDeploymentInactive(&rd) { obj := &rd - controller.Enqueue(obj) + if _, err := controller.Enqueue(obj); err != nil { + utilruntime.HandleError(err) + } } } } }, - }) + }); err != nil { + utilruntime.HandleError(err) + } return controller } diff --git a/radix-operator/deployment/controller_test.go b/radix-operator/deployment/controller_test.go index 1e7b8482e..4374f61f3 100644 --- a/radix-operator/deployment/controller_test.go +++ b/radix-operator/deployment/controller_test.go @@ -49,7 +49,7 @@ func Test_Controller_Calls_Handler(t *testing.T) { // Setup tu, client, kubeUtil, radixClient, prometheusclient := setupTest() - client.CoreV1().Namespaces().Create( + if _, err := client.CoreV1().Namespaces().Create( context.TODO(), &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ @@ -60,7 +60,9 @@ func Test_Controller_Calls_Handler(t *testing.T) { }, }, }, - metav1.CreateOptions{}) + metav1.CreateOptions{}); err != nil { + panic(err) + } stop := make(chan struct{}) synced := make(chan bool) @@ -99,7 +101,9 @@ func Test_Controller_Calls_Handler(t *testing.T) { // Update deployment should sync. Only actual updates will be handled by the controller noReplicas := 0 rd.Spec.Components[0].Replicas = &noReplicas - radixClient.RadixV1().RadixDeployments(rd.ObjectMeta.Namespace).Update(context.TODO(), rd, metav1.UpdateOptions{}) + if _, err := radixClient.RadixV1().RadixDeployments(rd.ObjectMeta.Namespace).Update(context.TODO(), rd, metav1.UpdateOptions{}); err != nil { + panic(err) + } op, ok = <-synced assert.True(t, ok) @@ -118,7 +122,9 @@ func Test_Controller_Calls_Handler(t *testing.T) { }) for _, aservice := range services.Items { - client.CoreV1().Services(rd.ObjectMeta.Namespace).Delete(context.TODO(), aservice.Name, metav1.DeleteOptions{}) + if err := client.CoreV1().Services(rd.ObjectMeta.Namespace).Delete(context.TODO(), aservice.Name, metav1.DeleteOptions{}); err != nil { + panic(err) + } op, ok = <-synced assert.True(t, ok) @@ -151,6 +157,7 @@ func startDeploymentController(client kubernetes.Interface, kubeInformerFactory.Start(stop) radixInformerFactory.Start(stop) - controller.Run(4, stop) - + if err := controller.Run(4, stop); err != nil { + panic(err) + } } diff --git a/radix-operator/deployment/handler_test.go b/radix-operator/deployment/handler_test.go index c4a9fd4e2..62fc9133e 100644 --- a/radix-operator/deployment/handler_test.go +++ b/radix-operator/deployment/handler_test.go @@ -63,28 +63,36 @@ func (s *handlerSuite) Test_Sync() { appName := "any-app" namespace := "any-ns" - s.radixClient.Tracker().Add( + if err := s.radixClient.Tracker().Add( &radixv1.RadixDeployment{ ObjectMeta: v1.ObjectMeta{Name: inactiveRdName, Namespace: namespace}, Status: radixv1.RadixDeployStatus{Condition: radixv1.DeploymentInactive}, }, - ) - s.radixClient.Tracker().Add( + ); err != nil { + panic(err) + } + if err := s.radixClient.Tracker().Add( &radixv1.RadixDeployment{ ObjectMeta: v1.ObjectMeta{Name: activeRdMissingRrName, Namespace: namespace}, Status: radixv1.RadixDeployStatus{Condition: radixv1.DeploymentActive}, }, - ) + ); err != nil { + panic(err) + } activeRd := &radixv1.RadixDeployment{ ObjectMeta: v1.ObjectMeta{Name: activeRdName, Namespace: namespace}, Spec: radixv1.RadixDeploymentSpec{AppName: appName}, Status: radixv1.RadixDeployStatus{Condition: radixv1.DeploymentActive}, } - s.radixClient.Tracker().Add(activeRd) + if err := s.radixClient.Tracker().Add(activeRd); err != nil { + panic(err) + } rr := &radixv1.RadixRegistration{ ObjectMeta: v1.ObjectMeta{Name: appName}, } - s.radixClient.Tracker().Add(rr) + if err := s.radixClient.Tracker().Add(rr); err != nil { + panic(err) + } s.Run("non-existing RD should not call factory method", func() { ctrl := gomock.NewController(s.T()) diff --git a/radix-operator/environment/controller.go b/radix-operator/environment/controller.go index d1bb945ce..30733ba7a 100644 --- a/radix-operator/environment/controller.go +++ b/radix-operator/environment/controller.go @@ -16,6 +16,7 @@ import ( "github.com/equinor/radix-operator/radix-operator/common" "github.com/sirupsen/logrus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" kubeinformers "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" @@ -64,9 +65,11 @@ func NewController(client kubernetes.Interface, logger.Info("Setting up event handlers") - environmentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := environmentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { - controller.Enqueue(cur) + if _, err := controller.Enqueue(cur); err != nil { + utilruntime.HandleError(err) + } metrics.CustomResourceAdded(crType) }, UpdateFunc: func(old, cur interface{}) { @@ -79,7 +82,9 @@ func NewController(client kubernetes.Interface, return } - controller.Enqueue(cur) + if _, err := controller.Enqueue(cur); err != nil { + utilruntime.HandleError(err) + } metrics.CustomResourceUpdated(crType) }, DeleteFunc: func(obj interface{}) { @@ -94,33 +99,41 @@ func NewController(client kubernetes.Interface, } metrics.CustomResourceDeleted(crType) }, - }) + }); err != nil { + utilruntime.HandleError(err) + } namespaceInformer := kubeInformerFactory.Core().V1().Namespaces() - namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ DeleteFunc: func(obj interface{}) { // attempt to sync environment if it is the owner of this namespace controller.HandleObject(obj, radix.KindRadixEnvironment, getOwner) }, - }) + }); err != nil { + utilruntime.HandleError(err) + } rolebindingInformer := kubeInformerFactory.Rbac().V1().RoleBindings() - rolebindingInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := rolebindingInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ DeleteFunc: func(obj interface{}) { // attempt to sync environment if it is the owner of this role-binding controller.HandleObject(obj, radix.KindRadixEnvironment, getOwner) }, - }) + }); err != nil { + utilruntime.HandleError(err) + } limitrangeInformer := kubeInformerFactory.Core().V1().LimitRanges() - limitrangeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := limitrangeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ DeleteFunc: func(obj interface{}) { // attempt to sync environment if it is the owner of this limit-range controller.HandleObject(obj, radix.KindRadixEnvironment, getOwner) }, - }) + }); err != nil { + utilruntime.HandleError(err) + } - registrationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := registrationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: func(old, cur interface{}) { newRr := cur.(*v1.RadixRegistration) oldRr := old.(*v1.RadixRegistration) @@ -145,13 +158,17 @@ func NewController(client kubernetes.Interface, if err == nil { for _, environment := range environments.Items { // Will sync the environment - controller.Enqueue(&environment) + if _, err := controller.Enqueue(&environment); err != nil { + utilruntime.HandleError(err) + } } } }, - }) + }); err != nil { + utilruntime.HandleError(err) + } - applicationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := applicationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: func(old, cur interface{}) { newRa := cur.(*v1.RadixApplication) oldRa := old.(*v1.RadixApplication) @@ -164,7 +181,9 @@ func NewController(client kubernetes.Interface, uniqueName := utils.GetEnvironmentNamespace(oldRa.Name, envName) re, err := radixClient.RadixV1().RadixEnvironments().Get(context.TODO(), uniqueName, metav1.GetOptions{}) if err == nil { - controller.Enqueue(re) + if _, err := controller.Enqueue(re); err != nil { + utilruntime.HandleError(err) + } } } }, @@ -178,11 +197,15 @@ func NewController(client kubernetes.Interface, uniqueName := utils.GetEnvironmentNamespace(radixApplication.Name, env.Name) re, err := radixClient.RadixV1().RadixEnvironments().Get(context.TODO(), uniqueName, metav1.GetOptions{}) if err == nil { - controller.Enqueue(re) + if _, err := controller.Enqueue(re); err != nil { + utilruntime.HandleError(err) + } } } }, - }) + }); err != nil { + utilruntime.HandleError(err) + } return controller } diff --git a/radix-operator/job/controller.go b/radix-operator/job/controller.go index f1204d986..98b2532a3 100644 --- a/radix-operator/job/controller.go +++ b/radix-operator/job/controller.go @@ -15,6 +15,7 @@ import ( batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" kubeinformers "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" @@ -56,7 +57,7 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac } logger.Info("Setting up event handlers") - jobInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := jobInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { radixJob, _ := cur.(*v1.RadixJob) if job.IsRadixJobDone(radixJob) { @@ -66,7 +67,9 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac return } - controller.Enqueue(cur) + if _, err := controller.Enqueue(cur); err != nil { + utilruntime.HandleError(err) + } metrics.CustomResourceAdded(crType) }, UpdateFunc: func(old, cur interface{}) { @@ -78,7 +81,9 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac return } - controller.Enqueue(cur) + if _, err := controller.Enqueue(cur); err != nil { + utilruntime.HandleError(err) + } metrics.CustomResourceUpdated(crType) }, DeleteFunc: func(obj interface{}) { @@ -93,9 +98,11 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac } metrics.CustomResourceDeleted(crType) }, - }) + }); err != nil { + utilruntime.HandleError(err) + } - kubernetesJobInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := kubernetesJobInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: func(old, cur interface{}) { newJob := cur.(*batchv1.Job) oldJob := old.(*batchv1.Job) @@ -105,18 +112,20 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac controller.HandleObject(cur, radix.KindRadixJob, getObject) }, DeleteFunc: func(obj interface{}) { - job, converted := obj.(*batchv1.Job) + radixJob, converted := obj.(*batchv1.Job) if !converted { logger.Errorf("RadixJob object cast failed during deleted event received.") return } // If a kubernetes job gets deleted for a running job, the running radix job should // take this into account. The running job will get restarted - controller.HandleObject(job, radix.KindRadixJob, getObject) + controller.HandleObject(radixJob, radix.KindRadixJob, getObject) }, - }) + }); err != nil { + utilruntime.HandleError(err) + } - podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: func(old, cur interface{}) { newPod := cur.(*corev1.Pod) oldPod := old.(*corev1.Pod) @@ -139,7 +148,9 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac controller.HandleObject(job, radix.KindRadixJob, getObject) } }, - }) + }); err != nil { + utilruntime.HandleError(err) + } return controller } diff --git a/radix-operator/job/controller_test.go b/radix-operator/job/controller_test.go index 8fa91e9c0..c4df16b9a 100644 --- a/radix-operator/job/controller_test.go +++ b/radix-operator/job/controller_test.go @@ -110,7 +110,9 @@ func (s *jobTestSuite) Test_Controller_Calls_Handler() { // Update radix job should sync. Controller will skip if an update // changes nothing, except for spec or metadata, labels or annotations rj.Spec.Stop = true - s.kubeUtil.RadixClient().RadixV1().RadixJobs(rj.ObjectMeta.Namespace).Update(context.TODO(), rj, metav1.UpdateOptions{}) + if _, err := s.kubeUtil.RadixClient().RadixV1().RadixJobs(rj.ObjectMeta.Namespace).Update(context.TODO(), rj, metav1.UpdateOptions{}); err != nil { + panic(err) + } op, ok = <-synced s.True(ok) @@ -124,9 +126,13 @@ func (s *jobTestSuite) Test_Controller_Calls_Handler() { } // Only update of Kubernetes Job is something that the job-controller handles - s.kubeUtil.KubeClient().BatchV1().Jobs(rj.ObjectMeta.Namespace).Create(context.TODO(), &childJob, metav1.CreateOptions{}) + if _, err := s.kubeUtil.KubeClient().BatchV1().Jobs(rj.ObjectMeta.Namespace).Create(context.TODO(), &childJob, metav1.CreateOptions{}); err != nil { + panic(err) + } childJob.ObjectMeta.ResourceVersion = "1234" - s.kubeUtil.KubeClient().BatchV1().Jobs(rj.ObjectMeta.Namespace).Update(context.TODO(), &childJob, metav1.UpdateOptions{}) + if _, err := s.kubeUtil.KubeClient().BatchV1().Jobs(rj.ObjectMeta.Namespace).Update(context.TODO(), &childJob, metav1.UpdateOptions{}); err != nil { + panic(err) + } op, ok = <-synced s.True(ok) @@ -142,6 +148,8 @@ func startJobController(client kubernetes.Interface, radixClient radixclient.Int kubeInformerFactory.Start(stop) radixInformerFactory.Start(stop) - controller.Run(4, stop) + if err := controller.Run(4, stop); err != nil { + panic(err) + } } diff --git a/radix-operator/registration/controller.go b/radix-operator/registration/controller.go index 6a6775204..9a694304e 100644 --- a/radix-operator/registration/controller.go +++ b/radix-operator/registration/controller.go @@ -16,6 +16,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" kubeinformers "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" @@ -60,9 +61,11 @@ func NewController(client kubernetes.Interface, logger.Info("Setting up event handlers") - registrationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := registrationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { - controller.Enqueue(cur) + if _, err := controller.Enqueue(cur); err != nil { + utilruntime.HandleError(err) + } metrics.CustomResourceAdded(crType) }, UpdateFunc: func(old, cur interface{}) { @@ -75,7 +78,9 @@ func NewController(client kubernetes.Interface, return } - controller.Enqueue(cur) + if _, err := controller.Enqueue(cur); err != nil { + utilruntime.HandleError(err) + } metrics.CustomResourceUpdated(crType) }, DeleteFunc: func(obj interface{}) { @@ -90,17 +95,21 @@ func NewController(client kubernetes.Interface, } metrics.CustomResourceDeleted(crType) }, - }) + }); err != nil { + utilruntime.HandleError(err) + } namespaceInformer := kubeInformerFactory.Core().V1().Namespaces() - namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ DeleteFunc: func(obj interface{}) { controller.HandleObject(obj, radix.KindRadixRegistration, getObject) }, - }) + }); err != nil { + utilruntime.HandleError(err) + } secretInformer := kubeInformerFactory.Core().V1().Secrets() - secretInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := secretInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: func(oldObj, newObj interface{}) { oldSecret := oldObj.(*corev1.Secret) newSecret := newObj.(*corev1.Secret) @@ -142,7 +151,9 @@ func NewController(client kubernetes.Interface, controller.HandleObject(namespace, radix.KindRadixRegistration, getObject) } }, - }) + }); err != nil { + panic(err) + } return controller } diff --git a/radix-operator/registration/controller_test.go b/radix-operator/registration/controller_test.go index ed3251a8c..42cb2aa4d 100644 --- a/radix-operator/registration/controller_test.go +++ b/radix-operator/registration/controller_test.go @@ -139,6 +139,8 @@ func startRegistrationController( kubeInformerFactory.Start(stop) radixInformerFactory.Start(stop) - controller.Run(5, stop) + if err := controller.Run(5, stop); err != nil { + panic(err) + } } From 4196b7e70e077df6d1a7035589f6d27b6c976be1 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 4 Dec 2023 12:18:51 +0100 Subject: [PATCH 082/121] Added app alias as reserved --- charts/radix-operator/values.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/charts/radix-operator/values.yaml b/charts/radix-operator/values.yaml index d448ac4c7..c11ae1224 100644 --- a/charts/radix-operator/values.yaml +++ b/charts/radix-operator/values.yaml @@ -30,6 +30,7 @@ reservedDNSAlias: - grafana - prometheus - www + - app appAliasBaseURL: app.dev.radix.equinor.com dnsZone: dev.radix.equinor.com From 620cf013cf6aa98f10513cdebb37d6495f4115df Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 4 Dec 2023 14:47:32 +0100 Subject: [PATCH 083/121] Removed receiver from UpdatePrivateImageHubsSecretsPassword --- .../applicationconfig_test.go | 26 +++++++++---------- pkg/apis/applicationconfig/imagehubsecret.go | 10 +++---- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 49fa861a6..14897eb8b 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -431,7 +431,7 @@ func Test_AppReaderPrivateImageHubRoleAndRoleBindingExists(t *testing.T) { assert.True(t, roleBindingByNameExists("radix-private-image-hubs-reader", rolebindings)) } func Test_WithPrivateImageHubSet_SecretsCorrectly_Added(t *testing.T) { - client, _ := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ + client, _, _ := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ "privaterepodeleteme.azurecr.io": &radixv1.RadixPrivateImageHubCredential{ Username: "814607e6-3d71-44a7-8476-50e8b281abbc", Email: "radix@equinor.com", @@ -446,7 +446,7 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_Added(t *testing.T) { } func Test_WithPrivateImageHubSet_SecretsCorrectly_SetPassword(t *testing.T) { - client, appConfig := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ + client, appConfig, kubeUtil := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ "privaterepodeleteme.azurecr.io": &radixv1.RadixPrivateImageHubCredential{ Username: "814607e6-3d71-44a7-8476-50e8b281abbc", Email: "radix@equinor.com", @@ -456,7 +456,7 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_SetPassword(t *testing.T) { assert.Equal(t, "privaterepodeleteme.azurecr.io", pendingSecrets[0]) - if err := appConfig.UpdatePrivateImageHubsSecretsPassword("privaterepodeleteme.azurecr.io", "a-password"); err != nil { + if err := applicationconfig.UpdatePrivateImageHubsSecretsPassword(kubeUtil, "any-app", "privaterepodeleteme.azurecr.io", "a-password"); err != nil { panic(err) } secret, _ := client.CoreV1().Secrets("any-app-app").Get(context.TODO(), defaults.PrivateImageHubSecretName, metav1.GetOptions{}) @@ -476,7 +476,7 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_UpdatedNewAdded(t *testing.T) }, }) - client, _ := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ + client, _, _ := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ "privaterepodeleteme.azurecr.io": &radixv1.RadixPrivateImageHubCredential{ Username: "814607e6-3d71-44a7-8476-50e8b281abbc", Email: "radix@equinor.com", @@ -502,7 +502,7 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_UpdateUsername(t *testing.T) { }, }) - client, _ := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ + client, _, _ := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ "privaterepodeleteme.azurecr.io": &radixv1.RadixPrivateImageHubCredential{ Username: "814607e6-3d71-44a7-8476-50e8b281abb2", Email: "radix@equinor.com", @@ -524,7 +524,7 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_UpdateServerName(t *testing.T) }, }) - client, _ := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ + client, _, _ := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ "privaterepodeleteme1.azurecr.io": &radixv1.RadixPrivateImageHubCredential{ Username: "814607e6-3d71-44a7-8476-50e8b281abbc", Email: "radix@equinor.com", @@ -538,7 +538,7 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_UpdateServerName(t *testing.T) } func Test_WithPrivateImageHubSet_SecretsCorrectly_Delete(t *testing.T) { - client, _ := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ + client, _, _ := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ "privaterepodeleteme.azurecr.io": &radixv1.RadixPrivateImageHubCredential{ Username: "814607e6-3d71-44a7-8476-50e8b281abbc", Email: "radix@equinor.com", @@ -554,7 +554,7 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_Delete(t *testing.T) { "{\"auths\":{\"privaterepodeleteme.azurecr.io\":{\"username\":\"814607e6-3d71-44a7-8476-50e8b281abbc\",\"password\":\"\",\"email\":\"radix@equinor.com\",\"auth\":\"ODE0NjA3ZTYtM2Q3MS00NGE3LTg0NzYtNTBlOGIyODFhYmJjOg==\"},\"privaterepodeleteme2.azurecr.io\":{\"username\":\"814607e6-3d71-44a7-8476-50e8b281abbc\",\"password\":\"\",\"email\":\"radix@equinor.com\",\"auth\":\"ODE0NjA3ZTYtM2Q3MS00NGE3LTg0NzYtNTBlOGIyODFhYmJjOg==\"}}}", string(secret.Data[corev1.DockerConfigJsonKey])) - client, _ = applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ + client, _, _ = applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ "privaterepodeleteme2.azurecr.io": &radixv1.RadixPrivateImageHubCredential{ Username: "814607e6-3d71-44a7-8476-50e8b281abbc", Email: "radix@equinor.com", @@ -568,7 +568,7 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_Delete(t *testing.T) { } func Test_WithPrivateImageHubSet_SecretsCorrectly_NoImageHubs(t *testing.T) { - client, appConfig := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{}) + client, appConfig, kubeUtil := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{}) pendingSecrets, _ := appConfig.GetPendingPrivateImageHubSecrets() secret, _ := client.CoreV1().Secrets("any-app-app").Get(context.TODO(), defaults.PrivateImageHubSecretName, metav1.GetOptions{}) @@ -578,7 +578,7 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_NoImageHubs(t *testing.T) { "{\"auths\":{}}", string(secret.Data[corev1.DockerConfigJsonKey])) assert.Equal(t, 0, len(pendingSecrets)) - assert.Error(t, appConfig.UpdatePrivateImageHubsSecretsPassword("privaterepodeleteme.azurecr.io", "a-password")) + assert.Error(t, applicationconfig.UpdatePrivateImageHubsSecretsPassword(kubeUtil, "any-app", "privaterepodeleteme.azurecr.io", "a-password")) } func Test_RadixEnvironment(t *testing.T) { @@ -703,7 +703,7 @@ func rrAsOwnerReference(rr *radixv1.RadixRegistration) []metav1.OwnerReference { } } -func applyRadixAppWithPrivateImageHub(privateImageHubs radixv1.PrivateImageHubEntries) (kubernetes.Interface, *applicationconfig.ApplicationConfig) { +func applyRadixAppWithPrivateImageHub(privateImageHubs radixv1.PrivateImageHubEntries) (kubernetes.Interface, *applicationconfig.ApplicationConfig, *kube.Kube) { tu, client, kubeUtil, radixClient := setupTest() appBuilder := utils.ARadixApplication(). WithAppName("any-app"). @@ -714,10 +714,10 @@ func applyRadixAppWithPrivateImageHub(privateImageHubs radixv1.PrivateImageHubEn err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, appBuilder) if err != nil { - return nil, nil + return nil, nil, nil } appConfig := getAppConfig(client, kubeUtil, radixClient, appBuilder) - return client, appConfig + return client, appConfig, kubeUtil } func getAppConfig(client kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, applicationBuilder utils.ApplicationBuilder) *applicationconfig.ApplicationConfig { diff --git a/pkg/apis/applicationconfig/imagehubsecret.go b/pkg/apis/applicationconfig/imagehubsecret.go index 18ef54d3a..35ef0cf6a 100644 --- a/pkg/apis/applicationconfig/imagehubsecret.go +++ b/pkg/apis/applicationconfig/imagehubsecret.go @@ -26,11 +26,11 @@ func GetKubeDPrivateImageHubAnnotationValues(appName string) (key, value string) } // UpdatePrivateImageHubsSecretsPassword updates the private image hub secret -func (app *ApplicationConfig) UpdatePrivateImageHubsSecretsPassword(server, password string) error { - ns := utils.GetAppNamespace(app.config.Name) - secret, _ := app.kubeutil.GetSecret(ns, defaults.PrivateImageHubSecretName) +func UpdatePrivateImageHubsSecretsPassword(kubeutil *kube.Kube, appName, server, password string) error { + ns := utils.GetAppNamespace(appName) + secret, _ := kubeutil.GetSecret(ns, defaults.PrivateImageHubSecretName) if secret == nil { - return fmt.Errorf("private image hub secret does not exist for app %s", app.config.Name) + return fmt.Errorf("private image hub secret does not exist for app %s", appName) } imageHubs, err := getImageHubSecretValue(secret.Data[corev1.DockerConfigJsonKey]) @@ -45,7 +45,7 @@ func (app *ApplicationConfig) UpdatePrivateImageHubsSecretsPassword(server, pass if err != nil { return err } - return applyPrivateImageHubSecret(app.kubeutil, ns, app.config.Name, secretValue) + return applyPrivateImageHubSecret(kubeutil, ns, appName, secretValue) } return fmt.Errorf("private image hub secret does not contain config for server %s", server) } From 7a24ed4f2365bc54540934a06c5101f2af95c413 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 4 Dec 2023 15:11:58 +0100 Subject: [PATCH 084/121] Removed receiver from GetPendingPrivateImageHubSecrets --- pkg/apis/applicationconfig/applicationconfig_test.go | 10 +++++----- pkg/apis/applicationconfig/imagehubsecret.go | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 14897eb8b..8006c3cd4 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -446,13 +446,13 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_Added(t *testing.T) { } func Test_WithPrivateImageHubSet_SecretsCorrectly_SetPassword(t *testing.T) { - client, appConfig, kubeUtil := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ + client, _, kubeUtil := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ "privaterepodeleteme.azurecr.io": &radixv1.RadixPrivateImageHubCredential{ Username: "814607e6-3d71-44a7-8476-50e8b281abbc", Email: "radix@equinor.com", }, }) - pendingSecrets, _ := appConfig.GetPendingPrivateImageHubSecrets() + pendingSecrets, _ := applicationconfig.GetPendingPrivateImageHubSecrets(kubeUtil, "any-app") assert.Equal(t, "privaterepodeleteme.azurecr.io", pendingSecrets[0]) @@ -460,7 +460,7 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_SetPassword(t *testing.T) { panic(err) } secret, _ := client.CoreV1().Secrets("any-app-app").Get(context.TODO(), defaults.PrivateImageHubSecretName, metav1.GetOptions{}) - pendingSecrets, _ = appConfig.GetPendingPrivateImageHubSecrets() + pendingSecrets, _ = applicationconfig.GetPendingPrivateImageHubSecrets(kubeUtil, "any-app") assert.Equal(t, "{\"auths\":{\"privaterepodeleteme.azurecr.io\":{\"username\":\"814607e6-3d71-44a7-8476-50e8b281abbc\",\"password\":\"a-password\",\"email\":\"radix@equinor.com\",\"auth\":\"ODE0NjA3ZTYtM2Q3MS00NGE3LTg0NzYtNTBlOGIyODFhYmJjOmEtcGFzc3dvcmQ=\"}}}", @@ -568,8 +568,8 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_Delete(t *testing.T) { } func Test_WithPrivateImageHubSet_SecretsCorrectly_NoImageHubs(t *testing.T) { - client, appConfig, kubeUtil := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{}) - pendingSecrets, _ := appConfig.GetPendingPrivateImageHubSecrets() + client, _, kubeUtil := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{}) + pendingSecrets, _ := applicationconfig.GetPendingPrivateImageHubSecrets(kubeUtil, "any-app") secret, _ := client.CoreV1().Secrets("any-app-app").Get(context.TODO(), defaults.PrivateImageHubSecretName, metav1.GetOptions{}) diff --git a/pkg/apis/applicationconfig/imagehubsecret.go b/pkg/apis/applicationconfig/imagehubsecret.go index 35ef0cf6a..5d5ddf329 100644 --- a/pkg/apis/applicationconfig/imagehubsecret.go +++ b/pkg/apis/applicationconfig/imagehubsecret.go @@ -51,11 +51,10 @@ func UpdatePrivateImageHubsSecretsPassword(kubeutil *kube.Kube, appName, server, } // GetPendingPrivateImageHubSecrets returns a list of private image hubs where secret value is not set -func (app *ApplicationConfig) GetPendingPrivateImageHubSecrets() ([]string, error) { - appName := app.config.Name +func GetPendingPrivateImageHubSecrets(kubeUtil *kube.Kube, appName string) ([]string, error) { pendingSecrets := []string{} ns := utils.GetAppNamespace(appName) - secret, err := app.kubeutil.GetSecret(ns, defaults.PrivateImageHubSecretName) + secret, err := kubeUtil.GetSecret(ns, defaults.PrivateImageHubSecretName) if err != nil && !errors.IsNotFound(err) { return nil, err } From ffa7bc20dccd6f997fb989a63ea5f7987b8f7269 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 4 Dec 2023 15:33:16 +0100 Subject: [PATCH 085/121] Corrected error message --- pkg/apis/radixvalidators/errors.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/apis/radixvalidators/errors.go b/pkg/apis/radixvalidators/errors.go index 1c3f91a55..0e0da0e7f 100644 --- a/pkg/apis/radixvalidators/errors.go +++ b/pkg/apis/radixvalidators/errors.go @@ -343,7 +343,7 @@ func InvalidStringValueMaxLengthErrorWithMessage(resourceName, value string, max // ResourceNameCannotBeEmptyErrorWithMessage Resource name cannot be left empty func ResourceNameCannotBeEmptyErrorWithMessage(resourceName string) error { - return errors.WithMessagef(ErrResourceNameCannotBeEmpty, "%s cannot be empty", resourceName) + return errors.WithMessagef(ErrResourceNameCannotBeEmpty, "%s is empty", resourceName) } // InvalidUUIDErrorWithMessage Invalid UUID From 5d5a47537557f7d3fe400bfe629c40ecc4859048 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 5 Dec 2023 12:42:39 +0100 Subject: [PATCH 086/121] Fixed reported review issues --- Makefile | 1 - charts/radix-operator/Chart.yaml | 4 +- json-schema/radixdnsalias.json | 80 ---------------------- pipeline-runner/model/pipelineInfo_test.go | 19 +---- pipeline-runner/pipelines/app_test.go | 11 +-- 5 files changed, 6 insertions(+), 109 deletions(-) delete mode 100644 json-schema/radixdnsalias.json diff --git a/Makefile b/Makefile index 164e748db..6492f4d20 100644 --- a/Makefile +++ b/Makefile @@ -146,7 +146,6 @@ radixbatch-crd: temp-crds .PHONY: radixdnsalias-crd radixdnsalias-crd: temp-crds cp $(CRD_TEMP_DIR)radix.equinor.com_radixdnsaliases.yaml $(CRD_CHART_DIR)radixdnsalias.yaml - yq eval '.spec.versions[0].schema.openAPIV3Schema' -ojson $(CRD_CHART_DIR)radixdnsalias.yaml > $(JSON_SCHEMA_DIR)radixdnsalias.json .PHONY: temp-crds temp-crds: controller-gen diff --git a/charts/radix-operator/Chart.yaml b/charts/radix-operator/Chart.yaml index b9991ce91..07d617e5e 100644 --- a/charts/radix-operator/Chart.yaml +++ b/charts/radix-operator/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: radix-operator -version: 1.26.1 -appVersion: 1.46.1 +version: 1.27.0 +appVersion: 1.47.0 kubeVersion: ">=1.24.0" description: Radix Operator keywords: diff --git a/json-schema/radixdnsalias.json b/json-schema/radixdnsalias.json deleted file mode 100644 index 6754bb9d1..000000000 --- a/json-schema/radixdnsalias.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "description": "RadixDNSAlias is a Custom Resource Definition", - "properties": { - "apiVersion": { - "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", - "type": "string" - }, - "kind": { - "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", - "type": "string" - }, - "metadata": { - "type": "object" - }, - "spec": { - "description": "RadixDNSAliasSpec is the spec for an RadixDNSAlias", - "properties": { - "appName": { - "description": "Name of the application the DNS alias used in.", - "maxLength": 253, - "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", - "type": "string" - }, - "component": { - "description": "Name of the component that shall receive the incoming requests.", - "maxLength": 63, - "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", - "type": "string" - }, - "environment": { - "description": "Name of the environment for the component.", - "maxLength": 63, - "minLength": 1, - "pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$", - "type": "string" - }, - "port": { - "description": "Port number.", - "format": "int32", - "maximum": 65535, - "minimum": 1024, - "type": "integer" - } - }, - "required": [ - "appName", - "component", - "environment", - "port" - ], - "type": "object" - }, - "status": { - "description": "RadixDNSAliasStatus is the status for an RadixDNSAlias", - "properties": { - "condition": { - "description": "Condition of the RadixDNSAlias creating or updating", - "type": "string" - }, - "message": { - "description": "A human-readable message indicating details about the condition.", - "type": "string" - }, - "reconciled": { - "description": "Reconciled The timestamp when the RadixDNSAlias was reconciled", - "format": "date-time", - "type": "string" - } - }, - "type": "object" - } - }, - "required": [ - "metadata", - "spec" - ], - "type": "object" -} diff --git a/pipeline-runner/model/pipelineInfo_test.go b/pipeline-runner/model/pipelineInfo_test.go index 8367f19d6..e83c86b09 100644 --- a/pipeline-runner/model/pipelineInfo_test.go +++ b/pipeline-runner/model/pipelineInfo_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/equinor/radix-operator/pipeline-runner/model" - "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/pipeline" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/stretchr/testify/assert" @@ -74,7 +73,6 @@ func Test_GetImageTagNamesFromArgs(t *testing.T) { pipelineArguments: model.PipelineArguments{ ToEnvironment: "env1", ImageTagNames: map[string]string{}, - DNSConfig: getDNSAliasConfig(), }, expectedToEnvironment: "env1", expectedImageTagNames: map[string]string{}, @@ -84,7 +82,6 @@ func Test_GetImageTagNamesFromArgs(t *testing.T) { pipelineArguments: model.PipelineArguments{ ToEnvironment: "env1", ImageTagNames: map[string]string{"component1": "tag1", "component2": "tag22"}, - DNSConfig: getDNSAliasConfig(), }, expectedToEnvironment: "env1", expectedImageTagNames: map[string]string{"component1": "tag1", "component2": "tag22"}, @@ -107,7 +104,6 @@ func Test_BuildOnlyPipeline(t *testing.T) { pipelineArgs := &model.PipelineArguments{ PushImage: false, - DNSConfig: getDNSAliasConfig(), } p, _ := model.InitPipeline(pipelineType, pipelineArgs, prepareTektonPipelineStep, applyConfigStep, buildStep, runTektonPipelineStep, deployStep) @@ -125,7 +121,6 @@ func Test_BuildAndPushOnlyPipeline(t *testing.T) { pipelineArgs := &model.PipelineArguments{ PushImage: true, - DNSConfig: getDNSAliasConfig(), } p, _ := model.InitPipeline(pipelineType, pipelineArgs, prepareTektonPipelineStep, applyConfigStep, buildStep, runTektonPipelineStep, deployStep) @@ -151,12 +146,12 @@ func Test_DeployOnlyPipeline(t *testing.T) { scenarios := []scenario{ { name: "only target environment", - pipelineArguments: model.PipelineArguments{ToEnvironment: "target", DNSConfig: getDNSAliasConfig()}, + pipelineArguments: model.PipelineArguments{ToEnvironment: "target"}, expectedToEnvironment: "target", }, { name: "target environment with image tags", - pipelineArguments: model.PipelineArguments{ToEnvironment: "target", ImageTagNames: map[string]string{"component1": "tag1", "component2": "tag22"}, DNSConfig: getDNSAliasConfig()}, + pipelineArguments: model.PipelineArguments{ToEnvironment: "target", ImageTagNames: map[string]string{"component1": "tag1", "component2": "tag22"}}, expectedToEnvironment: "target", expectedImageTagNames: map[string]string{"component1": "tag1", "component2": "tag22"}, }, @@ -184,13 +179,5 @@ func Test_NonExistingPipelineType(t *testing.T) { } func getPipelineArguments() *model.PipelineArguments { - return &model.PipelineArguments{DNSConfig: getDNSAliasConfig()} -} - -func getDNSAliasConfig() *dnsalias.DNSConfig { - return &dnsalias.DNSConfig{ - DNSZone: "dev.radix.equinor.com", - ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, - ReservedDNSAliases: []string{"grafana"}, - } + return &model.PipelineArguments{} } diff --git a/pipeline-runner/pipelines/app_test.go b/pipeline-runner/pipelines/app_test.go index 9db4780ea..4792cce94 100644 --- a/pipeline-runner/pipelines/app_test.go +++ b/pipeline-runner/pipelines/app_test.go @@ -5,7 +5,6 @@ import ( "github.com/equinor/radix-operator/pipeline-runner/model" "github.com/equinor/radix-operator/pipeline-runner/pipelines" - dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/pipeline" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" commonTest "github.com/equinor/radix-operator/pkg/apis/test" @@ -31,14 +30,6 @@ func TestPrepare_NoRegistration_NotValid(t *testing.T) { pipelineDefinition, _ := pipeline.GetPipelineFromName(string(v1.BuildDeploy)) cli := pipelines.NewRunner(kubeclient, radixclient, &monitoring.Clientset{}, secretproviderclient, pipelineDefinition, "any-app") - err := cli.PrepareRun(&model.PipelineArguments{DNSConfig: getDNSAliasConfig()}) + err := cli.PrepareRun(&model.PipelineArguments{}) assert.Error(t, err) } - -func getDNSAliasConfig() *dnsaliasconfig.DNSConfig { - return &dnsaliasconfig.DNSConfig{ - DNSZone: "dev.radix.equinor.com", - ReservedAppDNSAliases: dnsaliasconfig.AppReservedDNSAlias{"api": "radix-api"}, - ReservedDNSAliases: []string{"grafana"}, - } -} From 3fb226cf0c1f287ff16da64e0c421bd11e3ba862 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 5 Dec 2023 12:49:56 +0100 Subject: [PATCH 087/121] Fixed reported review issues. --- pipeline-runner/steps/build_test.go | 39 +++++++++---------------- pipeline-runner/steps/deploy_test.go | 27 ++++++++--------- pipeline-runner/steps/promotion_test.go | 8 ----- 3 files changed, 25 insertions(+), 49 deletions(-) diff --git a/pipeline-runner/steps/build_test.go b/pipeline-runner/steps/build_test.go index 8fb4e126c..a74541d44 100644 --- a/pipeline-runner/steps/build_test.go +++ b/pipeline-runner/steps/build_test.go @@ -88,11 +88,10 @@ func (s *buildTestSuite) Test_BranchIsNotMapped_ShouldSkip() { pipelineInfo := &model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - JobName: anyJobName, - ImageTag: anyImageTag, - Branch: anyNoMappedBranch, - CommitID: anyCommitID, - DNSConfig: getDNSAliasConfig(), + JobName: anyJobName, + ImageTag: anyImageTag, + Branch: anyNoMappedBranch, + CommitID: anyCommitID, }, TargetEnvironments: targetEnvs, } @@ -143,7 +142,6 @@ func (s *buildTestSuite) Test_BuildDeploy_JobSpecAndDeploymentConsistent() { RadixZone: "radixzone", Clustername: "clustername", SubscriptionId: "subscriptionid", - DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, GitConfigMapName: gitConfigMapName, @@ -277,7 +275,6 @@ func (s *buildTestSuite) Test_BuildJobSpec_MultipleComponents() { ContainerRegistry: "registry", Clustertype: "clustertype", Clustername: "clustername", - DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -567,7 +564,6 @@ func (s *buildTestSuite) Test_BuildChangedComponents() { Clustertype: "clustertype", Clustername: "clustername", ContainerRegistry: "registry", - DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -686,7 +682,6 @@ func (s *buildTestSuite) Test_DetectComponentsToBuild() { ContainerRegistry: "registry", Clustertype: "clustertype", Clustername: "clustername", - DNSConfig: getDNSAliasConfig(), } imageNameFunc := func(s string) string { return fmt.Sprintf("%s/%s-%s:%s", piplineArgs.ContainerRegistry, appName, s, piplineArgs.ImageTag) @@ -1115,7 +1110,6 @@ func (s *buildTestSuite) Test_BuildJobSpec_ImageTagNames() { ToEnvironment: envName, JobName: rjName, ImageTagNames: map[string]string{"comp1": "comp1customtag", "job1": "job1customtag"}, - DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -1172,7 +1166,6 @@ func (s *buildTestSuite) Test_BuildJobSpec_PushImage() { Branch: "main", JobName: rjName, PushImage: true, - DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -1210,10 +1203,9 @@ func (s *buildTestSuite) Test_BuildJobSpec_UseCache() { s.Require().NoError(internaltest.CreatePreparePipelineConfigMapResponse(s.kubeClient, prepareConfigMapName, appName, ra, nil)) pipeline := model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - Branch: "main", - JobName: rjName, - UseCache: true, - DNSConfig: getDNSAliasConfig(), + Branch: "main", + JobName: rjName, + UseCache: true, }, RadixConfigMapName: prepareConfigMapName, } @@ -1251,9 +1243,8 @@ func (s *buildTestSuite) Test_BuildJobSpec_WithDockerfileName() { s.Require().NoError(internaltest.CreatePreparePipelineConfigMapResponse(s.kubeClient, prepareConfigMapName, appName, ra, nil)) pipeline := model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - Branch: "main", - JobName: rjName, - DNSConfig: getDNSAliasConfig(), + Branch: "main", + JobName: rjName, }, RadixConfigMapName: prepareConfigMapName, } @@ -1291,9 +1282,8 @@ func (s *buildTestSuite) Test_BuildJobSpec_WithSourceFolder() { s.Require().NoError(internaltest.CreatePreparePipelineConfigMapResponse(s.kubeClient, prepareConfigMapName, appName, ra, nil)) pipeline := model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - Branch: "main", - JobName: rjName, - DNSConfig: getDNSAliasConfig(), + Branch: "main", + JobName: rjName, }, RadixConfigMapName: prepareConfigMapName, } @@ -1333,9 +1323,8 @@ func (s *buildTestSuite) Test_BuildJobSpec_WithBuildSecrets() { s.Require().NoError(internaltest.CreateBuildSecret(s.kubeClient, appName, map[string][]byte{"SECRET1": nil, "SECRET2": nil})) pipeline := model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - Branch: "main", - JobName: rjName, - DNSConfig: getDNSAliasConfig(), + Branch: "main", + JobName: rjName, }, RadixConfigMapName: prepareConfigMapName, } @@ -1397,7 +1386,6 @@ func (s *buildTestSuite) Test_BuildJobSpec_BuildKit() { Clustertype: "anyclustertype", Clustername: "anyclustername", Builder: model.Builder{ResourcesLimitsMemory: "100M", ResourcesRequestsCPU: "50m", ResourcesRequestsMemory: "50M"}, - DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } @@ -1462,7 +1450,6 @@ func (s *buildTestSuite) Test_BuildJobSpec_BuildKit_PushImage() { Clustername: "anyclustername", PushImage: true, Builder: model.Builder{ResourcesLimitsMemory: "100M", ResourcesRequestsCPU: "50m", ResourcesRequestsMemory: "50M"}, - DNSConfig: getDNSAliasConfig(), }, RadixConfigMapName: prepareConfigMapName, } diff --git a/pipeline-runner/steps/deploy_test.go b/pipeline-runner/steps/deploy_test.go index eff8dfc9a..5e7dee997 100644 --- a/pipeline-runner/steps/deploy_test.go +++ b/pipeline-runner/steps/deploy_test.go @@ -79,11 +79,10 @@ func TestDeploy_BranchIsNotMapped_ShouldSkip(t *testing.T) { pipelineInfo := &model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - JobName: anyJobName, - ImageTag: anyImageTag, - Branch: anyNoMappedBranch, - CommitID: anyCommitID, - DNSConfig: getDNSAliasConfig(), + JobName: anyJobName, + ImageTag: anyImageTag, + Branch: anyNoMappedBranch, + CommitID: anyCommitID, }, TargetEnvironments: targetEnvs, } @@ -185,11 +184,10 @@ func TestDeploy_PromotionSetup_ShouldCreateNamespacesForAllBranchesIfNotExists(t pipelineInfo := &model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - JobName: anyJobName, - ImageTag: anyImageTag, - Branch: "master", - CommitID: anyCommitID, - DNSConfig: getDNSAliasConfig(), + JobName: anyJobName, + ImageTag: anyImageTag, + Branch: "master", + CommitID: anyCommitID, }, TargetEnvironments: targetEnvs, GitCommitHash: anyCommitID, @@ -302,11 +300,10 @@ func TestDeploy_SetCommitID_whenSet(t *testing.T) { pipelineInfo := &model.PipelineInfo{ PipelineArguments: model.PipelineArguments{ - JobName: anyJobName, - ImageTag: anyImageTag, - Branch: "master", - CommitID: anyCommitID, - DNSConfig: getDNSAliasConfig(), + JobName: anyJobName, + ImageTag: anyImageTag, + Branch: "master", + CommitID: anyCommitID, }, TargetEnvironments: []string{"master"}, GitCommitHash: commitID, diff --git a/pipeline-runner/steps/promotion_test.go b/pipeline-runner/steps/promotion_test.go index df080e528..1fb1f1d00 100644 --- a/pipeline-runner/steps/promotion_test.go +++ b/pipeline-runner/steps/promotion_test.go @@ -127,7 +127,6 @@ func TestPromote_ErrorScenarios_ErrorIsReturned(t *testing.T) { JobName: scenario.jobName, ImageTag: scenario.imageTag, CommitID: anyCommitID, - DNSConfig: getDNSAliasConfig(), }, } @@ -286,7 +285,6 @@ func TestPromote_PromoteToOtherEnvironment_NewStateIsExpected(t *testing.T) { JobName: anyPromoteJobName, ImageTag: anyImageTag, CommitID: anyCommitID, - DNSConfig: getDNSAliasConfig(), }, } @@ -414,7 +412,6 @@ func TestPromote_PromoteToOtherEnvironment_Resources_NoOverride(t *testing.T) { JobName: anyPromoteJobName, ImageTag: anyImageTag, CommitID: anyCommitID, - DNSConfig: getDNSAliasConfig(), }, } @@ -509,7 +506,6 @@ func TestPromote_PromoteToOtherEnvironment_Authentication(t *testing.T) { JobName: anyPromoteJobName, ImageTag: anyImageTag, CommitID: anyCommitID, - DNSConfig: getDNSAliasConfig(), }, } @@ -626,7 +622,6 @@ func TestPromote_PromoteToOtherEnvironment_Resources_WithOverride(t *testing.T) JobName: anyPromoteJobName, ImageTag: anyImageTag, CommitID: anyCommitID, - DNSConfig: getDNSAliasConfig(), }, } @@ -688,7 +683,6 @@ func TestPromote_PromoteToSameEnvironment_NewStateIsExpected(t *testing.T) { JobName: anyPromoteJobName, ImageTag: anyImageTag, CommitID: anyCommitID, - DNSConfig: getDNSAliasConfig(), }, } @@ -807,7 +801,6 @@ func TestPromote_PromoteToOtherEnvironment_Identity(t *testing.T) { JobName: anyPromoteJobName, ImageTag: anyImageTag, CommitID: anyCommitID, - DNSConfig: getDNSAliasConfig(), }, } @@ -869,7 +862,6 @@ func TestPromote_AnnotatedBySourceDeploymentAttributes(t *testing.T) { JobName: anyPromoteJobName, ImageTag: anyImageTag, CommitID: anyCommitID, - DNSConfig: getDNSAliasConfig(), }, } From 592811be0868e6b4e0a44d1bd48d5203f776dc2a Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 5 Dec 2023 13:02:55 +0100 Subject: [PATCH 088/121] Fixed reported review issues. --- pipeline-runner/steps/deploy_test.go | 2 +- pipeline-runner/steps/promotion_test.go | 14 +++++++------- .../applicationconfig/applicationconfig_test.go | 15 +++------------ 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/pipeline-runner/steps/deploy_test.go b/pipeline-runner/steps/deploy_test.go index 5e7dee997..d2984a4e8 100644 --- a/pipeline-runner/steps/deploy_test.go +++ b/pipeline-runner/steps/deploy_test.go @@ -294,7 +294,7 @@ func TestDeploy_SetCommitID_whenSet(t *testing.T) { cli := steps.NewDeployStep(FakeNamespaceWatcher{}) cli.Init(kubeclient, radixclient, kubeUtil, &monitoring.Clientset{}, rr) - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil) const commitID = "222ca8595c5283a9d0f17a623b9255a0d9866a2e" diff --git a/pipeline-runner/steps/promotion_test.go b/pipeline-runner/steps/promotion_test.go index 1fb1f1d00..a40a57a5d 100644 --- a/pipeline-runner/steps/promotion_test.go +++ b/pipeline-runner/steps/promotion_test.go @@ -288,7 +288,7 @@ func TestPromote_PromoteToOtherEnvironment_NewStateIsExpected(t *testing.T) { }, } - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -415,7 +415,7 @@ func TestPromote_PromoteToOtherEnvironment_Resources_NoOverride(t *testing.T) { }, } - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -509,7 +509,7 @@ func TestPromote_PromoteToOtherEnvironment_Authentication(t *testing.T) { }, } - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -625,7 +625,7 @@ func TestPromote_PromoteToOtherEnvironment_Resources_WithOverride(t *testing.T) }, } - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -686,7 +686,7 @@ func TestPromote_PromoteToSameEnvironment_NewStateIsExpected(t *testing.T) { }, } - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) @@ -804,7 +804,7 @@ func TestPromote_PromoteToOtherEnvironment_Identity(t *testing.T) { }, } - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil) pipelineInfo.SetApplicationConfig(applicationConfig) err = cli.Run(pipelineInfo) require.NoError(t, err) @@ -865,7 +865,7 @@ func TestPromote_AnnotatedBySourceDeploymentAttributes(t *testing.T) { }, } - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, nil) gitCommitHash := pipelineInfo.GitCommitHash gitTags := pipelineInfo.GitTags pipelineInfo.SetApplicationConfig(applicationConfig) diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 8006c3cd4..f0f1f26da 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -8,7 +8,6 @@ import ( "testing" "github.com/equinor/radix-operator/pkg/apis/applicationconfig" - "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix" @@ -115,7 +114,7 @@ func Test_Reconciles_Radix_Environments(t *testing.T) { WithEnvironment("prod", "master"). BuildRA() - app := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, rr, ra, getDNSAliasConfig()) + app := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, rr, ra, nil) label := fmt.Sprintf("%s=%s", kube.RadixAppLabel, rr.Name) // Test @@ -724,7 +723,7 @@ func getAppConfig(client kubernetes.Interface, kubeUtil *kube.Kube, radixClient ra := applicationBuilder.BuildRA() radixRegistration, _ := radixClient.RadixV1().RadixRegistrations().Get(context.TODO(), ra.Name, metav1.GetOptions{}) - return applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra, getDNSAliasConfig()) + return applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra, nil) } func applyApplicationWithSync(tu *test.Utils, client kubernetes.Interface, kubeUtil *kube.Kube, @@ -740,7 +739,7 @@ func applyApplicationWithSync(tu *test.Utils, client kubernetes.Interface, kubeU return err } - applicationConfig := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra, getDNSAliasConfig()) + applicationConfig := applicationconfig.NewApplicationConfig(client, kubeUtil, radixClient, radixRegistration, ra, nil) err = applicationConfig.OnSync() if err != nil { @@ -801,11 +800,3 @@ func getRoleBindingByName(name string, roleBindings *rbacv1.RoleBindingList) *rb func roleBindingByNameExists(name string, roleBindings *rbacv1.RoleBindingList) bool { return getRoleBindingByName(name, roleBindings) != nil } - -func getDNSAliasConfig() *dnsalias.DNSConfig { - return &dnsalias.DNSConfig{ - DNSZone: "dev.radix.equinor.com", - ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, - ReservedDNSAliases: []string{"grafana"}, - } -} From 8e6db46430dd32433858ad04b8abcf601f0f8f22 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 5 Dec 2023 13:13:38 +0100 Subject: [PATCH 089/121] Fixed reported review issues. --- pipeline-runner/steps/build_test.go | 9 --------- pipeline-runner/steps/deploy_test.go | 8 +++++++- pkg/apis/radixvalidators/validate_ra_test.go | 1 + 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/pipeline-runner/steps/build_test.go b/pipeline-runner/steps/build_test.go index a74541d44..21653c6fe 100644 --- a/pipeline-runner/steps/build_test.go +++ b/pipeline-runner/steps/build_test.go @@ -15,7 +15,6 @@ import ( "github.com/equinor/radix-operator/pipeline-runner/model" "github.com/equinor/radix-operator/pipeline-runner/steps" application "github.com/equinor/radix-operator/pkg/apis/applicationconfig" - "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -103,14 +102,6 @@ func (s *buildTestSuite) Test_BranchIsNotMapped_ShouldSkip() { s.Empty(radixJobList.Items) } -func getDNSAliasConfig() *dnsalias.DNSConfig { - return &dnsalias.DNSConfig{ - DNSZone: "dev.radix.equinor.com", - ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, - ReservedDNSAliases: []string{"grafana"}, - } -} - func (s *buildTestSuite) Test_BuildDeploy_JobSpecAndDeploymentConsistent() { appName, envName, rjName, compName, cloneURL, buildBranch := "anyapp", "dev", "anyrj", "c1", "git@github.com:anyorg/anyrepo", "anybranch" prepareConfigMapName := "preparecm" diff --git a/pipeline-runner/steps/deploy_test.go b/pipeline-runner/steps/deploy_test.go index d2984a4e8..148ebf4c0 100644 --- a/pipeline-runner/steps/deploy_test.go +++ b/pipeline-runner/steps/deploy_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" commonTest "github.com/equinor/radix-operator/pkg/apis/test" radix "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" @@ -179,7 +180,12 @@ func TestDeploy_PromotionSetup_ShouldCreateNamespacesForAllBranchesIfNotExists(t cli := steps.NewDeployStep(FakeNamespaceWatcher{}) cli.Init(kubeclient, radixclient, kubeUtil, &monitoring.Clientset{}, rr) - applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, getDNSAliasConfig()) + dnsConfig := dnsalias.DNSConfig{ + DNSZone: "dev.radix.equinor.com", + ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, + ReservedDNSAliases: []string{"grafana"}, + } + applicationConfig := application.NewApplicationConfig(kubeclient, kubeUtil, radixclient, rr, ra, &dnsConfig) targetEnvs := application.GetTargetEnvironments("master", ra) pipelineInfo := &model.PipelineInfo{ diff --git a/pkg/apis/radixvalidators/validate_ra_test.go b/pkg/apis/radixvalidators/validate_ra_test.go index 37ebdf932..2a42d8766 100644 --- a/pkg/apis/radixvalidators/validate_ra_test.go +++ b/pkg/apis/radixvalidators/validate_ra_test.go @@ -28,6 +28,7 @@ func Test_valid_ra_returns_true(t *testing.T) { assert.NoError(t, err) } + func Test_missing_rr(t *testing.T) { client := radixfake.NewSimpleClientset() validRA := createValidRA() From 7cf218c72102ebdd9e5b772dad92de014fc6ed73 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 5 Dec 2023 13:19:24 +0100 Subject: [PATCH 090/121] Fixed reported review issues. --- pkg/apis/alert/alert_test.go | 54 +++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/pkg/apis/alert/alert_test.go b/pkg/apis/alert/alert_test.go index 9f330ea26..66dfb692f 100644 --- a/pkg/apis/alert/alert_test.go +++ b/pkg/apis/alert/alert_test.go @@ -118,7 +118,8 @@ func (s *alertTestSuite) Test_OnSync_ResourcesCreated() { sut := s.createAlertSyncer(radixAlert) err := sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + _, err = s.kubeClient.CoreV1().Secrets(namespace).Get(context.Background(), GetAlertSecretName(alertName), metav1.GetOptions{}) s.Nil(err, "secret not found") actualRoles, _ := s.kubeClient.RbacV1().Roles(namespace).List(context.Background(), metav1.ListOptions{}) @@ -139,7 +140,8 @@ func (s *alertTestSuite) Test_OnSync_Rbac_SkipCreateOnMissingRR() { sut := s.createAlertSyncer(radixalert) err := sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + actualRoles, _ := s.kubeClient.RbacV1().Roles(namespace).List(context.Background(), metav1.ListOptions{}) s.Len(actualRoles.Items, 0) actualRoleBindings, _ := s.kubeClient.RbacV1().RoleBindings(namespace).List(context.Background(), metav1.ListOptions{}) @@ -164,7 +166,8 @@ func (s *alertTestSuite) Test_OnSync_Rbac_DeleteExistingOnMissingRR() { sut := s.createAlertSyncer(radixalert) err = sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + actualRoles, _ := s.kubeClient.RbacV1().Roles(namespace).List(context.Background(), metav1.ListOptions{}) s.Len(actualRoles.Items, 0) actualRoleBindings, _ := s.kubeClient.RbacV1().RoleBindings(namespace).List(context.Background(), metav1.ListOptions{}) @@ -187,7 +190,8 @@ func (s *alertTestSuite) Test_OnSync_Rbac_CreateWithOwnerReference() { sut := s.createAlertSyncer(radixalert) err := sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + actualRoles, _ := s.kubeClient.RbacV1().Roles(namespace).List(context.Background(), metav1.ListOptions{}) s.Len(actualRoles.Items, 2) for _, actualRole := range actualRoles.Items { @@ -229,7 +233,8 @@ func (s *alertTestSuite) Test_OnSync_Rbac_UpdateWithOwnerReference() { sut := s.createAlertSyncer(radixalert) err = sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + actualRoles, _ := s.kubeClient.RbacV1().Roles(namespace).List(context.Background(), metav1.ListOptions{}) s.Len(actualRoles.Items, 2) for _, actualRole := range actualRoles.Items { @@ -260,7 +265,8 @@ func (s *alertTestSuite) Test_OnSync_Rbac_ConfiguredCorrectly() { sut := s.createAlertSyncer(radixalert) err := sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + actualAdminRole, _ := s.kubeClient.RbacV1().Roles(namespace).Get(context.Background(), getAlertConfigSecretAdminRoleName(alertName), metav1.GetOptions{}) s.Len(actualAdminRole.Rules, 1, "role rules not as expected") s.ElementsMatch([]string{GetAlertSecretName(alertName)}, actualAdminRole.Rules[0].ResourceNames, "role rule resource names not as expected") @@ -311,7 +317,8 @@ func (s *alertTestSuite) Test_OnSync_Secret_RemoveOrphanedKeys() { sut := s.createAlertSyncer(radixalert) err := sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + actualSecret, _ := s.kubeClient.CoreV1().Secrets(namespace).Get(context.Background(), GetAlertSecretName(alertName), metav1.GetOptions{}) s.Len(actualSecret.Data, 2) s.Equal(receiver1, string(actualSecret.Data[GetSlackConfigSecretKeyName(receiver1)])) @@ -330,7 +337,8 @@ func (s *alertTestSuite) Test_OnSync_Secret_CreateWithOwnerReference() { sut := s.createAlertSyncer(radixalert) err := sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + actualSecret, _ := s.kubeClient.CoreV1().Secrets(namespace).Get(context.Background(), GetAlertSecretName(alertName), metav1.GetOptions{}) s.Len(actualSecret.OwnerReferences, 1, "secret ownerReference length not as expected") s.Equal(expectedAlertOwnerRef, actualSecret.OwnerReferences[0], "secret ownerReference not as expected") @@ -350,7 +358,8 @@ func (s *alertTestSuite) Test_OnSync_Secret_UpdateWithOwnerReference() { sut := s.createAlertSyncer(radixalert) err = sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + actualSecret, _ := s.kubeClient.CoreV1().Secrets(namespace).Get(context.Background(), GetAlertSecretName(alertName), metav1.GetOptions{}) s.Len(actualSecret.OwnerReferences, 1, "secret ownerReference length not as expected") s.Equal(expectedAlertOwnerRef, actualSecret.OwnerReferences[0], "secret ownerReference not as expected") @@ -367,7 +376,8 @@ func (s *alertTestSuite) Test_OnSync_Secret_CreateWithAppLabel() { sut := s.createAlertSyncer(radixalert) err := sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + actualSecret, _ := s.kubeClient.CoreV1().Secrets(namespace).Get(context.Background(), GetAlertSecretName(alertName), metav1.GetOptions{}) s.Equal(map[string]string{kube.RadixAppLabel: appName}, actualSecret.Labels, "secret labels not as expected") } @@ -383,7 +393,8 @@ func (s *alertTestSuite) Test_OnSync_Secret_CreateWithoutAppLabel() { sut := s.createAlertSyncer(radixalert) err := sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + actualSecret, _ := s.kubeClient.CoreV1().Secrets(namespace).Get(context.Background(), GetAlertSecretName(alertName), metav1.GetOptions{}) s.Empty(actualSecret.Labels, "secret labels not as expected") } @@ -401,7 +412,8 @@ func (s *alertTestSuite) Test_OnSync_Secret_UpdateSetAppLabel() { sut := s.createAlertSyncer(radixalert) err = sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + actualSecret, _ := s.kubeClient.CoreV1().Secrets(namespace).Get(context.Background(), GetAlertSecretName(alertName), metav1.GetOptions{}) s.Equal(map[string]string{kube.RadixAppLabel: appName}, actualSecret.Labels, "secret labels not as expected") } @@ -419,7 +431,8 @@ func (s *alertTestSuite) Test_OnSync_Secret_UpdateRemoveAppLabel() { sut := s.createAlertSyncer(radixalert) err = sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + actualSecret, _ := s.kubeClient.CoreV1().Secrets(namespace).Get(context.Background(), GetAlertSecretName(alertName), metav1.GetOptions{}) s.Empty(actualSecret.Labels, "secret labels not as expected") } @@ -436,7 +449,8 @@ func (s *alertTestSuite) Test_OnSync_AlertmanagerConfig_CreateWithOwnerReference sut := s.createAlertSyncer(radixalert) err := sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + actualAmr, _ := s.promClient.MonitoringV1alpha1().AlertmanagerConfigs(namespace).Get(context.Background(), getAlertmanagerConfigName(alertName), metav1.GetOptions{}) s.Len(actualAmr.OwnerReferences, 1, "alertmanagerconfig ownerReference length not as expected") s.Equal(expectedAlertOwnerRef, actualAmr.OwnerReferences[0], "alertmanagerconfig ownerReference not as expected") @@ -456,7 +470,8 @@ func (s *alertTestSuite) Test_OnSync_AlertmanagerConfig_UpdateWithOwnerReference sut := s.createAlertSyncer(radixalert) err = sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + actualAmr, _ := s.promClient.MonitoringV1alpha1().AlertmanagerConfigs(namespace).Get(context.Background(), getAlertmanagerConfigName(alertName), metav1.GetOptions{}) s.Len(actualAmr.OwnerReferences, 1, "alertmanagerconfig ownerReference length not as expected") s.Equal(expectedAlertOwnerRef, actualAmr.OwnerReferences[0], "alertmanagerconfig ownerReference not as expected") @@ -537,7 +552,8 @@ func (s *alertTestSuite) Test_OnSync_AlertmanagerConfig_ConfiguredCorrectly() { sut := s.createAlertSyncer(radixalert, testAlertSyncerWithAlertConfigs(alertConfigs), testAlertSyncerWithSlackMessageTemplate(slackTemplate)) err := sut.OnSync() - s.Nil(err) + s.Require().NoError(err) + // Receivers actualAmr, _ := s.promClient.MonitoringV1alpha1().AlertmanagerConfigs(namespace).Get(context.Background(), getAlertmanagerConfigName(alertName), metav1.GetOptions{}) s.Len(actualAmr.Spec.Receivers, 5) @@ -597,9 +613,9 @@ func (s *alertTestSuite) Test_OnSync_AlertmanagerConfig_ConfiguredCorrectly() { radixalert, err = s.radixClient.RadixV1().RadixAlerts(namespace).Update(context.Background(), radixalert, metav1.UpdateOptions{}) s.Nil(err) sut = s.createAlertSyncer(radixalert, testAlertSyncerWithAlertConfigs(alertConfigs), testAlertSyncerWithSlackMessageTemplate(slackTemplate)) - if err := sut.OnSync(); err != nil { - panic(err) - } + err = sut.OnSync() + s.Require().NoError(err) + actualAmr, _ = s.promClient.MonitoringV1alpha1().AlertmanagerConfigs(namespace).Get(context.Background(), getAlertmanagerConfigName(alertName), metav1.GetOptions{}) s.Len(actualAmr.Spec.Receivers, 3) s.Len(actualAmr.Spec.Route.Routes, 2) From 1447bbeefeadcc297bf6daba9374618176b3e939 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 5 Dec 2023 13:21:44 +0100 Subject: [PATCH 091/121] Fixed reported review issues. --- pkg/apis/application/application.go | 4 ++-- pkg/apis/application/limitrange.go | 2 +- pkg/apis/application/namespace.go | 2 +- pkg/apis/application/ownerreference.go | 2 +- pkg/apis/application/rolebinding.go | 26 +++++++++++++------------- pkg/apis/application/roles.go | 6 +++--- pkg/apis/application/secrets.go | 14 +++++++------- pkg/apis/application/serviceaccount.go | 2 +- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/pkg/apis/application/application.go b/pkg/apis/application/application.go index 2287473ff..5f4fbc8b1 100644 --- a/pkg/apis/application/application.go +++ b/pkg/apis/application/application.go @@ -42,7 +42,7 @@ func NewApplication( // OnSync compares the actual state with the desired, and attempts to // converge the two -func (app Application) OnSync() error { +func (app *Application) OnSync() error { radixRegistration := app.registration logger = log.WithFields(log.Fields{"registrationName": radixRegistration.GetName()}) @@ -113,7 +113,7 @@ func (app Application) OnSync() error { return nil } -func (app Application) updateRadixRegistrationStatus(rr *v1.RadixRegistration, changeStatusFunc func(currStatus *v1.RadixRegistrationStatus)) error { +func (app *Application) updateRadixRegistrationStatus(rr *v1.RadixRegistration, changeStatusFunc func(currStatus *v1.RadixRegistrationStatus)) error { rrInterface := app.radixclient.RadixV1().RadixRegistrations() return retry.RetryOnConflict(retry.DefaultRetry, func() error { currentRR, err := rrInterface.Get(context.TODO(), rr.GetName(), metav1.GetOptions{}) diff --git a/pkg/apis/application/limitrange.go b/pkg/apis/application/limitrange.go index db8b5aedf..a4f910173 100644 --- a/pkg/apis/application/limitrange.go +++ b/pkg/apis/application/limitrange.go @@ -9,7 +9,7 @@ const ( limitRangeName = "mem-cpu-limit-range-app" ) -func (app Application) createLimitRangeOnAppNamespace(namespace string) error { +func (app *Application) createLimitRangeOnAppNamespace(namespace string) error { defaultMemoryLimit := defaults.GetDefaultMemoryLimitForAppNamespace() defaultCPURequest := defaults.GetDefaultCPURequestForAppNamespace() defaultMemoryRequest := defaults.GetDefaultMemoryRequestForAppNamespace() diff --git a/pkg/apis/application/namespace.go b/pkg/apis/application/namespace.go index a243d7894..c48f36f36 100644 --- a/pkg/apis/application/namespace.go +++ b/pkg/apis/application/namespace.go @@ -7,7 +7,7 @@ import ( ) // createAppNamespace creates an app namespace with RadixRegistration as owner -func (app Application) createAppNamespace() error { +func (app *Application) createAppNamespace() error { registration := app.registration name := utils.GetAppNamespace(registration.Name) diff --git a/pkg/apis/application/ownerreference.go b/pkg/apis/application/ownerreference.go index 84ec8c3d1..220c9b97d 100644 --- a/pkg/apis/application/ownerreference.go +++ b/pkg/apis/application/ownerreference.go @@ -7,7 +7,7 @@ import ( ) // GetOwnerReference Gets owner reference of application -func (app Application) getOwnerReference() []metav1.OwnerReference { +func (app *Application) getOwnerReference() []metav1.OwnerReference { return GetOwnerReferenceOfRegistration(app.registration) } diff --git a/pkg/apis/application/rolebinding.go b/pkg/apis/application/rolebinding.go index f0cde5d76..34dc666f8 100644 --- a/pkg/apis/application/rolebinding.go +++ b/pkg/apis/application/rolebinding.go @@ -13,7 +13,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func (app Application) applyRbacAppNamespace() error { +func (app *Application) applyRbacAppNamespace() error { k := app.kubeutil registration := app.registration @@ -39,7 +39,7 @@ func (app Application) applyRbacAppNamespace() error { } // ApplyRbacRadixRegistration Grants access to radix registration -func (app Application) applyRbacRadixRegistration() error { +func (app *Application) applyRbacRadixRegistration() error { rr := app.registration appName := rr.Name @@ -86,7 +86,7 @@ func getAppAdminSubjects(rr *v1.RadixRegistration) ([]auth.Subject, error) { } // ApplyRbacOnPipelineRunner Grants access to radix pipeline -func (app Application) applyRbacOnPipelineRunner() error { +func (app *Application) applyRbacOnPipelineRunner() error { serviceAccount, err := app.applyPipelineServiceAccount() if err != nil { logger.Errorf("Failed to apply service account needed by pipeline. %v", err) @@ -101,7 +101,7 @@ func (app Application) applyRbacOnPipelineRunner() error { return app.givePipelineAccessToAppNamespace(serviceAccount) } -func (app Application) applyRbacOnRadixTekton() error { +func (app *Application) applyRbacOnRadixTekton() error { serviceAccount, err := app.kubeutil.CreateServiceAccount(utils.GetAppNamespace(app.registration.Name), defaults.RadixTektonServiceAccountName) if err != nil { return err @@ -115,39 +115,39 @@ func (app Application) applyRbacOnRadixTekton() error { return app.giveRadixTektonAccessToAppNamespace(serviceAccount) } -func (app Application) givePipelineAccessToRR(serviceAccount *corev1.ServiceAccount, clusterRoleNamePrefix string) error { +func (app *Application) givePipelineAccessToRR(serviceAccount *corev1.ServiceAccount, clusterRoleNamePrefix string) error { clusterRoleName := fmt.Sprintf("%s-%s", clusterRoleNamePrefix, app.registration.Name) clusterRole := app.buildRRClusterRole(clusterRoleName, []string{"get"}) clusterRoleBinding := app.clusterRoleBinding(serviceAccount, clusterRole) return app.applyClusterRoleAndBinding(clusterRole, clusterRoleBinding) } -func (app Application) giveAccessToRadixDNSAliases(serviceAccount *corev1.ServiceAccount, clusterRoleNamePrefix string) error { +func (app *Application) giveAccessToRadixDNSAliases(serviceAccount *corev1.ServiceAccount, clusterRoleNamePrefix string) error { clusterRole := app.buildRadixDNSAliasClusterRole(clusterRoleNamePrefix) clusterRoleBinding := app.clusterRoleBinding(serviceAccount, clusterRole) return app.applyClusterRoleAndBinding(clusterRole, clusterRoleBinding) } -func (app Application) applyClusterRoleAndBinding(clusterRole *auth.ClusterRole, clusterRoleBinding *auth.ClusterRoleBinding) error { +func (app *Application) applyClusterRoleAndBinding(clusterRole *auth.ClusterRole, clusterRoleBinding *auth.ClusterRoleBinding) error { if err := app.kubeutil.ApplyClusterRole(clusterRole); err != nil { return err } return app.kubeutil.ApplyClusterRoleBinding(clusterRoleBinding) } -func (app Application) givePipelineAccessToAppNamespace(serviceAccount *corev1.ServiceAccount) error { +func (app *Application) givePipelineAccessToAppNamespace(serviceAccount *corev1.ServiceAccount) error { namespace := utils.GetAppNamespace(app.registration.Name) rolebinding := app.pipelineRoleBinding(serviceAccount) return app.kubeutil.ApplyRoleBinding(namespace, rolebinding) } -func (app Application) giveRadixTektonAccessToAppNamespace(serviceAccount *corev1.ServiceAccount) error { +func (app *Application) giveRadixTektonAccessToAppNamespace(serviceAccount *corev1.ServiceAccount) error { namespace := utils.GetAppNamespace(app.registration.Name) roleBinding := app.radixTektonRoleBinding(serviceAccount) return app.kubeutil.ApplyRoleBinding(namespace, roleBinding) } -func (app Application) pipelineRoleBinding(serviceAccount *corev1.ServiceAccount) *auth.RoleBinding { +func (app *Application) pipelineRoleBinding(serviceAccount *corev1.ServiceAccount) *auth.RoleBinding { registration := app.registration appName := registration.Name logger.Debugf("Create rolebinding config %s", defaults.PipelineAppRoleName) @@ -179,7 +179,7 @@ func (app Application) pipelineRoleBinding(serviceAccount *corev1.ServiceAccount return rolebinding } -func (app Application) radixTektonRoleBinding(serviceAccount *corev1.ServiceAccount) *auth.RoleBinding { +func (app *Application) radixTektonRoleBinding(serviceAccount *corev1.ServiceAccount) *auth.RoleBinding { registration := app.registration appName := registration.Name logger.Debugf("Create rolebinding config %s", defaults.RadixTektonAppRoleName) @@ -211,7 +211,7 @@ func (app Application) radixTektonRoleBinding(serviceAccount *corev1.ServiceAcco return rolebinding } -func (app Application) clusterRoleBinding(serviceAccount *corev1.ServiceAccount, clusterRole *auth.ClusterRole) *auth.ClusterRoleBinding { +func (app *Application) clusterRoleBinding(serviceAccount *corev1.ServiceAccount, clusterRole *auth.ClusterRole) *auth.ClusterRoleBinding { appName := app.registration.Name clusterRoleBindingName := clusterRole.Name ownerReference := app.getOwnerReference() @@ -245,7 +245,7 @@ func (app Application) clusterRoleBinding(serviceAccount *corev1.ServiceAccount, return clusterRoleBinding } -func (app Application) rrClusterroleBinding(clusterrole *auth.ClusterRole, subjects []auth.Subject) *auth.ClusterRoleBinding { +func (app *Application) rrClusterroleBinding(clusterrole *auth.ClusterRole, subjects []auth.Subject) *auth.ClusterRoleBinding { registration := app.registration appName := registration.Name clusterroleBindingName := clusterrole.Name diff --git a/pkg/apis/application/roles.go b/pkg/apis/application/roles.go index 1a0f35d47..e28f525f3 100644 --- a/pkg/apis/application/roles.go +++ b/pkg/apis/application/roles.go @@ -10,7 +10,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func (app Application) buildRRClusterRole(clusterRoleName string, verbs []string) *auth.ClusterRole { +func (app *Application) buildRRClusterRole(clusterRoleName string, verbs []string) *auth.ClusterRole { appName := app.registration.Name return app.buildClusterRole(clusterRoleName, auth.PolicyRule{APIGroups: []string{radix.GroupName}, Resources: []string{radix.ResourceRadixRegistrations}, @@ -19,7 +19,7 @@ func (app Application) buildRRClusterRole(clusterRoleName string, verbs []string }) } -func (app Application) buildRadixDNSAliasClusterRole(roleNamePrefix string) *auth.ClusterRole { +func (app *Application) buildRadixDNSAliasClusterRole(roleNamePrefix string) *auth.ClusterRole { clusterRoleName := fmt.Sprintf("%s-%s", roleNamePrefix, app.registration.Name) return app.buildClusterRole(clusterRoleName, auth.PolicyRule{APIGroups: []string{radix.GroupName}, Resources: []string{radix.ResourceRadixDNSAliases}, @@ -27,7 +27,7 @@ func (app Application) buildRadixDNSAliasClusterRole(roleNamePrefix string) *aut }) } -func (app Application) buildClusterRole(clusterRoleName string, rules ...auth.PolicyRule) *auth.ClusterRole { +func (app *Application) buildClusterRole(clusterRoleName string, rules ...auth.PolicyRule) *auth.ClusterRole { logger.Debugf("Creating clusterrole config %s", clusterRoleName) clusterRole := &auth.ClusterRole{ TypeMeta: metav1.TypeMeta{ diff --git a/pkg/apis/application/secrets.go b/pkg/apis/application/secrets.go index 033554e5d..e5e369930 100644 --- a/pkg/apis/application/secrets.go +++ b/pkg/apis/application/secrets.go @@ -14,7 +14,7 @@ import ( ) // ApplySecretsForPipelines creates secrets needed by pipeline to run -func (app Application) applySecretsForPipelines() error { +func (app *Application) applySecretsForPipelines() error { radixRegistration := app.registration log.Debugf("Apply secrets for pipelines") @@ -31,7 +31,7 @@ func (app Application) applySecretsForPipelines() error { return nil } -func (app Application) applyGitDeployKeyToBuildNamespace(namespace string) error { +func (app *Application) applyGitDeployKeyToBuildNamespace(namespace string) error { radixRegistration := app.registration secret, err := app.kubeutil.GetSecret(namespace, defaults.GitPrivateKeySecretName) if err != nil { @@ -103,7 +103,7 @@ func deriveKeyPairFromSecret(secret *corev1.Secret) (*utils.DeployKey, error) { return deployKey, nil } -func (app Application) applyServicePrincipalACRSecretToBuildNamespace(buildNamespace string) error { +func (app *Application) applyServicePrincipalACRSecretToBuildNamespace(buildNamespace string) error { servicePrincipalSecretForBuild, err := app.createNewServicePrincipalACRSecret(buildNamespace, defaults.AzureACRServicePrincipleSecretName) if err != nil { return err @@ -129,7 +129,7 @@ func (app Application) applyServicePrincipalACRSecretToBuildNamespace(buildNames return nil } -func (app Application) createNewGitDeployKey(namespace, deployKey string, registration *v1.RadixRegistration) (*corev1.Secret, error) { +func (app *Application) createNewGitDeployKey(namespace, deployKey string, registration *v1.RadixRegistration) (*corev1.Secret, error) { knownHostsSecret, err := app.kubeutil.GetSecret(corev1.NamespaceDefault, "radix-known-hosts-git") if err != nil { log.Errorf("Failed to get known hosts secret. %v", err) @@ -152,7 +152,7 @@ func (app Application) createNewGitDeployKey(namespace, deployKey string, regist return &secret, nil } -func (app Application) createNewServicePrincipalACRSecret(namespace, secretName string) (*corev1.Secret, error) { +func (app *Application) createNewServicePrincipalACRSecret(namespace, secretName string) (*corev1.Secret, error) { servicePrincipalSecret, err := app.kubeutil.GetSecret(corev1.NamespaceDefault, secretName) if err != nil { log.Errorf("Failed to get %s secret from default. %v", secretName, err) @@ -175,13 +175,13 @@ func (app Application) createNewServicePrincipalACRSecret(namespace, secretName return &secret, nil } -func (app Application) gitPrivateKeyExists(secret *corev1.Secret) bool { +func (app *Application) gitPrivateKeyExists(secret *corev1.Secret) bool { if secret == nil { return false } return len(strings.TrimSpace(string(secret.Data[defaults.GitPrivateKeySecretKey]))) > 0 } -func (app Application) createGitPublicKeyConfigMap(namespace string, key string, registration *v1.RadixRegistration) *corev1.ConfigMap { +func (app *Application) createGitPublicKeyConfigMap(namespace string, key string, registration *v1.RadixRegistration) *corev1.ConfigMap { // Create a configmap with the public key cm := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/apis/application/serviceaccount.go b/pkg/apis/application/serviceaccount.go index 46fa43e5f..47d851d69 100644 --- a/pkg/apis/application/serviceaccount.go +++ b/pkg/apis/application/serviceaccount.go @@ -7,6 +7,6 @@ import ( ) // ApplyPipelineServiceAccount create service account needed by pipeline -func (app Application) applyPipelineServiceAccount() (*corev1.ServiceAccount, error) { +func (app *Application) applyPipelineServiceAccount() (*corev1.ServiceAccount, error) { return app.kubeutil.CreateServiceAccount(utils.GetAppNamespace(app.registration.Name), defaults.PipelineServiceAccountName) } From 028b32730e3025ab810d1639946e63f3e812ce20 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 5 Dec 2023 14:01:59 +0100 Subject: [PATCH 092/121] Fixed reported review issues. Replaced commonerrors.Concat with standard lib --- pipeline-runner/steps/apply_radixconfig.go | 3 +-- pkg/apis/applicationconfig/applicationconfig.go | 4 ++-- pkg/apis/applicationconfig/dns_alias.go | 6 +++--- pkg/apis/deployment/config_maps.go | 5 +++-- pkg/apis/deployment/deployment.go | 6 +++--- pkg/apis/deployment/deployment_test.go | 4 ++-- pkg/apis/deployment/job.go | 4 ++-- pkg/apis/deployment/pdb.go | 6 +++--- pkg/apis/deployment/radixjobcomponent.go | 5 +++-- pkg/apis/radixvalidators/validate_rd.go | 4 ++-- pkg/apis/radixvalidators/validate_rr.go | 6 +++--- radix-operator/main.go | 4 ++-- 12 files changed, 29 insertions(+), 28 deletions(-) diff --git a/pipeline-runner/steps/apply_radixconfig.go b/pipeline-runner/steps/apply_radixconfig.go index 1e07aca62..2a020ae7d 100644 --- a/pipeline-runner/steps/apply_radixconfig.go +++ b/pipeline-runner/steps/apply_radixconfig.go @@ -8,7 +8,6 @@ import ( "strings" commonutils "github.com/equinor/radix-common/utils" - errorUtils "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pipeline-runner/model" pipelineDefaults "github.com/equinor/radix-operator/pipeline-runner/model/defaults" @@ -510,7 +509,7 @@ func (cli *ApplyConfigStepImplementation) getHashAndTags(namespace string, pipel } gitCommitHash, commitErr := getValueFromConfigMap(defaults.RadixGitCommitHashKey, gitConfigMap) gitTags, tagsErr := getValueFromConfigMap(defaults.RadixGitTagsKey, gitConfigMap) - err = errorUtils.Concat([]error{commitErr, tagsErr}) + err = stderrors.Join(commitErr, tagsErr) if err != nil { log.Errorf("could not retrieve git values from temporary configmap %s, %v", pipelineInfo.GitConfigMapName, err) return "", "" diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index bb1aae913..fefaed14b 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -3,11 +3,11 @@ package applicationconfig import ( "context" "encoding/json" + stderrors "errors" "fmt" "reflect" "strings" - commonErrors "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" @@ -207,7 +207,7 @@ func (app *ApplicationConfig) createEnvironments() error { errs = append(errs, err) } } - return commonErrors.Concat(errs) + return stderrors.Join(errs...) } // applyEnvironment creates an environment or applies changes if it exists diff --git a/pkg/apis/applicationconfig/dns_alias.go b/pkg/apis/applicationconfig/dns_alias.go index c4f353190..6858ba1f8 100644 --- a/pkg/apis/applicationconfig/dns_alias.go +++ b/pkg/apis/applicationconfig/dns_alias.go @@ -1,10 +1,10 @@ package applicationconfig import ( + stderrors "errors" "fmt" "strings" - "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -46,7 +46,7 @@ func (app *ApplicationConfig) createOrUpdateDNSAliases() error { radixDNSAliasesToCreate = append(radixDNSAliasesToCreate, app.buildRadixDNSAlias(appName, dnsAlias, port)) } if len(errs) > 0 { - return errors.Concat(errs) + return stderrors.Join(errs...) } for _, radixDNSAlias := range existingRadixDNSAliasesMap { if err = app.kubeutil.DeleteRadixDNSAliases(radixDNSAlias); err != nil { @@ -63,7 +63,7 @@ func (app *ApplicationConfig) createOrUpdateDNSAliases() error { errs = append(errs, err) } } - return errors.Concat(errs) + return stderrors.Join(errs...) } func getComponentPublicPort(component *radixv1.RadixComponent) *radixv1.ComponentPort { diff --git a/pkg/apis/deployment/config_maps.go b/pkg/apis/deployment/config_maps.go index f8edb4882..5332f2d21 100644 --- a/pkg/apis/deployment/config_maps.go +++ b/pkg/apis/deployment/config_maps.go @@ -1,8 +1,9 @@ package deployment import ( + stderrors "errors" "fmt" - "github.com/equinor/radix-common/utils/errors" + log "github.com/sirupsen/logrus" ) @@ -41,5 +42,5 @@ func (deploy *Deployment) garbageCollectConfigMapsNoLongerInSpec() error { } } - return errors.Concat(errs) + return stderrors.Join(errs...) } diff --git a/pkg/apis/deployment/deployment.go b/pkg/apis/deployment/deployment.go index 8ab479fa8..77bac5844 100644 --- a/pkg/apis/deployment/deployment.go +++ b/pkg/apis/deployment/deployment.go @@ -3,12 +3,12 @@ package deployment import ( "context" "encoding/json" + stderrors "errors" "fmt" "sort" "strings" "time" - "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/ingress" @@ -241,7 +241,7 @@ func (deploy *Deployment) syncDeployment() error { // If any error occurred when setting network policies if len(errs) > 0 { - combinedErrs := errors.Concat(errs) + combinedErrs := stderrors.Join(errs...) log.Errorf("%s", combinedErrs) return combinedErrs } @@ -261,7 +261,7 @@ func (deploy *Deployment) syncDeployment() error { // If any error occurred when syncing of components if len(errs) > 0 { - return errors.Concat(errs) + return stderrors.Join(errs...) } if err := deploy.syncAuxiliaryResources(); err != nil { diff --git a/pkg/apis/deployment/deployment_test.go b/pkg/apis/deployment/deployment_test.go index db2dc4944..f5ba9482d 100644 --- a/pkg/apis/deployment/deployment_test.go +++ b/pkg/apis/deployment/deployment_test.go @@ -4,6 +4,7 @@ package deployment import ( "context" "errors" + stderrors "errors" "fmt" "os" "strings" @@ -11,7 +12,6 @@ import ( "time" radixutils "github.com/equinor/radix-common/utils" - radixerrors "github.com/equinor/radix-common/utils/errors" radixmaps "github.com/equinor/radix-common/utils/maps" "github.com/equinor/radix-common/utils/pointers" "github.com/equinor/radix-common/utils/slice" @@ -1759,7 +1759,7 @@ func addRadixBatches(radixclient radixclient.Interface, envNamespace string, dep errs = append(errs, err) } } - return radixerrors.Concat(errs) + return stderrors.Join(errs...) } func TestObjectUpdated_MultipleReplicasExistsAndNotSpecifiedReplicas_SetsDefaultReplicaCount(t *testing.T) { diff --git a/pkg/apis/deployment/job.go b/pkg/apis/deployment/job.go index d1d38ecff..cb95123b0 100644 --- a/pkg/apis/deployment/job.go +++ b/pkg/apis/deployment/job.go @@ -2,8 +2,8 @@ package deployment import ( "context" + stderrors "errors" - "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-operator/pkg/apis/utils/labels" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -63,5 +63,5 @@ func (deploy *Deployment) garbageCollectScheduledJobAuxDeploymentsNoLongerInSpec } } } - return errors.Concat(errs) + return stderrors.Join(errs...) } diff --git a/pkg/apis/deployment/pdb.go b/pkg/apis/deployment/pdb.go index ae888c515..010c55c97 100644 --- a/pkg/apis/deployment/pdb.go +++ b/pkg/apis/deployment/pdb.go @@ -2,9 +2,9 @@ package deployment import ( "context" + stderrors "errors" "fmt" - "github.com/equinor/radix-common/utils/errors" "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -81,7 +81,7 @@ func (deploy *Deployment) garbageCollectPodDisruptionBudgetNoLongerInSpecForComp } } - return errors.Concat(errs) + return stderrors.Join(errs...) } func (deploy *Deployment) garbageCollectPodDisruptionBudgetsNoLongerInSpec() error { @@ -113,5 +113,5 @@ func (deploy *Deployment) garbageCollectPodDisruptionBudgetsNoLongerInSpec() err } } - return errors.Concat(errs) + return stderrors.Join(errs...) } diff --git a/pkg/apis/deployment/radixjobcomponent.go b/pkg/apis/deployment/radixjobcomponent.go index 9f869d283..255446f0c 100644 --- a/pkg/apis/deployment/radixjobcomponent.go +++ b/pkg/apis/deployment/radixjobcomponent.go @@ -1,7 +1,8 @@ package deployment import ( - commonErrors "github.com/equinor/radix-common/utils/errors" + stderrors "errors" + "github.com/equinor/radix-common/utils/numbers" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/pipeline" @@ -75,7 +76,7 @@ func (c *jobComponentsBuilder) buildJobComponent(radixJobComponent v1.RadixJobCo errs = append(errs, err) } if len(errs) > 0 { - return nil, commonErrors.Concat(errs) + return nil, stderrors.Join(errs...) } image, err := getImagePath(componentName, componentImage, environmentSpecificConfig) diff --git a/pkg/apis/radixvalidators/validate_rd.go b/pkg/apis/radixvalidators/validate_rd.go index 5719be21e..54052561d 100644 --- a/pkg/apis/radixvalidators/validate_rd.go +++ b/pkg/apis/radixvalidators/validate_rd.go @@ -1,10 +1,10 @@ package radixvalidators import ( + stderrors "errors" "fmt" "strings" - "github.com/equinor/radix-common/utils/errors" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" ) @@ -62,7 +62,7 @@ func CanRadixDeploymentBeInserted(deploy *radixv1.RadixDeployment) error { errs = append(errs, err) } - return errors.Concat(errs) + return stderrors.Join(errs...) } func validateDeployComponents(deployment *radixv1.RadixDeployment) []error { diff --git a/pkg/apis/radixvalidators/validate_rr.go b/pkg/apis/radixvalidators/validate_rr.go index e50906c9d..d2deeee27 100644 --- a/pkg/apis/radixvalidators/validate_rr.go +++ b/pkg/apis/radixvalidators/validate_rr.go @@ -2,15 +2,15 @@ package radixvalidators import ( "context" + stderrors "errors" "fmt" "regexp" "strings" - commonErrors "github.com/equinor/radix-common/utils/errors" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils/branch" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" - errors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -73,7 +73,7 @@ func validateRadixRegistration(radixRegistration *v1.RadixRegistration, validato errs = append(errs, err) } } - return commonErrors.Concat(errs) + return stderrors.Join(errs...) } // GetRadixRegistrationBeInsertedWarnings Get warnings for inserting RadixRegistration diff --git a/radix-operator/main.go b/radix-operator/main.go index e3b9c44eb..c1d738c11 100644 --- a/radix-operator/main.go +++ b/radix-operator/main.go @@ -3,6 +3,7 @@ package main import ( "context" "encoding/json" + stderrors "errors" "fmt" "net/http" "os" @@ -10,7 +11,6 @@ import ( "syscall" "time" - errorUtils "github.com/equinor/radix-common/utils/errors" apiconfig "github.com/equinor/radix-operator/pkg/apis/config" dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" @@ -130,7 +130,7 @@ func getInitParams() (int, int, int, int, int, int, int, float32, error) { kubeClientRateLimitBurst, burstErr := defaults.GetKubeClientRateLimitBurst() kubeClientRateLimitQPS, qpsErr := defaults.GetKubeClientRateLimitQps() - errCat := errorUtils.Concat([]error{regErr, appErr, envErr, depErr, jobErr, aleErr, burstErr, qpsErr}) + errCat := stderrors.Join(regErr, appErr, envErr, depErr, jobErr, aleErr, burstErr, qpsErr) return registrationControllerThreads, applicationControllerThreads, environmentControllerThreads, deploymentControllerThreads, jobControllerThreads, alertControllerThreads, kubeClientRateLimitBurst, kubeClientRateLimitQPS, errCat } From 5af0c2a29beea8829ab69dc15a29a8fb084b3696 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 5 Dec 2023 15:10:47 +0100 Subject: [PATCH 093/121] Fixed reported review issues. Replaced k8s attributes --- pkg/apis/application/rolebinding.go | 64 +++++++++---------- pkg/apis/application/roles.go | 16 ++--- pkg/apis/defaults/k8s/k8s.go | 6 -- pkg/apis/deployment/deploymentrbac.go | 6 +- .../oauthproxyresourcemanager_test.go | 10 +-- pkg/apis/environment/environment.go | 28 ++++---- pkg/apis/ingress/ownerreferences.go | 6 +- pkg/apis/kube/rolebinding.go | 24 +++---- pkg/apis/kube/roles.go | 2 +- 9 files changed, 78 insertions(+), 84 deletions(-) diff --git a/pkg/apis/application/rolebinding.go b/pkg/apis/application/rolebinding.go index 34dc666f8..cc77d520e 100644 --- a/pkg/apis/application/rolebinding.go +++ b/pkg/apis/application/rolebinding.go @@ -9,7 +9,7 @@ import ( v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" corev1 "k8s.io/api/core/v1" - auth "k8s.io/api/rbac/v1" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -29,7 +29,7 @@ func (app *Application) applyRbacAppNamespace() error { readerSubjects := kube.GetRoleBindingGroups(readerAdGroups) readerRoleBinding := kube.GetRolebindingToClusterRoleForSubjects(registration.Name, defaults.AppReaderRoleName, readerSubjects) - for _, roleBinding := range []*auth.RoleBinding{adminRoleBinding, readerRoleBinding} { + for _, roleBinding := range []*rbacv1.RoleBinding{adminRoleBinding, readerRoleBinding} { err = k.ApplyRoleBinding(appNamespace, roleBinding) if err != nil { return err @@ -59,14 +59,14 @@ func (app *Application) applyRbacRadixRegistration() error { readerClusterRoleBinding := app.rrClusterroleBinding(readerClusterRole, appReaderSubjects) // Apply roles and bindings - for _, clusterRole := range []*auth.ClusterRole{adminClusterRole, readerClusterRole} { + for _, clusterRole := range []*rbacv1.ClusterRole{adminClusterRole, readerClusterRole} { err := app.kubeutil.ApplyClusterRole(clusterRole) if err != nil { return err } } - for _, clusterRoleBindings := range []*auth.ClusterRoleBinding{adminClusterRoleBinding, readerClusterRoleBinding} { + for _, clusterRoleBindings := range []*rbacv1.ClusterRoleBinding{adminClusterRoleBinding, readerClusterRoleBinding} { err := app.kubeutil.ApplyClusterRoleBinding(clusterRoleBindings) if err != nil { return err @@ -76,7 +76,7 @@ func (app *Application) applyRbacRadixRegistration() error { return nil } -func getAppAdminSubjects(rr *v1.RadixRegistration) ([]auth.Subject, error) { +func getAppAdminSubjects(rr *v1.RadixRegistration) ([]rbacv1.Subject, error) { adGroups, err := utils.GetAdGroups(rr) if err != nil { return nil, err @@ -128,7 +128,7 @@ func (app *Application) giveAccessToRadixDNSAliases(serviceAccount *corev1.Servi return app.applyClusterRoleAndBinding(clusterRole, clusterRoleBinding) } -func (app *Application) applyClusterRoleAndBinding(clusterRole *auth.ClusterRole, clusterRoleBinding *auth.ClusterRoleBinding) error { +func (app *Application) applyClusterRoleAndBinding(clusterRole *rbacv1.ClusterRole, clusterRoleBinding *rbacv1.ClusterRoleBinding) error { if err := app.kubeutil.ApplyClusterRole(clusterRole); err != nil { return err } @@ -147,14 +147,14 @@ func (app *Application) giveRadixTektonAccessToAppNamespace(serviceAccount *core return app.kubeutil.ApplyRoleBinding(namespace, roleBinding) } -func (app *Application) pipelineRoleBinding(serviceAccount *corev1.ServiceAccount) *auth.RoleBinding { +func (app *Application) pipelineRoleBinding(serviceAccount *corev1.ServiceAccount) *rbacv1.RoleBinding { registration := app.registration appName := registration.Name logger.Debugf("Create rolebinding config %s", defaults.PipelineAppRoleName) - rolebinding := &auth.RoleBinding{ + rolebinding := &rbacv1.RoleBinding{ TypeMeta: metav1.TypeMeta{ - APIVersion: k8s.RbacApiVersion, + APIVersion: rbacv1.SchemeGroupVersion.Identifier(), Kind: "RoleBinding", }, ObjectMeta: metav1.ObjectMeta{ @@ -163,14 +163,14 @@ func (app *Application) pipelineRoleBinding(serviceAccount *corev1.ServiceAccoun kube.RadixAppLabel: appName, }, }, - RoleRef: auth.RoleRef{ - APIGroup: k8s.RbacApiGroup, + RoleRef: rbacv1.RoleRef{ + APIGroup: rbacv1.GroupName, Kind: k8s.KindClusterRole, Name: defaults.PipelineAppRoleName, }, - Subjects: []auth.Subject{ + Subjects: []rbacv1.Subject{ { - Kind: k8s.KindServiceAccount, + Kind: rbacv1.ServiceAccountKind, Name: serviceAccount.Name, Namespace: serviceAccount.Namespace, }, @@ -179,14 +179,14 @@ func (app *Application) pipelineRoleBinding(serviceAccount *corev1.ServiceAccoun return rolebinding } -func (app *Application) radixTektonRoleBinding(serviceAccount *corev1.ServiceAccount) *auth.RoleBinding { +func (app *Application) radixTektonRoleBinding(serviceAccount *corev1.ServiceAccount) *rbacv1.RoleBinding { registration := app.registration appName := registration.Name logger.Debugf("Create rolebinding config %s", defaults.RadixTektonAppRoleName) - rolebinding := &auth.RoleBinding{ + rolebinding := &rbacv1.RoleBinding{ TypeMeta: metav1.TypeMeta{ - APIVersion: k8s.RbacApiVersion, + APIVersion: rbacv1.SchemeGroupVersion.Identifier(), Kind: "RoleBinding", }, ObjectMeta: metav1.ObjectMeta{ @@ -195,14 +195,14 @@ func (app *Application) radixTektonRoleBinding(serviceAccount *corev1.ServiceAcc kube.RadixAppLabel: appName, }, }, - RoleRef: auth.RoleRef{ - APIGroup: k8s.RbacApiGroup, + RoleRef: rbacv1.RoleRef{ + APIGroup: rbacv1.GroupName, Kind: k8s.KindClusterRole, Name: defaults.RadixTektonAppRoleName, }, - Subjects: []auth.Subject{ + Subjects: []rbacv1.Subject{ { - Kind: k8s.KindServiceAccount, + Kind: rbacv1.ServiceAccountKind, Name: serviceAccount.Name, Namespace: serviceAccount.Namespace, }, @@ -211,15 +211,15 @@ func (app *Application) radixTektonRoleBinding(serviceAccount *corev1.ServiceAcc return rolebinding } -func (app *Application) clusterRoleBinding(serviceAccount *corev1.ServiceAccount, clusterRole *auth.ClusterRole) *auth.ClusterRoleBinding { +func (app *Application) clusterRoleBinding(serviceAccount *corev1.ServiceAccount, clusterRole *rbacv1.ClusterRole) *rbacv1.ClusterRoleBinding { appName := app.registration.Name clusterRoleBindingName := clusterRole.Name ownerReference := app.getOwnerReference() logger.Debugf("Create clusterrolebinding config %s", clusterRoleBindingName) - clusterRoleBinding := &auth.ClusterRoleBinding{ + clusterRoleBinding := &rbacv1.ClusterRoleBinding{ TypeMeta: metav1.TypeMeta{ - APIVersion: k8s.RbacApiVersion, + APIVersion: rbacv1.SchemeGroupVersion.Identifier(), Kind: k8s.KindClusterRoleBinding, }, ObjectMeta: metav1.ObjectMeta{ @@ -229,14 +229,14 @@ func (app *Application) clusterRoleBinding(serviceAccount *corev1.ServiceAccount }, OwnerReferences: ownerReference, }, - RoleRef: auth.RoleRef{ - APIGroup: k8s.RbacApiGroup, + RoleRef: rbacv1.RoleRef{ + APIGroup: rbacv1.GroupName, Kind: k8s.KindClusterRole, Name: clusterRole.Name, }, - Subjects: []auth.Subject{ + Subjects: []rbacv1.Subject{ { - Kind: k8s.KindServiceAccount, + Kind: rbacv1.ServiceAccountKind, Name: serviceAccount.Name, Namespace: serviceAccount.Namespace, }, @@ -245,16 +245,16 @@ func (app *Application) clusterRoleBinding(serviceAccount *corev1.ServiceAccount return clusterRoleBinding } -func (app *Application) rrClusterroleBinding(clusterrole *auth.ClusterRole, subjects []auth.Subject) *auth.ClusterRoleBinding { +func (app *Application) rrClusterroleBinding(clusterrole *rbacv1.ClusterRole, subjects []rbacv1.Subject) *rbacv1.ClusterRoleBinding { registration := app.registration appName := registration.Name clusterroleBindingName := clusterrole.Name logger.Debugf("Create clusterrolebinding config %s", clusterroleBindingName) ownerReference := app.getOwnerReference() - clusterrolebinding := &auth.ClusterRoleBinding{ + clusterrolebinding := &rbacv1.ClusterRoleBinding{ TypeMeta: metav1.TypeMeta{ - APIVersion: k8s.RbacApiVersion, + APIVersion: rbacv1.SchemeGroupVersion.Identifier(), Kind: k8s.KindClusterRoleBinding, }, ObjectMeta: metav1.ObjectMeta{ @@ -264,8 +264,8 @@ func (app *Application) rrClusterroleBinding(clusterrole *auth.ClusterRole, subj }, OwnerReferences: ownerReference, }, - RoleRef: auth.RoleRef{ - APIGroup: k8s.RbacApiGroup, + RoleRef: rbacv1.RoleRef{ + APIGroup: rbacv1.GroupName, Kind: k8s.KindClusterRole, Name: clusterrole.Name, }, diff --git a/pkg/apis/application/roles.go b/pkg/apis/application/roles.go index e28f525f3..25a53f448 100644 --- a/pkg/apis/application/roles.go +++ b/pkg/apis/application/roles.go @@ -6,32 +6,32 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults/k8s" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix" - auth "k8s.io/api/rbac/v1" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func (app *Application) buildRRClusterRole(clusterRoleName string, verbs []string) *auth.ClusterRole { +func (app *Application) buildRRClusterRole(clusterRoleName string, verbs []string) *rbacv1.ClusterRole { appName := app.registration.Name - return app.buildClusterRole(clusterRoleName, auth.PolicyRule{APIGroups: []string{radix.GroupName}, + return app.buildClusterRole(clusterRoleName, rbacv1.PolicyRule{APIGroups: []string{radix.GroupName}, Resources: []string{radix.ResourceRadixRegistrations}, ResourceNames: []string{appName}, Verbs: verbs, }) } -func (app *Application) buildRadixDNSAliasClusterRole(roleNamePrefix string) *auth.ClusterRole { +func (app *Application) buildRadixDNSAliasClusterRole(roleNamePrefix string) *rbacv1.ClusterRole { clusterRoleName := fmt.Sprintf("%s-%s", roleNamePrefix, app.registration.Name) - return app.buildClusterRole(clusterRoleName, auth.PolicyRule{APIGroups: []string{radix.GroupName}, + return app.buildClusterRole(clusterRoleName, rbacv1.PolicyRule{APIGroups: []string{radix.GroupName}, Resources: []string{radix.ResourceRadixDNSAliases}, Verbs: []string{"list"}, }) } -func (app *Application) buildClusterRole(clusterRoleName string, rules ...auth.PolicyRule) *auth.ClusterRole { +func (app *Application) buildClusterRole(clusterRoleName string, rules ...rbacv1.PolicyRule) *rbacv1.ClusterRole { logger.Debugf("Creating clusterrole config %s", clusterRoleName) - clusterRole := &auth.ClusterRole{ + clusterRole := &rbacv1.ClusterRole{ TypeMeta: metav1.TypeMeta{ - APIVersion: k8s.RbacApiVersion, + APIVersion: rbacv1.SchemeGroupVersion.Identifier(), Kind: k8s.KindClusterRole, }, ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/apis/defaults/k8s/k8s.go b/pkg/apis/defaults/k8s/k8s.go index d04c40bf0..72a3bab71 100644 --- a/pkg/apis/defaults/k8s/k8s.go +++ b/pkg/apis/defaults/k8s/k8s.go @@ -1,15 +1,9 @@ package k8s const ( - RbacApiConfig = "rbac.authorization.k8s.io" - RbacApiVersion = "rbac.authorization.k8s.io/v1" - RbacApiGroup = "rbac.authorization.k8s.io" KindClusterRole = "ClusterRole" KindClusterRoleBinding = "ClusterRoleBinding" KindRole = "Role" KindRoleBinding = "RoleBinding" - KindServiceAccount = "ServiceAccount" - KindGroup = "Group" KindIngress = "Ingress" - APIVersionNetworking = "networking.k8s.io/v1" ) diff --git a/pkg/apis/deployment/deploymentrbac.go b/pkg/apis/deployment/deploymentrbac.go index b80c718cd..f627aa032 100644 --- a/pkg/apis/deployment/deploymentrbac.go +++ b/pkg/apis/deployment/deploymentrbac.go @@ -8,7 +8,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults/k8s" "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - auth "k8s.io/api/rbac/v1" + rbacv1 "k8s.io/api/rbac/v1" ) // ConfigureDeploymentRbacFunc defines a function that configures RBAC @@ -78,9 +78,9 @@ func configureRbacForRadixJobComponents(deploy *Deployment) ConfigureDeploymentR if err != nil { return fmt.Errorf("error creating Service account for radix job scheduler. %v", err) } - subjects := []auth.Subject{ + subjects := []rbacv1.Subject{ { - Kind: k8s.KindServiceAccount, + Kind: rbacv1.ServiceAccountKind, Name: serviceAccount.Name, Namespace: serviceAccount.Namespace, }} diff --git a/pkg/apis/deployment/oauthproxyresourcemanager_test.go b/pkg/apis/deployment/oauthproxyresourcemanager_test.go index 26b96f239..1d5c2afc5 100644 --- a/pkg/apis/deployment/oauthproxyresourcemanager_test.go +++ b/pkg/apis/deployment/oauthproxyresourcemanager_test.go @@ -429,8 +429,8 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyRbacCreated() { s.Equal(expectedLabels, admRoleBinding.Labels) s.Equal(admRole.Name, admRoleBinding.RoleRef.Name) expectedSubjects := []rbacv1.Subject{ - {Kind: k8s.KindGroup, APIGroup: k8s.RbacApiGroup, Name: "ad1"}, - {Kind: k8s.KindGroup, APIGroup: k8s.RbacApiGroup, Name: "ad2"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "ad1"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "ad2"}, } s.ElementsMatch(expectedSubjects, admRoleBinding.Subjects) @@ -438,8 +438,8 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyRbacCreated() { s.Equal(expectedLabels, readerRoleBinding.Labels) s.Equal(readerRole.Name, readerRoleBinding.RoleRef.Name) expectedSubjects = []rbacv1.Subject{ - {Kind: k8s.KindGroup, APIGroup: k8s.RbacApiGroup, Name: "rd1"}, - {Kind: k8s.KindGroup, APIGroup: k8s.RbacApiGroup, Name: "rd2"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "rd1"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "rd2"}, } s.ElementsMatch(expectedSubjects, readerRoleBinding.Subjects) } @@ -763,7 +763,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyUninstall() { func (s *OAuthProxyResourceManagerTestSuite) Test_GetOwnerReferenceOfIngress() { actualOwnerReferences := ingress.GetOwnerReferenceOfIngress(&networkingv1.Ingress{ObjectMeta: metav1.ObjectMeta{Name: "anyingress", UID: "anyuid"}}) - s.ElementsMatch([]metav1.OwnerReference{{APIVersion: k8s.APIVersionNetworking, Kind: k8s.KindIngress, Name: "anyingress", UID: "anyuid", Controller: utils.BoolPtr(true)}}, actualOwnerReferences) + s.ElementsMatch([]metav1.OwnerReference{{APIVersion: networkingv1.SchemeGroupVersion.Identifier(), Kind: k8s.KindIngress, Name: "anyingress", UID: "anyuid", Controller: utils.BoolPtr(true)}}, actualOwnerReferences) } func (s *OAuthProxyResourceManagerTestSuite) Test_GetIngressName() { diff --git a/pkg/apis/environment/environment.go b/pkg/apis/environment/environment.go index 16b581e83..af11e2b3a 100644 --- a/pkg/apis/environment/environment.go +++ b/pkg/apis/environment/environment.go @@ -15,7 +15,7 @@ import ( radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" "github.com/sirupsen/logrus" - rbac "k8s.io/api/rbac/v1" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/kubernetes" @@ -197,7 +197,7 @@ func (env *Environment) ApplyAdGroupRoleBinding(namespace string) error { readerRoleBinding := kube.GetRolebindingToClusterRoleForSubjects(env.config.Spec.AppName, defaults.AppReaderEnvironmentsRoleName, readerSubjects) readerRoleBinding.SetOwnerReferences(env.AsOwnerReference()) - for _, roleBinding := range []*rbac.RoleBinding{adminRoleBinding, readerRoleBinding} { + for _, roleBinding := range []*rbacv1.RoleBinding{adminRoleBinding, readerRoleBinding} { err = env.kubeutil.ApplyRoleBinding(namespace, roleBinding) if err != nil { return err @@ -208,9 +208,9 @@ func (env *Environment) ApplyAdGroupRoleBinding(namespace string) error { } func (env *Environment) applyRadixTektonEnvRoleBinding(namespace string) error { - roleBinding := &rbac.RoleBinding{ + roleBinding := &rbacv1.RoleBinding{ TypeMeta: metav1.TypeMeta{ - APIVersion: k8s.RbacApiVersion, + APIVersion: rbacv1.SchemeGroupVersion.Identifier(), Kind: k8s.KindRoleBinding, }, ObjectMeta: metav1.ObjectMeta{ @@ -219,14 +219,14 @@ func (env *Environment) applyRadixTektonEnvRoleBinding(namespace string) error { kube.RadixAppLabel: env.config.Spec.AppName, }, }, - RoleRef: rbac.RoleRef{ - APIGroup: k8s.RbacApiGroup, + RoleRef: rbacv1.RoleRef{ + APIGroup: rbacv1.GroupName, Kind: k8s.KindClusterRole, Name: defaults.RadixTektonEnvRoleName, }, - Subjects: []rbac.Subject{ + Subjects: []rbacv1.Subject{ { - Kind: k8s.KindServiceAccount, + Kind: rbacv1.ServiceAccountKind, Name: defaults.RadixTektonServiceAccountName, Namespace: utils.GetAppNamespace(env.config.Spec.AppName), }, @@ -237,9 +237,9 @@ func (env *Environment) applyRadixTektonEnvRoleBinding(namespace string) error { } func (env *Environment) ApplyRadixPipelineRunnerRoleBinding(namespace string) error { - roleBinding := &rbac.RoleBinding{ + roleBinding := &rbacv1.RoleBinding{ TypeMeta: metav1.TypeMeta{ - APIVersion: k8s.RbacApiVersion, + APIVersion: rbacv1.SchemeGroupVersion.Identifier(), Kind: k8s.KindRoleBinding, }, ObjectMeta: metav1.ObjectMeta{ @@ -248,14 +248,14 @@ func (env *Environment) ApplyRadixPipelineRunnerRoleBinding(namespace string) er kube.RadixAppLabel: env.config.Spec.AppName, }, }, - RoleRef: rbac.RoleRef{ - APIGroup: k8s.RbacApiGroup, + RoleRef: rbacv1.RoleRef{ + APIGroup: rbacv1.GroupName, Kind: k8s.KindClusterRole, Name: defaults.PipelineEnvRoleName, }, - Subjects: []rbac.Subject{ + Subjects: []rbacv1.Subject{ { - Kind: k8s.KindServiceAccount, + Kind: rbacv1.ServiceAccountKind, Name: defaults.PipelineServiceAccountName, Namespace: utils.GetAppNamespace(env.config.Spec.AppName), }, diff --git a/pkg/apis/ingress/ownerreferences.go b/pkg/apis/ingress/ownerreferences.go index f7667244f..3476ba389 100644 --- a/pkg/apis/ingress/ownerreferences.go +++ b/pkg/apis/ingress/ownerreferences.go @@ -3,15 +3,15 @@ package ingress import ( "github.com/equinor/radix-operator/pkg/apis/defaults/k8s" "github.com/equinor/radix-operator/pkg/apis/utils" - "k8s.io/api/networking/v1" + networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // GetOwnerReferenceOfIngress Get an Ingress as an owner reference -func GetOwnerReferenceOfIngress(ingress *v1.Ingress) []metav1.OwnerReference { +func GetOwnerReferenceOfIngress(ingress *networkingv1.Ingress) []metav1.OwnerReference { return []metav1.OwnerReference{ { - APIVersion: k8s.APIVersionNetworking, + APIVersion: networkingv1.SchemeGroupVersion.Identifier(), Kind: k8s.KindIngress, Name: ingress.Name, UID: ingress.UID, diff --git a/pkg/apis/kube/rolebinding.go b/pkg/apis/kube/rolebinding.go index 6ab372a89..f67197783 100644 --- a/pkg/apis/kube/rolebinding.go +++ b/pkg/apis/kube/rolebinding.go @@ -23,9 +23,9 @@ func GetRoleBindingGroups(groups []string) []rbacv1.Subject { subjects := []rbacv1.Subject{} for _, group := range groups { subjects = append(subjects, rbacv1.Subject{ - Kind: k8s.KindGroup, + Kind: rbacv1.GroupKind, Name: group, - APIGroup: k8s.RbacApiGroup, + APIGroup: rbacv1.GroupName, }) } return subjects @@ -83,7 +83,7 @@ func GetRolebindingToRoleForSubjectsWithLabels(appName, roleName string, subject func GetRolebindingToRoleForServiceAccountWithLabels(roleName, serviceAccountName, serviceAccountNamespace string, labels map[string]string) *rbacv1.RoleBinding { subjects := []rbacv1.Subject{ { - Kind: k8s.KindServiceAccount, + Kind: rbacv1.ServiceAccountKind, Name: serviceAccountName, Namespace: serviceAccountNamespace, }} @@ -95,7 +95,7 @@ func GetRolebindingToRoleForServiceAccountWithLabels(roleName, serviceAccountNam func GetRolebindingToClusterRoleForServiceAccountWithLabels(roleName, serviceAccountName, serviceAccountNamespace string, labels map[string]string) *rbacv1.RoleBinding { subjects := []rbacv1.Subject{ { - Kind: k8s.KindServiceAccount, + Kind: rbacv1.ServiceAccountKind, Name: serviceAccountName, Namespace: serviceAccountNamespace, }} @@ -106,7 +106,7 @@ func GetRolebindingToClusterRoleForServiceAccountWithLabels(roleName, serviceAcc func getRoleBindingForSubjects(roleName, kind string, subjects []rbacv1.Subject, labels map[string]string) *rbacv1.RoleBinding { return &rbacv1.RoleBinding{ TypeMeta: metav1.TypeMeta{ - APIVersion: k8s.RbacApiVersion, + APIVersion: rbacv1.SchemeGroupVersion.Identifier(), Kind: k8s.KindRoleBinding, }, ObjectMeta: metav1.ObjectMeta{ @@ -114,7 +114,7 @@ func getRoleBindingForSubjects(roleName, kind string, subjects []rbacv1.Subject, Labels: labels, }, RoleRef: rbacv1.RoleRef{ - APIGroup: k8s.RbacApiGroup, + APIGroup: rbacv1.GroupName, Kind: kind, Name: roleName, }, @@ -231,7 +231,7 @@ func (kubeutil *Kube) ApplyClusterRoleBinding(clusterrolebinding *rbacv1.Cluster func (kubeutil *Kube) ApplyClusterRoleBindingToServiceAccount(roleName string, serviceAccount *corev1.ServiceAccount, ownerReference []metav1.OwnerReference) error { rolebinding := &rbacv1.ClusterRoleBinding{ TypeMeta: metav1.TypeMeta{ - APIVersion: k8s.RbacApiVersion, + APIVersion: rbacv1.SchemeGroupVersion.Identifier(), Kind: k8s.KindClusterRoleBinding, }, ObjectMeta: metav1.ObjectMeta{ @@ -239,13 +239,13 @@ func (kubeutil *Kube) ApplyClusterRoleBindingToServiceAccount(roleName string, s OwnerReferences: ownerReference, }, RoleRef: rbacv1.RoleRef{ - APIGroup: k8s.RbacApiGroup, + APIGroup: rbacv1.GroupName, Kind: k8s.KindClusterRole, Name: roleName, }, Subjects: []rbacv1.Subject{ { - Kind: k8s.KindServiceAccount, + Kind: rbacv1.ServiceAccountKind, Name: serviceAccount.Name, Namespace: serviceAccount.Namespace, }, @@ -258,7 +258,7 @@ func (kubeutil *Kube) ApplyClusterRoleBindingToServiceAccount(roleName string, s func (kubeutil *Kube) ApplyRoleBindingToServiceAccount(roleKind, roleName, namespace string, serviceAccount *corev1.ServiceAccount, ownerReference []metav1.OwnerReference) error { rolebinding := &rbacv1.RoleBinding{ TypeMeta: metav1.TypeMeta{ - APIVersion: k8s.RbacApiVersion, + APIVersion: rbacv1.SchemeGroupVersion.Identifier(), Kind: k8s.KindRoleBinding, }, ObjectMeta: metav1.ObjectMeta{ @@ -267,13 +267,13 @@ func (kubeutil *Kube) ApplyRoleBindingToServiceAccount(roleKind, roleName, names OwnerReferences: ownerReference, }, RoleRef: rbacv1.RoleRef{ - APIGroup: k8s.RbacApiGroup, + APIGroup: rbacv1.GroupName, Kind: roleKind, Name: roleName, }, Subjects: []rbacv1.Subject{ { - Kind: k8s.KindServiceAccount, + Kind: rbacv1.ServiceAccountKind, Name: serviceAccount.Name, Namespace: serviceAccount.Namespace, }, diff --git a/pkg/apis/kube/roles.go b/pkg/apis/kube/roles.go index 033d28a7f..d7b078d6a 100644 --- a/pkg/apis/kube/roles.go +++ b/pkg/apis/kube/roles.go @@ -156,7 +156,7 @@ func UpdateDeploymentsRule(deployments []string) RuleBuilder { func CreateAppRole(appName, roleName string, customLabels map[string]string, ruleBuilders ...RuleBuilder) *rbacv1.Role { role := &rbacv1.Role{ TypeMeta: metav1.TypeMeta{ - APIVersion: k8s.RbacApiVersion, + APIVersion: rbacv1.SchemeGroupVersion.Identifier(), Kind: k8s.KindRole, }, ObjectMeta: metav1.ObjectMeta{ From d606135b711e57a91d85212cbcd5281b36a0cbe1 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 7 Dec 2023 09:53:10 +0100 Subject: [PATCH 094/121] Merge --- pkg/apis/applicationconfig/applicationconfig.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index 7c5a4f551..da7c984b4 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -10,7 +10,6 @@ import ( "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" - "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/radixvalidators" @@ -96,17 +95,17 @@ func GetEnvironment(component radixv1.RadixCommonComponent, envName string) radi } // GetConfigBranch Returns config branch name from radix registration, or "master" if not set. -func GetConfigBranch(rr *v1.RadixRegistration) string { +func GetConfigBranch(rr *radixv1.RadixRegistration) string { return utils.TernaryString(strings.TrimSpace(rr.Spec.ConfigBranch) == "", ConfigBranchFallback, rr.Spec.ConfigBranch) } // IsConfigBranch Checks if given branch is where radix config lives -func IsConfigBranch(branch string, rr *v1.RadixRegistration) bool { +func IsConfigBranch(branch string, rr *radixv1.RadixRegistration) bool { return strings.EqualFold(branch, GetConfigBranch(rr)) } // GetTargetEnvironments Checks if given branch requires deployment to environments -func GetTargetEnvironments(branchToBuild string, ra *v1.RadixApplication) []string { +func GetTargetEnvironments(branchToBuild string, ra *radixv1.RadixApplication) []string { var targetEnvs []string for _, env := range ra.Spec.Environments { if env.Build.From != "" && branch.MatchesPattern(env.Build.From, branchToBuild) { @@ -172,8 +171,7 @@ func (app *ApplicationConfig) OnSync() error { return err } - err = app.syncBuildSecrets() - if err != nil { + if err := app.syncBuildSecrets(); err != nil { log.Errorf("Failed to create build secrets. %v", err) return err } From 679a66e2ed2d7373955628c8fc933ee7cfa72645 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 7 Dec 2023 10:15:51 +0100 Subject: [PATCH 095/121] Moved methods, used only in radix-api to radix-api --- .../applicationconfig/applicationconfig.go | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index da7c984b4..6f05a35f9 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -59,41 +59,6 @@ func (app *ApplicationConfig) GetRadixRegistration() *radixv1.RadixRegistration return app.registration } -// GetComponent Gets the component for a provided name -func GetComponent(ra *radixv1.RadixApplication, name string) radixv1.RadixCommonComponent { - for _, component := range ra.Spec.Components { - if strings.EqualFold(component.Name, name) { - return &component - } - } - for _, jobComponent := range ra.Spec.Jobs { - if strings.EqualFold(jobComponent.Name, name) { - return &jobComponent - } - } - return nil -} - -// GetComponentEnvironmentConfig Gets environment config of component. This method is used by radix-api -func GetComponentEnvironmentConfig(ra *radixv1.RadixApplication, envName, componentName string) radixv1.RadixCommonEnvironmentConfig { - // TODO: Add interface for RA + EnvConfig - return GetEnvironment(GetComponent(ra, componentName), envName) -} - -// GetEnvironment Gets environment config of component -func GetEnvironment(component radixv1.RadixCommonComponent, envName string) radixv1.RadixCommonEnvironmentConfig { - if component == nil { - return nil - } - - for _, environment := range component.GetEnvironmentConfig() { - if strings.EqualFold(environment.GetEnvironment(), envName) { - return environment - } - } - return nil -} - // GetConfigBranch Returns config branch name from radix registration, or "master" if not set. func GetConfigBranch(rr *radixv1.RadixRegistration) string { return utils.TernaryString(strings.TrimSpace(rr.Spec.ConfigBranch) == "", ConfigBranchFallback, rr.Spec.ConfigBranch) From c226cc02440af5a02970354b06efad563d1a96ae Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 7 Dec 2023 10:21:18 +0100 Subject: [PATCH 096/121] Cleanup --- pkg/apis/deployment/deployment_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/apis/deployment/deployment_test.go b/pkg/apis/deployment/deployment_test.go index f5ba9482d..6956e478e 100644 --- a/pkg/apis/deployment/deployment_test.go +++ b/pkg/apis/deployment/deployment_test.go @@ -4,7 +4,6 @@ package deployment import ( "context" "errors" - stderrors "errors" "fmt" "os" "strings" @@ -1759,7 +1758,7 @@ func addRadixBatches(radixclient radixclient.Interface, envNamespace string, dep errs = append(errs, err) } } - return stderrors.Join(errs...) + return errors.Join(errs...) } func TestObjectUpdated_MultipleReplicasExistsAndNotSpecifiedReplicas_SetsDefaultReplicaCount(t *testing.T) { From a2f13f326696cb271e5bbebdbb352eb8227a9412 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 7 Dec 2023 14:51:55 +0100 Subject: [PATCH 097/121] Reworked method syncDNSAliases. Added unit-tests --- .../applicationconfig/applicationconfig.go | 23 +--- pkg/apis/applicationconfig/dns_alias.go | 101 ++++++++++------ pkg/apis/applicationconfig/dns_alias_test.go | 110 +++++++++++++----- pkg/apis/kube/radix_dns_alias.go | 6 +- pkg/apis/radixvalidators/validate_ra.go | 2 +- pkg/apis/test/utils.go | 16 ++- 6 files changed, 165 insertions(+), 93 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig.go b/pkg/apis/applicationconfig/applicationconfig.go index 6f05a35f9..994013d6e 100644 --- a/pkg/apis/applicationconfig/applicationconfig.go +++ b/pkg/apis/applicationconfig/applicationconfig.go @@ -8,7 +8,6 @@ import ( "reflect" "strings" - "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" @@ -140,7 +139,7 @@ func (app *ApplicationConfig) OnSync() error { log.Errorf("Failed to create build secrets. %v", err) return err } - if err := app.createOrUpdateDNSAliases(); err != nil { + if err := app.syncDNSAliases(); err != nil { return fmt.Errorf("failed to process DNS aliases: %w", err) } return app.syncSubPipelineServiceAccounts() @@ -201,26 +200,6 @@ func (app *ApplicationConfig) applyEnvironment(newRe *radixv1.RadixEnvironment) return nil } -func (app *ApplicationConfig) getPortForDNSAlias(dnsAlias radixv1.DNSAlias) (int32, error) { - component, componentFound := slice.FindFirst(app.config.Spec.Components, func(c radixv1.RadixComponent) bool { - return c.Name == dnsAlias.Component - }) - if !componentFound { - // TODO test - return 0, fmt.Errorf("component %s does not exist in the application %s", dnsAlias.Component, app.config.GetName()) - } - if !component.GetEnabledForEnvironment(dnsAlias.Environment) { - // TODO test - return 0, fmt.Errorf("component %s is not enabled for the environment %s in the application %s", dnsAlias.Component, dnsAlias.Environment, app.config.GetName()) - } - componentPublicPort := getComponentPublicPort(&component) - if componentPublicPort == nil { - // TODO test - return 0, fmt.Errorf("component %s does not have public port in the application %s", dnsAlias.Component, app.config.GetName()) - } - return componentPublicPort.Port, nil -} - // patchDifference creates a mergepatch, comparing old and new RadixEnvironments and issues the patch to radix func patchDifference(repository radixTypes.RadixEnvironmentInterface, oldRe *radixv1.RadixEnvironment, newRe *radixv1.RadixEnvironment, logger *log.Entry) error { radixEnvironment := oldRe.DeepCopy() diff --git a/pkg/apis/applicationconfig/dns_alias.go b/pkg/apis/applicationconfig/dns_alias.go index 6858ba1f8..8a5393a0a 100644 --- a/pkg/apis/applicationconfig/dns_alias.go +++ b/pkg/apis/applicationconfig/dns_alias.go @@ -12,58 +12,70 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func (app *ApplicationConfig) createOrUpdateDNSAliases() error { - appName := app.registration.Name - existingRadixDNSAliasesMap, err := kube.GetRadixDNSAliasMapWithSelector(app.radixclient, labels.ForApplicationName(app.config.Name).String()) +func (app *ApplicationConfig) syncDNSAliases() error { + aliasesToCreate, aliasesToUpdate, aliasesToDelete, errs := app.getDNSAliasesToSync() + // first - delete + for _, dnsAlias := range aliasesToDelete { + if err := app.kubeutil.DeleteRadixDNSAliases(dnsAlias); err != nil { + errs = append(errs, err) + } + } + // then - update + for _, dnsAlias := range aliasesToUpdate { + if err := app.kubeutil.UpdateRadixDNSAlias(dnsAlias); err != nil { + errs = append(errs, err) + } + } + // then - create + for _, dnsAlias := range aliasesToCreate { + if err := app.kubeutil.CreateRadixDNSAlias(dnsAlias); err != nil { + errs = append(errs, err) + } + } + return stderrors.Join(errs...) +} + +func (app *ApplicationConfig) getDNSAliasesToSync() ([]*radixv1.RadixDNSAlias, []*radixv1.RadixDNSAlias, []*radixv1.RadixDNSAlias, []error) { + existingAliases, err := kube.GetRadixDNSAliasMap(app.radixclient) if err != nil { - return err + return nil, nil, nil, []error{err} } + + var aliasesToCreate, aliasesToUpdate, aliasesToDelete []*radixv1.RadixDNSAlias + processedAliases := make(map[string]any) + appName := app.registration.Name var errs []error - var radixDNSAliasesToCreate []*radixv1.RadixDNSAlias - var radixDNSAliasesToUpdate []*radixv1.RadixDNSAlias for _, dnsAlias := range app.config.Spec.DNSAlias { port, err := app.getPortForDNSAlias(dnsAlias) if err != nil { - return err + errs = append(errs, fmt.Errorf("failed to get a port for DNS alias %s: %v", dnsAlias.Alias, err)) + processedAliases[dnsAlias.Alias] = true + continue } - if existingRadixDNSAlias, ok := existingRadixDNSAliasesMap[dnsAlias.Alias]; ok { - switch { - case !strings.EqualFold(appName, existingRadixDNSAlias.Spec.AppName): - errs = append(errs, fmt.Errorf("existing DNS alias %s is used by the application %s", dnsAlias.Alias, existingRadixDNSAlias.Spec.AppName)) - delete(existingRadixDNSAliasesMap, dnsAlias.Alias) + if existingAlias, exists := existingAliases[dnsAlias.Alias]; exists { + if !strings.EqualFold(appName, existingAlias.Spec.AppName) { + errs = append(errs, fmt.Errorf("existing DNS alias %s is used by another application", dnsAlias.Alias)) + processedAliases[dnsAlias.Alias] = true continue - case strings.EqualFold(dnsAlias.Environment, existingRadixDNSAlias.Spec.Environment) && - strings.EqualFold(dnsAlias.Component, existingRadixDNSAlias.Spec.Component): - if port != existingRadixDNSAlias.Spec.Port { - updatingRadixDNSAlias := existingRadixDNSAlias.DeepCopy() + } + if strings.EqualFold(dnsAlias.Environment, existingAlias.Spec.Environment) && strings.EqualFold(dnsAlias.Component, existingAlias.Spec.Component) { + if port != existingAlias.Spec.Port { + updatingRadixDNSAlias := existingAlias.DeepCopy() updatingRadixDNSAlias.Spec.Port = port - radixDNSAliasesToUpdate = append(radixDNSAliasesToUpdate, updatingRadixDNSAlias) + aliasesToUpdate = append(aliasesToUpdate, updatingRadixDNSAlias) } - delete(existingRadixDNSAliasesMap, dnsAlias.Alias) + processedAliases[dnsAlias.Alias] = true continue } } - radixDNSAliasesToCreate = append(radixDNSAliasesToCreate, app.buildRadixDNSAlias(appName, dnsAlias, port)) - } - if len(errs) > 0 { - return stderrors.Join(errs...) - } - for _, radixDNSAlias := range existingRadixDNSAliasesMap { - if err = app.kubeutil.DeleteRadixDNSAliases(radixDNSAlias); err != nil { - errs = append(errs, err) - } + aliasesToCreate = append(aliasesToCreate, app.buildRadixDNSAlias(appName, dnsAlias, port)) // new alias or an alias with changed environment or component } - for _, radixDNSAlias := range radixDNSAliasesToUpdate { - if err = app.kubeutil.UpdateRadixDNSAlias(radixDNSAlias); err != nil { - errs = append(errs, err) + for aliasName, dnsAlias := range existingAliases { + if _, ok := processedAliases[aliasName]; !ok && strings.EqualFold(dnsAlias.Spec.AppName, appName) { + aliasesToDelete = append(aliasesToDelete, dnsAlias) } } - for _, radixDNSAlias := range radixDNSAliasesToCreate { - if err = app.kubeutil.CreateRadixDNSAlias(radixDNSAlias); err != nil { - errs = append(errs, err) - } - } - return stderrors.Join(errs...) + return aliasesToCreate, aliasesToUpdate, aliasesToDelete, errs } func getComponentPublicPort(component *radixv1.RadixComponent) *radixv1.ComponentPort { @@ -89,3 +101,20 @@ func (app *ApplicationConfig) buildRadixDNSAlias(appName string, dnsAlias radixv }, } } + +func (app *ApplicationConfig) getPortForDNSAlias(dnsAlias radixv1.DNSAlias) (int32, error) { + component, componentFound := slice.FindFirst(app.config.Spec.Components, func(c radixv1.RadixComponent) bool { + return c.Name == dnsAlias.Component + }) + if !componentFound { + return 0, fmt.Errorf("component %s does not exist in the application %s", dnsAlias.Component, app.config.GetName()) + } + if !component.GetEnabledForEnvironment(dnsAlias.Environment) { + return 0, fmt.Errorf("component %s is not enabled for the environment %s in the application %s", dnsAlias.Component, dnsAlias.Environment, app.config.GetName()) + } + componentPublicPort := getComponentPublicPort(&component) + if componentPublicPort == nil { + return 0, fmt.Errorf("component %s does not have public port in the application %s", dnsAlias.Component, app.config.GetName()) + } + return componentPublicPort.Port, nil +} diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go index 5bc6f2267..d000b628c 100644 --- a/pkg/apis/applicationconfig/dns_alias_test.go +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -7,7 +7,6 @@ import ( "github.com/equinor/radix-operator/pkg/apis/applicationconfig" dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" - "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" commonTest "github.com/equinor/radix-operator/pkg/apis/test" @@ -28,6 +27,7 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { branch1 = "branch1" branch2 = "branch2" portA = "port-a" + portB = "port-b" port8080 = 8080 port9090 = 9090 alias1 = "alias1" @@ -159,6 +159,16 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port9090}, }, }, + { + name: "alias with a second port as public port2", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). + WithComponent(utils.NewApplicationComponentBuilder().WithName(component1). + WithPorts([]radixv1.ComponentPort{{Name: portA, Port: port8080}, {Name: portB, Port: port9090}}).WithPublicPort(portB)), + expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port9090}, + }, + }, { name: "swap env and component for existing aliases-s", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). @@ -278,33 +288,6 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { } } -func Test_DNSAliases_FileOndInvalidAppName(t *testing.T) { - const ( - appName1 = "any-app1" - appName2 = "any-app2" - env1 = "env1" - component1 = "server1" - alias1 = "alias1" - branch1 = "branch1" - portA = "port-a" - port8080 = 8080 - ) - tu, kubeClient, kubeUtil, radixClient := setupTest() - - _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), - &radixv1.RadixDNSAlias{ - ObjectMeta: metav1.ObjectMeta{Name: alias1, Labels: map[string]string{kube.RadixAppLabel: appName1}}, - Spec: radixv1.RadixDNSAliasSpec{AppName: appName2, Environment: env1, Component: component1}, - }, metav1.CreateOptions{}) - require.NoError(t, err, "create existing RadixDNSAlias") - - applicationBuilder := utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). - WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)) - err = applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, applicationBuilder) - require.Error(t, err, "register radix application") -} - func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { const ( raAppName = "anyapp" @@ -402,3 +385,74 @@ func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { }) } } + +func Test_DNSAliases_FailScenarios(t *testing.T) { + const ( + appName1 = "any-app1" + appName2 = "any-app2" + env1 = "env1" + component1 = "server1" + component2 = "server2" + branch1 = "branch1" + portA = "port-a" + port8080 = 8080 + alias1 = "alias1" + ) + var testScenarios = []struct { + name string + applicationBuilder utils.ApplicationBuilder + existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec + expectedError string + }{ + { + name: "aliases for not existing component", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). + WithComponents(utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA)), + expectedError: "failed to process DNS aliases: failed to get a port for DNS alias alias1: component server1 does not exist in the application any-app1", + }, + { + name: "aliases for a disabled component", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). + WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA).WithEnabled(false)), + expectedError: "failed to process DNS aliases: failed to get a port for DNS alias alias1: component server1 is not enabled for the environment env1 in the application any-app1", + }, + { + name: "aliases for a component, disabled for an environment", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). + WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA).WithEnabled(true). + WithEnvironmentConfig(utils.AnEnvironmentConfig().WithEnvironment(env1).WithEnabled(false))), + expectedError: "failed to process DNS aliases: failed to get a port for DNS alias alias1: component server1 is not enabled for the environment env1 in the application any-app1", + }, + { + name: "aliases for a component without public port", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). + WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080)), + expectedError: "failed to process DNS aliases: failed to get a port for DNS alias alias1: component server1 does not have public port in the application any-app1", + }, + { + name: "exists an alias for different application", + applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). + WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). + WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), + existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{alias1: {AppName: appName2, Environment: env1, Component: component1, Port: port8080}}, + expectedError: "failed to process DNS aliases: existing DNS alias alias1 is used by another application", + }, + } + + for _, ts := range testScenarios { + t.Run(ts.name, func(t *testing.T) { + tu, kubeClient, kubeUtil, radixClient := setupTest() + + require.NoError(t, commonTest.RegisterRadixDNSAliases(radixClient, ts.existingRadixDNSAliases), "create existing RadixDNSAlias") + err := applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, ts.applicationBuilder) + assert.Error(t, err, ts.expectedError) + if err != nil { + assert.Equal(t, ts.expectedError, err.Error()) + } + }) + } +} diff --git a/pkg/apis/kube/radix_dns_alias.go b/pkg/apis/kube/radix_dns_alias.go index 838aa82e3..e66598a26 100644 --- a/pkg/apis/kube/radix_dns_alias.go +++ b/pkg/apis/kube/radix_dns_alias.go @@ -64,9 +64,9 @@ func (kubeutil *Kube) GetRadixDNSAliasWithSelector(labelSelectorString string) ( return kubeutil.radixclient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{LabelSelector: labelSelectorString}) } -// GetRadixDNSAliasMapWithSelector Gets a map of RadixDNSAliases by an optional selector -func GetRadixDNSAliasMapWithSelector(radixClient radixclient.Interface, labelSelectorString string) (map[string]*radixv1.RadixDNSAlias, error) { - radixDNSAliases, err := radixClient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{LabelSelector: labelSelectorString}) +// GetRadixDNSAliasMap Gets a map of all RadixDNSAliases +func GetRadixDNSAliasMap(radixClient radixclient.Interface) (map[string]*radixv1.RadixDNSAlias, error) { + radixDNSAliases, err := radixClient.RadixV1().RadixDNSAliases().List(context.TODO(), metav1.ListOptions{}) if err != nil { return make(map[string]*radixv1.RadixDNSAlias), err } diff --git a/pkg/apis/radixvalidators/validate_ra.go b/pkg/apis/radixvalidators/validate_ra.go index 458bf30a8..4425e9bbf 100644 --- a/pkg/apis/radixvalidators/validate_ra.go +++ b/pkg/apis/radixvalidators/validate_ra.go @@ -146,7 +146,7 @@ func validateDNSAppAlias(app *radixv1.RadixApplication) error { func validateDNSAlias(radixClient radixclient.Interface, app *radixv1.RadixApplication, dnsAliasConfig *dnsalias.DNSConfig) error { var errs []error - radixDNSAliasMap, err := kube.GetRadixDNSAliasMapWithSelector(radixClient, "") + radixDNSAliasMap, err := kube.GetRadixDNSAliasMap(radixClient) if err != nil { return err } diff --git a/pkg/apis/test/utils.go b/pkg/apis/test/utils.go index e52b71e12..44e341a64 100644 --- a/pkg/apis/test/utils.go +++ b/pkg/apis/test/utils.go @@ -9,6 +9,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" + "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" log "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" @@ -414,6 +415,9 @@ func AssertError(t *testing.T, expectedError string, err error) { // RegisterRadixDNSAliases Register RadixDNSAliases func RegisterRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]radixv1.RadixDNSAliasSpec) error { + if radixDNSAliasesMap == nil { + return nil + } for alias, aliasesSpec := range radixDNSAliasesMap { err := RegisterRadixDNSAliasBySpec(radixClient, alias, aliasesSpec) if err != nil { @@ -438,10 +442,16 @@ func RegisterRadixDNSAliasBySpec(radixClient radixclient.Interface, alias string _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), &radixv1.RadixDNSAlias{ ObjectMeta: metav1.ObjectMeta{ - Name: alias, - Labels: map[string]string{kube.RadixAppLabel: aliasesSpec.AppName}, + Name: alias, + Labels: labels.Merge(labels.ForApplicationName(aliasesSpec.AppName), labels.ForComponentName(aliasesSpec.Component), labels.ForEnvironmentName(aliasesSpec.Environment)), + Finalizers: []string{kube.RadixDNSAliasFinalizer}, + }, + Spec: radixv1.RadixDNSAliasSpec{ + AppName: aliasesSpec.AppName, + Environment: aliasesSpec.Environment, + Component: aliasesSpec.Component, + Port: aliasesSpec.Port, }, - Spec: aliasesSpec, }, metav1.CreateOptions{}) return err } From e008b8134f52a4d3a3625885790941555ff69a2a Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 7 Dec 2023 17:03:50 +0100 Subject: [PATCH 098/121] Removed port from RadixDNSAlias.Take it from RadixDeployment. RDA AppName and environment are unmutable --- .../templates/radixdnsalias.yaml | 13 +- pkg/apis/applicationconfig/dns_alias.go | 73 ++---- pkg/apis/applicationconfig/dns_alias_test.go | 222 ++---------------- pkg/apis/applicationconfig/errors.go | 18 -- pkg/apis/dnsalias/ingress.go | 6 +- pkg/apis/dnsalias/syncer.go | 20 +- pkg/apis/dnsalias/syncer_test.go | 87 ++++--- pkg/apis/radix/v1/radixdnsaliastypes.go | 9 +- pkg/apis/radixvalidators/validate_ra_test.go | 110 ++++++++- pkg/apis/test/utils.go | 18 +- radix-operator/dnsalias/controller_test.go | 2 +- radix-operator/dnsalias/handler_test.go | 4 +- 12 files changed, 232 insertions(+), 350 deletions(-) delete mode 100644 pkg/apis/applicationconfig/errors.go diff --git a/charts/radix-operator/templates/radixdnsalias.yaml b/charts/radix-operator/templates/radixdnsalias.yaml index 4355ac591..8ad524e3e 100644 --- a/charts/radix-operator/templates/radixdnsalias.yaml +++ b/charts/radix-operator/templates/radixdnsalias.yaml @@ -53,6 +53,9 @@ spec: minLength: 1 pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf component: description: Name of the component that shall receive the incoming requests. @@ -66,17 +69,13 @@ spec: minLength: 1 pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ type: string - port: - description: Port number. - format: int32 - maximum: 65535 - minimum: 1024 - type: integer + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf required: - appName - component - environment - - port type: object status: description: RadixDNSAliasStatus is the status for an RadixDNSAlias diff --git a/pkg/apis/applicationconfig/dns_alias.go b/pkg/apis/applicationconfig/dns_alias.go index 8a5393a0a..9cae52df9 100644 --- a/pkg/apis/applicationconfig/dns_alias.go +++ b/pkg/apis/applicationconfig/dns_alias.go @@ -2,10 +2,8 @@ package applicationconfig import ( stderrors "errors" - "fmt" "strings" - "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils/labels" @@ -13,7 +11,12 @@ import ( ) func (app *ApplicationConfig) syncDNSAliases() error { - aliasesToCreate, aliasesToUpdate, aliasesToDelete, errs := app.getDNSAliasesToSync() + existingAliases, err := kube.GetRadixDNSAliasMap(app.radixclient) + if err != nil { + return err + } + aliasesToCreate, aliasesToUpdate, aliasesToDelete := app.getDNSAliasesToSync(existingAliases) + var errs []error // first - delete for _, dnsAlias := range aliasesToDelete { if err := app.kubeutil.DeleteRadixDNSAliases(dnsAlias); err != nil { @@ -35,57 +38,31 @@ func (app *ApplicationConfig) syncDNSAliases() error { return stderrors.Join(errs...) } -func (app *ApplicationConfig) getDNSAliasesToSync() ([]*radixv1.RadixDNSAlias, []*radixv1.RadixDNSAlias, []*radixv1.RadixDNSAlias, []error) { - existingAliases, err := kube.GetRadixDNSAliasMap(app.radixclient) - if err != nil { - return nil, nil, nil, []error{err} - } - +func (app *ApplicationConfig) getDNSAliasesToSync(existingAliases map[string]*radixv1.RadixDNSAlias) ([]*radixv1.RadixDNSAlias, []*radixv1.RadixDNSAlias, []*radixv1.RadixDNSAlias) { var aliasesToCreate, aliasesToUpdate, aliasesToDelete []*radixv1.RadixDNSAlias processedAliases := make(map[string]any) appName := app.registration.Name - var errs []error for _, dnsAlias := range app.config.Spec.DNSAlias { - port, err := app.getPortForDNSAlias(dnsAlias) - if err != nil { - errs = append(errs, fmt.Errorf("failed to get a port for DNS alias %s: %v", dnsAlias.Alias, err)) + if existingAlias, exists := existingAliases[dnsAlias.Alias]; exists { + updatingRadixDNSAlias := existingAlias.DeepCopy() + updatingRadixDNSAlias.Spec.AppName = appName + updatingRadixDNSAlias.Spec.Environment = dnsAlias.Environment + updatingRadixDNSAlias.Spec.Component = dnsAlias.Component + aliasesToUpdate = append(aliasesToUpdate, updatingRadixDNSAlias) processedAliases[dnsAlias.Alias] = true continue } - if existingAlias, exists := existingAliases[dnsAlias.Alias]; exists { - if !strings.EqualFold(appName, existingAlias.Spec.AppName) { - errs = append(errs, fmt.Errorf("existing DNS alias %s is used by another application", dnsAlias.Alias)) - processedAliases[dnsAlias.Alias] = true - continue - } - if strings.EqualFold(dnsAlias.Environment, existingAlias.Spec.Environment) && strings.EqualFold(dnsAlias.Component, existingAlias.Spec.Component) { - if port != existingAlias.Spec.Port { - updatingRadixDNSAlias := existingAlias.DeepCopy() - updatingRadixDNSAlias.Spec.Port = port - aliasesToUpdate = append(aliasesToUpdate, updatingRadixDNSAlias) - } - processedAliases[dnsAlias.Alias] = true - continue - } - } - aliasesToCreate = append(aliasesToCreate, app.buildRadixDNSAlias(appName, dnsAlias, port)) // new alias or an alias with changed environment or component + aliasesToCreate = append(aliasesToCreate, app.buildRadixDNSAlias(appName, dnsAlias)) // new alias or an alias with changed environment or component } for aliasName, dnsAlias := range existingAliases { if _, ok := processedAliases[aliasName]; !ok && strings.EqualFold(dnsAlias.Spec.AppName, appName) { aliasesToDelete = append(aliasesToDelete, dnsAlias) } } - return aliasesToCreate, aliasesToUpdate, aliasesToDelete, errs -} - -func getComponentPublicPort(component *radixv1.RadixComponent) *radixv1.ComponentPort { - if port, ok := slice.FindFirst(component.GetPorts(), func(p radixv1.ComponentPort) bool { return p.Name == component.PublicPort }); ok { - return &port - } - return nil + return aliasesToCreate, aliasesToUpdate, aliasesToDelete } -func (app *ApplicationConfig) buildRadixDNSAlias(appName string, dnsAlias radixv1.DNSAlias, port int32) *radixv1.RadixDNSAlias { +func (app *ApplicationConfig) buildRadixDNSAlias(appName string, dnsAlias radixv1.DNSAlias) *radixv1.RadixDNSAlias { return &radixv1.RadixDNSAlias{ ObjectMeta: metav1.ObjectMeta{ Name: dnsAlias.Alias, @@ -97,24 +74,6 @@ func (app *ApplicationConfig) buildRadixDNSAlias(appName string, dnsAlias radixv AppName: appName, Environment: dnsAlias.Environment, Component: dnsAlias.Component, - Port: port, }, } } - -func (app *ApplicationConfig) getPortForDNSAlias(dnsAlias radixv1.DNSAlias) (int32, error) { - component, componentFound := slice.FindFirst(app.config.Spec.Components, func(c radixv1.RadixComponent) bool { - return c.Name == dnsAlias.Component - }) - if !componentFound { - return 0, fmt.Errorf("component %s does not exist in the application %s", dnsAlias.Component, app.config.GetName()) - } - if !component.GetEnabledForEnvironment(dnsAlias.Environment) { - return 0, fmt.Errorf("component %s is not enabled for the environment %s in the application %s", dnsAlias.Component, dnsAlias.Environment, app.config.GetName()) - } - componentPublicPort := getComponentPublicPort(&component) - if componentPublicPort == nil { - return 0, fmt.Errorf("component %s does not have public port in the application %s", dnsAlias.Component, app.config.GetName()) - } - return componentPublicPort.Port, nil -} diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go index d000b628c..9e65dd6b2 100644 --- a/pkg/apis/applicationconfig/dns_alias_test.go +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -5,8 +5,6 @@ import ( "fmt" "testing" - "github.com/equinor/radix-operator/pkg/apis/applicationconfig" - dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" commonTest "github.com/equinor/radix-operator/pkg/apis/test" @@ -38,21 +36,21 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { var testScenarios = []struct { name string applicationBuilder utils.ApplicationBuilder - existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec - expectedRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec + existingRadixDNSAliases map[string]commonTest.DNSAlias + expectedRadixDNSAliases map[string]commonTest.DNSAlias }{ { name: "no aliases", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{}, + expectedRadixDNSAliases: map[string]commonTest.DNSAlias{}, }, { name: "one alias", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + expectedRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, }, @@ -67,7 +65,7 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + expectedRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, alias2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, }, @@ -83,7 +81,7 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + expectedRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, alias2: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, }, @@ -96,7 +94,7 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { radixv1.DNSAlias{Alias: alias2, Environment: env1, Component: component1}, ). WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + expectedRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, alias2: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, @@ -112,7 +110,7 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + expectedRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, alias2: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, }, @@ -122,10 +120,10 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). WithComponent(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + existingRadixDNSAliases: map[string]commonTest.DNSAlias{ alias2: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, }, - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + expectedRadixDNSAliases: map[string]commonTest.DNSAlias{ alias2: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, @@ -138,10 +136,10 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + existingRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + expectedRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, }, }, @@ -152,10 +150,10 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { WithComponents( utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port9090).WithPublicPort(portA), ), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + existingRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + expectedRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port9090}, }, }, @@ -165,7 +163,7 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). WithComponent(utils.NewApplicationComponentBuilder().WithName(component1). WithPorts([]radixv1.ComponentPort{{Name: portA, Port: port8080}, {Name: portB, Port: port9090}}).WithPublicPort(portB)), - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + expectedRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port9090}, }, }, @@ -180,11 +178,11 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + existingRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, alias2: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, }, - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + expectedRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env2, Component: component2, Port: port9090}, alias2: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, @@ -193,10 +191,10 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { name: "remove single alias", applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1).WithEnvironment(env2, branch2). WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + existingRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, }, - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{}, + expectedRadixDNSAliases: map[string]commonTest.DNSAlias{}, }, { name: "remove multiple aliases, keep other", @@ -209,13 +207,13 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + existingRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, alias2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, alias3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, alias4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, }, - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + expectedRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, alias3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, alias4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, @@ -232,12 +230,12 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA), utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port9090).WithPublicPort(portA), ), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + existingRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component1, Port: port8080}, alias2: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, alias4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, }, - expectedRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ + expectedRadixDNSAliases: map[string]commonTest.DNSAlias{ alias1: {AppName: appName1, Environment: env1, Component: component2, Port: port9090}, alias3: {AppName: appName1, Environment: env2, Component: component1, Port: port8080}, alias4: {AppName: appName2, Environment: env1, Component: component1, Port: port9090}, @@ -267,7 +265,6 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { assert.Equal(t, expectedDNSAlias.AppName, radixDNSAlias.Spec.AppName, "app name") assert.Equal(t, expectedDNSAlias.Environment, radixDNSAlias.Spec.Environment, "environment") assert.Equal(t, expectedDNSAlias.Component, radixDNSAlias.Spec.Component, "component") - assert.Equal(t, expectedDNSAlias.Port, radixDNSAlias.Spec.Port, "port") if _, itWasExistingAlias := ts.existingRadixDNSAliases[radixDNSAlias.Name]; !itWasExistingAlias { ownerReferences := radixDNSAlias.GetOwnerReferences() require.Len(t, ownerReferences, 1) @@ -280,179 +277,10 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { } continue } - assert.Fail(t, fmt.Sprintf("found not expected RadixDNSAlias %s: env %s, component %s, port %d, appName %s", - radixDNSAlias.GetName(), radixDNSAlias.Spec.Environment, radixDNSAlias.Spec.Component, radixDNSAlias.Spec.Port, radixDNSAlias.Spec.AppName)) + assert.Fail(t, fmt.Sprintf("found not expected RadixDNSAlias %s: env %s, component %s, appName %s", + radixDNSAlias.GetName(), radixDNSAlias.Spec.Environment, radixDNSAlias.Spec.Component, radixDNSAlias.Spec.AppName)) } } }) } } - -func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { - const ( - raAppName = "anyapp" - otherAppName = "anyapp2" - raEnv = "test" - raComponentName = "app" - raPublicPort = 8080 - someEnv = "dev" - someComponentName = "component-abc" - somePort = 9090 - alias1 = "alias1" - alias2 = "alias2" - ) - dnsConfig := &dnsaliasconfig.DNSConfig{ - DNSZone: "dev.radix.equinor.com", - ReservedAppDNSAliases: dnsaliasconfig.AppReservedDNSAlias{"api": "radix-api"}, - ReservedDNSAliases: []string{"grafana"}, - } - var testScenarios = []struct { - name string - applicationBuilder utils.ApplicationBuilder - existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec - expectedValidationError error - }{ - { - name: "No dns aliases", - applicationBuilder: utils.ARadixApplication(), - expectedValidationError: nil, - }, - { - name: "Added dns aliases", - applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: raEnv, Component: raComponentName}), - expectedValidationError: nil, - }, - { - name: "Existing dns aliases for the app", - applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: raEnv, Component: raComponentName}), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - alias1: {AppName: raAppName, Environment: raEnv, Component: raComponentName, Port: raPublicPort}, - }, - expectedValidationError: nil, - }, - { - name: "Existing dns aliases for the app and another app", - applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: raEnv, Component: raComponentName}), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - alias1: {AppName: raAppName, Environment: raEnv, Component: raComponentName, Port: raPublicPort}, - alias2: {AppName: otherAppName, Environment: someEnv, Component: someComponentName, Port: somePort}, - }, - expectedValidationError: nil, - }, - { - name: "Same alias exists in dns alias for another app", - applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: raEnv, Component: raComponentName}), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{ - alias1: {AppName: otherAppName, Environment: someEnv, Component: someComponentName, Port: somePort}, - }, - expectedValidationError: applicationconfig.RadixDNSAliasAlreadyUsedByAnotherApplicationError(alias1), - }, - { - name: "Reserved alias api for another app", - applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Alias: "api", Environment: raEnv, Component: raComponentName}), - expectedValidationError: applicationconfig.RadixDNSAliasIsReservedForRadixPlatformApplicationError("api"), - }, - { - name: "Reserved alias api for another service", - applicationBuilder: utils.ARadixApplication().WithDNSAlias(radixv1.DNSAlias{Alias: "grafana", Environment: raEnv, Component: raComponentName}), - expectedValidationError: applicationconfig.RadixDNSAliasIsReservedForRadixPlatformServiceError("grafana"), - }, - { - name: "Reserved alias api for this app", - applicationBuilder: utils.ARadixApplication().WithAppName("radix-api").WithDNSAlias(radixv1.DNSAlias{Alias: "api", Environment: raEnv, Component: raComponentName}), - expectedValidationError: nil, - }, - } - - for _, ts := range testScenarios { - t.Run(ts.name, func(t *testing.T) { - _, kubeClient, kubeUtil, radixClient := setupTest() - err := commonTest.RegisterRadixDNSAliases(radixClient, ts.existingRadixDNSAliases) - require.NoError(t, err) - rr := ts.applicationBuilder.GetRegistrationBuilder().BuildRR() - _, err = radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) - require.NoError(t, err) - ra := ts.applicationBuilder.BuildRA() - applicationConfig := applicationconfig.NewApplicationConfig(kubeClient, kubeUtil, radixClient, rr, ra, dnsConfig) - - actualValidationErr := applicationConfig.ApplyConfigToApplicationNamespace() - - if ts.expectedValidationError == nil { - require.NoError(t, actualValidationErr) - } else { - require.EqualError(t, actualValidationErr, ts.expectedValidationError.Error(), "missing or unexpected error") - } - }) - } -} - -func Test_DNSAliases_FailScenarios(t *testing.T) { - const ( - appName1 = "any-app1" - appName2 = "any-app2" - env1 = "env1" - component1 = "server1" - component2 = "server2" - branch1 = "branch1" - portA = "port-a" - port8080 = 8080 - alias1 = "alias1" - ) - var testScenarios = []struct { - name string - applicationBuilder utils.ApplicationBuilder - existingRadixDNSAliases map[string]radixv1.RadixDNSAliasSpec - expectedError string - }{ - { - name: "aliases for not existing component", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). - WithComponents(utils.NewApplicationComponentBuilder().WithName(component2).WithPort(portA, port8080).WithPublicPort(portA)), - expectedError: "failed to process DNS aliases: failed to get a port for DNS alias alias1: component server1 does not exist in the application any-app1", - }, - { - name: "aliases for a disabled component", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). - WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA).WithEnabled(false)), - expectedError: "failed to process DNS aliases: failed to get a port for DNS alias alias1: component server1 is not enabled for the environment env1 in the application any-app1", - }, - { - name: "aliases for a component, disabled for an environment", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). - WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA).WithEnabled(true). - WithEnvironmentConfig(utils.AnEnvironmentConfig().WithEnvironment(env1).WithEnabled(false))), - expectedError: "failed to process DNS aliases: failed to get a port for DNS alias alias1: component server1 is not enabled for the environment env1 in the application any-app1", - }, - { - name: "aliases for a component without public port", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). - WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080)), - expectedError: "failed to process DNS aliases: failed to get a port for DNS alias alias1: component server1 does not have public port in the application any-app1", - }, - { - name: "exists an alias for different application", - applicationBuilder: utils.ARadixApplication().WithAppName(appName1).WithEnvironment(env1, branch1). - WithDNSAlias(radixv1.DNSAlias{Alias: alias1, Environment: env1, Component: component1}). - WithComponents(utils.NewApplicationComponentBuilder().WithName(component1).WithPort(portA, port8080).WithPublicPort(portA)), - existingRadixDNSAliases: map[string]radixv1.RadixDNSAliasSpec{alias1: {AppName: appName2, Environment: env1, Component: component1, Port: port8080}}, - expectedError: "failed to process DNS aliases: existing DNS alias alias1 is used by another application", - }, - } - - for _, ts := range testScenarios { - t.Run(ts.name, func(t *testing.T) { - tu, kubeClient, kubeUtil, radixClient := setupTest() - - require.NoError(t, commonTest.RegisterRadixDNSAliases(radixClient, ts.existingRadixDNSAliases), "create existing RadixDNSAlias") - err := applyApplicationWithSync(tu, kubeClient, kubeUtil, radixClient, ts.applicationBuilder) - assert.Error(t, err, ts.expectedError) - if err != nil { - assert.Equal(t, ts.expectedError, err.Error()) - } - }) - } -} diff --git a/pkg/apis/applicationconfig/errors.go b/pkg/apis/applicationconfig/errors.go deleted file mode 100644 index 24284efec..000000000 --- a/pkg/apis/applicationconfig/errors.go +++ /dev/null @@ -1,18 +0,0 @@ -package applicationconfig - -import "fmt" - -// RadixDNSAliasAlreadyUsedByAnotherApplicationError Error when RadixDNSAlias already used by another application -func RadixDNSAliasAlreadyUsedByAnotherApplicationError(alias string) error { - return fmt.Errorf("DNS alias %s already used by another application", alias) -} - -// RadixDNSAliasIsReservedForRadixPlatformApplicationError Error when RadixDNSAlias is reserved by Radix platform for a Radix application -func RadixDNSAliasIsReservedForRadixPlatformApplicationError(alias string) error { - return fmt.Errorf("DNS alias %s is reserved by Radix platform application", alias) -} - -// RadixDNSAliasIsReservedForRadixPlatformServiceError Error when RadixDNSAlias is reserved by Radix platform for a Radix service -func RadixDNSAliasIsReservedForRadixPlatformServiceError(alias string) error { - return fmt.Errorf("DNS alias %s is reserved by Radix platform service", alias) -} diff --git a/pkg/apis/dnsalias/ingress.go b/pkg/apis/dnsalias/ingress.go index 4f6afd19e..2b6e09968 100644 --- a/pkg/apis/dnsalias/ingress.go +++ b/pkg/apis/dnsalias/ingress.go @@ -16,12 +16,12 @@ func CreateRadixDNSAliasIngress(kubeClient kubernetes.Interface, appName, envNam } // GetDNSAliasIngressName Gets name of the ingress for the custom DNS alias -func GetDNSAliasIngressName(service string, alias string) string { - return fmt.Sprintf("%s.%s.custom-alias", service, alias) +func GetDNSAliasIngressName(alias string) string { + return fmt.Sprintf("%s.custom-alias", alias) } // GetDNSAliasHost Gets DNS alias host. // Example for the alias "my-app" and the cluster "Playground": my-app.playground.radix.equinor.com -func GetDNSAliasHost(alias string, dnsZone string) string { +func GetDNSAliasHost(alias, dnsZone string) string { return fmt.Sprintf("%s.%s", alias, dnsZone) } diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 1a7fba3bc..4f97ce7dd 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -12,6 +12,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/radixvalidators" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/annotations" radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" @@ -60,7 +61,7 @@ func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient // OnSync is called by the handler when changes are applied and must be // reconciled with current state. func (s *syncer) OnSync() error { - log.Debugf("OnSync RadixDNSAlias %s, application %s, environment %s, component %s, port %d", s.radixDNSAlias.GetName(), s.radixDNSAlias.Spec.AppName, s.radixDNSAlias.Spec.Environment, s.radixDNSAlias.Spec.Component, s.radixDNSAlias.Spec.Port) + log.Debugf("OnSync RadixDNSAlias %s, application %s, environment %s, component %s", s.radixDNSAlias.GetName(), s.radixDNSAlias.Spec.AppName, s.radixDNSAlias.Spec.Environment, s.radixDNSAlias.Spec.Component) if err := s.restoreStatus(); err != nil { return fmt.Errorf("failed to update status on DNS alias %s: %v", s.radixDNSAlias.GetName(), err) } @@ -84,7 +85,7 @@ func (s *syncer) syncAlias() error { } aliasSpec := s.radixDNSAlias.Spec - ingressName := GetDNSAliasIngressName(aliasSpec.Component, aliasName) + ingressName := GetDNSAliasIngressName(aliasName) namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) ing, err := s.createOrUpdateIngress(namespace, radixDeployComponent, ingressName) if err != nil { @@ -198,16 +199,20 @@ func (s *syncer) deletedIngressesForRadixDNSAlias() error { func buildIngress(radixDeployComponent radixv1.RadixCommonDeployComponent, radixDNSAlias *radixv1.RadixDNSAlias, dnsConfig *dnsalias.DNSConfig, oauth2Config defaults.OAuth2Config, ingressConfiguration ingress.IngressConfiguration) (*networkingv1.Ingress, error) { log.Debug("build an ingress for the RadixDNSAlias") + publicPort := getComponentPublicPort(radixDeployComponent) + if publicPort == nil { + return nil, radixvalidators.ComponentForDNSAliasIsNotMarkedAsPublicError(radixDeployComponent.GetName()) + } aliasSpec := radixDNSAlias.Spec appName := aliasSpec.AppName envName := aliasSpec.Environment componentName := aliasSpec.Component namespace := utils.GetEnvironmentNamespace(appName, envName) aliasName := radixDNSAlias.GetName() - ingressName := GetDNSAliasIngressName(componentName, aliasName) + ingressName := GetDNSAliasIngressName(aliasName) hostName := GetDNSAliasHost(aliasName, dnsConfig.DNSZone) - ingressSpec := ingress.GetIngressSpec(hostName, componentName, defaults.TLSSecretName, aliasSpec.Port) + ingressSpec := ingress.GetIngressSpec(hostName, componentName, defaults.TLSSecretName, publicPort.Port) ingressAnnotations := ingress.GetAnnotationProvider(ingressConfiguration, namespace, oauth2Config) ingressConfig, err := ingress.GetIngressConfig(namespace, appName, radixDeployComponent, ingressName, ingressSpec, ingressAnnotations, ingress.DNSAlias, internal.GetOwnerReferences(radixDNSAlias)) if err != nil { @@ -218,3 +223,10 @@ func buildIngress(radixDeployComponent radixv1.RadixCommonDeployComponent, radix log.Debugf("built the Ingress %s in the environment %s with a host %s", ingressConfig.GetName(), namespace, hostName) return ingressConfig, nil } + +func getComponentPublicPort(component radixv1.RadixCommonDeployComponent) *radixv1.ComponentPort { + if port, ok := slice.FindFirst(component.GetPorts(), func(p radixv1.ComponentPort) bool { return p.Name == component.GetPublicPort() }); ok { + return &port + } + return nil +} diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 7edf1eb46..30df18ffa 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -15,6 +15,7 @@ import ( radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" commonTest "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" + radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" "github.com/stretchr/testify/assert" @@ -65,17 +66,11 @@ type testIngress struct { component string port int32 } -type testDNSAlias struct { - Alias string - Environment string - Component string - Port int32 -} type scenario struct { name string expectedError string - dnsAlias testDNSAlias + dnsAlias commonTest.DNSAlias dnsZone string existingIngress map[string]testIngress expectedIngress map[string]testIngress @@ -83,86 +78,86 @@ type scenario struct { func (s *syncerTestSuite) Test_syncer_OnSync() { const ( - appName1 = "app1" - appName2 = "app2" - envName1 = "env1" - envName2 = "env2" - component1 = "component1" - component2 = "component2" - alias1 = "alias1" - alias2 = "alias2" - port8080 = 8080 - port9090 = 9090 - dnsZone1 = "dev.radix.equinor.com" + appName1 = "app1" + appName2 = "app2" + envName1 = "env1" + envName2 = "env2" + component1 = "component1" + component2 = "component2" + alias1 = "alias1" + alias2 = "alias2" + component1Port8080 = 8080 + component2Port9090 = 9090 + dnsZone1 = "dev.radix.equinor.com" ) - rd1 := buildRadixDeployment(appName1, component1, component2, envName1, port8080, port9090) - rd2 := buildRadixDeployment(appName1, component1, component2, envName2, port8080, port9090) - rd3 := buildRadixDeployment(appName1, component1, component2, envName1, port8080, port9090) - rd4 := buildRadixDeployment(appName2, component1, component2, envName2, port8080, port9090) + rd1 := buildRadixDeployment(appName1, component1, component2, envName1, component1Port8080, component2Port9090) + rd2 := buildRadixDeployment(appName1, component1, component2, envName2, component1Port8080, component2Port9090) + rd3 := buildRadixDeployment(appName1, component1, component2, envName1, component1Port8080, component2Port9090) + rd4 := buildRadixDeployment(appName2, component1, component2, envName2, component1Port8080, component2Port9090) scenarios := []scenario{ { name: "created an ingress", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsAlias: commonTest.DNSAlias{Alias: alias1, Environment: envName1, Component: component1}, dnsZone: dnsZone1, expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: component1Port8080}, }, }, { name: "created additional ingress for another component", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsAlias: commonTest.DNSAlias{Alias: alias1, Environment: envName1, Component: component1}, dnsZone: dnsZone1, existingIngress: map[string]testIngress{ - "component2.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: port8080}, + "alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: component1Port8080}, }, expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - "component2.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: port8080}, + "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: component1Port8080}, + "alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: component1Port8080}, }, }, { name: "changed port changes port in existing ingress", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port9090}, + dnsAlias: commonTest.DNSAlias{Alias: alias1, Environment: envName1, Component: component1}, dnsZone: dnsZone1, existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: component2Port9090}, }, expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port9090}, + "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: component1Port8080}, }, }, { name: "created additional ingress on another alias for the same component", - dnsAlias: testDNSAlias{Alias: alias2, Environment: envName1, Component: component1, Port: port8080}, + dnsAlias: commonTest.DNSAlias{Alias: alias2, Environment: envName1, Component: component1}, dnsZone: dnsZone1, existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: component1Port8080}, }, expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, - "component1.alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: port8080}, + "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: component1Port8080}, + "alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component1, port: component1Port8080}, }, }, { name: "manually changed port repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsAlias: commonTest.DNSAlias{Alias: alias1, Environment: envName1, Component: component1}, dnsZone: dnsZone1, existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port9090}, + "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: component2Port9090}, }, expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: component1Port8080}, }, }, { name: "manually changed host repaired", - dnsAlias: testDNSAlias{Alias: alias1, Environment: envName1, Component: component1, Port: port8080}, + dnsAlias: commonTest.DNSAlias{Alias: alias1, Environment: envName1, Component: component1}, dnsZone: dnsZone1, existingIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: "/manually/edited/host", component: component1, port: port8080}, + "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: "/manually/edited/host", component: component1, port: component1Port8080}, }, expectedIngress: map[string]testIngress{ - "component1.alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: port8080}, + "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: component1Port8080}, }, }, } @@ -170,9 +165,8 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { s.T().Run(ts.name, func(t *testing.T) { s.SetupTest() radixDNSAlias := &radixv1.RadixDNSAlias{ObjectMeta: metav1.ObjectMeta{Name: ts.dnsAlias.Alias, UID: uuid.NewUUID()}, - Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component, Port: ts.dnsAlias.Port}} - s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Alias, radixDNSAlias.Spec), "create existing alias") - // cfg := &dnsalias2.DNSConfig{DNSZone: ts.dnsZone} + Spec: radixv1.RadixDNSAliasSpec{AppName: appName1, Environment: ts.dnsAlias.Environment, Component: ts.dnsAlias.Component}} + s.Require().NoError(commonTest.RegisterRadixDNSAliasBySpec(s.radixClient, ts.dnsAlias.Alias, ts.dnsAlias), "create existing alias") s.registeringRadixDeployments(rd1, rd2, rd3, rd4) err := registerExistingIngresses(s.kubeClient, ts.existingIngress) @@ -182,7 +176,8 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { err = syncer.OnSync() commonTest.AssertError(s.T(), ts.expectedError, err) - ingresses, err := s.kubeClient.NetworkingV1().Ingresses("").List(context.Background(), metav1.ListOptions{}) + ingresses, err := s.kubeClient.NetworkingV1().Ingresses(utils.GetEnvironmentNamespace(appName1, ts.dnsAlias.Environment)). + List(context.Background(), metav1.ListOptions{LabelSelector: radixlabels.ForDNSAlias().String()}) s.Require().NoError(err) // assert ingresses @@ -260,7 +255,7 @@ func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses ma for _, ingProps := range testIngresses { ing := &networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{ - Name: dnsalias.GetDNSAliasIngressName(ingProps.component, ingProps.alias), + Name: dnsalias.GetDNSAliasIngressName(ingProps.alias), Labels: map[string]string{ kube.RadixAppLabel: ingProps.appName, kube.RadixComponentLabel: ingProps.component, diff --git a/pkg/apis/radix/v1/radixdnsaliastypes.go b/pkg/apis/radix/v1/radixdnsaliastypes.go index cfe5f50e5..fddb76180 100644 --- a/pkg/apis/radix/v1/radixdnsaliastypes.go +++ b/pkg/apis/radix/v1/radixdnsaliastypes.go @@ -31,12 +31,16 @@ type RadixDNSAliasList struct { // RadixDNSAliasSpec is the spec for an RadixDNSAlias type RadixDNSAliasSpec struct { // Name of the application the DNS alias used in. + // +kubebuilder:validation:Required + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable" // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ AppName string `json:"appName"` // Name of the environment for the component. + // +kubebuilder:validation:Required + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable" // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ @@ -47,11 +51,6 @@ type RadixDNSAliasSpec struct { // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Pattern=^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$ Component string `json:"component"` - - // Port number. - // +kubebuilder:validation:Minimum=1024 - // +kubebuilder:validation:Maximum=65535 - Port int32 `json:"port"` } // RadixDNSAliasCondition Holds the condition of a RadixDNSAlias diff --git a/pkg/apis/radixvalidators/validate_ra_test.go b/pkg/apis/radixvalidators/validate_ra_test.go index 2a42d8766..d3e268b85 100644 --- a/pkg/apis/radixvalidators/validate_ra_test.go +++ b/pkg/apis/radixvalidators/validate_ra_test.go @@ -1,20 +1,24 @@ package radixvalidators_test import ( + "context" "fmt" "strings" "testing" commonUtils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-common/utils/pointers" - "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/radixvalidators" + commonTest "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" radixfake "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kubefake "k8s.io/client-go/kubernetes/fake" ) @@ -1851,6 +1855,104 @@ func Test_validateNotificationsRA(t *testing.T) { } } +func Test_ValidateApplicationCanBeAppliedWithDNSAliases(t *testing.T) { + const ( + raAppName = "anyapp" + otherAppName = "anyapp2" + raEnv = "test" + raComponentName = "app" + raPublicPort = 8080 + someEnv = "dev" + someComponentName = "component-abc" + somePort = 9090 + alias1 = "alias1" + alias2 = "alias2" + ) + dnsConfig := &dnsaliasconfig.DNSConfig{ + DNSZone: "dev.radix.equinor.com", + ReservedAppDNSAliases: dnsaliasconfig.AppReservedDNSAlias{"api": "radix-api"}, + ReservedDNSAliases: []string{"grafana"}, + } + var testScenarios = []struct { + name string + applicationBuilder utils.ApplicationBuilder + existingRadixDNSAliases map[string]commonTest.DNSAlias + expectedValidationError error + }{ + { + name: "No dns aliases", + applicationBuilder: utils.ARadixApplication(), + expectedValidationError: nil, + }, + { + name: "Added dns aliases", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(v1.DNSAlias{Alias: alias1, Environment: raEnv, Component: raComponentName}), + expectedValidationError: nil, + }, + { + name: "Existing dns aliases for the app", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(v1.DNSAlias{Alias: alias1, Environment: raEnv, Component: raComponentName}), + existingRadixDNSAliases: map[string]commonTest.DNSAlias{ + alias1: {AppName: raAppName, Environment: raEnv, Component: raComponentName}, + }, + expectedValidationError: nil, + }, + { + name: "Existing dns aliases for the app and another app", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(v1.DNSAlias{Alias: alias1, Environment: raEnv, Component: raComponentName}), + existingRadixDNSAliases: map[string]commonTest.DNSAlias{ + alias1: {AppName: raAppName, Environment: raEnv, Component: raComponentName}, + alias2: {AppName: otherAppName, Environment: someEnv, Component: someComponentName}, + }, + expectedValidationError: nil, + }, + { + name: "Same alias exists in dns alias for another app", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(v1.DNSAlias{Alias: alias1, Environment: raEnv, Component: raComponentName}), + existingRadixDNSAliases: map[string]commonTest.DNSAlias{ + alias1: {AppName: otherAppName, Environment: someEnv, Component: someComponentName}, + }, + expectedValidationError: radixvalidators.RadixDNSAliasAlreadyUsedByAnotherApplicationError(alias1), + }, + { + name: "Reserved alias api for another app", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(v1.DNSAlias{Alias: "api", Environment: raEnv, Component: raComponentName}), + expectedValidationError: radixvalidators.RadixDNSAliasIsReservedForRadixPlatformApplicationError("api"), + }, + { + name: "Reserved alias api for another service", + applicationBuilder: utils.ARadixApplication().WithDNSAlias(v1.DNSAlias{Alias: "grafana", Environment: raEnv, Component: raComponentName}), + expectedValidationError: radixvalidators.RadixDNSAliasIsReservedForRadixPlatformServiceError("grafana"), + }, + { + name: "Reserved alias api for this app", + applicationBuilder: utils.ARadixApplication().WithAppName("radix-api").WithDNSAlias(v1.DNSAlias{Alias: "api", Environment: raEnv, Component: raComponentName}), + expectedValidationError: nil, + }, + } + + for _, ts := range testScenarios { + t.Run(ts.name, func(t *testing.T) { + _, radixClient := validRASetup() + + err := commonTest.RegisterRadixDNSAliases(radixClient, ts.existingRadixDNSAliases) + require.NoError(t, err) + rr := ts.applicationBuilder.GetRegistrationBuilder().BuildRR() + _, err = radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) + require.NoError(t, err) + ra := ts.applicationBuilder.BuildRA() + + actualValidationErr := radixvalidators.CanRadixApplicationBeInserted(radixClient, ra, dnsConfig) + + if ts.expectedValidationError == nil { + require.NoError(t, actualValidationErr) + } else { + require.EqualError(t, actualValidationErr, ts.expectedValidationError.Error(), "missing or unexpected error") + } + }) + } +} + func createValidRA() *v1.RadixApplication { validRA, _ := utils.GetRadixApplicationFromFile("testdata/radixconfig.yaml") @@ -1865,10 +1967,10 @@ func validRASetup() (kubernetes.Interface, radixclient.Interface) { return kubeclient, client } -func getDNSAliasConfig() *dnsalias.DNSConfig { - return &dnsalias.DNSConfig{ +func getDNSAliasConfig() *dnsaliasconfig.DNSConfig { + return &dnsaliasconfig.DNSConfig{ DNSZone: "dev.radix.equinor.com", - ReservedAppDNSAliases: dnsalias.AppReservedDNSAlias{"api": "radix-api"}, + ReservedAppDNSAliases: dnsaliasconfig.AppReservedDNSAlias{"api": "radix-api"}, ReservedDNSAliases: []string{"grafana"}, } } diff --git a/pkg/apis/test/utils.go b/pkg/apis/test/utils.go index 44e341a64..49ff401a8 100644 --- a/pkg/apis/test/utils.go +++ b/pkg/apis/test/utils.go @@ -414,7 +414,7 @@ func AssertError(t *testing.T, expectedError string, err error) { } // RegisterRadixDNSAliases Register RadixDNSAliases -func RegisterRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]radixv1.RadixDNSAliasSpec) error { +func RegisterRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]DNSAlias) error { if radixDNSAliasesMap == nil { return nil } @@ -428,17 +428,16 @@ func RegisterRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesM } // RegisterRadixDNSAlias Register RadixDNSAlias by properties -func RegisterRadixDNSAlias(radixClient radixclient.Interface, appName, componentName, envName, alias string, port int32) error { - return RegisterRadixDNSAliasBySpec(radixClient, alias, radixv1.RadixDNSAliasSpec{ +func RegisterRadixDNSAlias(radixClient radixclient.Interface, appName, componentName, envName, alias string) error { + return RegisterRadixDNSAliasBySpec(radixClient, alias, DNSAlias{ AppName: appName, Environment: envName, Component: componentName, - Port: port, }) } // RegisterRadixDNSAliasBySpec Register RadixDNSAlias by its spec -func RegisterRadixDNSAliasBySpec(radixClient radixclient.Interface, alias string, aliasesSpec radixv1.RadixDNSAliasSpec) error { +func RegisterRadixDNSAliasBySpec(radixClient radixclient.Interface, alias string, aliasesSpec DNSAlias) error { _, err := radixClient.RadixV1().RadixDNSAliases().Create(context.Background(), &radixv1.RadixDNSAlias{ ObjectMeta: metav1.ObjectMeta{ @@ -450,8 +449,15 @@ func RegisterRadixDNSAliasBySpec(radixClient radixclient.Interface, alias string AppName: aliasesSpec.AppName, Environment: aliasesSpec.Environment, Component: aliasesSpec.Component, - Port: aliasesSpec.Port, }, }, metav1.CreateOptions{}) return err } + +type DNSAlias struct { + Alias string + AppName string + Environment string + Component string + Port int +} diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go index 64d8ce1ae..41c6747df 100644 --- a/radix-operator/dnsalias/controller_test.go +++ b/radix-operator/dnsalias/controller_test.go @@ -125,7 +125,7 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { func buildRadixDNSAliasIngress(aliasName, component string, port int32, cfg *dnsalias2.DNSConfig) *networkingv1.Ingress { return &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{Name: dnsaliasapi.GetDNSAliasIngressName(component, aliasName)}, + ObjectMeta: metav1.ObjectMeta{Name: dnsaliasapi.GetDNSAliasIngressName(aliasName)}, Spec: ingress.GetIngressSpec(dnsaliasapi.GetDNSAliasHost(aliasName, cfg.DNSZone), component, defaults.TLSSecretName, port), } } diff --git a/radix-operator/dnsalias/handler_test.go b/radix-operator/dnsalias/handler_test.go index cc90878fa..3ecfafc76 100644 --- a/radix-operator/dnsalias/handler_test.go +++ b/radix-operator/dnsalias/handler_test.go @@ -55,7 +55,7 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_NotFound() { func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} - s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1, 8080), "create existing RadixDNSAlias") + s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1), "create existing RadixDNSAlias") handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) expectedError := fmt.Errorf("some error") @@ -68,7 +68,7 @@ func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsError() { func (s *handlerTestSuite) Test_RadixDNSAliases_ReturnsNoError() { dnsConfig := &dnsalias2.DNSConfig{DNSZone: "dev.radix.equinor.com"} - s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1, 8080), "create existing RadixDNSAlias") + s.Require().NoError(commonTest.RegisterRadixDNSAlias(s.RadixClient, appName1, env1, component1, alias1), "create existing RadixDNSAlias") handler := dnsalias.NewHandler(s.KubeClient, s.KubeUtil, s.RadixClient, dnsConfig, func(synced bool) {}, dnsalias.WithSyncerFactory(s.syncerFactory)) s.syncerFactory.EXPECT().CreateSyncer(gomock.Any(), gomock.Any(), gomock.Any(), dnsConfig, gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(s.syncer).Times(1) From 189e9344c5da346a48b03f78be646d3d798e322c Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 11 Dec 2023 12:01:59 +0100 Subject: [PATCH 099/121] Replaced panic for test errs with required --- pkg/apis/alert/alert_test.go | 12 ++-- pkg/apis/application/application_test.go | 14 ++-- .../applicationconfig_test.go | 20 +++--- pkg/apis/batch/syncer_test.go | 2 +- pkg/apis/deployment/deployment_test.go | 66 +++++++++--------- .../deployment/environmentvariables_test.go | 67 +++++++++---------- .../oauthproxyresourcemanager_test.go | 32 ++++----- pkg/apis/job/job_test.go | 12 ++-- pkg/apis/kube/environment_variables_test.go | 48 ++++++++----- radix-operator/alert/controller_test.go | 20 +++--- radix-operator/application/controller_test.go | 14 ++-- radix-operator/batch/controller_test.go | 2 +- radix-operator/common/controller_test.go | 20 +++--- radix-operator/deployment/controller_test.go | 24 ++++--- radix-operator/deployment/handler_test.go | 8 +-- radix-operator/dnsalias/controller_test.go | 2 +- radix-operator/job/controller_test.go | 19 ++++-- .../registration/controller_test.go | 21 +++--- 18 files changed, 209 insertions(+), 194 deletions(-) diff --git a/pkg/apis/alert/alert_test.go b/pkg/apis/alert/alert_test.go index 66dfb692f..64f9b1119 100644 --- a/pkg/apis/alert/alert_test.go +++ b/pkg/apis/alert/alert_test.go @@ -108,7 +108,7 @@ func (s *alertTestSuite) Test_OnSync_ResourcesCreated() { Spec: radixv1.RadixRegistrationSpec{AdGroups: []string{"admin"}, ReaderAdGroups: []string{"reader"}}, } if _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } radixAlert := &radixv1.RadixAlert{ ObjectMeta: metav1.ObjectMeta{Name: alertName, Labels: map[string]string{kube.RadixAppLabel: appName}, UID: alertUID}, @@ -184,7 +184,7 @@ func (s *alertTestSuite) Test_OnSync_Rbac_CreateWithOwnerReference() { radixalert, _ = s.radixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), radixalert, metav1.CreateOptions{}) rr := &radixv1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}} if _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } expectedAlertOwnerRef := s.getRadixAlertAsOwnerReference(radixalert) @@ -215,11 +215,11 @@ func (s *alertTestSuite) Test_OnSync_Rbac_UpdateWithOwnerReference() { } radixalert, err := s.radixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), radixalert, metav1.CreateOptions{}) if err != nil { - panic(err) + s.Require().NoError(err) } rr := &radixv1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}} if _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } _, err = s.kubeClient.RbacV1().Roles(namespace).Create(context.Background(), &rbacv1.Role{ObjectMeta: metav1.ObjectMeta{Name: getAlertConfigSecretAdminRoleName(alertName)}}, metav1.CreateOptions{}) s.Nil(err) @@ -260,7 +260,7 @@ func (s *alertTestSuite) Test_OnSync_Rbac_ConfiguredCorrectly() { radixalert, _ = s.radixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), radixalert, metav1.CreateOptions{}) rr := &radixv1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}, Spec: radixv1.RadixRegistrationSpec{AdGroups: adminGroups, ReaderAdGroups: readerGroups}} if _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } sut := s.createAlertSyncer(radixalert) @@ -312,7 +312,7 @@ func (s *alertTestSuite) Test_OnSync_Secret_RemoveOrphanedKeys() { }, } if _, err := s.kubeClient.CoreV1().Secrets(namespace).Create(context.Background(), secret, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } sut := s.createAlertSyncer(radixalert) diff --git a/pkg/apis/application/application_test.go b/pkg/apis/application/application_test.go index 73bba62cd..c31e0f01f 100644 --- a/pkg/apis/application/application_test.go +++ b/pkg/apis/application/application_test.go @@ -100,7 +100,7 @@ func TestOnSync_RegistrationCreated_AppNamespaceWithResourcesCreated(t *testing. appName := "any-app" if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). WithName(appName)); err != nil { - panic(err) + require.NoError(t, err) } ns, err := client.CoreV1().Namespaces().Get(context.TODO(), utils.GetAppNamespace(appName), metav1.GetOptions{}) @@ -146,7 +146,7 @@ func TestOnSync_PodSecurityStandardLabelsSetOnNamespace(t *testing.T) { appName := "any-app" if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). WithName(appName)); err != nil { - panic(err) + require.NoError(t, err) } ns, err := client.CoreV1().Namespaces().Get(context.TODO(), utils.GetAppNamespace(appName), metav1.GetOptions{}) @@ -180,7 +180,7 @@ func TestOnSync_RegistrationCreated_AppNamespaceReconciled(t *testing.T) { }, }, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } label := fmt.Sprintf("%s=%s", kube.RadixAppLabel, "any-app") @@ -188,7 +188,7 @@ func TestOnSync_RegistrationCreated_AppNamespaceReconciled(t *testing.T) { // Test if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). WithName("any-app")); err != nil { - panic(err) + require.NoError(t, err) } namespaces, _ := client.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{ @@ -209,7 +209,7 @@ func TestOnSync_NoUserGroupDefined_DefaultUserGroupSet(t *testing.T) { WithName("any-app"). WithAdGroups([]string{}). WithReaderAdGroups([]string{})); err != nil { - panic(err) + require.NoError(t, err) } rolebindings, _ := client.RbacV1().RoleBindings("any-app-app").List(context.TODO(), metav1.ListOptions{}) @@ -236,7 +236,7 @@ func TestOnSync_LimitsDefined_LimitsSet(t *testing.T) { // Test if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). WithName("any-app")); err != nil { - panic(err) + require.NoError(t, err) } limitRanges, _ := client.CoreV1().LimitRanges(utils.GetAppNamespace("any-app")).List(context.TODO(), metav1.ListOptions{}) @@ -256,7 +256,7 @@ func TestOnSync_NoLimitsDefined_NoLimitsSet(t *testing.T) { // Test if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). WithName("any-app")); err != nil { - panic(err) + require.NoError(t, err) } limitRanges, _ := client.CoreV1().LimitRanges(utils.GetAppNamespace("any-app")).List(context.TODO(), metav1.ListOptions{}) diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 0aa77a281..cb718ee94 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -221,7 +221,7 @@ func Test_WithBuildSecretsSet_SecretsCorrectlyAdded(t *testing.T) { WithAppName("any-app"). WithEnvironment("dev", "master"). WithBuildSecrets("secret1", "secret2")); err != nil { - panic(err) + require.NoError(t, err) } secrets, _ := client.CoreV1().Secrets(appNamespace).List(context.TODO(), metav1.ListOptions{}) @@ -246,7 +246,7 @@ func Test_WithBuildSecretsSet_SecretsCorrectlyAdded(t *testing.T) { WithAppName("any-app"). WithEnvironment("dev", "master"). WithBuildSecrets("secret4", "secret5", "secret6")); err != nil { - panic(err) + require.NoError(t, err) } secrets, _ = client.CoreV1().Secrets(appNamespace).List(context.TODO(), metav1.ListOptions{}) @@ -335,7 +335,7 @@ func Test_WithBuildSecretsDeleted_SecretsCorrectlyDeleted(t *testing.T) { WithAppName("any-app"). WithEnvironment("dev", "master"). WithBuildSecrets("secret1", "secret2")); err != nil { - panic(err) + require.NoError(t, err) } // Delete secret @@ -345,7 +345,7 @@ func Test_WithBuildSecretsDeleted_SecretsCorrectlyDeleted(t *testing.T) { WithAppName("any-app"). WithEnvironment("dev", "master"). WithBuildSecrets("secret2")); err != nil { - panic(err) + require.NoError(t, err) } secrets, _ := client.CoreV1().Secrets(appNamespace).List(context.TODO(), metav1.ListOptions{}) @@ -363,7 +363,7 @@ func Test_WithBuildSecretsDeleted_SecretsCorrectlyDeleted(t *testing.T) { WithAppName("any-app"). WithEnvironment("dev", "master"). WithBuildSecrets()); err != nil { - panic(err) + require.NoError(t, err) } // Secret is deleted @@ -389,7 +389,7 @@ func Test_AppReaderBuildSecretsRoleAndRoleBindingExists(t *testing.T) { WithAppName("any-app"). WithEnvironment("dev", "master"). WithBuildSecrets("secret1", "secret2")); err != nil { - panic(err) + require.NoError(t, err) } roles, _ := client.RbacV1().Roles("any-app-app").List(context.TODO(), metav1.ListOptions{}) @@ -403,7 +403,7 @@ func Test_AppReaderBuildSecretsRoleAndRoleBindingExists(t *testing.T) { utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master")); err != nil { - panic(err) + require.NoError(t, err) } roles, _ = client.RbacV1().Roles("any-app-app").List(context.TODO(), metav1.ListOptions{}) @@ -480,7 +480,7 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_SetPassword(t *testing.T) { assert.Equal(t, "privaterepodeleteme.azurecr.io", pendingSecrets[0]) if err := applicationconfig.UpdatePrivateImageHubsSecretsPassword(kubeUtil, "any-app", "privaterepodeleteme.azurecr.io", "a-password"); err != nil { - panic(err) + require.NoError(t, err) } secret, _ := client.CoreV1().Secrets("any-app-app").Get(context.TODO(), defaults.PrivateImageHubSecretName, metav1.GetOptions{}) pendingSecrets, _ = applicationconfig.GetPendingPrivateImageHubSecrets(kubeUtil, "any-app") @@ -610,7 +610,7 @@ func Test_RadixEnvironment(t *testing.T) { if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app")); err != nil { - panic(err) + require.NoError(t, err) } rr, _ := radixClient.RadixV1().RadixRegistrations().Get(context.TODO(), "any-app", metav1.GetOptions{}) @@ -665,7 +665,7 @@ func Test_UseBuildKit(t *testing.T) { ra = ra.WithBuildKit(testScenario.useBuildKit) } if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, ra); err != nil { - panic(err) + require.NoError(t, err) } raAfterSync, _ := radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(testScenario.appName)).Get(context.TODO(), testScenario.appName, metav1.GetOptions{}) diff --git a/pkg/apis/batch/syncer_test.go b/pkg/apis/batch/syncer_test.go index a8adb49ec..531f19e78 100644 --- a/pkg/apis/batch/syncer_test.go +++ b/pkg/apis/batch/syncer_test.go @@ -72,7 +72,7 @@ func (s *syncerTestSuite) ensurePopulatedEnvVarsConfigMaps(kubeUtil *kube.Kube, desiredConfigMap.Data[envVarName] = envVarValue } if err := kubeUtil.ApplyConfigMap(rd.GetNamespace(), initialEnvVarsConfigMap, desiredConfigMap); err != nil { - panic(err) + s.Require().NoError(err) } return desiredConfigMap } diff --git a/pkg/apis/deployment/deployment_test.go b/pkg/apis/deployment/deployment_test.go index 6956e478e..e177ca92e 100644 --- a/pkg/apis/deployment/deployment_test.go +++ b/pkg/apis/deployment/deployment_test.go @@ -838,7 +838,7 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { WithJobComponents(). WithAppName("any-other-app"). WithEnvironment("test")); err != nil { - panic(err) + require.NoError(t, err) } serviceAccounts, _ := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace("any-other-app", "test")).List(context.TODO(), metav1.ListOptions{}) @@ -863,7 +863,7 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { WithJobComponents(). WithAppName(appName). WithEnvironment(envName)); err != nil { - panic(err) + require.NoError(t, err) } serviceAccounts, _ := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) @@ -889,7 +889,7 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { WithJobComponents(). WithAppName(appName). WithEnvironment(envName)); err != nil { - panic(err) + require.NoError(t, err) } serviceAccounts, _ = client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) @@ -911,7 +911,7 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { WithJobComponents(). WithAppName(appName). WithEnvironment(envName)); err != nil { - panic(err) + require.NoError(t, err) } serviceAccounts, _ = client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) @@ -932,7 +932,7 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { context.Background(), &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: utils.GetComponentServiceAccountName(componentName), Labels: map[string]string{kube.RadixComponentLabel: componentName}}}, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). @@ -955,7 +955,7 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { context.Background(), &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: utils.GetComponentServiceAccountName(componentName), Labels: map[string]string{kube.RadixComponentLabel: componentName, kube.IsServiceAccountForComponent: "true", "any-other-label": "any-value"}}}, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). @@ -986,7 +986,7 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { context.Background(), &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: anyOtherServiceAccountName, Labels: map[string]string{kube.RadixComponentLabel: "anything"}}}, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } // Deploy component with Azure identity must create custom SA @@ -1002,12 +1002,12 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { WithJobComponents(). WithAppName(appName). WithEnvironment(envName)); err != nil { - panic(err) + require.NoError(t, err) } serviceAccounts, err := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) if err != nil { - panic(err) + require.NoError(t, err) } assert.Equal(t, 3, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -1021,7 +1021,7 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { WithJobComponents(). WithAppName(appName). WithEnvironment(envName)); err != nil { - panic(err) + require.NoError(t, err) } serviceAccounts, _ = client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) @@ -1567,7 +1567,7 @@ func TestObjectSynced_DeploymentReplicasFromCurrentDeploymentWhenHPAEnabled(t *t // Simulate HPA scaling up comp1 to 3 replicas comp1.Spec.Replicas = pointers.Ptr[int32](3) if _, err := client.AppsV1().Deployments(envNamespace).Update(context.Background(), comp1, metav1.UpdateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } // Resync existing RD should use replicas from current deployment for HPA enabled component @@ -2627,7 +2627,7 @@ func TestObjectUpdated_RemoveOneSecret_SecretIsRemoved(t *testing.T) { anyComponentSecret.Data = secretData if _, err := client.CoreV1().Secrets(envNamespace).Update(context.TODO(), anyComponentSecret, metav1.UpdateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } // Removing one secret from config and therefor from the deployment @@ -3587,7 +3587,7 @@ func Test_JobScheduler_ObjectsGarbageCollected(t *testing.T) { }, }, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } } @@ -3606,7 +3606,7 @@ func Test_JobScheduler_ObjectsGarbageCollected(t *testing.T) { }, }, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } } @@ -3625,7 +3625,7 @@ func Test_JobScheduler_ObjectsGarbageCollected(t *testing.T) { }, }, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } } @@ -3793,10 +3793,10 @@ func Test_IngressAnnotations_Called(t *testing.T) { rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http").WithDNSAppAlias(true)).BuildRD() if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -3832,10 +3832,10 @@ func Test_IngressAnnotations_ReturnError(t *testing.T) { rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http")).BuildRD() if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -3862,10 +3862,10 @@ func Test_AuxiliaryResourceManagers_Called(t *testing.T) { rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http")).BuildRD() if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -3893,10 +3893,10 @@ func Test_AuxiliaryResourceManagers_Sync_ReturnErr(t *testing.T) { rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http")).BuildRD() if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -3925,10 +3925,10 @@ func Test_AuxiliaryResourceManagers_GarbageCollect_ReturnErr(t *testing.T) { rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http")).BuildRD() if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -4127,28 +4127,28 @@ func TestRadixBatch_IsGarbageCollected(t *testing.T) { } if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch1", "job1"), metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch2", "job1"), metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch3", "job2"), metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch4", "job2"), metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch5", "job3"), metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch6", "job4"), metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch7", ""), metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } if _, err := radixclient.RadixV1().RadixBatches("other-ns").Create(context.Background(), batchFactory("batch8", "job1"), metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } // Test diff --git a/pkg/apis/deployment/environmentvariables_test.go b/pkg/apis/deployment/environmentvariables_test.go index a0888d527..6419020ef 100644 --- a/pkg/apis/deployment/environmentvariables_test.go +++ b/pkg/apis/deployment/environmentvariables_test.go @@ -10,8 +10,8 @@ import ( "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" prometheusclient "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned" - log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -91,40 +91,37 @@ func Test_getEnvironmentVariablesForRadixOperator(t *testing.T) { testEnv := setupTestEnv() defer teardownTest() - t.Run("Get env vars", func(t *testing.T) { - rd := testEnv.applyRdComponent(t, appName, envName, componentName, func(componentBuilder utils.DeployComponentBuilder) { - componentBuilder.WithEnvironmentVariables(map[string]string{ - "VAR1": "val1", - "VAR2": "val2", - "VAR3": "val3", - }) + rd := testEnv.applyRdComponent(t, appName, envName, componentName, func(componentBuilder utils.DeployComponentBuilder) { + componentBuilder.WithEnvironmentVariables(map[string]string{ + "VAR1": "val1", + "VAR2": "val2", + "VAR3": "val3", }) - //goland:noinspection GoUnhandledErrorResult - if _, err := testEnv.kubeUtil.CreateConfigMap(corev1.NamespaceDefault, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "radix-config"}, Data: map[string]string{ - "clustername": testClusterName, - }}); err != nil { - log.Error(err) - } + }) + if cm, err := testEnv.kubeUtil.GetConfigMap(corev1.NamespaceDefault, "radix-config"); err != nil { + require.NoError(t, err) + require.Equal(t, testClusterName, cm.Data["clustername"]) + } - envVars, err := GetEnvironmentVariablesForRadixOperator(testEnv.kubeUtil, appName, rd, &rd.Spec.Components[0]) + envVars, err := GetEnvironmentVariablesForRadixOperator(testEnv.kubeUtil, appName, rd, &rd.Spec.Components[0]) + + assert.NoError(t, err) + assert.True(t, len(envVars) > 3) + envVarsConfigMap, envVarsConfigMapMetadata, err := testEnv.kubeUtil.GetOrCreateEnvVarsConfigMapAndMetadataMap(utils.GetEnvironmentNamespace(appName, env), appName, componentName) + assert.NoError(t, err) + assert.NotNil(t, envVarsConfigMap) + assert.NotNil(t, envVarsConfigMap.Data) + assert.Equal(t, "val1", envVarsConfigMap.Data["VAR1"]) + assert.Equal(t, "val2", envVarsConfigMap.Data["VAR2"]) + assert.Equal(t, "val3", envVarsConfigMap.Data["VAR3"]) + resultEnvVarsMap := map[string]corev1.EnvVar{} + for _, envVar := range envVars { + envVar := envVar + resultEnvVarsMap[envVar.Name] = envVar + } + assert.Equal(t, testClusterName, resultEnvVarsMap["RADIX_CLUSTERNAME"].Value) + assert.NotNil(t, envVarsConfigMapMetadata) - assert.NoError(t, err) - assert.True(t, len(envVars) > 3) - envVarsConfigMap, envVarsConfigMapMetadata, err := testEnv.kubeUtil.GetOrCreateEnvVarsConfigMapAndMetadataMap(utils.GetEnvironmentNamespace(appName, env), appName, componentName) - assert.NoError(t, err) - assert.NotNil(t, envVarsConfigMap) - assert.NotNil(t, envVarsConfigMap.Data) - assert.Equal(t, "val1", envVarsConfigMap.Data["VAR1"]) - assert.Equal(t, "val2", envVarsConfigMap.Data["VAR2"]) - assert.Equal(t, "val3", envVarsConfigMap.Data["VAR3"]) - resultEnvVarsMap := map[string]corev1.EnvVar{} - for _, envVar := range envVars { - envVar := envVar - resultEnvVarsMap[envVar.Name] = envVar - } - assert.Equal(t, testClusterName, resultEnvVarsMap["RADIX_CLUSTERNAME"].Value) - assert.NotNil(t, envVarsConfigMapMetadata) - }) } func Test_RemoveFromConfigMapEnvVarsNotExistingInRadixDeployment(t *testing.T) { @@ -140,7 +137,7 @@ func Test_RemoveFromConfigMapEnvVarsNotExistingInRadixDeployment(t *testing.T) { "VAR1": "val1", "OUTDATED_VAR1": "val1z", }}); err != nil { - panic(err) + require.NoError(t, err) } existingEnvVarsMetadataConfigMap := corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: kube.GetEnvVarsMetadataConfigMapName(componentName)}} //goland:noinspection GoUnhandledErrorResult @@ -150,11 +147,11 @@ func Test_RemoveFromConfigMapEnvVarsNotExistingInRadixDeployment(t *testing.T) { "OUTDATED_VAR1": {RadixConfigValue: "orig-val1a"}, "OUTDATED_VAR2": {RadixConfigValue: "orig-val2a"}, }); err != nil { - panic(err) + require.NoError(t, err) } //goland:noinspection GoUnhandledErrorResult if _, err := testEnv.kubeUtil.CreateConfigMap(namespace, &existingEnvVarsMetadataConfigMap); err != nil { - panic(err) + require.NoError(t, err) } rd := testEnv.applyRdComponent(t, appName, envName, componentName, func(componentBuilder utils.DeployComponentBuilder) { diff --git a/pkg/apis/deployment/oauthproxyresourcemanager_test.go b/pkg/apis/deployment/oauthproxyresourcemanager_test.go index 1d5c2afc5..9c17e9686 100644 --- a/pkg/apis/deployment/oauthproxyresourcemanager_test.go +++ b/pkg/apis/deployment/oauthproxyresourcemanager_test.go @@ -485,7 +485,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxySecret_KeysGarb // Remove redispassword if sessionstoretype is cookie s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(1).Return(&v1.OAuth2{SessionStoreType: v1.SessionStoreCookie}, nil) if err := sut.Sync(); err != nil { - panic(err) + s.Require().NoError(err) } actualSecret, _ = s.kubeClient.CoreV1().Secrets(envNs).Get(context.Background(), secretName, metav1.GetOptions{}) s.Equal( @@ -573,22 +573,22 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate }, } if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingServer, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingServerNoRules, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } if _, err := s.kubeClient.NetworkingV1().Ingresses("otherns").Create(context.Background(), &ingServerOtherNs, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingOtherComponent, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingWeb1, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingWeb2, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } rr := utils.NewRegistrationBuilder().WithName(appName).BuildRR() @@ -681,7 +681,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyUninstall() { Spec: networkingv1.IngressSpec{Rules: []networkingv1.IngressRule{{Host: "anyhost"}}}}, metav1.CreateOptions{}, ); err != nil { - panic(err) + s.Require().NoError(err) } if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create( context.Background(), @@ -690,7 +690,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyUninstall() { Spec: networkingv1.IngressSpec{Rules: []networkingv1.IngressRule{{Host: "anyhost"}}}}, metav1.CreateOptions{}, ); err != nil { - panic(err) + s.Require().NoError(err) } if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create( context.Background(), @@ -699,7 +699,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyUninstall() { Spec: networkingv1.IngressSpec{Rules: []networkingv1.IngressRule{{Host: "anyhost"}}}}, metav1.CreateOptions{}, ); err != nil { - panic(err) + s.Require().NoError(err) } rr := utils.NewRegistrationBuilder().WithName(appName).BuildRR() @@ -919,7 +919,7 @@ func (s *OAuthProxyResourceManagerTestSuite) addDeployment(name, namespace, appN } _, err := s.kubeClient.AppsV1().Deployments(namespace).Create(context.Background(), deploy, metav1.CreateOptions{}) if err != nil { - panic(err) + s.Require().NoError(err) } } @@ -933,7 +933,7 @@ func (s *OAuthProxyResourceManagerTestSuite) addSecret(name, namespace, appName, } _, err := s.kubeClient.CoreV1().Secrets(namespace).Create(context.Background(), secret, metav1.CreateOptions{}) if err != nil { - panic(err) + s.Require().NoError(err) } } @@ -947,7 +947,7 @@ func (s *OAuthProxyResourceManagerTestSuite) addService(name, namespace, appName } _, err := s.kubeClient.CoreV1().Services(namespace).Create(context.Background(), service, metav1.CreateOptions{}) if err != nil { - panic(err) + s.Require().NoError(err) } } @@ -961,7 +961,7 @@ func (s *OAuthProxyResourceManagerTestSuite) addIngress(name, namespace, appName } _, err := s.kubeClient.NetworkingV1().Ingresses(namespace).Create(context.Background(), ingress, metav1.CreateOptions{}) if err != nil { - panic(err) + s.Require().NoError(err) } } @@ -975,7 +975,7 @@ func (s *OAuthProxyResourceManagerTestSuite) addRole(name, namespace, appName, a } _, err := s.kubeClient.RbacV1().Roles(namespace).Create(context.Background(), role, metav1.CreateOptions{}) if err != nil { - panic(err) + s.Require().NoError(err) } } @@ -989,7 +989,7 @@ func (s *OAuthProxyResourceManagerTestSuite) addRoleBinding(name, namespace, app } _, err := s.kubeClient.RbacV1().RoleBindings(namespace).Create(context.Background(), rolebinding, metav1.CreateOptions{}) if err != nil { - panic(err) + s.Require().NoError(err) } } diff --git a/pkg/apis/job/job_test.go b/pkg/apis/job/job_test.go index b60f7540d..9d6367487 100644 --- a/pkg/apis/job/job_test.go +++ b/pkg/apis/job/job_test.go @@ -269,7 +269,7 @@ func (s *RadixJobTestSuite) TestObjectSynced_FirstJobRunning_SecondJobQueued() { // Stopping first job should set second job to running firstJob.Spec.Stop = true if _, err := s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } err = s.runSync(firstJob, config) s.Require().NoError(err) @@ -292,7 +292,7 @@ func (s *RadixJobTestSuite) TestObjectSynced_FirstJobWaiting_SecondJobQueued() { // Stopping first job should set second job to running firstJob.Spec.Stop = true if _, err := s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } err = s.runSync(firstJob, config) s.Require().NoError(err) @@ -320,7 +320,7 @@ func (s *RadixJobTestSuite) TestObjectSynced_MultipleJobs_MissingRadixApplicatio // Stopping first job should set second job to running firstJob.Spec.Stop = true if _, err := s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } err = s.runSync(firstJob, config) @@ -665,7 +665,7 @@ func (s *RadixJobTestSuite) TestHistoryLimit_EachEnvHasOwnHistory() { WithActiveFrom(testTime)) s.NoError(err) if err := s.applyJobWithSyncFor(raBuilder, appName, rdJob, config); err != nil { - panic(err) + s.Require().NoError(err) } testTime = testTime.Add(time.Hour) } @@ -676,7 +676,7 @@ func (s *RadixJobTestSuite) TestHistoryLimit_EachEnvHasOwnHistory() { WithActiveFrom(testTime)) s.NoError(err) if err := s.applyJobWithSyncFor(raBuilder, appName, scenario.testingRadixDeploymentJob, config); err != nil { - panic(err) + s.Require().NoError(err) } radixJobList, err := s.radixClient.RadixV1().RadixJobs(appNamespace).List(context.TODO(), metav1.ListOptions{}) @@ -802,7 +802,7 @@ func (s *RadixJobTestSuite) Test_WildCardJobs() { testTime := time.Now().Add(time.Hour * -100) raBuilder := scenario.raBuilder.WithAppName(appName) if _, err := s.testUtils.ApplyApplication(raBuilder); err != nil { - panic(err) + s.Require().NoError(err) } for _, rdJob := range scenario.existingRadixDeploymentJobs { if rdJob.jobStatus == radixv1.JobSucceeded { diff --git a/pkg/apis/kube/environment_variables_test.go b/pkg/apis/kube/environment_variables_test.go index 145b2329d..57102a276 100644 --- a/pkg/apis/kube/environment_variables_test.go +++ b/pkg/apis/kube/environment_variables_test.go @@ -10,6 +10,7 @@ import ( prometheusclient "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned" prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -100,7 +101,7 @@ func Test_GetEnvVarsMetadataConfigMapAndMap(t *testing.T) { namespace := "some-namespace" componentName := "comp1" createEnvVarConfigMapFunc := func(testEnv EnvironmentVariablesTestEnv) { - createConfigMap(testEnv.kubeUtil, namespace, &corev1.ConfigMap{ + if err := createConfigMap(testEnv.kubeUtil, namespace, &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "env-vars-" + componentName, Namespace: namespace, @@ -110,10 +111,12 @@ func Test_GetEnvVarsMetadataConfigMapAndMap(t *testing.T) { "VAR2": "val2", "VAR3": "setVal3", }, - }) + }); err != nil { + require.NoError(t, err) + } } createEnvVarMetadataConfigMapFunc := func(testEnv EnvironmentVariablesTestEnv) { - createConfigMap( + if err := createConfigMap( testEnv.kubeUtil, namespace, &corev1.ConfigMap{ @@ -130,7 +133,9 @@ func Test_GetEnvVarsMetadataConfigMapAndMap(t *testing.T) { `, }, }, - ) + ); err != nil { + require.NoError(t, err) + } } t.Run("Get existing", func(t *testing.T) { t.Parallel() @@ -213,7 +218,7 @@ func Test_SetEnvVarsMetadataMapToConfigMap(t *testing.T) { "VAR2": {RadixConfigValue: "added"}, // VAR3: removed }); err != nil { - panic(err) + require.NoError(t, err) } assert.NotNil(t, currentMetadataConfigMap.Data) @@ -262,7 +267,7 @@ func Test_ApplyEnvVarsMetadataConfigMap(t *testing.T) { Name: name, Namespace: namespace, }}, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } err := testEnv.kubeUtil.ApplyEnvVarsMetadataConfigMap(namespace, ¤tMetadataConfigMap, metadata) @@ -299,7 +304,7 @@ func Test_GetEnvVarsConfigMapAndMetadataMap(t *testing.T) { t.Run("Get existing", func(t *testing.T) { t.Parallel() testEnv := getEnvironmentVariablesTestEnv() - createConfigMap(testEnv.kubeUtil, namespace, &corev1.ConfigMap{ + if err := createConfigMap(testEnv.kubeUtil, namespace, &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "env-vars-" + componentName, Namespace: namespace, @@ -309,8 +314,10 @@ func Test_GetEnvVarsConfigMapAndMetadataMap(t *testing.T) { "VAR2": "val2", "VAR3": "setVal3", }, - }) - createConfigMap( + }); err != nil { + require.NoError(t, err) + } + if err := createConfigMap( testEnv.kubeUtil, namespace, &corev1.ConfigMap{ @@ -327,7 +334,9 @@ func Test_GetEnvVarsConfigMapAndMetadataMap(t *testing.T) { `, }, }, - ) + ); err != nil { + require.NoError(t, err) + } envVarsConfigMap, envVarsMetadataConfigMap, metadataMap, err := testEnv.kubeUtil.GetEnvVarsConfigMapAndMetadataMap(namespace, componentName) assert.NoError(t, err) assert.NotNil(t, envVarsConfigMap) @@ -373,7 +382,7 @@ func Test_GetOrCreateEnvVarsConfigMapAndMetadataMap(t *testing.T) { t.Run("Get existing", func(t *testing.T) { t.Parallel() testEnv := getEnvironmentVariablesTestEnv() - createConfigMap(testEnv.kubeUtil, namespace, &corev1.ConfigMap{ + if err := createConfigMap(testEnv.kubeUtil, namespace, &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "env-vars-" + componentName, Namespace: namespace, @@ -383,8 +392,10 @@ func Test_GetOrCreateEnvVarsConfigMapAndMetadataMap(t *testing.T) { "VAR2": "val2", "VAR3": "setVal3", }, - }) - createConfigMap( + }); err != nil { + require.NoError(t, err) + } + if err := createConfigMap( testEnv.kubeUtil, namespace, &corev1.ConfigMap{ @@ -401,7 +412,9 @@ func Test_GetOrCreateEnvVarsConfigMapAndMetadataMap(t *testing.T) { `, }, }, - ) + ); err != nil { + require.NoError(t, err) + } envVarsConfigMap, envVarsMetadataConfigMap, err := testEnv.kubeUtil.GetOrCreateEnvVarsConfigMapAndMetadataMap(namespace, appName, componentName) @@ -457,8 +470,7 @@ func Test_BuildRadixConfigEnvVarsMetadataConfigMap(t *testing.T) { }) } -func createConfigMap(kubeUtil *Kube, namespace string, configMap *corev1.ConfigMap) { - if _, err := kubeUtil.kubeClient.CoreV1().ConfigMaps(namespace).Create(context.Background(), configMap, metav1.CreateOptions{}); err != nil { - panic(err) - } +func createConfigMap(kubeUtil *Kube, namespace string, configMap *corev1.ConfigMap) error { + _, err := kubeUtil.kubeClient.CoreV1().ConfigMaps(namespace).Create(context.Background(), configMap, metav1.CreateOptions{}) + return err } diff --git a/radix-operator/alert/controller_test.go b/radix-operator/alert/controller_test.go index 594dfc3d8..f70cafdbd 100644 --- a/radix-operator/alert/controller_test.go +++ b/radix-operator/alert/controller_test.go @@ -30,7 +30,7 @@ func (s *controllerTestSuite) Test_RadixAlertEvents() { s.KubeInformerFactory.Start(s.Stop) go func() { if err := sut.Run(5, s.Stop); err != nil { - panic(err) + s.Require().NoError(err) } }() @@ -38,7 +38,7 @@ func (s *controllerTestSuite) Test_RadixAlertEvents() { s.Handler.EXPECT().Sync(namespace, alertName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) alert, err := s.RadixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), alert, metav1.CreateOptions{}) if err != nil { - panic(err) + s.Require().NoError(err) } s.WaitForSynced("first call") @@ -47,14 +47,14 @@ func (s *controllerTestSuite) Test_RadixAlertEvents() { s.Handler.EXPECT().Sync(namespace, alertName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) alert.Labels = map[string]string{"foo": "bar"} if _, err := s.RadixClient.RadixV1().RadixAlerts(namespace).Update(context.TODO(), alert, metav1.UpdateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } s.WaitForSynced("second call") // Updating the RadixAlert with no changes should not trigger a sync s.Handler.EXPECT().Sync(namespace, alertName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) if _, err := s.RadixClient.RadixV1().RadixAlerts(namespace).Update(context.TODO(), alert, metav1.UpdateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } s.WaitForNotSynced("Sync should not be called when updating RadixAlert with no changes") } @@ -66,7 +66,7 @@ func (s *controllerTestSuite) Test_RadixRegistrationEvents() { rr := &v1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}, Spec: v1.RadixRegistrationSpec{Owner: "first-owner", AdGroups: []string{"first-admin-group"}, ReaderAdGroups: []string{"first-reader-group"}}} rr, err := s.RadixClient.RadixV1().RadixRegistrations().Create(context.TODO(), rr, metav1.CreateOptions{}) if err != nil { - panic(err) + s.Require().NoError(err) } sut := NewController(s.KubeClient, s.RadixClient, s.Handler, s.KubeInformerFactory, s.RadixInformerFactory, false, s.EventRecorder) @@ -74,7 +74,7 @@ func (s *controllerTestSuite) Test_RadixRegistrationEvents() { s.KubeInformerFactory.Start(s.Stop) go func() { if err := sut.Run(5, s.Stop); err != nil { - panic(err) + s.Require().NoError(err) } }() @@ -83,13 +83,13 @@ func (s *controllerTestSuite) Test_RadixRegistrationEvents() { // Initial Sync for the two alerts if _, err := s.RadixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), alert1, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } s.Handler.EXPECT().Sync(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("sync of alert1") if _, err := s.RadixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), alert2, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } s.Handler.EXPECT().Sync(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("initial sync of alert2") @@ -99,7 +99,7 @@ func (s *controllerTestSuite) Test_RadixRegistrationEvents() { rr.ResourceVersion = "2" rr, err = s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}) if err != nil { - panic(err) + s.Require().NoError(err) } s.Handler.EXPECT().Sync(namespace, alert1Name, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("sync on adGroups update") @@ -115,7 +115,7 @@ func (s *controllerTestSuite) Test_RadixRegistrationEvents() { rr.Spec.Owner = "owner" rr.ResourceVersion = "4" if _, err := s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } s.Handler.EXPECT().Sync(namespace, alert1Name, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) s.WaitForNotSynced("Sync should not be called when updating other RR props") diff --git a/radix-operator/application/controller_test.go b/radix-operator/application/controller_test.go index dd33e394b..2cf2a8a97 100644 --- a/radix-operator/application/controller_test.go +++ b/radix-operator/application/controller_test.go @@ -31,13 +31,13 @@ func (s *controllerTestSuite) Test_Controller_Calls_Handler() { go func() { if err := sut.Run(1, s.Stop); err != nil { - panic(err) + s.Require().NoError(err) } }() ra := utils.ARadixApplication().WithAppName(appName).WithEnvironment("dev", "master").BuildRA() if _, err := s.RadixClient.RadixV1().RadixApplications(appNamespace).Create(context.TODO(), ra, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } s.Handler.EXPECT().Sync(namespace, appName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) @@ -51,7 +51,7 @@ func (s *controllerTestSuite) Test_Controller_Calls_Handler_On_Admin_Or_Reader_C rr := &v1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}, Spec: v1.RadixRegistrationSpec{AdGroups: []string{"first-admin"}, ReaderAdGroups: []string{"first-reader-group"}}} rr, err := s.RadixClient.RadixV1().RadixRegistrations().Create(context.TODO(), rr, metav1.CreateOptions{}) if err != nil { - panic(err) + s.Require().NoError(err) } sut := NewController(s.KubeClient, s.RadixClient, s.Handler, s.KubeInformerFactory, s.RadixInformerFactory, false, s.EventRecorder) @@ -60,27 +60,27 @@ func (s *controllerTestSuite) Test_Controller_Calls_Handler_On_Admin_Or_Reader_C go func() { if err := sut.Run(1, s.Stop); err != nil { - panic(err) + s.Require().NoError(err) } }() ra := utils.ARadixApplication().WithAppName(appName).WithEnvironment("dev", "master").BuildRA() if _, err := s.RadixClient.RadixV1().RadixApplications(appNamespace).Create(context.TODO(), ra, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } s.Handler.EXPECT().Sync(namespace, appName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("added app") rr.Spec.AdGroups = []string{"another-admin-group"} if _, err := s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } s.Handler.EXPECT().Sync(namespace, appName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("AdGroups changed") rr.Spec.ReaderAdGroups = []string{"another-reader-group"} if _, err := s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } s.Handler.EXPECT().Sync(namespace, appName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("ReaderAdGroups changed") diff --git a/radix-operator/batch/controller_test.go b/radix-operator/batch/controller_test.go index 14cb78589..94e39bbb5 100644 --- a/radix-operator/batch/controller_test.go +++ b/radix-operator/batch/controller_test.go @@ -31,7 +31,7 @@ func (s *controllerTestSuite) Test_RadixBatchEvents() { go func() { err := sut.Run(5, s.Stop) if err != nil { - panic(err) + s.Require().NoError(err) } }() diff --git a/radix-operator/common/controller_test.go b/radix-operator/common/controller_test.go index 444430fe5..cdd783fb2 100644 --- a/radix-operator/common/controller_test.go +++ b/radix-operator/common/controller_test.go @@ -79,7 +79,7 @@ func (s *commonControllerTestSuite) Test_SyncSuccess() { go func() { if err := sut.Run(1, stopCh); err != nil { - panic(err) + s.Require().NoError(err) } }() @@ -126,7 +126,7 @@ func (s *commonControllerTestSuite) Test_RequeueWhenSyncError() { go func() { if err := sut.Run(1, stopCh); err != nil { - panic(err) + s.Require().NoError(err) } }() @@ -172,7 +172,7 @@ func (s *commonControllerTestSuite) Test_ForgetWhenLockKeyAndIdentifierError() { go func() { if err := sut.Run(1, stopCh); err != nil { - panic(err) + s.Require().NoError(err) } }() @@ -215,7 +215,7 @@ func (s *commonControllerTestSuite) Test_SkipItemWhenNil() { go func() { if err := sut.Run(1, stopCh); err != nil { - panic(err) + s.Require().NoError(err) } }() @@ -256,7 +256,7 @@ func (s *commonControllerTestSuite) Test_SkipItemWhenEmpty() { go func() { if err := sut.Run(1, stopCh); err != nil { - panic(err) + s.Require().NoError(err) } }() @@ -298,7 +298,7 @@ func (s *commonControllerTestSuite) Test_QuitRunWhenShutdownTrue() { doneCh := make(chan struct{}) go func() { if err := sut.Run(1, stopCh); err != nil { - panic(err) + s.Require().NoError(err) } close(doneCh) }() @@ -338,7 +338,7 @@ func (s *commonControllerTestSuite) Test_QuitRunWhenShuttingDownTrue() { doneCh := make(chan struct{}) go func() { if err := sut.Run(1, stopCh); err != nil { - panic(err) + s.Require().NoError(err) } close(doneCh) }() @@ -380,7 +380,7 @@ func (s *commonControllerTestSuite) Test_RequeueWhenLocked() { go func() { if err := sut.Run(1, stopCh); err != nil { - panic(err) + s.Require().NoError(err) } }() @@ -438,7 +438,7 @@ func (s *commonControllerTestSuite) Test_ProcessParallell() { go func() { if err := sut.Run(threadiness, stopCh); err != nil { - panic(err) + s.Require().NoError(err) } }() @@ -478,7 +478,7 @@ func (s *commonControllerTestSuite) Test_ProcessParallell() { select { case <-doneCh: - // Check than max number of goroutines didn't exceed threadiness + // Check if max number of goroutines didn't exceed threadiness actualMax := <-maxThreadsCh expectedMax := threadiness if len(testItems) < threadiness { diff --git a/radix-operator/deployment/controller_test.go b/radix-operator/deployment/controller_test.go index 4374f61f3..94f4c242d 100644 --- a/radix-operator/deployment/controller_test.go +++ b/radix-operator/deployment/controller_test.go @@ -15,6 +15,7 @@ import ( prometheusclient "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned" prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubeinformers "k8s.io/client-go/informers" @@ -61,7 +62,7 @@ func Test_Controller_Calls_Handler(t *testing.T) { }, }, metav1.CreateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } stop := make(chan struct{}) @@ -80,7 +81,11 @@ func Test_Controller_Calls_Handler(t *testing.T) { prometheusclient, WithHasSyncedCallback(func(syncedOk bool) { synced <- syncedOk }), ) - go startDeploymentController(client, radixClient, radixInformerFactory, kubeInformerFactory, deploymentHandler, stop) + go func() { + if err := startDeploymentController(client, radixClient, radixInformerFactory, kubeInformerFactory, deploymentHandler, stop); err != nil { + require.NoError(t, err) + } + }() // Test @@ -102,7 +107,7 @@ func Test_Controller_Calls_Handler(t *testing.T) { noReplicas := 0 rd.Spec.Components[0].Replicas = &noReplicas if _, err := radixClient.RadixV1().RadixDeployments(rd.ObjectMeta.Namespace).Update(context.TODO(), rd, metav1.UpdateOptions{}); err != nil { - panic(err) + require.NoError(t, err) } op, ok = <-synced @@ -123,7 +128,7 @@ func Test_Controller_Calls_Handler(t *testing.T) { for _, aservice := range services.Items { if err := client.CoreV1().Services(rd.ObjectMeta.Namespace).Delete(context.TODO(), aservice.Name, metav1.DeleteOptions{}); err != nil { - panic(err) + require.NoError(t, err) } op, ok = <-synced @@ -139,15 +144,11 @@ func Test_Controller_Calls_Handler(t *testing.T) { teardownTest() } -func startDeploymentController(client kubernetes.Interface, - radixClient radixclient.Interface, - radixInformerFactory informers.SharedInformerFactory, - kubeInformerFactory kubeinformers.SharedInformerFactory, - handler *Handler, stop chan struct{}) { +func startDeploymentController(client kubernetes.Interface, radixClient radixclient.Interface, radixInformerFactory informers.SharedInformerFactory, kubeInformerFactory kubeinformers.SharedInformerFactory, handler *Handler, stop chan struct{}) error { eventRecorder := &record.FakeRecorder{} - waitForChildrenToSync := false + const waitForChildrenToSync = false controller := NewController( client, radixClient, handler, kubeInformerFactory, @@ -158,6 +159,7 @@ func startDeploymentController(client kubernetes.Interface, kubeInformerFactory.Start(stop) radixInformerFactory.Start(stop) if err := controller.Run(4, stop); err != nil { - panic(err) + return err } + return nil } diff --git a/radix-operator/deployment/handler_test.go b/radix-operator/deployment/handler_test.go index 62fc9133e..afe141946 100644 --- a/radix-operator/deployment/handler_test.go +++ b/radix-operator/deployment/handler_test.go @@ -69,7 +69,7 @@ func (s *handlerSuite) Test_Sync() { Status: radixv1.RadixDeployStatus{Condition: radixv1.DeploymentInactive}, }, ); err != nil { - panic(err) + s.Require().NoError(err) } if err := s.radixClient.Tracker().Add( &radixv1.RadixDeployment{ @@ -77,7 +77,7 @@ func (s *handlerSuite) Test_Sync() { Status: radixv1.RadixDeployStatus{Condition: radixv1.DeploymentActive}, }, ); err != nil { - panic(err) + s.Require().NoError(err) } activeRd := &radixv1.RadixDeployment{ ObjectMeta: v1.ObjectMeta{Name: activeRdName, Namespace: namespace}, @@ -85,13 +85,13 @@ func (s *handlerSuite) Test_Sync() { Status: radixv1.RadixDeployStatus{Condition: radixv1.DeploymentActive}, } if err := s.radixClient.Tracker().Add(activeRd); err != nil { - panic(err) + s.Require().NoError(err) } rr := &radixv1.RadixRegistration{ ObjectMeta: v1.ObjectMeta{Name: appName}, } if err := s.radixClient.Tracker().Add(rr); err != nil { - panic(err) + s.Require().NoError(err) } s.Run("non-existing RD should not call factory method", func() { diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go index 41c6747df..5d10f8f7f 100644 --- a/radix-operator/dnsalias/controller_test.go +++ b/radix-operator/dnsalias/controller_test.go @@ -38,7 +38,7 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { go func() { err := sut.Run(5, s.Stop) if err != nil { - panic(err) + s.Require().NoError(err) } }() diff --git a/radix-operator/job/controller_test.go b/radix-operator/job/controller_test.go index c4df16b9a..1f7e441dd 100644 --- a/radix-operator/job/controller_test.go +++ b/radix-operator/job/controller_test.go @@ -94,7 +94,11 @@ func (s *jobTestSuite) Test_Controller_Calls_Handler() { synced <- syncedOk }, ) - go startJobController(s.kubeUtil.KubeClient(), s.kubeUtil.RadixClient(), radixInformerFactory, kubeInformerFactory, jobHandler, stop) + go func() { + if err := startJobController(s.kubeUtil.KubeClient(), s.kubeUtil.RadixClient(), radixInformerFactory, kubeInformerFactory, jobHandler, stop); err != nil { + s.Require().NoError(err) + } + }() // Test @@ -111,7 +115,7 @@ func (s *jobTestSuite) Test_Controller_Calls_Handler() { // changes nothing, except for spec or metadata, labels or annotations rj.Spec.Stop = true if _, err := s.kubeUtil.RadixClient().RadixV1().RadixJobs(rj.ObjectMeta.Namespace).Update(context.TODO(), rj, metav1.UpdateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } op, ok = <-synced @@ -127,11 +131,11 @@ func (s *jobTestSuite) Test_Controller_Calls_Handler() { // Only update of Kubernetes Job is something that the job-controller handles if _, err := s.kubeUtil.KubeClient().BatchV1().Jobs(rj.ObjectMeta.Namespace).Create(context.TODO(), &childJob, metav1.CreateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } childJob.ObjectMeta.ResourceVersion = "1234" if _, err := s.kubeUtil.KubeClient().BatchV1().Jobs(rj.ObjectMeta.Namespace).Update(context.TODO(), &childJob, metav1.UpdateOptions{}); err != nil { - panic(err) + s.Require().NoError(err) } op, ok = <-synced @@ -139,17 +143,18 @@ func (s *jobTestSuite) Test_Controller_Calls_Handler() { s.True(op) } -func startJobController(client kubernetes.Interface, radixClient radixclient.Interface, radixInformerFactory informers.SharedInformerFactory, kubeInformerFactory kubeinformers.SharedInformerFactory, handler Handler, stop chan struct{}) { +func startJobController(client kubernetes.Interface, radixClient radixclient.Interface, radixInformerFactory informers.SharedInformerFactory, kubeInformerFactory kubeinformers.SharedInformerFactory, handler Handler, stop chan struct{}) error { eventRecorder := &record.FakeRecorder{} - waitForChildrenToSync := false + const waitForChildrenToSync = false controller := NewController(client, radixClient, &handler, kubeInformerFactory, radixInformerFactory, waitForChildrenToSync, eventRecorder) kubeInformerFactory.Start(stop) radixInformerFactory.Start(stop) if err := controller.Run(4, stop); err != nil { - panic(err) + return err } + return nil } diff --git a/radix-operator/registration/controller_test.go b/radix-operator/registration/controller_test.go index 42cb2aa4d..f52811e70 100644 --- a/radix-operator/registration/controller_test.go +++ b/radix-operator/registration/controller_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/equinor/radix-operator/pkg/apis/defaults" - "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -14,6 +13,7 @@ import ( informers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubeinformers "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" @@ -53,7 +53,11 @@ func Test_Controller_Calls_Handler(t *testing.T) { synced <- syncedOk }, ) - go startRegistrationController(client, radixClient, radixInformerFactory, kubeInformerFactory, registrationHandler, stop) + go func() { + if err := startRegistrationController(client, radixClient, radixInformerFactory, kubeInformerFactory, registrationHandler, stop); err != nil { + require.NoError(t, err) + } + }() // Test @@ -123,24 +127,19 @@ func Test_Controller_Calls_Handler(t *testing.T) { assert.True(t, op) } -func startRegistrationController( - client kubernetes.Interface, - radixClient radixclient.Interface, - radixInformerFactory informers.SharedInformerFactory, - kubeInformerFactory kubeinformers.SharedInformerFactory, - handler Handler, - stop chan struct{}) { +func startRegistrationController(client kubernetes.Interface, radixClient radixclient.Interface, radixInformerFactory informers.SharedInformerFactory, kubeInformerFactory kubeinformers.SharedInformerFactory, handler Handler, stop chan struct{}) error { eventRecorder := &record.FakeRecorder{} - waitForChildrenToSync := false + const waitForChildrenToSync = false controller := NewController(client, radixClient, &handler, kubeInformerFactory, radixInformerFactory, waitForChildrenToSync, eventRecorder) kubeInformerFactory.Start(stop) radixInformerFactory.Start(stop) if err := controller.Run(5, stop); err != nil { - panic(err) + return err } + return nil } From e6d58bbaa0d23d0338d142890be58e111af88bb8 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 12 Dec 2023 11:12:42 +0100 Subject: [PATCH 100/121] DNS alias specific ingresses are processed independently from other ingresses --- pkg/apis/deployment/deployment_test.go | 32 +++---- pkg/apis/deployment/ingress.go | 27 +++++- .../deployment/oauthproxyresourcemanager.go | 16 +++- .../oauthproxyresourcemanager_test.go | 15 ++-- pkg/apis/deployment/radixcomponent_test.go | 37 -------- pkg/apis/deployment/secrets.go | 2 +- pkg/apis/dnsalias/ingress.go | 71 ++++++++++++++++ pkg/apis/dnsalias/status.go | 4 +- pkg/apis/dnsalias/syncer.go | 84 ++++++------------- pkg/apis/dnsalias/syncer_test.go | 29 +++---- pkg/apis/ingress/ingress.go | 26 +----- pkg/apis/ingress/oauth.go | 18 +--- pkg/apis/kube/ingress.go | 9 +- pkg/apis/kube/kube.go | 1 + pkg/apis/utils/labels/labels.go | 30 +++++-- pkg/apis/utils/labels/labels_test.go | 6 +- pkg/apis/utils/oauth/oauth.go | 11 +++ radix-operator/dnsalias/controller_test.go | 14 +++- 18 files changed, 231 insertions(+), 201 deletions(-) diff --git a/pkg/apis/deployment/deployment_test.go b/pkg/apis/deployment/deployment_test.go index e177ca92e..73b72cce8 100644 --- a/pkg/apis/deployment/deployment_test.go +++ b/pkg/apis/deployment/deployment_test.go @@ -719,16 +719,16 @@ func TestObjectSynced_MultiComponent_NonActiveCluster_ContainsOnlyClusterSpecifi appIngress := getIngressByName("app", ingresses) assert.Equal(t, int32(8080), appIngress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "Port was unexpected") - assert.Equal(t, "false", appIngress.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") - assert.Equal(t, "false", appIngress.Labels[kube.RadixExternalAliasLabel], "Ingress should not be an external app alias") - assert.Equal(t, "false", appIngress.Labels[kube.RadixActiveClusterAliasLabel], "Ingress should not be an active cluster alias") + assert.Empty(t, appIngress.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") + assert.Empty(t, appIngress.Labels[kube.RadixExternalAliasLabel], "Ingress should not be an external app alias") + assert.Empty(t, appIngress.Labels[kube.RadixActiveClusterAliasLabel], "Ingress should not be an active cluster alias") assert.Equal(t, "app", appIngress.Labels[kube.RadixComponentLabel], "Ingress should have the corresponding component") quoteIngress := getIngressByName("radixquote", ingresses) assert.Equal(t, int32(3000), quoteIngress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "Port was unexpected") - assert.Equal(t, "false", quoteIngress.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") - assert.Equal(t, "false", quoteIngress.Labels[kube.RadixExternalAliasLabel], "Ingress should not be an external app alias") - assert.Equal(t, "false", quoteIngress.Labels[kube.RadixActiveClusterAliasLabel], "Ingress should not be an active cluster alias") + assert.Empty(t, quoteIngress.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") + assert.Empty(t, quoteIngress.Labels[kube.RadixExternalAliasLabel], "Ingress should not be an external app alias") + assert.Empty(t, quoteIngress.Labels[kube.RadixActiveClusterAliasLabel], "Ingress should not be an active cluster alias") assert.Equal(t, "radixquote", quoteIngress.Labels[kube.RadixComponentLabel], "Ingress should have the corresponding component") } @@ -775,38 +775,38 @@ func TestObjectSynced_MultiComponent_ActiveCluster_ContainsAllAliasesAndSupporti appAlias := getIngressByName("edcradix-url-alias", ingresses) assert.Equal(t, int32(8080), appAlias.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "Port was unexpected") assert.Equal(t, "true", appAlias.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") - assert.Equal(t, "false", appAlias.Labels[kube.RadixExternalAliasLabel], "Ingress should not be an external app alias") - assert.Equal(t, "false", appAlias.Labels[kube.RadixActiveClusterAliasLabel], "Ingress should not be an active cluster alias") + assert.Empty(t, appAlias.Labels[kube.RadixExternalAliasLabel], "Ingress should not be an external app alias") + assert.Empty(t, appAlias.Labels[kube.RadixActiveClusterAliasLabel], "Ingress should not be an active cluster alias") assert.Equal(t, "app", appAlias.Labels[kube.RadixComponentLabel], "Ingress should have the corresponding component") assert.Equal(t, "edcradix.app.dev.radix.equinor.com", appAlias.Spec.Rules[0].Host, "App should have an external alias") externalAlias := getIngressByName("some.alias.com", ingresses) assert.Equal(t, int32(8080), externalAlias.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "Port was unexpected") - assert.Equal(t, "false", externalAlias.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") + assert.Empty(t, externalAlias.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") assert.Equal(t, "true", externalAlias.Labels[kube.RadixExternalAliasLabel], "Ingress should not be an external app alias") - assert.Equal(t, "false", externalAlias.Labels[kube.RadixActiveClusterAliasLabel], "Ingress should not be an active cluster alias") + assert.Empty(t, externalAlias.Labels[kube.RadixActiveClusterAliasLabel], "Ingress should not be an active cluster alias") assert.Equal(t, "app", externalAlias.Labels[kube.RadixComponentLabel], "Ingress should have the corresponding component") assert.Equal(t, "some.alias.com", externalAlias.Spec.Rules[0].Host, "App should have an external alias") anotherExternalAlias := getIngressByName("another.alias.com", ingresses) assert.Equal(t, int32(8080), anotherExternalAlias.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "Port was unexpected") - assert.Equal(t, "false", anotherExternalAlias.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") + assert.Empty(t, anotherExternalAlias.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") assert.Equal(t, "true", anotherExternalAlias.Labels[kube.RadixExternalAliasLabel], "Ingress should not be an external app alias") - assert.Equal(t, "false", anotherExternalAlias.Labels[kube.RadixActiveClusterAliasLabel], "Ingress should not be an active cluster alias") + assert.Empty(t, anotherExternalAlias.Labels[kube.RadixActiveClusterAliasLabel], "Ingress should not be an active cluster alias") assert.Equal(t, "app", anotherExternalAlias.Labels[kube.RadixComponentLabel], "Ingress should have the corresponding component") assert.Equal(t, "another.alias.com", anotherExternalAlias.Spec.Rules[0].Host, "App should have an external alias") appActiveClusterIngress := getIngressByName("app-active-cluster-url-alias", ingresses) assert.Equal(t, int32(8080), appActiveClusterIngress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "Port was unexpected") - assert.Equal(t, "false", appActiveClusterIngress.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") - assert.Equal(t, "false", appActiveClusterIngress.Labels[kube.RadixExternalAliasLabel], "Ingress should not be an external app alias") + assert.Empty(t, appActiveClusterIngress.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") + assert.Empty(t, appActiveClusterIngress.Labels[kube.RadixExternalAliasLabel], "Ingress should not be an external app alias") assert.Equal(t, "true", appActiveClusterIngress.Labels[kube.RadixActiveClusterAliasLabel], "Ingress should not be an active cluster alias") assert.Equal(t, "app", appActiveClusterIngress.Labels[kube.RadixComponentLabel], "Ingress should have the corresponding component") quoteActiveClusterIngress := getIngressByName("radixquote-active-cluster-url-alias", ingresses) assert.Equal(t, int32(3000), quoteActiveClusterIngress.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "Port was unexpected") - assert.Equal(t, "false", quoteActiveClusterIngress.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") - assert.Equal(t, "false", quoteActiveClusterIngress.Labels[kube.RadixExternalAliasLabel], "Ingress should not be an external app alias") + assert.Empty(t, quoteActiveClusterIngress.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") + assert.Empty(t, quoteActiveClusterIngress.Labels[kube.RadixExternalAliasLabel], "Ingress should not be an external app alias") assert.Equal(t, "true", quoteActiveClusterIngress.Labels[kube.RadixActiveClusterAliasLabel], "Ingress should not be an active cluster alias") assert.Equal(t, "radixquote", quoteActiveClusterIngress.Labels[kube.RadixComponentLabel], "Ingress should have the corresponding component") diff --git a/pkg/apis/deployment/ingress.go b/pkg/apis/deployment/ingress.go index 0bd6b29a0..1baad4982 100644 --- a/pkg/apis/deployment/ingress.go +++ b/pkg/apis/deployment/ingress.go @@ -215,7 +215,12 @@ func (deploy *Deployment) getAppAliasIngressConfig(appName string, ownerReferenc hostname := fmt.Sprintf("%s.%s", appName, appAlias) ingressSpec := ingress.GetIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) - return ingress.GetIngressConfig(namespace, appName, component, getAppAliasIngressName(appName), ingressSpec, deploy.ingressAnnotationProviders, ingress.DNSAppAlias, ownerReference) + ingressConfig, err := ingress.GetIngressConfig(namespace, appName, component, getAppAliasIngressName(appName), ingressSpec, deploy.ingressAnnotationProviders, ownerReference) + if err != nil { + return nil, err + } + ingressConfig.ObjectMeta.Labels[kube.RadixAppAliasLabel] = "true" + return ingressConfig, err } func getAppAliasIngressName(appName string) string { @@ -236,7 +241,12 @@ func (deploy *Deployment) getActiveClusterAliasIngressConfig( ingressSpec := ingress.GetIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) ingressName := getActiveClusterIngressName(component.GetName()) - return ingress.GetIngressConfig(namespace, appName, component, ingressName, ingressSpec, deploy.ingressAnnotationProviders, ingress.DNSActiveClusterAlias, ownerReference) + ingressConfig, err := ingress.GetIngressConfig(namespace, appName, component, ingressName, ingressSpec, deploy.ingressAnnotationProviders, ownerReference) + if err != nil { + return nil, err + } + ingressConfig.ObjectMeta.Labels[kube.RadixActiveClusterAliasLabel] = "true" + return ingressConfig, err } func getActiveClusterIngressName(componentName string) string { @@ -257,7 +267,11 @@ func (deploy *Deployment) getDefaultIngressConfig( hostname := getHostName(component.GetName(), namespace, clustername, dnsZone) ingressSpec := ingress.GetIngressSpec(hostname, component.GetName(), defaults.TLSSecretName, publicPortNumber) - return ingress.GetIngressConfig(namespace, appName, component, getDefaultIngressName(component.GetName()), ingressSpec, deploy.ingressAnnotationProviders, ingress.DNSDefaultAlias, ownerReference) + ingressConfig, err := ingress.GetIngressConfig(namespace, appName, component, getDefaultIngressName(component.GetName()), ingressSpec, deploy.ingressAnnotationProviders, ownerReference) + if err != nil { + return nil, err + } + return ingressConfig, err } func getDefaultIngressName(componentName string) string { @@ -273,7 +287,12 @@ func (deploy *Deployment) getExternalAliasIngressConfig( publicPortNumber int32, ) (*networkingv1.Ingress, error) { ingressSpec := ingress.GetIngressSpec(externalAlias, component.GetName(), externalAlias, publicPortNumber) - return ingress.GetIngressConfig(namespace, appName, component, externalAlias, ingressSpec, deploy.ingressAnnotationProviders, ingress.DNSExternalAlias, ownerReference) + ingressConfig, err := ingress.GetIngressConfig(namespace, appName, component, externalAlias, ingressSpec, deploy.ingressAnnotationProviders, ownerReference) + if err != nil { + return nil, err + } + ingressConfig.ObjectMeta.Labels[kube.RadixExternalAliasLabel] = "true" + return ingressConfig, err } func getActiveClusterHostName(componentName, namespace string) string { diff --git a/pkg/apis/deployment/oauthproxyresourcemanager.go b/pkg/apis/deployment/oauthproxyresourcemanager.go index 773ed2314..2b76a5785 100644 --- a/pkg/apis/deployment/oauthproxyresourcemanager.go +++ b/pkg/apis/deployment/oauthproxyresourcemanager.go @@ -15,6 +15,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/securitycontext" "github.com/equinor/radix-operator/pkg/apis/utils" radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" + "github.com/equinor/radix-operator/pkg/apis/utils/oauth" oauthutil "github.com/equinor/radix-operator/pkg/apis/utils/oauth" log "github.com/sirupsen/logrus" appsv1 "k8s.io/api/apps/v1" @@ -287,12 +288,12 @@ func (o *oauthProxyResourceManager) deleteDeployment(component v1.RadixCommonDep } func (o *oauthProxyResourceManager) deleteIngresses(component v1.RadixCommonDeployComponent) error { - selector := labels.SelectorFromValidatedSet(radixlabels.ForAuxComponent(o.rd.Spec.AppName, component)).String() + selector := labels.SelectorFromValidatedSet(radixlabels.ForAuxComponentIngress(o.rd.Spec.AppName, component)).String() ingresses, err := o.kubeutil.ListIngressesWithSelector(o.rd.Namespace, selector) if err != nil { return err } - return o.kubeutil.DeleteIngresses(true, ingresses...) + return o.kubeutil.DeleteIngresses(ingresses...) } func (o *oauthProxyResourceManager) deleteServices(component v1.RadixCommonDeployComponent) error { @@ -370,7 +371,16 @@ func (o *oauthProxyResourceManager) createOrUpdateIngresses(component v1.RadixCo } for _, ing := range ingresses.Items { - if err := ingress.CreateOrUpdateOAuthProxyIngressForComponentIngress(o.kubeutil, namespace, o.rd.Spec.AppName, component, &ing, o.ingressAnnotationProviders); err != nil { + appName := o.rd.Spec.AppName + auxIngress, err := ingress.BuildOAuthProxyIngressForComponentIngress(namespace, component, &ing, o.ingressAnnotationProviders) + if err != nil { + return err + } + if auxIngress == nil { + continue + } + oauth.MergeAuxComponentIngressResourceLabels(auxIngress, appName, component) + if err := o.kubeutil.ApplyIngress(namespace, auxIngress); err != nil { return err } } diff --git a/pkg/apis/deployment/oauthproxyresourcemanager_test.go b/pkg/apis/deployment/oauthproxyresourcemanager_test.go index 9c17e9686..56ad75768 100644 --- a/pkg/apis/deployment/oauthproxyresourcemanager_test.go +++ b/pkg/apis/deployment/oauthproxyresourcemanager_test.go @@ -641,8 +641,9 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate } } // Ingresses for server component - actualIngress := getIngress(fmt.Sprintf("%s-%s", ingServer.Name, defaults.OAuthProxyAuxiliaryComponentSuffix), actualIngresses.Items) - s.NotNil(actualIngress) + ingressName := fmt.Sprintf("%s-%s", ingServer.Name, defaults.OAuthProxyAuxiliaryComponentSuffix) + actualIngress := getIngress(ingressName, actualIngresses.Items) + s.Require().NotNil(actualIngress, "not fount aux ingress %s", ingressName) s.Equal(expectedIngServerAnnotations, actualIngress.Annotations) s.ElementsMatch(ingress.GetOwnerReferenceOfIngress(&ingServer), actualIngress.OwnerReferences) s.Equal(ingServer.Spec.IngressClassName, actualIngress.Spec.IngressClassName) @@ -651,8 +652,9 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate s.Equal(getExpectedIngressRule(component1Name, "auth1"), actualIngress.Spec.Rules[0].IngressRuleValue) // Ingresses for web component - actualIngress = getIngress(fmt.Sprintf("%s-%s", ingWeb1.Name, defaults.OAuthProxyAuxiliaryComponentSuffix), actualIngresses.Items) - s.NotNil(actualIngress) + ingressName = fmt.Sprintf("%s-%s", ingWeb1.Name, defaults.OAuthProxyAuxiliaryComponentSuffix) + actualIngress = getIngress(ingressName, actualIngresses.Items) + s.Require().NotNil(actualIngress, "not fount aux ingress %s", ingressName) s.Equal(expectedIngWebAnnotations, actualIngress.Annotations) s.ElementsMatch(ingress.GetOwnerReferenceOfIngress(&ingWeb1), actualIngress.OwnerReferences) s.Equal(ingWeb1.Spec.IngressClassName, actualIngress.Spec.IngressClassName) @@ -660,8 +662,9 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate s.Equal(ingWeb1.Spec.Rules[0].Host, actualIngress.Spec.Rules[0].Host) s.Equal(getExpectedIngressRule(component2Name, "auth2"), actualIngress.Spec.Rules[0].IngressRuleValue) - actualIngress = getIngress(fmt.Sprintf("%s-%s", ingWeb2.Name, defaults.OAuthProxyAuxiliaryComponentSuffix), actualIngresses.Items) - s.NotNil(actualIngress) + ingressName = fmt.Sprintf("%s-%s", ingWeb2.Name, defaults.OAuthProxyAuxiliaryComponentSuffix) + actualIngress = getIngress(ingressName, actualIngresses.Items) + s.Require().NotNil(actualIngress, "not fount aux ingress %s", ingressName) s.Equal(expectedIngWebAnnotations, actualIngress.Annotations) s.ElementsMatch(ingress.GetOwnerReferenceOfIngress(&ingWeb2), actualIngress.OwnerReferences) s.Equal(ingWeb2.Spec.IngressClassName, actualIngress.Spec.IngressClassName) diff --git a/pkg/apis/deployment/radixcomponent_test.go b/pkg/apis/deployment/radixcomponent_test.go index b392643f4..349214acd 100644 --- a/pkg/apis/deployment/radixcomponent_test.go +++ b/pkg/apis/deployment/radixcomponent_test.go @@ -275,43 +275,6 @@ func TestGetRadixComponentsForEnv_ListOfExternalAliasesForComponent_GetListOfAli assert.Equal(t, 0, len(deployComponent[0].DNSExternalAlias)) } -func TestGetRadixComponentsForEnv_ListOfDNSAliasesForComponent_GetListOfAliases(t *testing.T) { - componentImages := make(pipeline.DeployComponentImages) - componentImages["app"] = pipeline.DeployComponentImage{ImagePath: anyImagePath} - envVarsMap := make(radixv1.EnvVarsMap) - envVarsMap[defaults.RadixCommitHashEnvironmentVariable] = "anycommit" - envVarsMap[defaults.RadixGitTagsEnvironmentVariable] = "anytag" - - ra := utils.ARadixApplication(). - WithEnvironment("prod", "release"). - WithEnvironment("dev", "master"). - WithComponents( - utils.NewApplicationComponentBuilder(). - WithName("componentA"), - utils.NewApplicationComponentBuilder(). - WithName("componentB")). - WithDNSAlias( - radixv1.DNSAlias{Alias: "alias1", Component: "componentA", Environment: "prod"}, - radixv1.DNSAlias{Alias: "alias2", Component: "componentA", Environment: "prod"}, - radixv1.DNSAlias{Alias: "alias3", Component: "componentA", Environment: "dev"}, - ).BuildRA() - - prodDeployComponent, _ := GetRadixComponentsForEnv(ra, "prod", componentImages, envVarsMap) - assert.Equal(t, 2, len(prodDeployComponent)) - assert.Equal(t, 2, len(prodDeployComponent[0].DNSAlias)) - require.Len(t, prodDeployComponent[0].DNSAlias, 2) - assert.Equal(t, "alias1", prodDeployComponent[0].DNSAlias[0]) - assert.Equal(t, "componentA", prodDeployComponent[0].GetName()) - assert.Equal(t, "alias2", prodDeployComponent[0].DNSAlias[1]) - - devDeployComponent, _ := GetRadixComponentsForEnv(ra, "dev", componentImages, envVarsMap) - assert.Equal(t, 2, len(devDeployComponent)) - assert.Equal(t, 1, len(devDeployComponent[0].DNSAlias)) - require.Len(t, devDeployComponent[0].DNSAlias, 1) - assert.Equal(t, "alias3", devDeployComponent[0].DNSAlias[0]) - assert.Equal(t, "componentA", devDeployComponent[0].GetName()) -} - func TestGetRadixComponentsForEnv_CommonEnvironmentVariables_No_Override(t *testing.T) { componentImages := make(pipeline.DeployComponentImages) componentImages["app"] = pipeline.DeployComponentImage{ImagePath: anyImagePath} diff --git a/pkg/apis/deployment/secrets.go b/pkg/apis/deployment/secrets.go index 92af69332..e7dee4710 100644 --- a/pkg/apis/deployment/secrets.go +++ b/pkg/apis/deployment/secrets.go @@ -231,7 +231,7 @@ func (deploy *Deployment) garbageCollectSecretsNoLongerInSpecForComponent(compon for _, secret := range secrets { // External alias not handled here - if secret.ObjectMeta.Labels[kube.RadixExternalAliasLabel] != "" { + if secret.ObjectMeta.Labels[kube.RadixExternalAliasLabel] == "" { continue } diff --git a/pkg/apis/dnsalias/ingress.go b/pkg/apis/dnsalias/ingress.go index 2b6e09968..344ce6bed 100644 --- a/pkg/apis/dnsalias/ingress.go +++ b/pkg/apis/dnsalias/ingress.go @@ -4,8 +4,14 @@ import ( "context" "fmt" + "github.com/equinor/radix-operator/pkg/apis/ingress" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" + radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" + "github.com/equinor/radix-operator/pkg/apis/utils/oauth" + log "github.com/sirupsen/logrus" networkingv1 "k8s.io/api/networking/v1" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" ) @@ -25,3 +31,68 @@ func GetDNSAliasIngressName(alias string) string { func GetDNSAliasHost(alias, dnsZone string) string { return fmt.Sprintf("%s.%s", alias, dnsZone) } + +func (s *syncer) syncIngress(namespace string, radixDeployComponent radixv1.RadixCommonDeployComponent, ingressName string) (*networkingv1.Ingress, error) { + newIngress, err := buildIngress(radixDeployComponent, s.radixDNSAlias, s.dnsConfig, s.oauth2DefaultConfig, s.ingressConfiguration) + if err != nil { + return nil, err + } + existingIngress, err := s.kubeUtil.GetIngress(namespace, ingressName) + if err != nil { + if errors.IsNotFound(err) { + log.Debugf("not found Ingress %s in the namespace %s. Create new.", ingressName, namespace) + return s.createIngress(s.radixDNSAlias, newIngress) + } + return nil, err + } + log.Debugf("found Ingress %s in the namespace %s.", ingressName, namespace) + patchesIngress, err := s.applyIngress(namespace, existingIngress, newIngress) + if err != nil { + return nil, err + } + return patchesIngress, nil +} + +func (s *syncer) applyIngress(namespace string, existingIngress *networkingv1.Ingress, ing *networkingv1.Ingress) (*networkingv1.Ingress, error) { + patchesIngress, err := s.kubeUtil.PatchIngress(namespace, existingIngress, ing) + if err != nil { + return nil, fmt.Errorf("failed to patch an ingress %s: %w", ing.GetName(), err) + } + return patchesIngress, nil +} + +func (s *syncer) createIngress(radixDNSAlias *radixv1.RadixDNSAlias, ing *networkingv1.Ingress) (*networkingv1.Ingress, error) { + log.Debugf("create an ingress %s for the RadixDNSAlias", ing.GetName()) + return CreateRadixDNSAliasIngress(s.kubeClient, radixDNSAlias.Spec.AppName, radixDNSAlias.Spec.Environment, ing) +} + +func (s *syncer) syncOAuthProxyIngress(deployComponent radixv1.RadixCommonDeployComponent, namespace string, aliasSpec radixv1.RadixDNSAliasSpec, radixDeployComponent radixv1.RadixCommonDeployComponent, ing *networkingv1.Ingress) error { + appName := aliasSpec.AppName + authentication := deployComponent.GetAuthentication() + oauthEnabled := authentication != nil && authentication.OAuth2 != nil + if !oauthEnabled { + return s.deleteOAuthAuxIngresses(deployComponent, namespace, appName) + } + oauth2, err := s.oauth2DefaultConfig.MergeWith(authentication.OAuth2) + if err != nil { + return err + } + authentication.OAuth2 = oauth2 + auxIngress, err := ingress.BuildOAuthProxyIngressForComponentIngress(namespace, deployComponent, ing, s.ingressAnnotationProviders) + if err != nil { + return err + } + if auxIngress == nil { + return nil + } + oauth.MergeAuxComponentDNSAliasIngressResourceLabels(auxIngress, appName, deployComponent, s.radixDNSAlias.GetName()) + return s.kubeUtil.ApplyIngress(namespace, auxIngress) +} + +func (s *syncer) deleteOAuthAuxIngresses(deployComponent radixv1.RadixCommonDeployComponent, namespace string, appName string) error { + oauthAuxIngresses, err := s.kubeUtil.GetIngressesWithSelector(namespace, radixlabels.ForAuxComponentDNSAliasIngress(appName, deployComponent, s.radixDNSAlias.GetName()).String()) + if err != nil { + return err + } + return s.kubeUtil.DeleteIngresses(oauthAuxIngresses...) +} diff --git a/pkg/apis/dnsalias/status.go b/pkg/apis/dnsalias/status.go index a4ec0a593..1f12cb6bb 100644 --- a/pkg/apis/dnsalias/status.go +++ b/pkg/apis/dnsalias/status.go @@ -22,7 +22,7 @@ func (s *syncer) restoreStatus() error { } var status radixv1.RadixDNSAliasStatus if err := json.Unmarshal([]byte(restoredStatus), &status); err != nil { - return fmt.Errorf("unable to deserealise status from annotation: %w", err) + return fmt.Errorf("unable to deserialize status from annotation: %w", err) } return s.updateStatus(func(currStatus *radixv1.RadixDNSAliasStatus) { *currStatus = status @@ -42,7 +42,7 @@ func (s *syncer) syncStatus(syncErr error) error { currStatus.Message = "" }) if err != nil { - return fmt.Errorf("failed to sync status: %v", err) + return fmt.Errorf("failed to sync status: %w", err) } return nil } diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 4f97ce7dd..70957bed9 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -19,7 +19,6 @@ import ( radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" log "github.com/sirupsen/logrus" networkingv1 "k8s.io/api/networking/v1" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/client-go/kubernetes" ) @@ -87,32 +86,27 @@ func (s *syncer) syncAlias() error { aliasSpec := s.radixDNSAlias.Spec ingressName := GetDNSAliasIngressName(aliasName) namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) - ing, err := s.createOrUpdateIngress(namespace, radixDeployComponent, ingressName) + + ing, err := s.syncIngress(namespace, radixDeployComponent, ingressName) if err != nil { - if admissionWebhookErrorMatcher := admissionWebhookErrorExpression.FindStringSubmatch(err.Error()); len(admissionWebhookErrorMatcher) == 5 { - log.Error(err) - return fmt.Errorf("DNS alias %s cannot be used, because the host %s with the path %s is already in use", s.radixDNSAlias.GetName(), admissionWebhookErrorMatcher[1], admissionWebhookErrorMatcher[2]) - } - return err + return s.getDNSAliasError(err) } - return s.createOrUpdateOAuthProxyIngressForComponentIngress(radixDeployComponent.GetAuthentication(), namespace, aliasSpec, radixDeployComponent, ing) + + return s.syncOAuthProxyIngress(radixDeployComponent, namespace, aliasSpec, radixDeployComponent, ing) } -func (s *syncer) createOrUpdateOAuthProxyIngressForComponentIngress(componentAuthentication *radixv1.Authentication, namespace string, aliasSpec radixv1.RadixDNSAliasSpec, radixDeployComponent radixv1.RadixCommonDeployComponent, ing *networkingv1.Ingress) error { - if componentAuthentication == nil || componentAuthentication.OAuth2 == nil { - return nil - } - oauth, err := s.oauth2DefaultConfig.MergeWith(componentAuthentication.OAuth2) - if err != nil { - return err +func (s *syncer) getDNSAliasError(err error) error { + if admissionWebhookErrorMatcher := admissionWebhookErrorExpression.FindStringSubmatch(err.Error()); len(admissionWebhookErrorMatcher) == 5 { + log.Error(err) + return fmt.Errorf("DNS alias %s cannot be used, because the host %s with the path %s is already in use", s.radixDNSAlias.GetName(), admissionWebhookErrorMatcher[1], admissionWebhookErrorMatcher[2]) } - componentAuthentication.OAuth2 = oauth - return ingress.CreateOrUpdateOAuthProxyIngressForComponentIngress(s.kubeUtil, namespace, aliasSpec.AppName, radixDeployComponent, ing, s.ingressAnnotationProviders) + return err } func (s *syncer) getRadixDeployComponent() (radixv1.RadixCommonDeployComponent, error) { aliasSpec := s.radixDNSAlias.Spec namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) + log.Debugf("get active deployment for the namespace %s", namespace) radixDeployment, err := s.kubeUtil.GetActiveDeployment(namespace) if err != nil { @@ -122,6 +116,7 @@ func (s *syncer) getRadixDeployComponent() (radixv1.RadixCommonDeployComponent, return nil, nil } log.Debugf("active deployment for the namespace %s is %s", namespace, radixDeployment.GetName()) + deployComponent := radixDeployment.GetCommonComponentByName(aliasSpec.Component) if commonUtils.IsNil(deployComponent) { return nil, DeployComponentNotFoundByName(aliasSpec.AppName, aliasSpec.Environment, aliasSpec.Component, radixDeployment.GetName()) @@ -129,41 +124,11 @@ func (s *syncer) getRadixDeployComponent() (radixv1.RadixCommonDeployComponent, return deployComponent, nil } -func (s *syncer) createOrUpdateIngress(namespace string, radixDeployComponent radixv1.RadixCommonDeployComponent, ingressName string) (*networkingv1.Ingress, error) { - existingIngress, err := s.kubeUtil.GetIngress(namespace, ingressName) - if err != nil { - if errors.IsNotFound(err) { - log.Debugf("not found Ingress %s in the namespace %s. Create new.", ingressName, namespace) - return s.createIngress(radixDeployComponent, s.radixDNSAlias, s.dnsConfig, s.oauth2DefaultConfig, s.ingressConfiguration) - } - return nil, err - } - log.Debugf("found Ingress %s in the namespace %s.", ingressName, namespace) - updatedIngress, err := buildIngress(radixDeployComponent, s.radixDNSAlias, s.dnsConfig, s.oauth2DefaultConfig, s.ingressConfiguration) - if err != nil { - return nil, err - } - ing, err := s.kubeUtil.PatchIngress(namespace, existingIngress, updatedIngress) - if err != nil { - return nil, fmt.Errorf("failed to patch an ingress %s: %w", ingressName, err) - } - return ing, nil -} - -func (s *syncer) createIngress(radixDeployComponent radixv1.RadixCommonDeployComponent, radixDNSAlias *radixv1.RadixDNSAlias, dnsConfig *dnsalias.DNSConfig, oauth2Config defaults.OAuth2Config, ingressConfiguration ingress.IngressConfiguration) (*networkingv1.Ingress, error) { - ing, err := buildIngress(radixDeployComponent, radixDNSAlias, dnsConfig, oauth2Config, ingressConfiguration) - if err != nil { - return nil, err - } - aliasSpec := radixDNSAlias.Spec - log.Debugf("create an ingress %s for the RadixDNSAlias", ing.GetName()) - return CreateRadixDNSAliasIngress(s.kubeClient, aliasSpec.AppName, aliasSpec.Environment, ing) -} - func (s *syncer) handleDeletedRadixDNSAlias() (bool, error) { if s.radixDNSAlias.ObjectMeta.DeletionTimestamp == nil { return false, nil } + log.Debugf("handle deleted RadixDNSAlias %s in the application %s", s.radixDNSAlias.Name, s.radixDNSAlias.Spec.AppName) finalizerIndex := slice.FindIndex(s.radixDNSAlias.ObjectMeta.Finalizers, func(val string) bool { return val == kube.RadixDNSAliasFinalizer @@ -173,13 +138,16 @@ func (s *syncer) handleDeletedRadixDNSAlias() (bool, error) { kube.RadixDNSAliasFinalizer, s.radixDNSAlias.Name, len(s.radixDNSAlias.ObjectMeta.Finalizers)) return false, nil } + if err := s.deletedIngressesForRadixDNSAlias(); err != nil { return true, err } + updatingAlias := s.radixDNSAlias.DeepCopy() updatingAlias.ObjectMeta.Finalizers = append(s.radixDNSAlias.ObjectMeta.Finalizers[:finalizerIndex], s.radixDNSAlias.ObjectMeta.Finalizers[finalizerIndex+1:]...) log.Debugf("removed finalizer %s from the RadixDNSAlias %s for the application %s. Left finalizers: %d", kube.RadixEnvironmentFinalizer, updatingAlias.Name, updatingAlias.Spec.AppName, len(updatingAlias.ObjectMeta.Finalizers)) + if err := s.kubeUtil.UpdateRadixDNSAlias(updatingAlias); err != nil { return false, err } @@ -188,13 +156,13 @@ func (s *syncer) handleDeletedRadixDNSAlias() (bool, error) { func (s *syncer) deletedIngressesForRadixDNSAlias() error { aliasSpec := s.radixDNSAlias.Spec - ingresses, err := s.kubeUtil.GetIngressesWithSelector(utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment), - radixlabels.Merge(radixlabels.ForApplicationName(aliasSpec.AppName), radixlabels.ForComponentName(aliasSpec.Component), radixlabels.ForDNSAlias()).String()) + namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) + dnsAliasIngressesSelector := radixlabels.ForDNSAliasIngress(aliasSpec.AppName, aliasSpec.Component, s.radixDNSAlias.GetName()).String() + ingresses, err := s.kubeUtil.GetIngressesWithSelector(namespace, dnsAliasIngressesSelector) if err != nil { return err } - log.Debugf("delete %d Ingress(es)", len(ingresses)) - return s.kubeUtil.DeleteIngresses(true, ingresses...) + return s.kubeUtil.DeleteIngresses(ingresses...) } func buildIngress(radixDeployComponent radixv1.RadixCommonDeployComponent, radixDNSAlias *radixv1.RadixDNSAlias, dnsConfig *dnsalias.DNSConfig, oauth2Config defaults.OAuth2Config, ingressConfiguration ingress.IngressConfiguration) (*networkingv1.Ingress, error) { @@ -203,23 +171,21 @@ func buildIngress(radixDeployComponent radixv1.RadixCommonDeployComponent, radix if publicPort == nil { return nil, radixvalidators.ComponentForDNSAliasIsNotMarkedAsPublicError(radixDeployComponent.GetName()) } - aliasSpec := radixDNSAlias.Spec - appName := aliasSpec.AppName - envName := aliasSpec.Environment - componentName := aliasSpec.Component - namespace := utils.GetEnvironmentNamespace(appName, envName) aliasName := radixDNSAlias.GetName() + aliasSpec := radixDNSAlias.Spec ingressName := GetDNSAliasIngressName(aliasName) hostName := GetDNSAliasHost(aliasName, dnsConfig.DNSZone) + ingressSpec := ingress.GetIngressSpec(hostName, aliasSpec.Component, defaults.TLSSecretName, publicPort.Port) - ingressSpec := ingress.GetIngressSpec(hostName, componentName, defaults.TLSSecretName, publicPort.Port) + namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) ingressAnnotations := ingress.GetAnnotationProvider(ingressConfiguration, namespace, oauth2Config) - ingressConfig, err := ingress.GetIngressConfig(namespace, appName, radixDeployComponent, ingressName, ingressSpec, ingressAnnotations, ingress.DNSAlias, internal.GetOwnerReferences(radixDNSAlias)) + ingressConfig, err := ingress.GetIngressConfig(namespace, aliasSpec.AppName, radixDeployComponent, ingressName, ingressSpec, ingressAnnotations, internal.GetOwnerReferences(radixDNSAlias)) if err != nil { return nil, err } ingressConfig.ObjectMeta.Annotations = annotations.Merge(ingressConfig.ObjectMeta.Annotations, annotations.ForManagedByRadixDNSAliasIngress(aliasName)) + ingressConfig.ObjectMeta.Labels[kube.RadixAliasLabel] = aliasName log.Debugf("built the Ingress %s in the environment %s with a host %s", ingressConfig.GetName(), namespace, hostName) return ingressConfig, nil } diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 30df18ffa..4b50f89ca 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -2,8 +2,6 @@ package dnsalias_test import ( "context" - "fmt" - "strconv" "testing" dnsalias2 "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" @@ -176,8 +174,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { err = syncer.OnSync() commonTest.AssertError(s.T(), ts.expectedError, err) - ingresses, err := s.kubeClient.NetworkingV1().Ingresses(utils.GetEnvironmentNamespace(appName1, ts.dnsAlias.Environment)). - List(context.Background(), metav1.ListOptions{LabelSelector: radixlabels.ForDNSAlias().String()}) + ingresses, err := s.getIngressesForAnyAliases(utils.GetEnvironmentNamespace(appName1, ts.dnsAlias.Environment)) s.Require().NoError(err) // assert ingresses @@ -186,14 +183,18 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { return } - s.Require().Len(ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") + s.Len(ingresses.Items, len(ts.expectedIngress), "not matching expected ingresses count") if len(ingresses.Items) == len(ts.expectedIngress) { for _, ing := range ingresses.Items { appNameLabel := ing.GetLabels()[kube.RadixAppLabel] componentNameLabel := ing.GetLabels()[kube.RadixComponentLabel] s.Require().Len(ing.Spec.Rules, 1, "rules count") rule := ing.Spec.Rules[0] - if expectedIngress, ok := ts.expectedIngress[ing.Name]; ok { + expectedIngress, ingressExists := ts.expectedIngress[ing.Name] + assert.True(t, ingressExists, "found not expected ingress %s for: appName %s, host %s, service %s, port %d", + ing.GetName(), appNameLabel, rule.Host, rule.HTTP.Paths[0].Backend.Service.Name, + rule.HTTP.Paths[0].Backend.Service.Port.Number) + if ingressExists { s.Assert().Equal(expectedIngress.appName, appNameLabel, "app name") expectedNamespace := utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName) s.Assert().Equal(expectedNamespace, ing.GetNamespace(), "namespace") @@ -213,11 +214,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { s.Assert().Equal(radixDNSAlias.GetUID(), ownerRef.UID, "ownerRef.UID") s.Assert().True(ownerRef.Controller != nil && *ownerRef.Controller, "ownerRef.Controller") } - continue } - assert.Fail(t, fmt.Sprintf("found not expected ingress %s for: appName %s, host %s, service %s, port %d", - ing.GetName(), appNameLabel, rule.Host, rule.HTTP.Paths[0].Backend.Service.Name, - rule.HTTP.Paths[0].Backend.Service.Port.Number)) } } @@ -225,6 +222,10 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { } } +func (s *syncerTestSuite) getIngressesForAnyAliases(namespace string) (*networkingv1.IngressList, error) { + return s.kubeClient.NetworkingV1().Ingresses(namespace).List(context.Background(), metav1.ListOptions{LabelSelector: kube.RadixAliasLabel}) +} + func buildRadixDeployment(appName, component1, component2, envName string, port8080, port9090 int32) *radixv1.RadixDeployment { return utils.NewDeploymentBuilder(). WithRadixApplication(utils.ARadixApplication()). @@ -255,12 +256,8 @@ func registerExistingIngresses(kubeClient kubernetes.Interface, testIngresses ma for _, ingProps := range testIngresses { ing := &networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{ - Name: dnsalias.GetDNSAliasIngressName(ingProps.alias), - Labels: map[string]string{ - kube.RadixAppLabel: ingProps.appName, - kube.RadixComponentLabel: ingProps.component, - kube.RadixAliasLabel: strconv.FormatBool(true), - }, + Name: dnsalias.GetDNSAliasIngressName(ingProps.alias), + Labels: radixlabels.ForDNSAliasIngress(ingProps.appName, ingProps.component, ingProps.alias), }, Spec: ingress.GetIngressSpec(ingProps.host, ingProps.component, defaults.TLSSecretName, ingProps.port), } diff --git a/pkg/apis/ingress/ingress.go b/pkg/apis/ingress/ingress.go index 8105988a4..3489ae1aa 100644 --- a/pkg/apis/ingress/ingress.go +++ b/pkg/apis/ingress/ingress.go @@ -1,8 +1,6 @@ package ingress import ( - "strconv" - "github.com/equinor/radix-common/utils/maps" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -12,16 +10,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -type DNSAliasType int - -const ( - DNSDefaultAlias = iota - DNSActiveClusterAlias - DNSAlias - DNSAppAlias - DNSExternalAlias -) - // IngressConfiguration Holds all ingress annotation configurations type IngressConfiguration struct { AnnotationConfigurations []AnnotationConfiguration `json:"configuration" yaml:"configuration"` @@ -94,10 +82,7 @@ func ParseClientCertificateConfiguration(clientCertificate radixv1.ClientCertifi } // GetIngressConfig Gets Ingress configuration -func GetIngressConfig(namespace string, appName string, component radixv1.RadixCommonDeployComponent, - ingressName string, ingressSpec networkingv1.IngressSpec, - ingressProviders []AnnotationProvider, aliasType DNSAliasType, - ownerReference []metav1.OwnerReference) (*networkingv1.Ingress, error) { +func GetIngressConfig(namespace string, appName string, component radixv1.RadixCommonDeployComponent, ingressName string, ingressSpec networkingv1.IngressSpec, ingressProviders []AnnotationProvider, ownerReference []metav1.OwnerReference) (*networkingv1.Ingress, error) { annotations := map[string]string{} for _, ingressProvider := range ingressProviders { @@ -113,18 +98,13 @@ func GetIngressConfig(namespace string, appName string, component radixv1.RadixC Name: ingressName, Annotations: annotations, Labels: map[string]string{ - kube.RadixAppLabel: appName, - kube.RadixComponentLabel: component.GetName(), - kube.RadixAliasLabel: strconv.FormatBool(aliasType == DNSAlias), - kube.RadixAppAliasLabel: strconv.FormatBool(aliasType == DNSAppAlias), - kube.RadixExternalAliasLabel: strconv.FormatBool(aliasType == DNSExternalAlias), - kube.RadixActiveClusterAliasLabel: strconv.FormatBool(aliasType == DNSActiveClusterAlias), + kube.RadixAppLabel: appName, + kube.RadixComponentLabel: component.GetName(), }, OwnerReferences: ownerReference, }, Spec: ingressSpec, } - return ing, nil } diff --git a/pkg/apis/ingress/oauth.go b/pkg/apis/ingress/oauth.go index ab0f52c6a..38930ff40 100644 --- a/pkg/apis/ingress/oauth.go +++ b/pkg/apis/ingress/oauth.go @@ -3,7 +3,6 @@ package ingress import ( "github.com/equinor/radix-common/utils/maps" "github.com/equinor/radix-operator/pkg/apis/defaults" - "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/equinor/radix-operator/pkg/apis/utils/oauth" @@ -17,19 +16,8 @@ func GetAuxOAuthProxyAnnotationProviders() []AnnotationProvider { return []AnnotationProvider{NewForceSslRedirectAnnotationProvider()} } -// CreateOrUpdateOAuthProxyIngressForComponentIngress Creates or updates OAuth proxy ingress for RadixDeploy component ingress -func CreateOrUpdateOAuthProxyIngressForComponentIngress(kubeutil *kube.Kube, namespace string, appName string, component v1.RadixCommonDeployComponent, ingress *networkingv1.Ingress, ingressAnnotationProviders []AnnotationProvider) error { - auxIngress, err := buildOAuthProxyIngressForComponentIngress(appName, ingressAnnotationProviders, component, ingress, namespace) - if err != nil { - return err - } - if auxIngress != nil { - return kubeutil.ApplyIngress(namespace, auxIngress) - } - return nil -} - -func buildOAuthProxyIngressForComponentIngress(appName string, ingressAnnotationProviders []AnnotationProvider, component v1.RadixCommonDeployComponent, componentIngress *networkingv1.Ingress, namespace string) (*networkingv1.Ingress, error) { +// BuildOAuthProxyIngressForComponentIngress builds OAuth proxy ingress for RadixDeploy component ingress +func BuildOAuthProxyIngressForComponentIngress(namespace string, component v1.RadixCommonDeployComponent, componentIngress *networkingv1.Ingress, ingressAnnotationProviders []AnnotationProvider) (*networkingv1.Ingress, error) { if len(componentIngress.Spec.Rules) == 0 { logrus.Debugf("the component ingress %s in the namespace %s has no rules. Do not create an OAuth proxy ingress", componentIngress.GetName(), namespace) return nil, nil @@ -89,7 +77,5 @@ func buildOAuthProxyIngressForComponentIngress(appName string, ingressAnnotation }, }, } - - oauth.MergeAuxComponentResourceLabels(ingress, appName, component) return ingress, nil } diff --git a/pkg/apis/kube/ingress.go b/pkg/apis/kube/ingress.go index d1f3acf06..1bb649c1f 100644 --- a/pkg/apis/kube/ingress.go +++ b/pkg/apis/kube/ingress.go @@ -108,13 +108,10 @@ func (kubeutil *Kube) GetIngressesWithSelector(namespace string, labelSelectorSt } // DeleteIngresses Deletes ingresses -func (kubeutil *Kube) DeleteIngresses(ignoreIsNotFoundError bool, ingresses ...*networkingv1.Ingress) error { +func (kubeutil *Kube) DeleteIngresses(ingresses ...*networkingv1.Ingress) error { + log.Debugf("delete %d Ingress(es)", len(ingresses)) for _, ing := range ingresses { - err := kubeutil.KubeClient().NetworkingV1().Ingresses(ing.Namespace).Delete(context.Background(), ing.Name, metav1.DeleteOptions{}) - if err != nil { - if errors.IsNotFound(err) && ignoreIsNotFoundError { - continue - } + if err := kubeutil.KubeClient().NetworkingV1().Ingresses(ing.Namespace).Delete(context.Background(), ing.Name, metav1.DeleteOptions{}); err != nil && !errors.IsNotFound(err) { return err } } diff --git a/pkg/apis/kube/kube.go b/pkg/apis/kube/kube.go index cab03d973..b31f2be32 100644 --- a/pkg/apis/kube/kube.go +++ b/pkg/apis/kube/kube.go @@ -52,6 +52,7 @@ const ( RadixJobTypeJob = "job" // Outer job RadixJobTypeBuild = "build" RadixJobTypeCloneConfig = "clone-config" + RadixStandardIngressLabel = "radix-standard-ingress" RadixAliasLabel = "radix-alias" RadixJobTypePreparePipelines = "prepare-pipelines" RadixJobTypeRunPipelines = "run-pipelines" diff --git a/pkg/apis/utils/labels/labels.go b/pkg/apis/utils/labels/labels.go index dbfd41993..26fc8fe81 100644 --- a/pkg/apis/utils/labels/labels.go +++ b/pkg/apis/utils/labels/labels.go @@ -1,8 +1,6 @@ package labels import ( - "strconv" - maputils "github.com/equinor/radix-common/utils/maps" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -236,9 +234,31 @@ func ForAuxComponent(appName string, component v1.RadixCommonDeployComponent) ma } } -// ForDNSAlias returns labels for ingress, created for Radix DNS alias -func ForDNSAlias() kubelabels.Set { +// ForAuxComponentIngress returns labels for application component aux OAuth proxy standard ingress +func ForAuxComponentIngress(appName string, component v1.RadixCommonDeployComponent) kubelabels.Set { + return kubelabels.Set{ + kube.RadixAppLabel: appName, + kube.RadixAuxiliaryComponentLabel: component.GetName(), + kube.RadixAuxiliaryComponentTypeLabel: defaults.OAuthProxyAuxiliaryComponentType, + kube.RadixStandardIngressLabel: "true", + } +} + +// ForAuxComponentDNSAliasIngress returns labels for application component aux DNS alias ingress OAuth proxy +func ForAuxComponentDNSAliasIngress(appName string, component v1.RadixCommonDeployComponent, dnsAlias string) kubelabels.Set { return kubelabels.Set{ - kube.RadixAliasLabel: strconv.FormatBool(true), + kube.RadixAppLabel: appName, + kube.RadixAuxiliaryComponentLabel: component.GetName(), + kube.RadixAuxiliaryComponentTypeLabel: defaults.OAuthProxyAuxiliaryComponentType, + kube.RadixAliasLabel: dnsAlias, + } +} + +// ForDNSAliasIngress returns labels for DNS alias ingress +func ForDNSAliasIngress(appName string, componentName, dnsAlias string) kubelabels.Set { + return kubelabels.Set{ + kube.RadixAppLabel: appName, + kube.RadixComponentLabel: componentName, + kube.RadixAliasLabel: dnsAlias, } } diff --git a/pkg/apis/utils/labels/labels_test.go b/pkg/apis/utils/labels/labels_test.go index 62bb9e099..06033ec53 100644 --- a/pkg/apis/utils/labels/labels_test.go +++ b/pkg/apis/utils/labels/labels_test.go @@ -136,9 +136,9 @@ func Test_ForRadixImageTag(t *testing.T) { assert.Equal(t, expected, actual) } -func Test_ForDNSAlias(t *testing.T) { - actual := ForDNSAlias() - expected := kubelabels.Set{kube.RadixAliasLabel: "true"} +func Test_ForDNSAliasIngress(t *testing.T) { + actual := ForDNSAliasIngress("any-app", "any-component", "any-dns-alias") + expected := kubelabels.Set{kube.RadixAppLabel: "any-app", kube.RadixComponentLabel: "any-component", kube.RadixAliasLabel: "any-dns-alias"} assert.Equal(t, expected, actual) } diff --git a/pkg/apis/utils/oauth/oauth.go b/pkg/apis/utils/oauth/oauth.go index 018512319..608b9d006 100644 --- a/pkg/apis/utils/oauth/oauth.go +++ b/pkg/apis/utils/oauth/oauth.go @@ -9,6 +9,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" + networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" ) @@ -37,3 +38,13 @@ func GetAuxAuthProxyIngressName(sourceIngressName string) string { func MergeAuxComponentResourceLabels(object metav1.Object, appName string, component radixv1.RadixCommonDeployComponent) { object.SetLabels(labels.Merge(object.GetLabels(), radixlabels.ForAuxComponent(appName, component))) } + +// MergeAuxComponentIngressResourceLabels Merge labels for ingress and aux OAuth proxy +func MergeAuxComponentIngressResourceLabels(auxIngress *networkingv1.Ingress, appName string, component radixv1.RadixCommonDeployComponent) { + auxIngress.SetLabels(labels.Merge(auxIngress.GetLabels(), radixlabels.ForAuxComponentIngress(appName, component))) +} + +// MergeAuxComponentDNSAliasIngressResourceLabels Merge labels for ingress and aux DNS alias OAuth proxy +func MergeAuxComponentDNSAliasIngressResourceLabels(auxIngress *networkingv1.Ingress, appName string, component radixv1.RadixCommonDeployComponent, dnsAlias string) { + auxIngress.SetLabels(labels.Merge(auxIngress.GetLabels(), radixlabels.ForAuxComponentDNSAliasIngress(appName, component, dnsAlias))) +} diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go index 5d10f8f7f..8c295496e 100644 --- a/radix-operator/dnsalias/controller_test.go +++ b/radix-operator/dnsalias/controller_test.go @@ -10,7 +10,9 @@ import ( dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/radix" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" + radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" "github.com/equinor/radix-operator/radix-operator/common" "github.com/equinor/radix-operator/radix-operator/dnsalias" "github.com/equinor/radix-operator/radix-operator/dnsalias/internal" @@ -89,7 +91,7 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { // Add Ingress with owner reference to RadixDNSAlias should not trigger sync cfg := &dnsalias2.DNSConfig{DNSZone: dnsZone} - ing := buildRadixDNSAliasIngress(alias.GetName(), alias.Spec.Component, int32(8080), cfg) + ing := buildRadixDNSAliasIngress(alias, int32(8080), cfg) ing.SetOwnerReferences([]metav1.OwnerReference{{APIVersion: radix.APIVersion, Kind: radix.KindRadixDNSAlias, Name: aliasName, Controller: pointers.Ptr(true)}}) namespace := utils.GetEnvironmentNamespace(alias.Spec.AppName, alias.Spec.Environment) s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) @@ -123,9 +125,13 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { s.WaitForNotSynced("Sync should be called when deleting RadixDNSAlias") } -func buildRadixDNSAliasIngress(aliasName, component string, port int32, cfg *dnsalias2.DNSConfig) *networkingv1.Ingress { +func buildRadixDNSAliasIngress(dnsAlias *radixv1.RadixDNSAlias, port int32, cfg *dnsalias2.DNSConfig) *networkingv1.Ingress { + aliasName := dnsAlias.GetName() return &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{Name: dnsaliasapi.GetDNSAliasIngressName(aliasName)}, - Spec: ingress.GetIngressSpec(dnsaliasapi.GetDNSAliasHost(aliasName, cfg.DNSZone), component, defaults.TLSSecretName, port), + ObjectMeta: metav1.ObjectMeta{ + Name: dnsaliasapi.GetDNSAliasIngressName(aliasName), + Labels: radixlabels.ForDNSAliasIngress(dnsAlias.Spec.AppName, dnsAlias.Spec.Component, aliasName), + }, + Spec: ingress.GetIngressSpec(dnsaliasapi.GetDNSAliasHost(aliasName, cfg.DNSZone), dnsAlias.Spec.Component, defaults.TLSSecretName, port), } } From fb96a9d92d8f0b01b8a9b5cbf4a185b06768889a Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 12 Dec 2023 11:19:06 +0100 Subject: [PATCH 101/121] Fixed tests --- pkg/apis/dnsalias/syncer_test.go | 16 ++++------------ pkg/apis/test/utils.go | 15 --------------- 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 4b50f89ca..e52697208 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -67,9 +67,7 @@ type testIngress struct { type scenario struct { name string - expectedError string dnsAlias commonTest.DNSAlias - dnsZone string existingIngress map[string]testIngress expectedIngress map[string]testIngress } @@ -96,7 +94,6 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { { name: "created an ingress", dnsAlias: commonTest.DNSAlias{Alias: alias1, Environment: envName1, Component: component1}, - dnsZone: dnsZone1, expectedIngress: map[string]testIngress{ "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: component1Port8080}, }, @@ -104,7 +101,6 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { { name: "created additional ingress for another component", dnsAlias: commonTest.DNSAlias{Alias: alias1, Environment: envName1, Component: component1}, - dnsZone: dnsZone1, existingIngress: map[string]testIngress{ "alias2.custom-alias": {appName: appName1, envName: envName1, alias: alias2, host: dnsalias.GetDNSAliasHost(alias2, dnsZone1), component: component2, port: component1Port8080}, }, @@ -116,7 +112,6 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { { name: "changed port changes port in existing ingress", dnsAlias: commonTest.DNSAlias{Alias: alias1, Environment: envName1, Component: component1}, - dnsZone: dnsZone1, existingIngress: map[string]testIngress{ "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: component2Port9090}, }, @@ -127,7 +122,6 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { { name: "created additional ingress on another alias for the same component", dnsAlias: commonTest.DNSAlias{Alias: alias2, Environment: envName1, Component: component1}, - dnsZone: dnsZone1, existingIngress: map[string]testIngress{ "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: component1Port8080}, }, @@ -139,7 +133,6 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { { name: "manually changed port repaired", dnsAlias: commonTest.DNSAlias{Alias: alias1, Environment: envName1, Component: component1}, - dnsZone: dnsZone1, existingIngress: map[string]testIngress{ "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: dnsalias.GetDNSAliasHost(alias1, dnsZone1), component: component1, port: component2Port9090}, }, @@ -150,7 +143,6 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { { name: "manually changed host repaired", dnsAlias: commonTest.DNSAlias{Alias: alias1, Environment: envName1, Component: component1}, - dnsZone: dnsZone1, existingIngress: map[string]testIngress{ "alias1.custom-alias": {appName: appName1, envName: envName1, alias: alias1, host: "/manually/edited/host", component: component1, port: component1Port8080}, }, @@ -172,14 +164,14 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { syncer := s.createSyncer(radixDNSAlias) err = syncer.OnSync() - commonTest.AssertError(s.T(), ts.expectedError, err) + s.Assert().NoError(err) ingresses, err := s.getIngressesForAnyAliases(utils.GetEnvironmentNamespace(appName1, ts.dnsAlias.Environment)) - s.Require().NoError(err) + s.Assert().NoError(err) // assert ingresses if ts.expectedIngress == nil { - s.Require().Len(ingresses.Items, 0, "not expected ingresses") + s.Assert().Len(ingresses.Items, 0, "not expected ingresses") return } @@ -188,7 +180,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { for _, ing := range ingresses.Items { appNameLabel := ing.GetLabels()[kube.RadixAppLabel] componentNameLabel := ing.GetLabels()[kube.RadixComponentLabel] - s.Require().Len(ing.Spec.Rules, 1, "rules count") + s.Assert().Len(ing.Spec.Rules, 1, "rules count") rule := ing.Spec.Rules[0] expectedIngress, ingressExists := ts.expectedIngress[ing.Name] assert.True(t, ingressExists, "found not expected ingress %s for: appName %s, host %s, service %s, port %d", diff --git a/pkg/apis/test/utils.go b/pkg/apis/test/utils.go index 49ff401a8..06eb97ca2 100644 --- a/pkg/apis/test/utils.go +++ b/pkg/apis/test/utils.go @@ -3,7 +3,6 @@ package test import ( "context" "os" - "testing" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" @@ -12,7 +11,6 @@ import ( "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" log "github.com/sirupsen/logrus" - "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -400,19 +398,6 @@ func GetAzureKeyVaultTypeSecrets(secrets *corev1.SecretList) *corev1.SecretList return &corev1.SecretList{Items: azureKeyVaultSecrets} } -func AssertError(t *testing.T, expectedError string, err error) { - switch { - case len(expectedError) > 0 && err == nil: - t.Errorf("missing expected OnSync() error %s", expectedError) - return - case len(expectedError) == 0 && err != nil: - t.Errorf("unexpected OnSync() error = %v", err) - return - case len(expectedError) > 0 && err != nil: - require.Equal(t, expectedError, err.Error()) - } -} - // RegisterRadixDNSAliases Register RadixDNSAliases func RegisterRadixDNSAliases(radixClient radixclient.Interface, radixDNSAliasesMap map[string]DNSAlias) error { if radixDNSAliasesMap == nil { From 911f68b1106d475a8c05654fb0b2d97b39617ea7 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 12 Dec 2023 12:22:35 +0100 Subject: [PATCH 102/121] Fixed deleted dnsalias logic, method moved to radix-api --- pkg/apis/applicationconfig/imagehubsecret.go | 28 ++++++++++---------- pkg/apis/environment/environment.go | 21 +++++---------- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/pkg/apis/applicationconfig/imagehubsecret.go b/pkg/apis/applicationconfig/imagehubsecret.go index 4ab46ef17..04e5b66b7 100644 --- a/pkg/apis/applicationconfig/imagehubsecret.go +++ b/pkg/apis/applicationconfig/imagehubsecret.go @@ -35,7 +35,7 @@ func UpdatePrivateImageHubsSecretsPassword(kubeutil *kube.Kube, appName, server, return fmt.Errorf("private image hub secret does not exist for app %s", appName) } - imageHubs, err := getImageHubSecretValue(secret.Data[corev1.DockerConfigJsonKey]) + imageHubs, err := GetImageHubSecretValue(secret.Data[corev1.DockerConfigJsonKey]) if err != nil { return err } @@ -43,11 +43,11 @@ func UpdatePrivateImageHubsSecretsPassword(kubeutil *kube.Kube, appName, server, if config, ok := imageHubs[server]; ok { config.Password = password imageHubs[server] = config - secretValue, err := getImageHubsSecretValue(imageHubs) + secretValue, err := GetImageHubsSecretValue(imageHubs) if err != nil { return err } - return applyPrivateImageHubSecret(kubeutil, ns, appName, secretValue) + return ApplyPrivateImageHubSecret(kubeutil, ns, appName, secretValue) } return fmt.Errorf("private image hub secret does not contain config for server %s", server) } @@ -61,7 +61,7 @@ func GetPendingPrivateImageHubSecrets(kubeUtil *kube.Kube, appName string) ([]st return nil, err } - imageHubs, err := getImageHubSecretValue(secret.Data[corev1.DockerConfigJsonKey]) + imageHubs, err := GetImageHubSecretValue(secret.Data[corev1.DockerConfigJsonKey]) if err != nil { return nil, err } @@ -91,7 +91,7 @@ func (app *ApplicationConfig) syncPrivateImageHubSecrets() error { } } else { // update if changes - imageHubs, err := getImageHubSecretValue(secret.Data[corev1.DockerConfigJsonKey]) + imageHubs, err := GetImageHubSecretValue(secret.Data[corev1.DockerConfigJsonKey]) if err != nil { log.Warnf("failed to get private image hub secret value %v", err) return err @@ -120,13 +120,13 @@ func (app *ApplicationConfig) syncPrivateImageHubSecrets() error { } } - secretValue, err = getImageHubsSecretValue(imageHubs) + secretValue, err = GetImageHubsSecretValue(imageHubs) if err != nil { log.Warnf("failed to update private image hub secret %v", err) return err } } - err = applyPrivateImageHubSecret(app.kubeutil, namespace, app.config.Name, secretValue) + err = ApplyPrivateImageHubSecret(app.kubeutil, namespace, app.config.Name, secretValue) if err != nil { return nil } @@ -146,8 +146,8 @@ func (app *ApplicationConfig) syncPrivateImageHubSecrets() error { return nil } -// applyPrivateImageHubSecret create a private image hub secret based on SecretTypeDockerConfigJson -func applyPrivateImageHubSecret(kubeutil *kube.Kube, ns, appName string, secretValue []byte) error { +// ApplyPrivateImageHubSecret create a private image hub secret based on SecretTypeDockerConfigJson +func ApplyPrivateImageHubSecret(kubeutil *kube.Kube, ns, appName string, secretValue []byte) error { secret := corev1.Secret{ Type: corev1.SecretTypeDockerConfigJson, ObjectMeta: metav1.ObjectMeta{ @@ -174,8 +174,8 @@ func applyPrivateImageHubSecret(kubeutil *kube.Kube, ns, appName string, secretV return nil } -// getImageHubSecretValue gets imagehub secret value -func getImageHubSecretValue(value []byte) (docker.Auths, error) { +// GetImageHubSecretValue gets imagehub secret value +func GetImageHubSecretValue(value []byte) (docker.Auths, error) { secretValue := docker.AuthConfig{} err := json.Unmarshal(value, &secretValue) if err != nil { @@ -198,11 +198,11 @@ func createImageHubsSecretValue(imagehubs v1.PrivateImageHubEntries) ([]byte, er } imageHubs[server] = imageHub } - return getImageHubsSecretValue(imageHubs) + return GetImageHubsSecretValue(imageHubs) } -// getImageHubsSecretValue turn SecretImageHubs into a correctly formated secret for k8s ImagePullSecrets -func getImageHubsSecretValue(imageHubs docker.Auths) ([]byte, error) { +// GetImageHubsSecretValue turn SecretImageHubs into a correctly formated secret for k8s ImagePullSecrets +func GetImageHubsSecretValue(imageHubs docker.Auths) ([]byte, error) { for server, config := range imageHubs { config.Auth = encodeAuthField(config.Username, config.Password) imageHubs[server] = config diff --git a/pkg/apis/environment/environment.go b/pkg/apis/environment/environment.go index af11e2b3a..931f0bc03 100644 --- a/pkg/apis/environment/environment.go +++ b/pkg/apis/environment/environment.go @@ -61,8 +61,8 @@ func NewEnvironment( func (env *Environment) OnSync(time metav1.Time) error { re := env.config - if handled, err := env.handleDeletedRadixEnvironment(re); handled || err != nil { - return err + if re.ObjectMeta.DeletionTimestamp != nil { + return env.handleDeletedRadixEnvironment(re) } if env.regConfig == nil { @@ -105,10 +105,7 @@ func (env *Environment) OnSync(time metav1.Time) error { return nil } -func (env *Environment) handleDeletedRadixEnvironment(re *v1.RadixEnvironment) (bool, error) { - if re.ObjectMeta.DeletionTimestamp == nil { - return false, nil - } +func (env *Environment) handleDeletedRadixEnvironment(re *v1.RadixEnvironment) error { logrus.Debugf("handle deleted RadixEnvironment %s in the application %s", re.Name, re.Spec.AppName) finalizerIndex := slice.FindIndex(re.ObjectMeta.Finalizers, func(val string) bool { return val == kube.RadixEnvironmentFinalizer @@ -116,20 +113,16 @@ func (env *Environment) handleDeletedRadixEnvironment(re *v1.RadixEnvironment) ( if finalizerIndex < 0 { logrus.Infof("missing finalizer %s in the Radix environment %s in the application %s. Exist finalizers: %d. Skip dependency handling", kube.RadixEnvironmentFinalizer, re.Name, re.Spec.AppName, len(re.ObjectMeta.Finalizers)) - return false, nil + return nil } - err := env.handleDeletedRadixEnvironmentDependencies(re) - if err != nil { - return true, err + if err := env.handleDeletedRadixEnvironmentDependencies(re); err != nil { + return err } updatingRE := re.DeepCopy() updatingRE.ObjectMeta.Finalizers = append(re.ObjectMeta.Finalizers[:finalizerIndex], re.ObjectMeta.Finalizers[finalizerIndex+1:]...) logrus.Debugf("removed finalizer %s from the Radix environment %s in the application %s. Left finalizers: %d", kube.RadixEnvironmentFinalizer, updatingRE.Name, updatingRE.Spec.AppName, len(updatingRE.ObjectMeta.Finalizers)) - if err = env.kubeutil.UpdateRadixEnvironment(updatingRE); err != nil { - return false, err - } - return true, nil + return env.kubeutil.UpdateRadixEnvironment(updatingRE) } func (env *Environment) handleDeletedRadixEnvironmentDependencies(re *v1.RadixEnvironment) error { From 299a6c79984a72f5a4913e94c9ff6668fb5badd4 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 12 Dec 2023 13:24:22 +0100 Subject: [PATCH 103/121] Removed GetIngresses methods, Changed log-level method --- .../applicationconfig_test.go | 37 --------------- pkg/apis/applicationconfig/imagehubsecret.go | 22 --------- pkg/apis/config/config.go | 12 +---- pkg/apis/dnsalias/ingress.go | 5 +- pkg/apis/dnsalias/syncer.go | 6 ++- pkg/apis/kube/ingress.go | 14 ++---- radix-operator/config/config.go | 12 ++--- radix-operator/main.go | 46 +++++-------------- 8 files changed, 31 insertions(+), 123 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index cb718ee94..887ac1976 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -468,29 +468,6 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_Added(t *testing.T) { assert.Equal(t, "radix-private-image-hubs-sync=any-app", secret.ObjectMeta.Annotations["kubed.appscode.com/sync"]) } -func Test_WithPrivateImageHubSet_SecretsCorrectly_SetPassword(t *testing.T) { - client, _, kubeUtil := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ - "privaterepodeleteme.azurecr.io": &radixv1.RadixPrivateImageHubCredential{ - Username: "814607e6-3d71-44a7-8476-50e8b281abbc", - Email: "radix@equinor.com", - }, - }) - pendingSecrets, _ := applicationconfig.GetPendingPrivateImageHubSecrets(kubeUtil, "any-app") - - assert.Equal(t, "privaterepodeleteme.azurecr.io", pendingSecrets[0]) - - if err := applicationconfig.UpdatePrivateImageHubsSecretsPassword(kubeUtil, "any-app", "privaterepodeleteme.azurecr.io", "a-password"); err != nil { - require.NoError(t, err) - } - secret, _ := client.CoreV1().Secrets("any-app-app").Get(context.TODO(), defaults.PrivateImageHubSecretName, metav1.GetOptions{}) - pendingSecrets, _ = applicationconfig.GetPendingPrivateImageHubSecrets(kubeUtil, "any-app") - - assert.Equal(t, - "{\"auths\":{\"privaterepodeleteme.azurecr.io\":{\"username\":\"814607e6-3d71-44a7-8476-50e8b281abbc\",\"password\":\"a-password\",\"email\":\"radix@equinor.com\",\"auth\":\"ODE0NjA3ZTYtM2Q3MS00NGE3LTg0NzYtNTBlOGIyODFhYmJjOmEtcGFzc3dvcmQ=\"}}}", - string(secret.Data[corev1.DockerConfigJsonKey])) - assert.Equal(t, 0, len(pendingSecrets)) -} - func Test_WithPrivateImageHubSet_SecretsCorrectly_UpdatedNewAdded(t *testing.T) { applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{ "privaterepodeleteme.azurecr.io": &radixv1.RadixPrivateImageHubCredential{ @@ -590,20 +567,6 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_Delete(t *testing.T) { string(secret.Data[corev1.DockerConfigJsonKey])) } -func Test_WithPrivateImageHubSet_SecretsCorrectly_NoImageHubs(t *testing.T) { - client, _, kubeUtil := applyRadixAppWithPrivateImageHub(radixv1.PrivateImageHubEntries{}) - pendingSecrets, _ := applicationconfig.GetPendingPrivateImageHubSecrets(kubeUtil, "any-app") - - secret, _ := client.CoreV1().Secrets("any-app-app").Get(context.TODO(), defaults.PrivateImageHubSecretName, metav1.GetOptions{}) - - assert.NotNil(t, secret) - assert.Equal(t, - "{\"auths\":{}}", - string(secret.Data[corev1.DockerConfigJsonKey])) - assert.Equal(t, 0, len(pendingSecrets)) - assert.Error(t, applicationconfig.UpdatePrivateImageHubsSecretsPassword(kubeUtil, "any-app", "privaterepodeleteme.azurecr.io", "a-password")) -} - func Test_RadixEnvironment(t *testing.T) { tu, client, kubeUtil, radixClient := setupTest() diff --git a/pkg/apis/applicationconfig/imagehubsecret.go b/pkg/apis/applicationconfig/imagehubsecret.go index 04e5b66b7..6202e06fa 100644 --- a/pkg/apis/applicationconfig/imagehubsecret.go +++ b/pkg/apis/applicationconfig/imagehubsecret.go @@ -52,28 +52,6 @@ func UpdatePrivateImageHubsSecretsPassword(kubeutil *kube.Kube, appName, server, return fmt.Errorf("private image hub secret does not contain config for server %s", server) } -// GetPendingPrivateImageHubSecrets returns a list of private image hubs where secret value is not set -func GetPendingPrivateImageHubSecrets(kubeUtil *kube.Kube, appName string) ([]string, error) { - pendingSecrets := []string{} - ns := utils.GetAppNamespace(appName) - secret, err := kubeUtil.GetSecret(ns, defaults.PrivateImageHubSecretName) - if err != nil && !errors.IsNotFound(err) { - return nil, err - } - - imageHubs, err := GetImageHubSecretValue(secret.Data[corev1.DockerConfigJsonKey]) - if err != nil { - return nil, err - } - - for key, imageHub := range imageHubs { - if imageHub.Password == "" { - pendingSecrets = append(pendingSecrets, key) - } - } - return pendingSecrets, nil -} - func (app *ApplicationConfig) syncPrivateImageHubSecrets() error { namespace := utils.GetAppNamespace(app.config.Name) secret, err := app.kubeutil.GetSecret(namespace, defaults.PrivateImageHubSecretName) diff --git a/pkg/apis/config/config.go b/pkg/apis/config/config.go index 5bda72a92..1680e6dc5 100644 --- a/pkg/apis/config/config.go +++ b/pkg/apis/config/config.go @@ -3,20 +3,12 @@ package config import ( "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/config/pipelinejob" -) - -type LogLevel string - -const ( - LogLevelError LogLevel = "ERROR" - LogLevelInfo LogLevel = "INFO" - LogLevelWarning LogLevel = "WARNING" - LogLevelDebug LogLevel = "DEBUG" + log "github.com/sirupsen/logrus" ) // Config from environment variables type Config struct { - LogLevel LogLevel + LogLevel log.Level DNSConfig *dnsalias.DNSConfig PipelineJobConfig *pipelinejob.Config } diff --git a/pkg/apis/dnsalias/ingress.go b/pkg/apis/dnsalias/ingress.go index 344ce6bed..9eba31de3 100644 --- a/pkg/apis/dnsalias/ingress.go +++ b/pkg/apis/dnsalias/ingress.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/ingress" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -90,9 +91,9 @@ func (s *syncer) syncOAuthProxyIngress(deployComponent radixv1.RadixCommonDeploy } func (s *syncer) deleteOAuthAuxIngresses(deployComponent radixv1.RadixCommonDeployComponent, namespace string, appName string) error { - oauthAuxIngresses, err := s.kubeUtil.GetIngressesWithSelector(namespace, radixlabels.ForAuxComponentDNSAliasIngress(appName, deployComponent, s.radixDNSAlias.GetName()).String()) + oauthAuxIngresses, err := s.kubeUtil.KubeClient().NetworkingV1().Ingresses(namespace).List(context.Background(), metav1.ListOptions{LabelSelector: radixlabels.ForAuxComponentDNSAliasIngress(appName, deployComponent, s.radixDNSAlias.GetName()).String()}) if err != nil { return err } - return s.kubeUtil.DeleteIngresses(oauthAuxIngresses...) + return s.kubeUtil.DeleteIngresses(slice.PointersOf(oauthAuxIngresses.Items).([]*networkingv1.Ingress)...) } diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 70957bed9..2a4f16f1a 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -1,6 +1,7 @@ package dnsalias import ( + "context" "fmt" "regexp" @@ -19,6 +20,7 @@ import ( radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" log "github.com/sirupsen/logrus" networkingv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" ) @@ -158,11 +160,11 @@ func (s *syncer) deletedIngressesForRadixDNSAlias() error { aliasSpec := s.radixDNSAlias.Spec namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) dnsAliasIngressesSelector := radixlabels.ForDNSAliasIngress(aliasSpec.AppName, aliasSpec.Component, s.radixDNSAlias.GetName()).String() - ingresses, err := s.kubeUtil.GetIngressesWithSelector(namespace, dnsAliasIngressesSelector) + ingresses, err := s.kubeUtil.KubeClient().NetworkingV1().Ingresses(namespace).List(context.Background(), metav1.ListOptions{LabelSelector: dnsAliasIngressesSelector}) if err != nil { return err } - return s.kubeUtil.DeleteIngresses(ingresses...) + return s.kubeUtil.DeleteIngresses(slice.PointersOf(ingresses.Items).([]*networkingv1.Ingress)...) } func buildIngress(radixDeployComponent radixv1.RadixCommonDeployComponent, radixDNSAlias *radixv1.RadixDNSAlias, dnsConfig *dnsalias.DNSConfig, oauth2Config defaults.OAuth2Config, ingressConfiguration ingress.IngressConfiguration) (*networkingv1.Ingress, error) { diff --git a/pkg/apis/kube/ingress.go b/pkg/apis/kube/ingress.go index 1bb649c1f..abb330803 100644 --- a/pkg/apis/kube/ingress.go +++ b/pkg/apis/kube/ingress.go @@ -86,7 +86,11 @@ func (kubeutil *Kube) ListIngresses(namespace string) ([]*networkingv1.Ingress, // ListIngressesWithSelector lists ingresses func (kubeutil *Kube) ListIngressesWithSelector(namespace string, labelSelectorString string) ([]*networkingv1.Ingress, error) { if kubeutil.IngressLister == nil { - return kubeutil.GetIngressesWithSelector(namespace, labelSelectorString) + list, err := kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).List(context.Background(), metav1.ListOptions{LabelSelector: labelSelectorString}) + if err != nil { + return nil, err + } + return slice.PointersOf(list.Items).([]*networkingv1.Ingress), nil } selector, err := labels.Parse(labelSelectorString) if err != nil { @@ -99,14 +103,6 @@ func (kubeutil *Kube) ListIngressesWithSelector(namespace string, labelSelectorS return ingresses, nil } -func (kubeutil *Kube) GetIngressesWithSelector(namespace string, labelSelectorString string) ([]*networkingv1.Ingress, error) { - list, err := kubeutil.kubeClient.NetworkingV1().Ingresses(namespace).List(context.Background(), metav1.ListOptions{LabelSelector: labelSelectorString}) - if err != nil { - return nil, err - } - return slice.PointersOf(list.Items).([]*networkingv1.Ingress), nil -} - // DeleteIngresses Deletes ingresses func (kubeutil *Kube) DeleteIngresses(ingresses ...*networkingv1.Ingress) error { log.Debugf("delete %d Ingress(es)", len(ingresses)) diff --git a/radix-operator/config/config.go b/radix-operator/config/config.go index bc76624f5..0e6f41277 100644 --- a/radix-operator/config/config.go +++ b/radix-operator/config/config.go @@ -9,17 +9,17 @@ import ( "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/config/pipelinejob" "github.com/equinor/radix-operator/pkg/apis/defaults" + log "github.com/sirupsen/logrus" "github.com/spf13/viper" ) -var logLevels = map[string]bool{string(apiconfig.LogLevelInfo): true, string(apiconfig.LogLevelWarning): true, string(apiconfig.LogLevelDebug): true, string(apiconfig.LogLevelError): true} - -func getLogLevel() apiconfig.LogLevel { +func getLogLevel() log.Level { logLevel := viper.GetString(defaults.LogLevel) - if _, ok := logLevels[logLevel]; ok { - return apiconfig.LogLevel(logLevel) + level, err := log.ParseLevel(logLevel) + if err != nil { + return log.InfoLevel } - return apiconfig.LogLevelInfo + return level } // Gets pipeline job history limit per each list, grouped by pipeline branch and job status diff --git a/radix-operator/main.go b/radix-operator/main.go index c1d738c11..e5d5b2faa 100644 --- a/radix-operator/main.go +++ b/radix-operator/main.go @@ -17,7 +17,6 @@ import ( "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/utils" - radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" radixinformers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" "github.com/equinor/radix-operator/radix-operator/alert" "github.com/equinor/radix-operator/radix-operator/application" @@ -35,11 +34,9 @@ import ( "gopkg.in/yaml.v3" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubeinformers "k8s.io/client-go/informers" - "k8s.io/client-go/kubernetes" _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/client-go/tools/record" "k8s.io/client-go/util/flowcontrol" - secretproviderclient "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned" ) const ( @@ -52,7 +49,7 @@ var logger *log.Entry func main() { logger = log.WithFields(log.Fields{"radixOperatorComponent": "main"}) cfg := config.NewConfig() - setLogLevel(cfg.LogLevel) + log.SetLevel(cfg.LogLevel) registrationControllerThreads, applicationControllerThreads, environmentControllerThreads, deploymentControllerThreads, jobControllerThreads, alertControllerThreads, kubeClientRateLimitBurst, kubeClientRateLimitQPS, err := getInitParams() if err != nil { @@ -92,7 +89,7 @@ func main() { startController(createDeploymentController(kubeUtil, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder, oauthDefaultConfig, ingressConfiguration), deploymentControllerThreads, stop) startController(createJobController(kubeUtil, kubeInformerFactory, radixInformerFactory, eventRecorder, cfg), jobControllerThreads, stop) startController(createAlertController(kubeUtil, prometheusOperatorClient, kubeInformerFactory, radixInformerFactory, eventRecorder), alertControllerThreads, stop) - startController(createBatchController(kubeUtil, client, radixClient, kubeInformerFactory, radixInformerFactory, eventRecorder, secretProviderClient), 1, stop) + startController(createBatchController(kubeUtil, kubeInformerFactory, radixInformerFactory, eventRecorder), 1, stop) startController(createDNSAliasesController(kubeUtil, kubeInformerFactory, radixInformerFactory, eventRecorder, oauthDefaultConfig, ingressConfiguration, cfg.DNSConfig), environmentControllerThreads, stop) // Start informers when all controllers are running @@ -142,14 +139,13 @@ func createRegistrationController(kubeUtil *kube.Kube, kubeInformerFactory kubei func(syncedOk bool) {}, // Not interested in getting notifications of synced ) - const waitForChildrenToSync = true return registration.NewController( kubeUtil.KubeClient(), kubeUtil.RadixClient(), &handler, kubeInformerFactory, radixInformerFactory, - waitForChildrenToSync, + true, recorder) } @@ -162,14 +158,13 @@ func createApplicationController(kubeUtil *kube.Kube, kubeInformerFactory kubein func(syncedOk bool) {}, // Not interested in getting notifications of synced ) - const waitForChildrenToSync = true return application.NewController( kubeUtil.KubeClient(), kubeUtil.RadixClient(), &handler, kubeInformerFactory, radixInformerFactory, - waitForChildrenToSync, + true, recorder) } @@ -181,14 +176,13 @@ func createEnvironmentController(kubeUtil *kube.Kube, kubeInformerFactory kubein func(syncedOk bool) {}, // Not interested in getting notifications of synced ) - const waitForChildrenToSync = true return environment.NewController( kubeUtil.KubeClient(), kubeUtil.RadixClient(), &handler, kubeInformerFactory, radixInformerFactory, - waitForChildrenToSync, + true, recorder) } @@ -207,14 +201,13 @@ func createDNSAliasesController(kubeUtil *kube.Kube, dnsalias.WithOAuth2DefaultConfig(oauthDefaultConfig), ) - const waitForChildrenToSync = true return dnsalias.NewController( kubeUtil.KubeClient(), kubeUtil.RadixClient(), handler, kubeInformerFactory, radixInformerFactory, - waitForChildrenToSync, + true, recorder) } @@ -239,14 +232,13 @@ func createDeploymentController(kubeUtil *kube.Kube, prometheusOperatorClient mo deployment.WithOAuth2ProxyDockerImage(oauth2DockerImage), ) - const waitForChildrenToSync = true return deployment.NewController( kubeUtil.KubeClient(), kubeUtil.RadixClient(), handler, kubeInformerFactory, radixInformerFactory, - waitForChildrenToSync, + true, recorder) } @@ -258,11 +250,10 @@ func createJobController(kubeUtil *kube.Kube, kubeInformerFactory kubeinformers. config, func(syncedOk bool) {}) // Not interested in getting notifications of synced - const waitForChildrenToSync = true return job.NewController( kubeUtil.KubeClient(), kubeUtil.RadixClient(), - &handler, kubeInformerFactory, radixInformerFactory, waitForChildrenToSync, recorder) + &handler, kubeInformerFactory, radixInformerFactory, true, recorder) } func createAlertController(kubeUtil *kube.Kube, prometheusOperatorClient monitoring.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder) *common.Controller { @@ -273,32 +264,30 @@ func createAlertController(kubeUtil *kube.Kube, prometheusOperatorClient monitor prometheusOperatorClient, ) - const waitForChildrenToSync = true return alert.NewController( kubeUtil.KubeClient(), kubeUtil.RadixClient(), handler, kubeInformerFactory, radixInformerFactory, - waitForChildrenToSync, + true, recorder) } -func createBatchController(kubeUtil *kube.Kube, client kubernetes.Interface, radixClient radixclient.Interface, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder, secretProviderClient secretproviderclient.Interface) *common.Controller { +func createBatchController(kubeUtil *kube.Kube, kubeInformerFactory kubeinformers.SharedInformerFactory, radixInformerFactory radixinformers.SharedInformerFactory, recorder record.EventRecorder) *common.Controller { handler := batch.NewHandler( kubeUtil.KubeClient(), kubeUtil, kubeUtil.RadixClient(), ) - const waitForChildrenToSync = true return batch.NewController( kubeUtil.KubeClient(), kubeUtil.RadixClient(), handler, kubeInformerFactory, radixInformerFactory, - waitForChildrenToSync, + true, recorder) } @@ -354,16 +343,3 @@ func Healthz(writer http.ResponseWriter, _ *http.Request) { _, _ = fmt.Fprintf(writer, "%s", response) } - -func setLogLevel(logLevel apiconfig.LogLevel) { - switch logLevel { - case apiconfig.LogLevelDebug: - log.SetLevel(log.DebugLevel) - case apiconfig.LogLevelWarning: - log.SetLevel(log.WarnLevel) - case apiconfig.LogLevelError: - log.SetLevel(log.ErrorLevel) - default: - log.SetLevel(log.InfoLevel) - } -} From 97a178a5908526510aa63db28af08c4a289fc38e Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 12 Dec 2023 13:42:36 +0100 Subject: [PATCH 104/121] Corrected logic for DNSAlias deletion --- pkg/apis/dnsalias/syncer.go | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 2a4f16f1a..bf4d45c57 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -66,8 +66,8 @@ func (s *syncer) OnSync() error { if err := s.restoreStatus(); err != nil { return fmt.Errorf("failed to update status on DNS alias %s: %v", s.radixDNSAlias.GetName(), err) } - if handled, err := s.handleDeletedRadixDNSAlias(); handled || err != nil { - return err + if s.radixDNSAlias.ObjectMeta.DeletionTimestamp != nil { + return s.syncStatus(s.handleDeletedRadixDNSAlias()) } return s.syncStatus(s.syncAlias()) @@ -126,11 +126,7 @@ func (s *syncer) getRadixDeployComponent() (radixv1.RadixCommonDeployComponent, return deployComponent, nil } -func (s *syncer) handleDeletedRadixDNSAlias() (bool, error) { - if s.radixDNSAlias.ObjectMeta.DeletionTimestamp == nil { - return false, nil - } - +func (s *syncer) handleDeletedRadixDNSAlias() error { log.Debugf("handle deleted RadixDNSAlias %s in the application %s", s.radixDNSAlias.Name, s.radixDNSAlias.Spec.AppName) finalizerIndex := slice.FindIndex(s.radixDNSAlias.ObjectMeta.Finalizers, func(val string) bool { return val == kube.RadixDNSAliasFinalizer @@ -138,11 +134,11 @@ func (s *syncer) handleDeletedRadixDNSAlias() (bool, error) { if finalizerIndex < 0 { log.Infof("missing finalizer %s in the RadixDNSAlias %s. Exist finalizers: %d. Skip dependency handling", kube.RadixDNSAliasFinalizer, s.radixDNSAlias.Name, len(s.radixDNSAlias.ObjectMeta.Finalizers)) - return false, nil + return nil } if err := s.deletedIngressesForRadixDNSAlias(); err != nil { - return true, err + return err } updatingAlias := s.radixDNSAlias.DeepCopy() @@ -150,10 +146,7 @@ func (s *syncer) handleDeletedRadixDNSAlias() (bool, error) { log.Debugf("removed finalizer %s from the RadixDNSAlias %s for the application %s. Left finalizers: %d", kube.RadixEnvironmentFinalizer, updatingAlias.Name, updatingAlias.Spec.AppName, len(updatingAlias.ObjectMeta.Finalizers)) - if err := s.kubeUtil.UpdateRadixDNSAlias(updatingAlias); err != nil { - return false, err - } - return true, nil + return s.kubeUtil.UpdateRadixDNSAlias(updatingAlias) } func (s *syncer) deletedIngressesForRadixDNSAlias() error { From e7e157a4765a66a0e65fc2c5a6249797f36909a3 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 12 Dec 2023 14:01:51 +0100 Subject: [PATCH 105/121] Cleaned linter reported issues --- pkg/apis/deployment/deployment_test.go | 169 +++++++++++++++---------- 1 file changed, 102 insertions(+), 67 deletions(-) diff --git a/pkg/apis/deployment/deployment_test.go b/pkg/apis/deployment/deployment_test.go index 1c09c2b54..40157bb28 100644 --- a/pkg/apis/deployment/deployment_test.go +++ b/pkg/apis/deployment/deployment_test.go @@ -834,12 +834,11 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { // Test t.Run("app with component use default SA", func(t *testing.T) { tu, client, kubeUtil, radixclient, prometheusclient, _ := setupTest() - if _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithJobComponents(). WithAppName("any-other-app"). - WithEnvironment("test")); err != nil { - require.NoError(t, err) - } + WithEnvironment("test")) + require.NoError(t, err) serviceAccounts, _ := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace("any-other-app", "test")).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 0, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -854,7 +853,7 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { appName, envName, componentName, clientId, newClientId := "any-app", "any-env", "any-component", "any-client-id", "new-client-id" // Deploy component with Azure identity must create custom SA - if _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( utils.NewDeployComponentBuilder(). WithName(componentName). @@ -862,9 +861,8 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { ). WithJobComponents(). WithAppName(appName). - WithEnvironment(envName)); err != nil { - require.NoError(t, err) - } + WithEnvironment(envName)) + require.NoError(t, err) serviceAccounts, _ := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 1, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -880,7 +878,7 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { assert.Equal(t, "true", expectedDeployments[0].Spec.Template.Labels["azure.workload.identity/use"]) // Deploy component with new Azure identity must update SA - if _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( utils.NewDeployComponentBuilder(). WithName(componentName). @@ -888,9 +886,8 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { ). WithJobComponents(). WithAppName(appName). - WithEnvironment(envName)); err != nil { - require.NoError(t, err) - } + WithEnvironment(envName)) + require.NoError(t, err) serviceAccounts, _ = client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 1, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -905,14 +902,13 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { assert.Equal(t, utils.GetComponentServiceAccountName(componentName), expectedDeployments[0].Spec.Template.Spec.ServiceAccountName) assert.Equal(t, "true", expectedDeployments[0].Spec.Template.Labels["azure.workload.identity/use"]) - // Redploy component without Azure identity should delete custom SA - if _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + // Re-deploy component without Azure identity should delete custom SA + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents(utils.NewDeployComponentBuilder().WithName(componentName)). WithJobComponents(). WithAppName(appName). - WithEnvironment(envName)); err != nil { - require.NoError(t, err) - } + WithEnvironment(envName)) + require.NoError(t, err) serviceAccounts, _ = client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 0, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -990,7 +986,7 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { } // Deploy component with Azure identity must create custom SA - if _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( utils.NewDeployComponentBuilder(). WithName(componentName). @@ -1001,9 +997,8 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { ). WithJobComponents(). WithAppName(appName). - WithEnvironment(envName)); err != nil { - require.NoError(t, err) - } + WithEnvironment(envName)) + require.NoError(t, err) serviceAccounts, err := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) if err != nil { @@ -1011,8 +1006,8 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { } assert.Equal(t, 3, len(serviceAccounts.Items), "Number of service accounts was not expected") - // Redploy component without Azure identity should delete custom SA - if _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + // Re-deploy component without Azure identity should delete custom SA + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( utils.NewDeployComponentBuilder(). WithName(componentName). @@ -1020,9 +1015,8 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { ). WithJobComponents(). WithAppName(appName). - WithEnvironment(envName)); err != nil { - require.NoError(t, err) - } + WithEnvironment(envName)) + require.NoError(t, err) serviceAccounts, _ = client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 2, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -1032,10 +1026,11 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { t.Run("app with job use radix-job-scheduler SA", func(t *testing.T) { tu, client, kubeUtil, radixclient, prometheusclient, _ := setupTest() - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents(). WithAppName("any-other-app"). WithEnvironment("test")) + require.NoError(t, err) serviceAccounts, _ := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace("any-other-app", "test")).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 1, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -1051,12 +1046,13 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { tu, client, kubeUtil, radixclient, prometheusclient, _ := setupTest() // Initial deployment, app is a component - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( utils.NewDeployComponentBuilder().WithName("comp1")). WithJobComponents(). WithAppName("any-other-app"). WithEnvironment("test")) + require.NoError(t, err) serviceAccounts, _ := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace("any-other-app", "test")).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 0, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -1066,12 +1062,13 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { assert.Equal(t, defaultServiceAccountName, expectedDeployments[0].Spec.Template.Spec.ServiceAccountName) // Change app to be a job - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents(). WithJobComponents( utils.NewDeployJobComponentBuilder().WithName("job1")). WithAppName("any-other-app"). WithEnvironment("test")) + require.NoError(t, err) serviceAccounts, _ = client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace("any-other-app", "test")).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 1, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -1087,12 +1084,13 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { assert.Equal(t, defaultServiceAccountName, expectedJobAuxDeployments[0].Spec.Template.Spec.ServiceAccountName) // And change app back to a component - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( utils.NewDeployComponentBuilder().WithName("comp1")). WithJobComponents(). WithAppName("any-other-app"). WithEnvironment("test")) + require.NoError(t, err) serviceAccounts, _ = client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace("any-other-app", "test")).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 1, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -1105,10 +1103,11 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { t.Run("webhook runs as radix-github-webhook SA", func(t *testing.T) { tu, client, kubeUtil, radixclient, prometheusclient, _ := setupTest() - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithJobComponents(). WithAppName("radix-github-webhook"). WithEnvironment("test")) + require.NoError(t, err) serviceAccounts, _ := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace("radix-github-webhook", "test")).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 1, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -1121,10 +1120,11 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { t.Run("radix-api runs as radix-api SA", func(t *testing.T) { tu, client, kubeUtil, radixclient, prometheusclient, _ := setupTest() - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithJobComponents(). WithAppName("radix-api"). WithEnvironment("test")) + require.NoError(t, err) serviceAccounts, _ := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace("radix-api", "test")).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 1, len(serviceAccounts.Items), "Number of service accounts was not expected") @@ -1140,7 +1140,7 @@ func TestObjectSynced_MultiComponentWithSameName_ContainsOneComponent(t *testing tu, client, kubeUtil, radixclient, prometheusclient, _ := setupTest() defer teardownTest() // Test - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName("app"). WithEnvironment("test"). WithJobComponents(). @@ -1155,6 +1155,7 @@ func TestObjectSynced_MultiComponentWithSameName_ContainsOneComponent(t *testing WithName("app"). WithPort("http", 8080). WithPublicPort("http"))) + require.NoError(t, err) envNamespace := utils.GetEnvironmentNamespace("app", "test") deployments, _ := client.AppsV1().Deployments(envNamespace).List(context.TODO(), metav1.ListOptions{}) @@ -1242,7 +1243,7 @@ func TestObjectSynced_NoEnvAndNoSecrets_ContainsDefaultEnvVariables(t *testing.T anyEnvironment := "test" // Test - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName("app"). WithEnvironment(anyEnvironment). WithJobComponents(). @@ -1251,6 +1252,7 @@ func TestObjectSynced_NoEnvAndNoSecrets_ContainsDefaultEnvVariables(t *testing.T WithName("component"). WithEnvironmentVariables(nil). WithSecrets(nil))) + require.NoError(t, err) envNamespace := utils.GetEnvironmentNamespace("app", "test") t.Run("validate deploy", func(t *testing.T) { @@ -1290,11 +1292,12 @@ func TestObjectSynced_WithLabels_LabelsAppliedToDeployment(t *testing.T) { defer teardownTest() // Test - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName("app"). WithEnvironment("test"). WithLabel("radix-branch", "master"). WithLabel("radix-commit", "4faca8595c5283a9d0f17a623b9255a0d9866a2e")) + require.NoError(t, err) envNamespace := utils.GetEnvironmentNamespace("app", "test") @@ -1318,7 +1321,7 @@ func TestObjectSynced_NotLatest_DeploymentIsIgnored(t *testing.T) { firstUID = "fda3d224-3115-11e9-b189-06c15a8f2fbb" secondUID = "5a8f2fbb-3115-11e9-b189-06c1fda3d224" - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("a_deployment_name"). WithAppName("app1"). WithEnvironment("prod"). @@ -1330,6 +1333,7 @@ func TestObjectSynced_NotLatest_DeploymentIsIgnored(t *testing.T) { WithName("app"). WithPort("http", 8080). WithPublicPort("http"))) + require.NoError(t, err) envNamespace := utils.GetEnvironmentNamespace("app1", "prod") deployments, _ := client.AppsV1().Deployments(envNamespace).List(context.TODO(), metav1.ListOptions{}) @@ -1343,7 +1347,7 @@ func TestObjectSynced_NotLatest_DeploymentIsIgnored(t *testing.T) { time.Sleep(1 * time.Millisecond) // This is one second newer deployment - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName("app1"). WithEnvironment("prod"). WithImageTag("seconddeployment"). @@ -1354,6 +1358,7 @@ func TestObjectSynced_NotLatest_DeploymentIsIgnored(t *testing.T) { WithName("app"). WithPort("http", 8080). WithPublicPort("http"))) + require.NoError(t, err) deployments, _ = client.AppsV1().Deployments(envNamespace).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, secondUID, deployments.Items[0].OwnerReferences[0].UID, "Second RD didn't take effect") @@ -1378,7 +1383,8 @@ func TestObjectSynced_NotLatest_DeploymentIsIgnored(t *testing.T) { WithPort("http", 8080). WithPublicPort("http")) - applyDeploymentUpdateWithSync(tu, client, kubeUtil, radixclient, prometheusclient, rdBuilder) + err = applyDeploymentUpdateWithSync(tu, client, kubeUtil, radixclient, prometheusclient, rdBuilder) + require.NoError(t, err) deployments, _ = client.AppsV1().Deployments(envNamespace).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, secondUID, deployments.Items[0].OwnerReferences[0].UID, "Should still be second RD which is the effective in the namespace") @@ -1394,7 +1400,7 @@ func Test_UpdateAndAddDeployment_DeploymentAnnotationIsCorrectlyUpdated(t *testi tu, client, kubeUtil, radixclient, prometheusclient, _ := setupTest() defer teardownTest() // Test first deployment - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("first_deployment"). WithAppName("anyapp1"). WithEnvironment("test"). @@ -1405,6 +1411,7 @@ func Test_UpdateAndAddDeployment_DeploymentAnnotationIsCorrectlyUpdated(t *testi utils.NewDeployComponentBuilder(). WithName("second"). WithAlwaysPullImageOnDeploy(false))) + require.NoError(t, err) envNamespace := utils.GetEnvironmentNamespace("anyapp1", "test") @@ -1415,7 +1422,7 @@ func Test_UpdateAndAddDeployment_DeploymentAnnotationIsCorrectlyUpdated(t *testi assert.Empty(t, secondDeployment.Spec.Template.Annotations[kube.RadixDeploymentNameAnnotation]) // Test second deployment - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("second_deployment"). WithAppName("anyapp1"). WithEnvironment("test"). @@ -1426,6 +1433,7 @@ func Test_UpdateAndAddDeployment_DeploymentAnnotationIsCorrectlyUpdated(t *testi utils.NewDeployComponentBuilder(). WithName("second"). WithAlwaysPullImageOnDeploy(false))) + require.NoError(t, err) deployments, _ = client.AppsV1().Deployments(envNamespace).List(context.TODO(), metav1.ListOptions{}) firstDeployment = getDeploymentByName("first", deployments.Items) @@ -1438,7 +1446,7 @@ func TestObjectUpdated_UpdatePort_IngressIsCorrectlyReconciled(t *testing.T) { tu, client, kubeUtil, radixclient, prometheusclient, _ := setupTest() defer teardownTest() // Test - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("a_deployment_name"). WithAppName("anyapp1"). WithEnvironment("test"). @@ -1457,6 +1465,7 @@ func TestObjectUpdated_UpdatePort_IngressIsCorrectlyReconciled(t *testing.T) { WithName("app3"). WithPort("http", 8080). WithPublicPort("http"))) + require.NoError(t, err) envNamespace := utils.GetEnvironmentNamespace("anyapp1", "test") ingresses, _ := client.NetworkingV1().Ingresses(envNamespace).List(context.TODO(), metav1.ListOptions{}) @@ -1464,7 +1473,7 @@ func TestObjectUpdated_UpdatePort_IngressIsCorrectlyReconciled(t *testing.T) { time.Sleep(1 * time.Second) - applyDeploymentUpdateWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + err = applyDeploymentUpdateWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("a_deployment_name"). WithAppName("anyapp1"). WithEnvironment("test"). @@ -1474,6 +1483,7 @@ func TestObjectUpdated_UpdatePort_IngressIsCorrectlyReconciled(t *testing.T) { WithPort("http", 8081). WithAlwaysPullImageOnDeploy(true). WithPublicPort("http"))) + require.NoError(t, err) ingresses, _ = client.NetworkingV1().Ingresses(envNamespace).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, int32(8081), ingresses.Items[0].Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.Service.Port.Number, "Port was unexpected") @@ -1485,7 +1495,7 @@ func TestObjectUpdated_ZeroReplicasExistsAndNotSpecifiedReplicas_SetsDefaultRepl envNamespace := utils.GetEnvironmentNamespace("anyapp", "test") // Test - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("a_deployment_name"). WithAppName("anyapp"). WithEnvironment("test"). @@ -1493,18 +1503,20 @@ func TestObjectUpdated_ZeroReplicasExistsAndNotSpecifiedReplicas_SetsDefaultRepl utils.NewDeployComponentBuilder(). WithName("app"). WithReplicas(test.IntPtr(0)))) + require.NoError(t, err) time.Sleep(1 * time.Second) deployments, _ := client.AppsV1().Deployments(envNamespace).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, int32(0), *deployments.Items[0].Spec.Replicas) - applyDeploymentUpdateWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + err = applyDeploymentUpdateWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("a_deployment_name"). WithAppName("anyapp"). WithEnvironment("test"). WithComponents( utils.NewDeployComponentBuilder(). WithName("app"))) + require.NoError(t, err) deployments, _ = client.AppsV1().Deployments(envNamespace).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, int32(1), *deployments.Items[0].Spec.Replicas) @@ -1516,7 +1528,7 @@ func TestObjectSynced_DeploymentReplicasSetAccordingToSpec(t *testing.T) { envNamespace := utils.GetEnvironmentNamespace("anyapp", "test") // Test - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("a_deployment_name"). WithAppName("anyapp"). WithEnvironment("test"). @@ -1529,6 +1541,7 @@ func TestObjectSynced_DeploymentReplicasSetAccordingToSpec(t *testing.T) { utils.NewDeployComponentBuilder().WithName("comp6").WithReplicas(pointers.Ptr(0)).WithHorizontalScaling(pointers.Ptr(int32(5)), int32(10), nil, nil), utils.NewDeployComponentBuilder().WithName("comp7").WithHorizontalScaling(pointers.Ptr(int32(5)), int32(10), nil, nil), )) + require.NoError(t, err) comp1, _ := client.AppsV1().Deployments(envNamespace).Get(context.TODO(), "comp1", metav1.GetOptions{}) assert.Equal(t, int32(1), *comp1.Spec.Replicas) @@ -1662,7 +1675,7 @@ func TestObjectSynced_DeploymentRevisionHistoryLimit(t *testing.T) { envNamespace := utils.GetEnvironmentNamespace("anyapp", "test") // Test - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("a_deployment_name"). WithAppName("anyapp"). WithEnvironment("test"). @@ -1670,6 +1683,7 @@ func TestObjectSynced_DeploymentRevisionHistoryLimit(t *testing.T) { utils.NewDeployComponentBuilder().WithName("comp1"), utils.NewDeployComponentBuilder().WithName("comp2").WithSecretRefs(v1.RadixSecretRefs{AzureKeyVaults: []v1.RadixAzureKeyVault{{}}}), )) + require.NoError(t, err) comp1, _ := client.AppsV1().Deployments(envNamespace).Get(context.TODO(), "comp1", metav1.GetOptions{}) assert.Nil(t, comp1.Spec.RevisionHistoryLimit) @@ -1711,7 +1725,7 @@ func TestObjectSynced_DeploymentsUsedByScheduledJobsMaintainHistoryLimit(t *test now := time.Now() timeShift := 1 for _, deploymentName := range ts.deploymentNames { - applyDeploymentWithModifiedSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.NewDeploymentBuilder(). + _, err := applyDeploymentWithModifiedSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.NewDeploymentBuilder(). WithRadixApplication(radixApplication). WithDeploymentName(deploymentName). WithAppName("anyapp"). @@ -1724,7 +1738,9 @@ func TestObjectSynced_DeploymentsUsedByScheduledJobsMaintainHistoryLimit(t *test s.deploymentHistoryLimit = 2 } }) - err := addRadixBatches(radixclient, envNamespace, deploymentName, ts.deploymentsReferencedInJobs[deploymentName]) + require.NoError(t, err) + + err = addRadixBatches(radixclient, envNamespace, deploymentName, ts.deploymentsReferencedInJobs[deploymentName]) assert.NoError(tt, err) timeShift++ } @@ -1767,7 +1783,7 @@ func TestObjectUpdated_MultipleReplicasExistsAndNotSpecifiedReplicas_SetsDefault envNamespace := utils.GetEnvironmentNamespace("anyapp", "test") // Test - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("a_deployment_name"). WithAppName("anyapp"). WithEnvironment("test"). @@ -1775,18 +1791,20 @@ func TestObjectUpdated_MultipleReplicasExistsAndNotSpecifiedReplicas_SetsDefault utils.NewDeployComponentBuilder(). WithName("app"). WithReplicas(test.IntPtr(3)))) + require.NoError(t, err) time.Sleep(1 * time.Second) deployments, _ := client.AppsV1().Deployments(envNamespace).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, int32(3), *deployments.Items[0].Spec.Replicas) - applyDeploymentUpdateWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + err = applyDeploymentUpdateWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("a_deployment_name"). WithAppName("anyapp"). WithEnvironment("test"). WithComponents( utils.NewDeployComponentBuilder(). WithName("app"))) + require.NoError(t, err) deployments, _ = client.AppsV1().Deployments(envNamespace).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, int32(1), *deployments.Items[0].Spec.Replicas) @@ -1797,7 +1815,7 @@ func TestObjectUpdated_WithAppAliasRemoved_AliasIngressIsCorrectlyReconciled(t * defer teardownTest() // Setup os.Setenv(defaults.ActiveClusternameEnvironmentVariable, testClusterName) - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName("any-app"). WithEnvironment("dev"). WithComponents( @@ -1806,6 +1824,7 @@ func TestObjectUpdated_WithAppAliasRemoved_AliasIngressIsCorrectlyReconciled(t * WithPort("http", 8080). WithPublicPort("http"). WithDNSAppAlias(true))) + require.NoError(t, err) // Test ingresses, _ := client.NetworkingV1().Ingresses(utils.GetEnvironmentNamespace("any-app", "dev")).List(context.TODO(), metav1.ListOptions{}) @@ -1815,7 +1834,7 @@ func TestObjectUpdated_WithAppAliasRemoved_AliasIngressIsCorrectlyReconciled(t * assert.Truef(t, ingressByNameExists("frontend-active-cluster-url-alias", ingresses), "App should have another external alias") // Remove app alias from dev - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName("any-app"). WithEnvironment("dev"). WithComponents( @@ -1824,6 +1843,7 @@ func TestObjectUpdated_WithAppAliasRemoved_AliasIngressIsCorrectlyReconciled(t * WithPort("http", 8080). WithPublicPort("http"). WithDNSAppAlias(false))) + require.NoError(t, err) ingresses, _ = client.NetworkingV1().Ingresses(utils.GetEnvironmentNamespace("any-app", "dev")).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 2, len(ingresses.Items), "Alias ingress should have been removed") @@ -2272,7 +2292,7 @@ func TestObjectUpdated_WithAllExternalAliasRemoved_ExternalAliasIngressIsCorrect defer teardownTest() // Setup os.Setenv(defaults.ActiveClusternameEnvironmentVariable, testClusterName) - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName(anyAppName). WithEnvironment(anyEnvironment). WithJobComponents(). @@ -2282,6 +2302,7 @@ func TestObjectUpdated_WithAllExternalAliasRemoved_ExternalAliasIngressIsCorrect WithPort("http", 8080). WithPublicPort("http"). WithDNSExternalAlias("some.alias.com"))) + require.NoError(t, err) // Test ingresses, _ := client.NetworkingV1().Ingresses(envNamespace).List(context.TODO(), metav1.ListOptions{}) @@ -2301,7 +2322,7 @@ func TestObjectUpdated_WithAllExternalAliasRemoved_ExternalAliasIngressIsCorrect assert.True(t, secretByNameExists("some.alias.com", secrets), "TLS certificate for external alias is not properly defined") // Remove app alias from dev - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName(anyAppName). WithEnvironment(anyEnvironment). WithJobComponents(). @@ -2310,6 +2331,7 @@ func TestObjectUpdated_WithAllExternalAliasRemoved_ExternalAliasIngressIsCorrect WithName(anyComponentName). WithPort("http", 8080). WithPublicPort("http"))) + require.NoError(t, err) ingresses, _ = client.NetworkingV1().Ingresses(envNamespace).List(context.TODO(), metav1.ListOptions{}) secrets, _ = client.CoreV1().Secrets(envNamespace).List(context.TODO(), metav1.ListOptions{}) @@ -2336,7 +2358,7 @@ func TestObjectUpdated_WithOneExternalAliasRemovedOrModified_AllChangesPropelyRe // Setup os.Setenv(defaults.ActiveClusternameEnvironmentVariable, testClusterName) - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName(anyAppName). WithEnvironment(anyEnvironment). WithComponents( @@ -2347,6 +2369,7 @@ func TestObjectUpdated_WithOneExternalAliasRemovedOrModified_AllChangesPropelyRe WithDNSExternalAlias("some.alias.com"). WithDNSExternalAlias("another.alias.com"). WithSecrets([]string{"a_secret"}))) + require.NoError(t, err) // Test ingresses, _ := client.NetworkingV1().Ingresses(envNamespace).List(context.TODO(), metav1.ListOptions{}) @@ -2370,7 +2393,7 @@ func TestObjectUpdated_WithOneExternalAliasRemovedOrModified_AllChangesPropelyRe assert.Equal(t, "some.alias.com", roles.Items[0].Rules[0].ResourceNames[1], "Expected role should be able to access TLS certificate for external alias") assert.Equal(t, "another.alias.com", roles.Items[0].Rules[0].ResourceNames[2], "Expected role should be able to access TLS certificate for second external alias") - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName(anyAppName). WithEnvironment(anyEnvironment). WithComponents( @@ -2381,6 +2404,7 @@ func TestObjectUpdated_WithOneExternalAliasRemovedOrModified_AllChangesPropelyRe WithDNSExternalAlias("some.alias.com"). WithDNSExternalAlias("yet.another.alias.com"). WithSecrets([]string{"a_secret"}))) + require.NoError(t, err) ingresses, _ = client.NetworkingV1().Ingresses(envNamespace).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 4, len(ingresses.Items), "Environment should have four ingresses") @@ -2402,7 +2426,7 @@ func TestObjectUpdated_WithOneExternalAliasRemovedOrModified_AllChangesPropelyRe assert.Equal(t, "some.alias.com", roles.Items[0].Rules[0].ResourceNames[1], "Expected role should be able to access TLS certificate for external alias") assert.Equal(t, "yet.another.alias.com", roles.Items[0].Rules[0].ResourceNames[2], "Expected role should be able to access TLS certificate for second external alias") - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName(anyAppName). WithEnvironment(anyEnvironment). WithComponents( @@ -2412,6 +2436,7 @@ func TestObjectUpdated_WithOneExternalAliasRemovedOrModified_AllChangesPropelyRe WithPublicPort("http"). WithDNSExternalAlias("yet.another.alias.com"). WithSecrets([]string{"a_secret"}))) + require.NoError(t, err) ingresses, _ = client.NetworkingV1().Ingresses(envNamespace).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 3, len(ingresses.Items), "Environment should have three ingresses") @@ -2428,7 +2453,7 @@ func TestObjectUpdated_WithOneExternalAliasRemovedOrModified_AllChangesPropelyRe assert.Equal(t, "yet.another.alias.com", roles.Items[0].Rules[0].ResourceNames[1], "Expected role should be able to access TLS certificate for second external alias") // Remove app alias from dev - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName(anyAppName). WithEnvironment(anyEnvironment). WithComponents( @@ -2436,6 +2461,7 @@ func TestObjectUpdated_WithOneExternalAliasRemovedOrModified_AllChangesPropelyRe WithName(anyComponentName). WithPort("http", 8080). WithPublicPort("http"))) + require.NoError(t, err) ingresses, _ = client.NetworkingV1().Ingresses(envNamespace).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 2, len(ingresses.Items), "External alias ingress should have been removed") @@ -2466,7 +2492,8 @@ func TestFixedAliasIngress_ActiveCluster(t *testing.T) { // Current cluster is active cluster os.Setenv(defaults.ActiveClusternameEnvironmentVariable, testClusterName) - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, radixDeployBuilder) + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, radixDeployBuilder) + require.NoError(t, err) ingresses, _ := client.NetworkingV1().Ingresses(envNamespace).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 2, len(ingresses.Items), "Environment should have two ingresses") @@ -2477,7 +2504,8 @@ func TestFixedAliasIngress_ActiveCluster(t *testing.T) { // Current cluster is not active cluster os.Setenv(defaults.ActiveClusternameEnvironmentVariable, "newClusterName") - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, radixDeployBuilder) + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, radixDeployBuilder) + require.NoError(t, err) ingresses, _ = client.NetworkingV1().Ingresses(envNamespace).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 1, len(ingresses.Items), "Environment should have one ingresses") assert.True(t, strings.Contains(ingresses.Items[0].Spec.Rules[0].Host, testClusterName)) @@ -2599,7 +2627,7 @@ func TestObjectUpdated_RemoveOneSecret_SecretIsRemoved(t *testing.T) { tu, client, kubeUtil, radixclient, prometheusclient, _ := setupTest() defer teardownTest() // Setup - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName(anyAppName). WithEnvironment(anyEnvironment). WithComponents( @@ -2610,6 +2638,7 @@ func TestObjectUpdated_RemoveOneSecret_SecretIsRemoved(t *testing.T) { WithDNSExternalAlias("some.alias.com"). WithDNSExternalAlias("another.alias.com"). WithSecrets([]string{"a_secret", "another_secret", "a_third_secret"}))) + require.NoError(t, err) secrets, _ := client.CoreV1().Secrets(envNamespace).List(context.TODO(), metav1.ListOptions{}) anyComponentSecret := getSecretByName(utils.GetComponentSecretName(anyComponentName), secrets) @@ -2632,7 +2661,7 @@ func TestObjectUpdated_RemoveOneSecret_SecretIsRemoved(t *testing.T) { // Removing one secret from config and therefor from the deployment // should cause it to disappear - applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName(anyAppName). WithEnvironment(anyEnvironment). WithComponents( @@ -2643,6 +2672,7 @@ func TestObjectUpdated_RemoveOneSecret_SecretIsRemoved(t *testing.T) { WithDNSExternalAlias("some.alias.com"). WithDNSExternalAlias("another.alias.com"). WithSecrets([]string{"a_secret", "a_third_secret"}))) + require.NoError(t, err) secrets, _ = client.CoreV1().Secrets(envNamespace).List(context.TODO(), metav1.ListOptions{}) anyComponentSecret = getSecretByName(utils.GetComponentSecretName(anyComponentName), secrets) @@ -2664,7 +2694,7 @@ func TestHistoryLimit_IsBroken_FixedAmountOfDeployments(t *testing.T) { } } envNamespace := utils.GetEnvironmentNamespace(anyAppName, anyEnvironment) - applyDeploymentWithModifiedSync(tu, client, kubeUtils, radixclient, prometheusclient, + _, err := applyDeploymentWithModifiedSync(tu, client, kubeUtils, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("firstdeployment"). WithAppName(anyAppName). @@ -2675,8 +2705,9 @@ func TestHistoryLimit_IsBroken_FixedAmountOfDeployments(t *testing.T) { WithPort("http", 8080). WithPublicPort("http")), deploymentHistoryLimitSetter) + require.NoError(t, err) - applyDeploymentWithModifiedSync(tu, client, kubeUtils, radixclient, prometheusclient, + _, err = applyDeploymentWithModifiedSync(tu, client, kubeUtils, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("seconddeployment"). WithAppName(anyAppName). @@ -2687,8 +2718,9 @@ func TestHistoryLimit_IsBroken_FixedAmountOfDeployments(t *testing.T) { WithPort("http", 8080). WithPublicPort("http")), deploymentHistoryLimitSetter) + require.NoError(t, err) - applyDeploymentWithModifiedSync(tu, client, kubeUtils, radixclient, prometheusclient, + _, err = applyDeploymentWithModifiedSync(tu, client, kubeUtils, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("thirddeployment"). WithAppName(anyAppName). @@ -2699,8 +2731,9 @@ func TestHistoryLimit_IsBroken_FixedAmountOfDeployments(t *testing.T) { WithPort("http", 8080). WithPublicPort("http")), deploymentHistoryLimitSetter) + require.NoError(t, err) - applyDeploymentWithModifiedSync(tu, client, kubeUtils, radixclient, prometheusclient, + _, err = applyDeploymentWithModifiedSync(tu, client, kubeUtils, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("fourthdeployment"). WithAppName(anyAppName). @@ -2711,6 +2744,7 @@ func TestHistoryLimit_IsBroken_FixedAmountOfDeployments(t *testing.T) { WithPort("http", 8080). WithPublicPort("http")), deploymentHistoryLimitSetter) + require.NoError(t, err) deployments, _ := radixclient.RadixV1().RadixDeployments(envNamespace).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, anyLimit, len(deployments.Items), "Number of deployments should match limit") @@ -2720,7 +2754,7 @@ func TestHistoryLimit_IsBroken_FixedAmountOfDeployments(t *testing.T) { assert.True(t, radixDeploymentByNameExists("thirddeployment", deployments)) assert.True(t, radixDeploymentByNameExists("fourthdeployment", deployments)) - applyDeploymentWithModifiedSync(tu, client, kubeUtils, radixclient, prometheusclient, + _, err = applyDeploymentWithModifiedSync(tu, client, kubeUtils, radixclient, prometheusclient, utils.ARadixDeployment(). WithDeploymentName("fifthdeployment"). WithAppName(anyAppName). @@ -2731,6 +2765,7 @@ func TestHistoryLimit_IsBroken_FixedAmountOfDeployments(t *testing.T) { WithPort("http", 8080). WithPublicPort("http")), deploymentHistoryLimitSetter) + require.NoError(t, err) deployments, _ = radixclient.RadixV1().RadixDeployments(envNamespace).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, anyLimit, len(deployments.Items), "Number of deployments should match limit") From d8f3aceace4b627025328dfa233590df35d66872 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 12 Dec 2023 14:12:32 +0100 Subject: [PATCH 106/121] Cleaned linter reported issues --- pkg/apis/deployment/oauthproxyresourcemanager.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/apis/deployment/oauthproxyresourcemanager.go b/pkg/apis/deployment/oauthproxyresourcemanager.go index 2b76a5785..78f3ccfd8 100644 --- a/pkg/apis/deployment/oauthproxyresourcemanager.go +++ b/pkg/apis/deployment/oauthproxyresourcemanager.go @@ -15,7 +15,6 @@ import ( "github.com/equinor/radix-operator/pkg/apis/securitycontext" "github.com/equinor/radix-operator/pkg/apis/utils" radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" - "github.com/equinor/radix-operator/pkg/apis/utils/oauth" oauthutil "github.com/equinor/radix-operator/pkg/apis/utils/oauth" log "github.com/sirupsen/logrus" appsv1 "k8s.io/api/apps/v1" @@ -379,7 +378,7 @@ func (o *oauthProxyResourceManager) createOrUpdateIngresses(component v1.RadixCo if auxIngress == nil { continue } - oauth.MergeAuxComponentIngressResourceLabels(auxIngress, appName, component) + oauthutil.MergeAuxComponentIngressResourceLabels(auxIngress, appName, component) if err := o.kubeutil.ApplyIngress(namespace, auxIngress); err != nil { return err } From b468e5148d842b9557c9c3e1773054018fafe4e8 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 12 Dec 2023 15:24:58 +0100 Subject: [PATCH 107/121] Added defaultAlias label to default ingresses --- pkg/apis/deployment/deployment.go | 4 ++++ pkg/apis/deployment/ingress.go | 1 + .../deployment/oauthproxyresourcemanager.go | 4 ++-- .../oauthproxyresourcemanager_test.go | 18 +++++++++--------- pkg/apis/kube/kube.go | 2 +- pkg/apis/utils/labels/labels.go | 6 +++--- pkg/apis/utils/oauth/oauth.go | 2 +- 7 files changed, 21 insertions(+), 16 deletions(-) diff --git a/pkg/apis/deployment/deployment.go b/pkg/apis/deployment/deployment.go index 77bac5844..f501985f0 100644 --- a/pkg/apis/deployment/deployment.go +++ b/pkg/apis/deployment/deployment.go @@ -520,6 +520,10 @@ func getLabelSelectorForComponent(component v1.RadixCommonDeployComponent) strin return fmt.Sprintf("%s=%s", kube.RadixComponentLabel, component.GetName()) } +func getLabelSelectorForComponentDefaultAlias(component v1.RadixCommonDeployComponent) string { + return fmt.Sprintf("%s=%s, %s", kube.RadixComponentLabel, component.GetName(), kube.RadixDefaultAliasLabel) +} + func getLabelSelectorForExternalAlias(component v1.RadixCommonDeployComponent) string { return fmt.Sprintf("%s=%s, %s=%s", kube.RadixComponentLabel, component.GetName(), kube.RadixExternalAliasLabel, "true") } diff --git a/pkg/apis/deployment/ingress.go b/pkg/apis/deployment/ingress.go index 1baad4982..b93bd250c 100644 --- a/pkg/apis/deployment/ingress.go +++ b/pkg/apis/deployment/ingress.go @@ -271,6 +271,7 @@ func (deploy *Deployment) getDefaultIngressConfig( if err != nil { return nil, err } + ingressConfig.ObjectMeta.Labels[kube.RadixDefaultAliasLabel] = "true" return ingressConfig, err } diff --git a/pkg/apis/deployment/oauthproxyresourcemanager.go b/pkg/apis/deployment/oauthproxyresourcemanager.go index 78f3ccfd8..e56257cfa 100644 --- a/pkg/apis/deployment/oauthproxyresourcemanager.go +++ b/pkg/apis/deployment/oauthproxyresourcemanager.go @@ -287,7 +287,7 @@ func (o *oauthProxyResourceManager) deleteDeployment(component v1.RadixCommonDep } func (o *oauthProxyResourceManager) deleteIngresses(component v1.RadixCommonDeployComponent) error { - selector := labels.SelectorFromValidatedSet(radixlabels.ForAuxComponentIngress(o.rd.Spec.AppName, component)).String() + selector := labels.SelectorFromValidatedSet(radixlabels.ForAuxComponentDefaultIngress(o.rd.Spec.AppName, component)).String() ingresses, err := o.kubeutil.ListIngressesWithSelector(o.rd.Namespace, selector) if err != nil { return err @@ -363,7 +363,7 @@ func (o *oauthProxyResourceManager) deleteRoles(component v1.RadixCommonDeployCo func (o *oauthProxyResourceManager) createOrUpdateIngresses(component v1.RadixCommonDeployComponent) error { namespace := o.rd.Namespace log.Debugf("create of update ingresses for the component %s in the namespace %s", component.GetName(), namespace) - listOptions := metav1.ListOptions{LabelSelector: getLabelSelectorForComponent(component)} + listOptions := metav1.ListOptions{LabelSelector: getLabelSelectorForComponentDefaultAlias(component)} ingresses, err := o.kubeutil.KubeClient().NetworkingV1().Ingresses(namespace).List(context.TODO(), listOptions) if err != nil { return err diff --git a/pkg/apis/deployment/oauthproxyresourcemanager_test.go b/pkg/apis/deployment/oauthproxyresourcemanager_test.go index 56ad75768..61141476c 100644 --- a/pkg/apis/deployment/oauthproxyresourcemanager_test.go +++ b/pkg/apis/deployment/oauthproxyresourcemanager_test.go @@ -526,7 +526,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate appName, envName, component1Name, component2Name := "anyapp", "qa", "server", "web" envNs := utils.GetEnvironmentNamespace(appName, envName) ingServer := networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{Name: "ing1", Labels: map[string]string{kube.RadixComponentLabel: component1Name}}, + ObjectMeta: metav1.ObjectMeta{Name: "ing1", Labels: map[string]string{kube.RadixComponentLabel: component1Name, kube.RadixDefaultAliasLabel: "true"}}, Spec: networkingv1.IngressSpec{ IngressClassName: utils.StringPtr("anyclass"), TLS: []networkingv1.IngressTLS{{SecretName: "ing1-tls"}}, @@ -534,14 +534,14 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate }, } ingServerNoRules := networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{Name: "ing2", Labels: map[string]string{kube.RadixComponentLabel: component1Name}}, + ObjectMeta: metav1.ObjectMeta{Name: "ing2", Labels: map[string]string{kube.RadixComponentLabel: component1Name, kube.RadixDefaultAliasLabel: "true"}}, Spec: networkingv1.IngressSpec{ IngressClassName: utils.StringPtr("anyclass"), TLS: []networkingv1.IngressTLS{{SecretName: "ing1-tls"}}, }, } ingOtherComponent := networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{Name: "ing3", Labels: map[string]string{kube.RadixComponentLabel: "othercomponent"}}, + ObjectMeta: metav1.ObjectMeta{Name: "ing3", Labels: map[string]string{kube.RadixComponentLabel: "othercomponent", kube.RadixDefaultAliasLabel: "true"}}, Spec: networkingv1.IngressSpec{ IngressClassName: utils.StringPtr("anyclass"), TLS: []networkingv1.IngressTLS{{SecretName: "ing1-tls"}}, @@ -549,7 +549,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate }, } ingServerOtherNs := networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{Name: "ing4", Labels: map[string]string{kube.RadixComponentLabel: component1Name}}, + ObjectMeta: metav1.ObjectMeta{Name: "ing4", Labels: map[string]string{kube.RadixComponentLabel: component1Name, kube.RadixDefaultAliasLabel: "true"}}, Spec: networkingv1.IngressSpec{ IngressClassName: utils.StringPtr("anyclass"), TLS: []networkingv1.IngressTLS{{SecretName: "ing1-tls"}}, @@ -557,7 +557,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate }, } ingWeb1 := networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{Name: "ing5", Labels: map[string]string{kube.RadixComponentLabel: component2Name}}, + ObjectMeta: metav1.ObjectMeta{Name: "ing5", Labels: map[string]string{kube.RadixComponentLabel: component2Name, kube.RadixDefaultAliasLabel: "true"}}, Spec: networkingv1.IngressSpec{ IngressClassName: utils.StringPtr("anyclass1"), TLS: []networkingv1.IngressTLS{{SecretName: "ing2-tls"}}, @@ -565,7 +565,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate }, } ingWeb2 := networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{Name: "ing6", Labels: map[string]string{kube.RadixComponentLabel: component2Name}}, + ObjectMeta: metav1.ObjectMeta{Name: "ing6", Labels: map[string]string{kube.RadixComponentLabel: component2Name, kube.RadixDefaultAliasLabel: "true"}}, Spec: networkingv1.IngressSpec{ IngressClassName: utils.StringPtr("anyclass2"), TLS: []networkingv1.IngressTLS{{SecretName: "ing2-tls"}}, @@ -680,7 +680,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyUninstall() { if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create( context.Background(), &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{Name: "ing1", Labels: map[string]string{kube.RadixAppLabel: appName, kube.RadixComponentLabel: component1Name}}, + ObjectMeta: metav1.ObjectMeta{Name: "ing1", Labels: map[string]string{kube.RadixAppLabel: appName, kube.RadixComponentLabel: component1Name, kube.RadixDefaultAliasLabel: "true"}}, Spec: networkingv1.IngressSpec{Rules: []networkingv1.IngressRule{{Host: "anyhost"}}}}, metav1.CreateOptions{}, ); err != nil { @@ -689,7 +689,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyUninstall() { if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create( context.Background(), &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{Name: "ing2", Labels: map[string]string{kube.RadixAppLabel: appName, kube.RadixComponentLabel: component2Name}}, + ObjectMeta: metav1.ObjectMeta{Name: "ing2", Labels: map[string]string{kube.RadixAppLabel: appName, kube.RadixComponentLabel: component2Name, kube.RadixDefaultAliasLabel: "true"}}, Spec: networkingv1.IngressSpec{Rules: []networkingv1.IngressRule{{Host: "anyhost"}}}}, metav1.CreateOptions{}, ); err != nil { @@ -698,7 +698,7 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyUninstall() { if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create( context.Background(), &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{Name: "ing3", Labels: map[string]string{kube.RadixAppLabel: appName, kube.RadixComponentLabel: component2Name}}, + ObjectMeta: metav1.ObjectMeta{Name: "ing3", Labels: map[string]string{kube.RadixAppLabel: appName, kube.RadixComponentLabel: component2Name, kube.RadixDefaultAliasLabel: "true"}}, Spec: networkingv1.IngressSpec{Rules: []networkingv1.IngressRule{{Host: "anyhost"}}}}, metav1.CreateOptions{}, ); err != nil { diff --git a/pkg/apis/kube/kube.go b/pkg/apis/kube/kube.go index b31f2be32..96414f236 100644 --- a/pkg/apis/kube/kube.go +++ b/pkg/apis/kube/kube.go @@ -52,7 +52,7 @@ const ( RadixJobTypeJob = "job" // Outer job RadixJobTypeBuild = "build" RadixJobTypeCloneConfig = "clone-config" - RadixStandardIngressLabel = "radix-standard-ingress" + RadixDefaultAliasLabel = "radix-default-alias" RadixAliasLabel = "radix-alias" RadixJobTypePreparePipelines = "prepare-pipelines" RadixJobTypeRunPipelines = "run-pipelines" diff --git a/pkg/apis/utils/labels/labels.go b/pkg/apis/utils/labels/labels.go index 26fc8fe81..a76ebfe4b 100644 --- a/pkg/apis/utils/labels/labels.go +++ b/pkg/apis/utils/labels/labels.go @@ -234,13 +234,13 @@ func ForAuxComponent(appName string, component v1.RadixCommonDeployComponent) ma } } -// ForAuxComponentIngress returns labels for application component aux OAuth proxy standard ingress -func ForAuxComponentIngress(appName string, component v1.RadixCommonDeployComponent) kubelabels.Set { +// ForAuxComponentDefaultIngress returns labels for application component aux OAuth proxy default ingress +func ForAuxComponentDefaultIngress(appName string, component v1.RadixCommonDeployComponent) kubelabels.Set { return kubelabels.Set{ kube.RadixAppLabel: appName, kube.RadixAuxiliaryComponentLabel: component.GetName(), kube.RadixAuxiliaryComponentTypeLabel: defaults.OAuthProxyAuxiliaryComponentType, - kube.RadixStandardIngressLabel: "true", + kube.RadixDefaultAliasLabel: "true", } } diff --git a/pkg/apis/utils/oauth/oauth.go b/pkg/apis/utils/oauth/oauth.go index 608b9d006..e00dcf811 100644 --- a/pkg/apis/utils/oauth/oauth.go +++ b/pkg/apis/utils/oauth/oauth.go @@ -41,7 +41,7 @@ func MergeAuxComponentResourceLabels(object metav1.Object, appName string, compo // MergeAuxComponentIngressResourceLabels Merge labels for ingress and aux OAuth proxy func MergeAuxComponentIngressResourceLabels(auxIngress *networkingv1.Ingress, appName string, component radixv1.RadixCommonDeployComponent) { - auxIngress.SetLabels(labels.Merge(auxIngress.GetLabels(), radixlabels.ForAuxComponentIngress(appName, component))) + auxIngress.SetLabels(labels.Merge(auxIngress.GetLabels(), radixlabels.ForAuxComponentDefaultIngress(appName, component))) } // MergeAuxComponentDNSAliasIngressResourceLabels Merge labels for ingress and aux DNS alias OAuth proxy From a7c9453c51aee48fe9b9c0edfe9c53b20be357c4 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 12 Dec 2023 16:36:33 +0100 Subject: [PATCH 108/121] Corrected deletion of radix environment. Added tests --- pkg/apis/environment/environment.go | 40 ++-------- pkg/apis/environment/environment_test.go | 96 +++++++++++++++++++----- pkg/apis/environment/status.go | 41 ++++++++++ pkg/apis/environment/testdata/re.yaml | 2 + 4 files changed, 127 insertions(+), 52 deletions(-) create mode 100644 pkg/apis/environment/status.go diff --git a/pkg/apis/environment/environment.go b/pkg/apis/environment/environment.go index 931f0bc03..39b791c2d 100644 --- a/pkg/apis/environment/environment.go +++ b/pkg/apis/environment/environment.go @@ -1,7 +1,6 @@ package environment import ( - "context" "fmt" "github.com/equinor/radix-common/utils/slice" @@ -19,7 +18,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/kubernetes" - "k8s.io/client-go/util/retry" ) // Environment is the aggregate-root for manipulating RadixEnvironments @@ -62,7 +60,10 @@ func (env *Environment) OnSync(time metav1.Time) error { re := env.config if re.ObjectMeta.DeletionTimestamp != nil { - return env.handleDeletedRadixEnvironment(re) + if err := env.handleDeletedRadixEnvironment(re); err != nil { + return err + } + return env.syncStatus(re, time) } if env.regConfig == nil { @@ -90,19 +91,7 @@ func (env *Environment) OnSync(time metav1.Time) error { if err := env.networkPolicy.UpdateEnvEgressRules(re.Spec.Egress.Rules, re.Spec.Egress.AllowRadix, re.Spec.EnvName); err != nil { return fmt.Errorf("failed to add egress rules in %s, environment %s: %v", re.Spec.AppName, re.Spec.EnvName, err) } - - isOrphaned := !existsInAppConfig(env.appConfig, re.Spec.EnvName) - - err := env.updateRadixEnvironmentStatus(re, func(currStatus *v1.RadixEnvironmentStatus) { - currStatus.Orphaned = isOrphaned - // time is parameterized for testability - currStatus.Reconciled = time - }) - if err != nil { - return fmt.Errorf("failed to update status on environment %s: %v", re.Spec.EnvName, err) - } - env.logger.Debugf("Environment %s reconciled", namespaceName) - return nil + return env.syncStatus(re, time) } func (env *Environment) handleDeletedRadixEnvironment(re *v1.RadixEnvironment) error { @@ -136,25 +125,6 @@ func (env *Environment) handleDeletedRadixEnvironmentDependencies(re *v1.RadixEn })...) } -func (env *Environment) updateRadixEnvironmentStatus(rEnv *v1.RadixEnvironment, changeStatusFunc func(currStatus *v1.RadixEnvironmentStatus)) error { - radixEnvironmentInterface := env.radixclient.RadixV1().RadixEnvironments() - return retry.RetryOnConflict(retry.DefaultRetry, func() error { - currentEnv, err := radixEnvironmentInterface.Get(context.TODO(), rEnv.GetName(), metav1.GetOptions{}) - if err != nil { - return err - } - changeStatusFunc(¤tEnv.Status) - _, err = radixEnvironmentInterface.UpdateStatus(context.TODO(), currentEnv, metav1.UpdateOptions{}) - if err == nil && env.config.GetName() == rEnv.GetName() { - currentEnv, err = radixEnvironmentInterface.Get(context.TODO(), rEnv.GetName(), metav1.GetOptions{}) - if err == nil { - env.config = currentEnv - } - } - return err - }) -} - // ApplyNamespace sets up namespace metadata and applies configuration to kubernetes func (env *Environment) ApplyNamespace(name string) error { diff --git a/pkg/apis/environment/environment_test.go b/pkg/apis/environment/environment_test.go index 26dd178b0..b4eedf7b8 100644 --- a/pkg/apis/environment/environment_test.go +++ b/pkg/apis/environment/environment_test.go @@ -17,9 +17,11 @@ import ( radix "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" core "k8s.io/api/core/v1" rbac "k8s.io/api/rbac/v1" - meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/fake" secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake" @@ -47,7 +49,6 @@ func setupTest() (test.Utils, kubernetes.Interface, *kube.Kube, radixclient.Inte os.Setenv(defaults.OperatorEnvLimitDefaultRequestCPUEnvironmentVariable, limitDefaultReqestCPU) os.Setenv(defaults.OperatorEnvLimitDefaultMemoryEnvironmentVariable, limitDefaultMemory) os.Setenv(defaults.OperatorEnvLimitDefaultRequestMemoryEnvironmentVariable, limitDefaultReqestMemory) - return handlerTestUtils, fakekube, kubeUtil, fakeradix } @@ -58,7 +59,7 @@ func newEnv(client kubernetes.Interface, kubeUtil *kube.Kube, radixclient radixc nw, _ := networkpolicy.NewNetworkPolicy(client, kubeUtil, logger, re.Spec.AppName) env, _ := NewEnvironment(client, kubeUtil, radixclient, re, rr, nil, logger, &nw) // register instance with radix-client so UpdateStatus() can find it - if _, err := radixclient.RadixV1().RadixEnvironments().Create(context.TODO(), re, meta.CreateOptions{}); err != nil { + if _, err := radixclient.RadixV1().RadixEnvironments().Create(context.TODO(), re, metav1.CreateOptions{}); err != nil { panic(err) } return rr, re, env @@ -71,7 +72,7 @@ func Test_Create_Namespace(t *testing.T) { sync(t, &env) - namespaces, _ := client.CoreV1().Namespaces().List(context.TODO(), meta.ListOptions{ + namespaces, _ := client.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{ LabelSelector: fmt.Sprintf("%s=%s", kube.RadixAppLabel, rr.Name), }) @@ -90,6 +91,67 @@ func Test_Create_Namespace(t *testing.T) { assert.Equal(t, expected, namespaces.Items[0].GetLabels()) } +func Test_DeleteEnvironment_Deleted(t *testing.T) { + _, client, kubeUtil, radixclient := setupTest() + defer os.Clearenv() + _, _, env := newEnv(client, kubeUtil, radixclient, envConfigFileName) + + sync(t, &env) + + re, err := radixclient.RadixV1().RadixEnvironments().Get(context.Background(), "testenv", metav1.GetOptions{}) + require.NoError(t, err) + timeNow := metav1.NewTime(time.Now()) + re.ObjectMeta.DeletionTimestamp = &timeNow + re, err = radixclient.RadixV1().RadixEnvironments().Update(context.Background(), re, metav1.UpdateOptions{}) + require.NoError(t, err) + re, err = radixclient.RadixV1().RadixEnvironments().Get(context.Background(), "testenv", metav1.GetOptions{}) + require.NoError(t, err) + assert.NotNil(t, re.ObjectMeta.DeletionTimestamp) + assert.Contains(t, re.ObjectMeta.Finalizers, kube.RadixEnvironmentFinalizer, "missing environment finalizer") + env.config = re + sync(t, &env) + + re, err = radixclient.RadixV1().RadixEnvironments().Get(context.Background(), "testenv", metav1.GetOptions{}) + assert.NotNil(t, re.ObjectMeta.DeletionTimestamp) + assert.NotContains(t, re.ObjectMeta.Finalizers, kube.RadixEnvironmentFinalizer, "unexpected environment finalizer") +} + +func Test_DeleteEnvironment_DeletedDNSAlias(t *testing.T) { + _, client, kubeUtil, radixclient := setupTest() + defer os.Clearenv() + _, _, env := newEnv(client, kubeUtil, radixclient, envConfigFileName) + + sync(t, &env) + + alias1Name := "alias1" + err := createRadixDNSAliasForEnvironment(radixclient, alias1Name) + require.NoError(t, err) + re, err := radixclient.RadixV1().RadixEnvironments().Get(context.Background(), "testenv", metav1.GetOptions{}) + require.NoError(t, err) + timeNow := metav1.NewTime(time.Now()) + re.ObjectMeta.DeletionTimestamp = &timeNow + re, err = radixclient.RadixV1().RadixEnvironments().Update(context.Background(), re, metav1.UpdateOptions{}) + require.NoError(t, err) + assert.NotNil(t, re.ObjectMeta.DeletionTimestamp) + env.config = re + sync(t, &env) + + re, err = radixclient.RadixV1().RadixEnvironments().Get(context.Background(), "testenv", metav1.GetOptions{}) + assert.NotNil(t, re.ObjectMeta.DeletionTimestamp) + assert.NotContains(t, re.ObjectMeta.Finalizers, kube.RadixEnvironmentFinalizer, "unexpected environment finalizer") + _, err = radixclient.RadixV1().RadixDNSAliases().Get(context.Background(), alias1Name, metav1.GetOptions{}) + require.Error(t, err) + assert.True(t, errors.IsNotFound(err)) +} + +func createRadixDNSAliasForEnvironment(radixClient radixclient.Interface, aliasName string) error { + return test.RegisterRadixDNSAliasBySpec(radixClient, aliasName, test.DNSAlias{ + AppName: "testapp", + Environment: "testenv", + Component: "testcomponent", + }) +} + func Test_Create_Namespace_PodSecurityStandardLabels(t *testing.T) { _, client, kubeUtil, radixclient := setupTest() os.Setenv(defaults.PodSecurityStandardEnforceLevelEnvironmentVariable, "enforceLvl") @@ -103,7 +165,7 @@ func Test_Create_Namespace_PodSecurityStandardLabels(t *testing.T) { sync(t, &env) - namespaces, _ := client.CoreV1().Namespaces().List(context.TODO(), meta.ListOptions{ + namespaces, _ := client.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{ LabelSelector: fmt.Sprintf("%s=%s", kube.RadixAppLabel, rr.Name), }) @@ -135,7 +197,7 @@ func Test_Create_EgressRules(t *testing.T) { sync(t, &env) - namespaces, _ := client.CoreV1().Namespaces().List(context.TODO(), meta.ListOptions{ + namespaces, _ := client.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{ LabelSelector: fmt.Sprintf("%s=%s", kube.RadixAppLabel, rr.Name), }) @@ -156,7 +218,7 @@ func Test_Create_RoleBinding(t *testing.T) { sync(t, &env) - rolebindings, _ := client.RbacV1().RoleBindings(namespaceName).List(context.TODO(), meta.ListOptions{}) + rolebindings, _ := client.RbacV1().RoleBindings(namespaceName).List(context.TODO(), metav1.ListOptions{}) commonAsserts(t, env, roleBindingsAsMeta(rolebindings.Items), "radix-tekton-env", "radix-app-admin-envs", "radix-pipeline-env", "radix-app-reader-envs") adGroupName := rr.Spec.AdGroups[0] @@ -181,7 +243,7 @@ func Test_Create_LimitRange(t *testing.T) { sync(t, &env) - limitranges, _ := client.CoreV1().LimitRanges(namespaceName).List(context.TODO(), meta.ListOptions{}) + limitranges, _ := client.CoreV1().LimitRanges(namespaceName).List(context.TODO(), metav1.ListOptions{}) commonAsserts(t, env, limitRangesAsMeta(limitranges.Items), "mem-cpu-limit-range-env") @@ -228,7 +290,7 @@ func Test_Orphaned_Status(t *testing.T) { // sync calls OnSync on the Environment resource and asserts success func sync(t *testing.T, env *Environment) { - time := meta.NewTime(time.Now().UTC()) + time := metav1.NewTime(time.Now().UTC()) err := env.OnSync(time) t.Run("Method succeeds", func(t *testing.T) { @@ -241,7 +303,7 @@ func sync(t *testing.T, env *Environment) { } // commonAsserts runs a generic set of assertions about resource creation -func commonAsserts(t *testing.T, env Environment, resources []meta.Object, names ...string) { +func commonAsserts(t *testing.T, env Environment, resources []metav1.Object, names ...string) { t.Run("It creates a single resource", func(t *testing.T) { assert.Len(t, resources, len(names)) }) @@ -259,7 +321,7 @@ func commonAsserts(t *testing.T, env Environment, resources []meta.Object, names }) t.Run("Creation is idempotent", func(t *testing.T) { - err := env.OnSync(meta.NewTime(time.Now().UTC())) + err := env.OnSync(metav1.NewTime(time.Now().UTC())) assert.NoError(t, err) assert.Len(t, resources, len(names)) }) @@ -268,24 +330,24 @@ func commonAsserts(t *testing.T, env Environment, resources []meta.Object, names // following code is necessary noise to account for the lack of covariance and overloading // it simply exposes a resource slice as a generic interface -func namespacesAsMeta(items []core.Namespace) []meta.Object { - var slice []meta.Object +func namespacesAsMeta(items []core.Namespace) []metav1.Object { + var slice []metav1.Object for _, w := range items { w := w slice = append(slice, w.GetObjectMeta()) } return slice } -func roleBindingsAsMeta(items []rbac.RoleBinding) []meta.Object { - var slice []meta.Object +func roleBindingsAsMeta(items []rbac.RoleBinding) []metav1.Object { + var slice []metav1.Object for _, w := range items { w := w slice = append(slice, w.GetObjectMeta()) } return slice } -func limitRangesAsMeta(items []core.LimitRange) []meta.Object { - var slice []meta.Object +func limitRangesAsMeta(items []core.LimitRange) []metav1.Object { + var slice []metav1.Object for _, w := range items { w := w slice = append(slice, w.GetObjectMeta()) diff --git a/pkg/apis/environment/status.go b/pkg/apis/environment/status.go new file mode 100644 index 000000000..728b0507f --- /dev/null +++ b/pkg/apis/environment/status.go @@ -0,0 +1,41 @@ +package environment + +import ( + "context" + "fmt" + + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/util/retry" +) + +func (env *Environment) syncStatus(re *radixv1.RadixEnvironment, time metav1.Time) error { + err := env.updateRadixEnvironmentStatus(re, func(currStatus *radixv1.RadixEnvironmentStatus) { + currStatus.Orphaned = !existsInAppConfig(env.appConfig, re.Spec.EnvName) + // time is parameterized for testability + currStatus.Reconciled = time + }) + if err != nil { + return fmt.Errorf("failed to update status on environment %s: %v", re.Spec.EnvName, err) + } + return nil +} + +func (env *Environment) updateRadixEnvironmentStatus(re *radixv1.RadixEnvironment, changeStatusFunc func(currStatus *radixv1.RadixEnvironmentStatus)) error { + radixEnvironmentInterface := env.radixclient.RadixV1().RadixEnvironments() + return retry.RetryOnConflict(retry.DefaultRetry, func() error { + currentEnv, err := radixEnvironmentInterface.Get(context.Background(), re.GetName(), metav1.GetOptions{}) + if err != nil { + return err + } + changeStatusFunc(¤tEnv.Status) + _, err = radixEnvironmentInterface.UpdateStatus(context.Background(), currentEnv, metav1.UpdateOptions{}) + if err == nil && env.config.GetName() == re.GetName() { + currentEnv, err = radixEnvironmentInterface.Get(context.Background(), re.GetName(), metav1.GetOptions{}) + if err == nil { + env.config = currentEnv + } + } + return err + }) +} diff --git a/pkg/apis/environment/testdata/re.yaml b/pkg/apis/environment/testdata/re.yaml index 949bb70bf..00535e197 100644 --- a/pkg/apis/environment/testdata/re.yaml +++ b/pkg/apis/environment/testdata/re.yaml @@ -3,6 +3,8 @@ kind: RadixEnvironment metadata: name: testenv uid: af1d2960-5eb7-40e8-9ca2-12fc1fd9916e + finalizers: + - radix.equinor.com/environment-finalizer spec: appName: "testapp" envName: "testenv" From 1e96ba678161ff78b34977eb72bdf373355bd2c0 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 12 Dec 2023 16:43:13 +0100 Subject: [PATCH 109/121] Added unit-tests for ingress labels --- pkg/apis/deployment/deployment_test.go | 2 ++ pkg/apis/dnsalias/syncer_test.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/pkg/apis/deployment/deployment_test.go b/pkg/apis/deployment/deployment_test.go index 40157bb28..d4026da69 100644 --- a/pkg/apis/deployment/deployment_test.go +++ b/pkg/apis/deployment/deployment_test.go @@ -722,6 +722,7 @@ func TestObjectSynced_MultiComponent_NonActiveCluster_ContainsOnlyClusterSpecifi assert.Empty(t, appIngress.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") assert.Empty(t, appIngress.Labels[kube.RadixExternalAliasLabel], "Ingress should not be an external app alias") assert.Empty(t, appIngress.Labels[kube.RadixActiveClusterAliasLabel], "Ingress should not be an active cluster alias") + assert.Equal(t, "true", appIngress.Labels[kube.RadixDefaultAliasLabel], "Ingress should be default") assert.Equal(t, "app", appIngress.Labels[kube.RadixComponentLabel], "Ingress should have the corresponding component") quoteIngress := getIngressByName("radixquote", ingresses) @@ -729,6 +730,7 @@ func TestObjectSynced_MultiComponent_NonActiveCluster_ContainsOnlyClusterSpecifi assert.Empty(t, quoteIngress.Labels[kube.RadixAppAliasLabel], "Ingress should not be an app alias") assert.Empty(t, quoteIngress.Labels[kube.RadixExternalAliasLabel], "Ingress should not be an external app alias") assert.Empty(t, quoteIngress.Labels[kube.RadixActiveClusterAliasLabel], "Ingress should not be an active cluster alias") + assert.Equal(t, "true", quoteIngress.Labels[kube.RadixDefaultAliasLabel], "Ingress should be default") assert.Equal(t, "radixquote", quoteIngress.Labels[kube.RadixComponentLabel], "Ingress should have the corresponding component") } diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index e52697208..4f7fc5df0 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -180,6 +180,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { for _, ing := range ingresses.Items { appNameLabel := ing.GetLabels()[kube.RadixAppLabel] componentNameLabel := ing.GetLabels()[kube.RadixComponentLabel] + aliasLabel := ing.GetLabels()[kube.RadixAliasLabel] s.Assert().Len(ing.Spec.Rules, 1, "rules count") rule := ing.Spec.Rules[0] expectedIngress, ingressExists := ts.expectedIngress[ing.Name] @@ -191,6 +192,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { expectedNamespace := utils.GetEnvironmentNamespace(expectedIngress.appName, expectedIngress.envName) s.Assert().Equal(expectedNamespace, ing.GetNamespace(), "namespace") s.Assert().Equal(expectedIngress.component, componentNameLabel, "component name") + s.Assert().Equal(expectedIngress.alias, aliasLabel, "alias name in the label") s.Assert().Equal(expectedIngress.host, rule.Host, "rule host") s.Assert().Len(rule.IngressRuleValue.HTTP.Paths, 1, "http path count") httpIngressPath := rule.IngressRuleValue.HTTP.Paths[0] From cba15663f9659b76e787cebc588a82d177b5189f Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Tue, 12 Dec 2023 16:49:40 +0100 Subject: [PATCH 110/121] Fixed unit-tests --- pkg/apis/environment/environment_test.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/apis/environment/environment_test.go b/pkg/apis/environment/environment_test.go index b4eedf7b8..f02724d88 100644 --- a/pkg/apis/environment/environment_test.go +++ b/pkg/apis/environment/environment_test.go @@ -102,7 +102,7 @@ func Test_DeleteEnvironment_Deleted(t *testing.T) { require.NoError(t, err) timeNow := metav1.NewTime(time.Now()) re.ObjectMeta.DeletionTimestamp = &timeNow - re, err = radixclient.RadixV1().RadixEnvironments().Update(context.Background(), re, metav1.UpdateOptions{}) + _, err = radixclient.RadixV1().RadixEnvironments().Update(context.Background(), re, metav1.UpdateOptions{}) require.NoError(t, err) re, err = radixclient.RadixV1().RadixEnvironments().Get(context.Background(), "testenv", metav1.GetOptions{}) require.NoError(t, err) @@ -112,6 +112,7 @@ func Test_DeleteEnvironment_Deleted(t *testing.T) { sync(t, &env) re, err = radixclient.RadixV1().RadixEnvironments().Get(context.Background(), "testenv", metav1.GetOptions{}) + require.NoError(t, err) assert.NotNil(t, re.ObjectMeta.DeletionTimestamp) assert.NotContains(t, re.ObjectMeta.Finalizers, kube.RadixEnvironmentFinalizer, "unexpected environment finalizer") } @@ -126,6 +127,9 @@ func Test_DeleteEnvironment_DeletedDNSAlias(t *testing.T) { alias1Name := "alias1" err := createRadixDNSAliasForEnvironment(radixclient, alias1Name) require.NoError(t, err) + dnsAlias, err := radixclient.RadixV1().RadixDNSAliases().Get(context.Background(), alias1Name, metav1.GetOptions{}) + require.NoError(t, err) + require.NotNil(t, dnsAlias) re, err := radixclient.RadixV1().RadixEnvironments().Get(context.Background(), "testenv", metav1.GetOptions{}) require.NoError(t, err) timeNow := metav1.NewTime(time.Now()) @@ -137,6 +141,7 @@ func Test_DeleteEnvironment_DeletedDNSAlias(t *testing.T) { sync(t, &env) re, err = radixclient.RadixV1().RadixEnvironments().Get(context.Background(), "testenv", metav1.GetOptions{}) + require.NoError(t, err) assert.NotNil(t, re.ObjectMeta.DeletionTimestamp) assert.NotContains(t, re.ObjectMeta.Finalizers, kube.RadixEnvironmentFinalizer, "unexpected environment finalizer") _, err = radixclient.RadixV1().RadixDNSAliases().Get(context.Background(), alias1Name, metav1.GetOptions{}) From 2932d35f371c5d51acd796f8df8879191e1c4e67 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 14 Dec 2023 15:11:21 +0100 Subject: [PATCH 111/121] Registry moved from radix to radixv1 --- pkg/apis/alert/alert.go | 5 ++- pkg/apis/alert/alert_test.go | 3 +- pkg/apis/application/ownerreference.go | 5 ++- pkg/apis/application/roles.go | 10 +++--- .../applicationconfig_test.go | 5 ++- pkg/apis/applicationconfig/dns_alias_test.go | 3 +- pkg/apis/applicationconfig/ownerreference.go | 5 ++- pkg/apis/batch/utils.go | 5 ++- pkg/apis/deployment/ownerreference.go | 5 ++- pkg/apis/dnsalias/internal/ownerreference.go | 5 ++- pkg/apis/dnsalias/syncer_test.go | 5 ++- pkg/apis/environment/environment.go | 5 ++- pkg/apis/job/ownerreference.go | 5 ++- pkg/apis/radix/register.go | 32 ----------------- pkg/apis/radix/v1/register.go | 35 ++++++++++++++++--- pkg/apis/utils/application_builder.go | 5 ++- pkg/apis/utils/deployment_builder.go | 5 ++- pkg/apis/utils/environment_builder.go | 9 +++-- pkg/apis/utils/environment_builder_test.go | 9 +++-- pkg/apis/utils/job_builder.go | 5 ++- pkg/apis/utils/registration_builder.go | 5 ++- radix-operator/batch/controller.go | 5 ++- radix-operator/batch/controller_test.go | 3 +- radix-operator/deployment/controller.go | 5 ++- radix-operator/dnsalias/controller.go | 17 +++++---- radix-operator/dnsalias/controller_test.go | 3 +- radix-operator/environment/controller.go | 7 ++-- radix-operator/job/controller.go | 7 ++-- radix-operator/registration/controller.go | 7 ++-- 29 files changed, 97 insertions(+), 128 deletions(-) delete mode 100644 pkg/apis/radix/register.go diff --git a/pkg/apis/alert/alert.go b/pkg/apis/alert/alert.go index b0455dbee..05f71386c 100644 --- a/pkg/apis/alert/alert.go +++ b/pkg/apis/alert/alert.go @@ -6,7 +6,6 @@ import ( commonUtils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-operator/pkg/apis/kube" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" monitoring "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned" @@ -110,8 +109,8 @@ func (syncer *alertSyncer) updateRadixAlertStatus(changeStatusFunc func(currStat func (syncer *alertSyncer) getOwnerReference() []metav1.OwnerReference { return []metav1.OwnerReference{ { - APIVersion: radix.APIVersion, - Kind: radix.KindRadixAlert, + APIVersion: radixv1.SchemeGroupVersion.Identifier(), + Kind: radixv1.KindRadixAlert, Name: syncer.radixAlert.Name, UID: syncer.radixAlert.UID, Controller: commonUtils.BoolPtr(true), diff --git a/pkg/apis/alert/alert_test.go b/pkg/apis/alert/alert_test.go index 64f9b1119..f7416b15a 100644 --- a/pkg/apis/alert/alert_test.go +++ b/pkg/apis/alert/alert_test.go @@ -8,7 +8,6 @@ import ( "github.com/equinor/radix-common/utils" "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/kube" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/test" fakeradix "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" @@ -83,7 +82,7 @@ func (s *alertTestSuite) createAlertSyncer(alert *radixv1.RadixAlert, options .. } func (s *alertTestSuite) getRadixAlertAsOwnerReference(radixAlert *radixv1.RadixAlert) metav1.OwnerReference { - return metav1.OwnerReference{Kind: radix.KindRadixAlert, Name: radixAlert.Name, UID: radixAlert.UID, APIVersion: radix.APIVersion, Controller: utils.BoolPtr(true)} + return metav1.OwnerReference{Kind: radixv1.KindRadixAlert, Name: radixAlert.Name, UID: radixAlert.UID, APIVersion: radixv1.SchemeGroupVersion.Identifier(), Controller: utils.BoolPtr(true)} } func (s *alertTestSuite) Test_New() { diff --git a/pkg/apis/application/ownerreference.go b/pkg/apis/application/ownerreference.go index 220c9b97d..8f9b35c5c 100644 --- a/pkg/apis/application/ownerreference.go +++ b/pkg/apis/application/ownerreference.go @@ -1,7 +1,6 @@ package application import ( - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -16,8 +15,8 @@ func GetOwnerReferenceOfRegistration(registration *radixv1.RadixRegistration) [] trueVar := true return []metav1.OwnerReference{ { - APIVersion: radix.APIVersion, - Kind: radix.KindRadixRegistration, + APIVersion: radixv1.SchemeGroupVersion.Identifier(), + Kind: radixv1.KindRadixRegistration, Name: registration.Name, UID: registration.UID, Controller: &trueVar, diff --git a/pkg/apis/application/roles.go b/pkg/apis/application/roles.go index 25a53f448..92a86a10f 100644 --- a/pkg/apis/application/roles.go +++ b/pkg/apis/application/roles.go @@ -5,15 +5,15 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults/k8s" "github.com/equinor/radix-operator/pkg/apis/kube" - "github.com/equinor/radix-operator/pkg/apis/radix" + "github.com/equinor/radix-operator/pkg/apis/radix/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func (app *Application) buildRRClusterRole(clusterRoleName string, verbs []string) *rbacv1.ClusterRole { appName := app.registration.Name - return app.buildClusterRole(clusterRoleName, rbacv1.PolicyRule{APIGroups: []string{radix.GroupName}, - Resources: []string{radix.ResourceRadixRegistrations}, + return app.buildClusterRole(clusterRoleName, rbacv1.PolicyRule{APIGroups: []string{v1.SchemeGroupVersion.Group}, + Resources: []string{v1.ResourceRadixRegistrations}, ResourceNames: []string{appName}, Verbs: verbs, }) @@ -21,8 +21,8 @@ func (app *Application) buildRRClusterRole(clusterRoleName string, verbs []strin func (app *Application) buildRadixDNSAliasClusterRole(roleNamePrefix string) *rbacv1.ClusterRole { clusterRoleName := fmt.Sprintf("%s-%s", roleNamePrefix, app.registration.Name) - return app.buildClusterRole(clusterRoleName, rbacv1.PolicyRule{APIGroups: []string{radix.GroupName}, - Resources: []string{radix.ResourceRadixDNSAliases}, + return app.buildClusterRole(clusterRoleName, rbacv1.PolicyRule{APIGroups: []string{"radix.equinor.com"}, + Resources: []string{v1.ResourceRadixDNSAliases}, Verbs: []string{"list"}, }) } diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 887ac1976..e8d75d1ec 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -11,7 +11,6 @@ import ( "github.com/equinor/radix-operator/pkg/apis/applicationconfig" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -680,8 +679,8 @@ func rrAsOwnerReference(rr *radixv1.RadixRegistration) []metav1.OwnerReference { trueVar := true return []metav1.OwnerReference{ { - APIVersion: radix.APIVersion, - Kind: radix.KindRadixRegistration, + APIVersion: radixv1.SchemeGroupVersion.Identifier(), + Kind: radixv1.KindRadixRegistration, Name: rr.Name, UID: rr.UID, Controller: &trueVar, diff --git a/pkg/apis/applicationconfig/dns_alias_test.go b/pkg/apis/applicationconfig/dns_alias_test.go index 9e65dd6b2..596e8b6bc 100644 --- a/pkg/apis/applicationconfig/dns_alias_test.go +++ b/pkg/apis/applicationconfig/dns_alias_test.go @@ -5,7 +5,6 @@ import ( "fmt" "testing" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" commonTest "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -270,7 +269,7 @@ func Test_DNSAliases_CreateUpdateDelete(t *testing.T) { require.Len(t, ownerReferences, 1) ownerReference := ownerReferences[0] assert.Equal(t, radixDNSAlias.Spec.AppName, ownerReference.Name, "invalid or empty ownerReference.Name") - assert.Equal(t, radix.KindRadixApplication, ownerReference.Kind, "invalid or empty ownerReference.Kind") + assert.Equal(t, radixv1.KindRadixApplication, ownerReference.Kind, "invalid or empty ownerReference.Kind") assert.NotEmpty(t, ownerReference.UID, "ownerReference.UID is empty") require.NotNil(t, ownerReference.Controller, "ownerReference.Controller is nil") assert.True(t, *ownerReference.Controller, "ownerReference.Controller is false") diff --git a/pkg/apis/applicationconfig/ownerreference.go b/pkg/apis/applicationconfig/ownerreference.go index 1db78de08..a3d4397a3 100644 --- a/pkg/apis/applicationconfig/ownerreference.go +++ b/pkg/apis/applicationconfig/ownerreference.go @@ -2,15 +2,14 @@ package applicationconfig import ( "github.com/equinor/radix-common/utils" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func getOwnerReferenceOfRadixRegistration(radixRegistration *radixv1.RadixRegistration) metav1.OwnerReference { return metav1.OwnerReference{ - APIVersion: radix.APIVersion, - Kind: radix.KindRadixApplication, + APIVersion: radixv1.SchemeGroupVersion.Identifier(), + Kind: radixv1.KindRadixApplication, Name: radixRegistration.Name, UID: radixRegistration.UID, Controller: utils.BoolPtr(true), diff --git a/pkg/apis/batch/utils.go b/pkg/apis/batch/utils.go index 29e61df01..58636dfd6 100644 --- a/pkg/apis/batch/utils.go +++ b/pkg/apis/batch/utils.go @@ -5,7 +5,6 @@ import ( "github.com/equinor/radix-common/utils" "github.com/equinor/radix-common/utils/slice" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -53,8 +52,8 @@ func isBatchJobDone(batch *radixv1.RadixBatch, batchJobName string) bool { func ownerReference(job *radixv1.RadixBatch) []metav1.OwnerReference { return []metav1.OwnerReference{ { - APIVersion: radix.APIVersion, - Kind: radix.KindRadixBatch, + APIVersion: radixv1.SchemeGroupVersion.Identifier(), + Kind: radixv1.KindRadixBatch, Name: job.Name, UID: job.UID, Controller: utils.BoolPtr(true), diff --git a/pkg/apis/deployment/ownerreference.go b/pkg/apis/deployment/ownerreference.go index 8f7081ba0..5f81515f0 100644 --- a/pkg/apis/deployment/ownerreference.go +++ b/pkg/apis/deployment/ownerreference.go @@ -2,7 +2,6 @@ package deployment import ( "github.com/equinor/radix-common/utils" - "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" secretsstorev1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1" @@ -10,8 +9,8 @@ import ( func getOwnerReferenceOfDeployment(radixDeployment *v1.RadixDeployment) metav1.OwnerReference { return metav1.OwnerReference{ - APIVersion: radix.APIVersion, - Kind: radix.KindRadixDeployment, + APIVersion: v1.SchemeGroupVersion.Identifier(), + Kind: v1.KindRadixDeployment, Name: radixDeployment.Name, UID: radixDeployment.UID, Controller: utils.BoolPtr(true), diff --git a/pkg/apis/dnsalias/internal/ownerreference.go b/pkg/apis/dnsalias/internal/ownerreference.go index a9658fc2b..893f3982d 100644 --- a/pkg/apis/dnsalias/internal/ownerreference.go +++ b/pkg/apis/dnsalias/internal/ownerreference.go @@ -2,7 +2,6 @@ package internal import ( "github.com/equinor/radix-common/utils/pointers" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -10,8 +9,8 @@ import ( // GetOwnerReferences Gets RadixDNSAlias as an owner reference func GetOwnerReferences(radixDNSAlias *radixv1.RadixDNSAlias) []metav1.OwnerReference { return []metav1.OwnerReference{{ - APIVersion: radix.APIVersion, - Kind: radix.KindRadixDNSAlias, + APIVersion: radixv1.SchemeGroupVersion.Identifier(), + Kind: radixv1.KindRadixDNSAlias, Name: radixDNSAlias.Name, UID: radixDNSAlias.UID, Controller: pointers.Ptr(true), diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 4f7fc5df0..15fea29c7 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -9,7 +9,6 @@ import ( "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" commonTest "github.com/equinor/radix-operator/pkg/apis/test" "github.com/equinor/radix-operator/pkg/apis/utils" @@ -202,8 +201,8 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { s.Assert().Equal(expectedIngress.port, service.Port.Number, "rule backend service port") if len(ing.ObjectMeta.OwnerReferences) > 0 { ownerRef := ing.ObjectMeta.OwnerReferences[0] - s.Assert().Equal(radix.APIVersion, ownerRef.APIVersion, "ownerRef.APIVersion") - s.Assert().Equal(radix.KindRadixDNSAlias, ownerRef.Kind, "ownerRef.Kind") + s.Assert().Equal(radixv1.APIVersion, ownerRef.APIVersion, "ownerRef.APIVersion") + s.Assert().Equal(radixv1.KindRadixDNSAlias, ownerRef.Kind, "ownerRef.Kind") s.Assert().Equal(radixDNSAlias.GetName(), ownerRef.Name, "ownerRef.Name") s.Assert().Equal(radixDNSAlias.GetUID(), ownerRef.UID, "ownerRef.UID") s.Assert().True(ownerRef.Controller != nil && *ownerRef.Controller, "ownerRef.Controller") diff --git a/pkg/apis/environment/environment.go b/pkg/apis/environment/environment.go index 39b791c2d..eccbe2f1a 100644 --- a/pkg/apis/environment/environment.go +++ b/pkg/apis/environment/environment.go @@ -8,7 +8,6 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults/k8s" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/networkpolicy" - "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" @@ -256,8 +255,8 @@ func (env *Environment) AsOwnerReference() []metav1.OwnerReference { trueVar := true return []metav1.OwnerReference{ { - APIVersion: radix.APIVersion, - Kind: radix.KindRadixEnvironment, + APIVersion: v1.SchemeGroupVersion.Identifier(), + Kind: v1.KindRadixEnvironment, Name: env.config.Name, UID: env.config.UID, Controller: &trueVar, diff --git a/pkg/apis/job/ownerreference.go b/pkg/apis/job/ownerreference.go index 314db0d0a..42af8cc00 100644 --- a/pkg/apis/job/ownerreference.go +++ b/pkg/apis/job/ownerreference.go @@ -3,7 +3,6 @@ package job import ( "context" - "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -14,8 +13,8 @@ func GetOwnerReference(radixJob *v1.RadixJob) []metav1.OwnerReference { trueVar := true return []metav1.OwnerReference{ { - APIVersion: radix.APIVersion, - Kind: radix.KindRadixJob, + APIVersion: v1.SchemeGroupVersion.Identifier(), + Kind: v1.KindRadixJob, Name: radixJob.Name, UID: radixJob.UID, Controller: &trueVar, diff --git a/pkg/apis/radix/register.go b/pkg/apis/radix/register.go deleted file mode 100644 index 2c9509203..000000000 --- a/pkg/apis/radix/register.go +++ /dev/null @@ -1,32 +0,0 @@ -package radix - -const ( - // GroupName Group name for this API - GroupName = "radix.equinor.com" - // APIVersion API version for Radix objects - APIVersion = "radix.equinor.com/v1" - // Version version for Radix objects - Version = "v1" - // KindRadixRegistration RadixRegistration object Kind - KindRadixRegistration = "RadixRegistration" - // KindRadixEnvironment RadixEnvironment object Kind - KindRadixEnvironment = "RadixEnvironment" - // KindRadixApplication RadixApplication object Kind - KindRadixApplication = "RadixApplication" - // KindRadixDeployment RadixDeployment object Kind - KindRadixDeployment = "RadixDeployment" - // KindRadixJob RadixJob object Kind - KindRadixJob = "RadixJob" - // KindRadixBatch RadixBatch object Kind - KindRadixBatch = "RadixBatch" - // KindRadixAlert RadixAlert object Kind - KindRadixAlert = "RadixAlert" - // KindRadixDNSAlias RadixDNSAlias object Kind - KindRadixDNSAlias = "RadixDNSAlias" - // ResourceRadixRegistrations RadixRegistrations API resource - ResourceRadixRegistrations = "radixregistrations" - // ResourceRadixDNSAliases RadixDNSAliases API resource - ResourceRadixDNSAliases = "radixdnsaliases" - // ResourceRadixDeployment RadixDeployment API resource - ResourceRadixDeployment = "radixdeployment" -) diff --git a/pkg/apis/radix/v1/register.go b/pkg/apis/radix/v1/register.go index 486f780e4..64f2f3538 100644 --- a/pkg/apis/radix/v1/register.go +++ b/pkg/apis/radix/v1/register.go @@ -4,14 +4,12 @@ import ( meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - - "github.com/equinor/radix-operator/pkg/apis/radix" ) // SchemeGroupVersion provides the group version var SchemeGroupVersion = schema.GroupVersion{ - Group: radix.GroupName, - Version: radix.Version, + Group: "radix.equinor.com", + Version: "v1", } var ( // SchemeBuilder builds a scheme @@ -57,3 +55,32 @@ func addKnownTypes(scheme *runtime.Scheme) error { meta_v1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil } + +const ( + + // APIVersion API version for Radix objects + APIVersion = "radix.equinor.com/v1" + + // KindRadixRegistration RadixRegistration object Kind + KindRadixRegistration = "RadixRegistration" + // KindRadixEnvironment RadixEnvironment object Kind + KindRadixEnvironment = "RadixEnvironment" + // KindRadixApplication RadixApplication object Kind + KindRadixApplication = "RadixApplication" + // KindRadixDeployment RadixDeployment object Kind + KindRadixDeployment = "RadixDeployment" + // KindRadixJob RadixJob object Kind + KindRadixJob = "RadixJob" + // KindRadixBatch RadixBatch object Kind + KindRadixBatch = "RadixBatch" + // KindRadixAlert RadixAlert object Kind + KindRadixAlert = "RadixAlert" + // KindRadixDNSAlias RadixDNSAlias object Kind + KindRadixDNSAlias = "RadixDNSAlias" + // ResourceRadixRegistrations RadixRegistrations API resource + ResourceRadixRegistrations = "radixregistrations" + // ResourceRadixDNSAliases RadixDNSAliases API resource + ResourceRadixDNSAliases = "radixdnsaliases" + // ResourceRadixDeployment RadixDeployment API resource + ResourceRadixDeployment = "radixdeployment" +) diff --git a/pkg/apis/utils/application_builder.go b/pkg/apis/utils/application_builder.go index 57d08f3a6..2d5742770 100644 --- a/pkg/apis/utils/application_builder.go +++ b/pkg/apis/utils/application_builder.go @@ -3,7 +3,6 @@ package utils import ( "strings" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils/numbers" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -220,8 +219,8 @@ func (ap *ApplicationBuilderStruct) BuildRA() *radixv1.RadixApplication { radixApplication := &radixv1.RadixApplication{ TypeMeta: metav1.TypeMeta{ - APIVersion: radix.APIVersion, - Kind: radix.KindRadixApplication, + APIVersion: radixv1.SchemeGroupVersion.Identifier(), + Kind: radixv1.KindRadixApplication, }, ObjectMeta: metav1.ObjectMeta{ Name: ap.appName, diff --git a/pkg/apis/utils/deployment_builder.go b/pkg/apis/utils/deployment_builder.go index d8e8432af..f0bf45e24 100644 --- a/pkg/apis/utils/deployment_builder.go +++ b/pkg/apis/utils/deployment_builder.go @@ -6,7 +6,6 @@ import ( "time" "github.com/equinor/radix-operator/pkg/apis/kube" - "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils/numbers" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -246,8 +245,8 @@ func (db *DeploymentBuilderStruct) BuildRD() *v1.RadixDeployment { radixDeployment := &v1.RadixDeployment{ TypeMeta: metav1.TypeMeta{ - APIVersion: radix.APIVersion, - Kind: radix.KindRadixDeployment, + APIVersion: v1.SchemeGroupVersion.Identifier(), + Kind: v1.KindRadixDeployment, }, ObjectMeta: metav1.ObjectMeta{ Name: deployName, diff --git a/pkg/apis/utils/environment_builder.go b/pkg/apis/utils/environment_builder.go index eeeba63cd..9cfb77daa 100644 --- a/pkg/apis/utils/environment_builder.go +++ b/pkg/apis/utils/environment_builder.go @@ -4,7 +4,6 @@ import ( "time" "github.com/equinor/radix-operator/pkg/apis/kube" - "github.com/equinor/radix-operator/pkg/apis/radix" rx "github.com/equinor/radix-operator/pkg/apis/radix/v1" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -101,8 +100,8 @@ func (eb *EnvironmentBuilderStruct) WithRegistrationOwner(registration *rx.Radix } trueVar := true return eb.WithOwner(meta.OwnerReference{ - APIVersion: radix.APIVersion, - Kind: radix.KindRadixRegistration, + APIVersion: rx.APIVersion, + Kind: rx.KindRadixRegistration, Name: registration.Name, UID: registration.UID, Controller: &trueVar, @@ -156,8 +155,8 @@ func (eb *EnvironmentBuilderStruct) BuildRE() *rx.RadixEnvironment { radixEnvironment := &rx.RadixEnvironment{ TypeMeta: meta.TypeMeta{ - APIVersion: radix.APIVersion, - Kind: radix.KindRadixEnvironment, + APIVersion: rx.APIVersion, + Kind: rx.KindRadixEnvironment, }, ObjectMeta: meta.ObjectMeta{ Name: uniqueName, diff --git a/pkg/apis/utils/environment_builder_test.go b/pkg/apis/utils/environment_builder_test.go index b25fad461..b71d4b3d1 100644 --- a/pkg/apis/utils/environment_builder_test.go +++ b/pkg/apis/utils/environment_builder_test.go @@ -5,7 +5,6 @@ import ( "time" "github.com/equinor/radix-operator/pkg/apis/kube" - "github.com/equinor/radix-operator/pkg/apis/radix" "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/stretchr/testify/assert" meta "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -20,8 +19,8 @@ func Test_RadixEnvironment_Defaults(t *testing.T) { nilTime := (*meta.Time)(nil) // TypeMeta - assert.Equal(t, radix.APIVersion, re.TypeMeta.APIVersion) - assert.Equal(t, radix.KindRadixEnvironment, re.TypeMeta.Kind) + assert.Equal(t, v1.APIVersion, re.TypeMeta.APIVersion) + assert.Equal(t, v1.KindRadixEnvironment, re.TypeMeta.Kind) // ObjectMeta assert.Len(t, re.ObjectMeta.Annotations, 0) @@ -112,7 +111,7 @@ func Test_WithRegistrationOwner(t *testing.T) { assert.Len(t, re.ObjectMeta.OwnerReferences, 1) assert.Equal(t, "RR", re.ObjectMeta.OwnerReferences[0].Name) - assert.Equal(t, radix.KindRadixRegistration, re.ObjectMeta.OwnerReferences[0].Kind) + assert.Equal(t, v1.KindRadixRegistration, re.ObjectMeta.OwnerReferences[0].Kind) } func Test_WithRegistrationBuilder(t *testing.T) { @@ -123,7 +122,7 @@ func Test_WithRegistrationBuilder(t *testing.T) { assert.Len(t, re.ObjectMeta.OwnerReferences, 1) assert.Equal(t, "RR", re.ObjectMeta.OwnerReferences[0].Name) - assert.Equal(t, radix.KindRadixRegistration, re.ObjectMeta.OwnerReferences[0].Kind) + assert.Equal(t, v1.KindRadixRegistration, re.ObjectMeta.OwnerReferences[0].Kind) } func Test_WithResourceVersion(t *testing.T) { diff --git a/pkg/apis/utils/job_builder.go b/pkg/apis/utils/job_builder.go index 68da8664f..67f5f4b8f 100644 --- a/pkg/apis/utils/job_builder.go +++ b/pkg/apis/utils/job_builder.go @@ -5,7 +5,6 @@ import ( "time" "github.com/equinor/radix-operator/pkg/apis/kube" - "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -157,8 +156,8 @@ func (jb *JobBuilderStruct) GetApplicationBuilder() ApplicationBuilder { func (jb *JobBuilderStruct) BuildRJ() *v1.RadixJob { radixJob := &v1.RadixJob{ TypeMeta: metav1.TypeMeta{ - APIVersion: radix.APIVersion, - Kind: radix.KindRadixJob, + APIVersion: v1.SchemeGroupVersion.Identifier(), + Kind: v1.KindRadixJob, }, ObjectMeta: metav1.ObjectMeta{ Name: jb.jobName, diff --git a/pkg/apis/utils/registration_builder.go b/pkg/apis/utils/registration_builder.go index 2cc60f4c3..dacb2e136 100644 --- a/pkg/apis/utils/registration_builder.go +++ b/pkg/apis/utils/registration_builder.go @@ -4,7 +4,6 @@ import ( "strings" "time" - "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -181,8 +180,8 @@ func (rb *RegistrationBuilderStruct) BuildRR() *v1.RadixRegistration { radixRegistration := &v1.RadixRegistration{ TypeMeta: metav1.TypeMeta{ - APIVersion: radix.APIVersion, - Kind: radix.KindRadixRegistration, + APIVersion: v1.SchemeGroupVersion.Identifier(), + Kind: v1.KindRadixRegistration, }, ObjectMeta: metav1.ObjectMeta{ Name: rb.name, diff --git a/radix-operator/batch/controller.go b/radix-operator/batch/controller.go index 8cbcfabbd..559f10459 100644 --- a/radix-operator/batch/controller.go +++ b/radix-operator/batch/controller.go @@ -5,7 +5,6 @@ import ( "reflect" "github.com/equinor/radix-operator/pkg/apis/metrics" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" informers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" @@ -97,10 +96,10 @@ func NewController(client kubernetes.Interface, if oldMeta.GetResourceVersion() == newMeta.GetResourceVersion() { return } - controller.HandleObject(newObj, radix.KindRadixBatch, getOwner) + controller.HandleObject(newObj, radixv1.KindRadixBatch, getOwner) }, DeleteFunc: func(obj interface{}) { - controller.HandleObject(obj, radix.KindRadixBatch, getOwner) + controller.HandleObject(obj, radixv1.KindRadixBatch, getOwner) }, }); err != nil { panic(err) diff --git a/radix-operator/batch/controller_test.go b/radix-operator/batch/controller_test.go index 94e39bbb5..ba8598a5b 100644 --- a/radix-operator/batch/controller_test.go +++ b/radix-operator/batch/controller_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/equinor/radix-common/utils" - "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/radix-operator/common" "github.com/stretchr/testify/suite" @@ -62,7 +61,7 @@ func (s *controllerTestSuite) Test_RadixBatchEvents() { Namespace: namespace, ResourceVersion: "1", OwnerReferences: []metav1.OwnerReference{ - {APIVersion: radix.APIVersion, Kind: radix.KindRadixBatch, Name: batchName, Controller: utils.BoolPtr(true)}, + {APIVersion: v1.SchemeGroupVersion.Identifier(), Kind: v1.KindRadixBatch, Name: batchName, Controller: utils.BoolPtr(true)}, }, }} s.Handler.EXPECT().Sync(namespace, batchName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) diff --git a/radix-operator/deployment/controller.go b/radix-operator/deployment/controller.go index 52bd43c6f..4f66248f9 100644 --- a/radix-operator/deployment/controller.go +++ b/radix-operator/deployment/controller.go @@ -9,7 +9,6 @@ import ( "github.com/equinor/radix-operator/pkg/apis/deployment" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/metrics" - "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" informers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" @@ -128,10 +127,10 @@ func NewController(client kubernetes.Interface, if newService.ResourceVersion == oldService.ResourceVersion { return } - controller.HandleObject(cur, radix.KindRadixDeployment, getObject) + controller.HandleObject(cur, v1.KindRadixDeployment, getObject) }, DeleteFunc: func(obj interface{}) { - controller.HandleObject(obj, radix.KindRadixDeployment, getObject) + controller.HandleObject(obj, v1.KindRadixDeployment, getObject) }, }); err != nil { utilruntime.HandleError(err) diff --git a/radix-operator/dnsalias/controller.go b/radix-operator/dnsalias/controller.go index c1d729a1f..bef0178db 100644 --- a/radix-operator/dnsalias/controller.go +++ b/radix-operator/dnsalias/controller.go @@ -5,7 +5,6 @@ import ( "reflect" "github.com/equinor/radix-operator/pkg/apis/metrics" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -48,13 +47,13 @@ func NewController(kubeClient kubernetes.Interface, controller := &common.Controller{ Name: controllerAgentName, - HandlerOf: radix.KindRadixDNSAlias, + HandlerOf: radixv1.KindRadixDNSAlias, KubeClient: kubeClient, RadixClient: radixClient, Informer: radixDNSAliasInformer.Informer(), KubeInformerFactory: kubeInformerFactory, WorkQueue: workqueue.NewRateLimitingQueueWithConfig(workqueue.DefaultControllerRateLimiter(), workqueue.RateLimitingQueueConfig{ - Name: radix.KindRadixDNSAlias, + Name: radixv1.KindRadixDNSAlias, }), Handler: handler, Log: logger, @@ -80,7 +79,7 @@ func addEventHandlersForIngresses(ingressInformer networkinginformersv1.IngressI return } logger.Debugf("updated Ingress %s", newIng.GetName()) - controller.HandleObject(newObj, radix.KindRadixDNSAlias, getOwner) // restore ingress if it does not correspond to RadixDNSAlias + controller.HandleObject(newObj, radixv1.KindRadixDNSAlias, getOwner) // restore ingress if it does not correspond to RadixDNSAlias }, DeleteFunc: func(obj interface{}) { ing, converted := obj.(*networkingv1.Ingress) @@ -89,7 +88,7 @@ func addEventHandlersForIngresses(ingressInformer networkinginformersv1.IngressI return } logger.Debugf("deleted Ingress %s", ing.GetName()) - controller.HandleObject(ing, radix.KindRadixDNSAlias, getOwner) // restore ingress if RadixDNSAlias exist + controller.HandleObject(ing, radixv1.KindRadixDNSAlias, getOwner) // restore ingress if RadixDNSAlias exist }, }) if err != nil { @@ -127,14 +126,14 @@ func addEventHandlersForRadixDNSAliases(radixDNSAliasInformer radixinformersv1.R if err != nil { logger.Errorf("failed to enqueue the RadixDNSAlias %s", alias.GetName()) } - metrics.CustomResourceAdded(radix.KindRadixDNSAlias) + metrics.CustomResourceAdded(radixv1.KindRadixDNSAlias) }, UpdateFunc: func(old, cur interface{}) { oldAlias := old.(*radixv1.RadixDNSAlias) newAlias := cur.(*radixv1.RadixDNSAlias) if deepEqual(oldAlias, newAlias) { logger.Debugf("RadixDNSAlias object is equal to old for %s. Do nothing", newAlias.GetName()) - metrics.CustomResourceUpdatedButSkipped(radix.KindRadixDNSAlias) + metrics.CustomResourceUpdatedButSkipped(radixv1.KindRadixDNSAlias) return } logger.Debugf("updated RadixDNSAlias %s", newAlias.GetName()) @@ -142,7 +141,7 @@ func addEventHandlersForRadixDNSAliases(radixDNSAliasInformer radixinformersv1.R if err != nil { logger.Errorf("failed to enqueue the RadixDNSAlias %s", newAlias.GetName()) } - metrics.CustomResourceUpdated(radix.KindRadixDNSAlias) + metrics.CustomResourceUpdated(radixv1.KindRadixDNSAlias) }, DeleteFunc: func(obj interface{}) { alias, converted := obj.(*radixv1.RadixDNSAlias) @@ -155,7 +154,7 @@ func addEventHandlersForRadixDNSAliases(radixDNSAliasInformer radixinformersv1.R if err != nil { logger.Errorf("error on RadixDNSAlias object deleted event received for %s: %v", key, err) } - metrics.CustomResourceDeleted(radix.KindRadixDNSAlias) + metrics.CustomResourceDeleted(radixv1.KindRadixDNSAlias) }, }) if err != nil { diff --git a/radix-operator/dnsalias/controller_test.go b/radix-operator/dnsalias/controller_test.go index 8c295496e..bba48e22e 100644 --- a/radix-operator/dnsalias/controller_test.go +++ b/radix-operator/dnsalias/controller_test.go @@ -9,7 +9,6 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults" dnsaliasapi "github.com/equinor/radix-operator/pkg/apis/dnsalias" "github.com/equinor/radix-operator/pkg/apis/ingress" - "github.com/equinor/radix-operator/pkg/apis/radix" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" @@ -92,7 +91,7 @@ func (s *controllerTestSuite) Test_RadixDNSAliasEvents() { // Add Ingress with owner reference to RadixDNSAlias should not trigger sync cfg := &dnsalias2.DNSConfig{DNSZone: dnsZone} ing := buildRadixDNSAliasIngress(alias, int32(8080), cfg) - ing.SetOwnerReferences([]metav1.OwnerReference{{APIVersion: radix.APIVersion, Kind: radix.KindRadixDNSAlias, Name: aliasName, Controller: pointers.Ptr(true)}}) + ing.SetOwnerReferences([]metav1.OwnerReference{{APIVersion: radixv1.SchemeGroupVersion.Identifier(), Kind: radixv1.KindRadixDNSAlias, Name: aliasName, Controller: pointers.Ptr(true)}}) namespace := utils.GetEnvironmentNamespace(alias.Spec.AppName, alias.Spec.Environment) s.Handler.EXPECT().Sync(namespace, aliasName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) ing, err = dnsaliasapi.CreateRadixDNSAliasIngress(s.KubeClient, alias.Spec.AppName, alias.Spec.Environment, ing) diff --git a/radix-operator/environment/controller.go b/radix-operator/environment/controller.go index 30733ba7a..f052c7458 100644 --- a/radix-operator/environment/controller.go +++ b/radix-operator/environment/controller.go @@ -8,7 +8,6 @@ import ( radixutils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/metrics" - "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" @@ -107,7 +106,7 @@ func NewController(client kubernetes.Interface, if _, err := namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ DeleteFunc: func(obj interface{}) { // attempt to sync environment if it is the owner of this namespace - controller.HandleObject(obj, radix.KindRadixEnvironment, getOwner) + controller.HandleObject(obj, v1.KindRadixEnvironment, getOwner) }, }); err != nil { utilruntime.HandleError(err) @@ -117,7 +116,7 @@ func NewController(client kubernetes.Interface, if _, err := rolebindingInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ DeleteFunc: func(obj interface{}) { // attempt to sync environment if it is the owner of this role-binding - controller.HandleObject(obj, radix.KindRadixEnvironment, getOwner) + controller.HandleObject(obj, v1.KindRadixEnvironment, getOwner) }, }); err != nil { utilruntime.HandleError(err) @@ -127,7 +126,7 @@ func NewController(client kubernetes.Interface, if _, err := limitrangeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ DeleteFunc: func(obj interface{}) { // attempt to sync environment if it is the owner of this limit-range - controller.HandleObject(obj, radix.KindRadixEnvironment, getOwner) + controller.HandleObject(obj, v1.KindRadixEnvironment, getOwner) }, }); err != nil { utilruntime.HandleError(err) diff --git a/radix-operator/job/controller.go b/radix-operator/job/controller.go index 98b2532a3..85ef02e50 100644 --- a/radix-operator/job/controller.go +++ b/radix-operator/job/controller.go @@ -6,7 +6,6 @@ import ( "github.com/equinor/radix-operator/pkg/apis/job" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/metrics" - "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" informers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" @@ -109,7 +108,7 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac if newJob.ResourceVersion == oldJob.ResourceVersion { return } - controller.HandleObject(cur, radix.KindRadixJob, getObject) + controller.HandleObject(cur, v1.KindRadixJob, getObject) }, DeleteFunc: func(obj interface{}) { radixJob, converted := obj.(*batchv1.Job) @@ -119,7 +118,7 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac } // If a kubernetes job gets deleted for a running job, the running radix job should // take this into account. The running job will get restarted - controller.HandleObject(radixJob, radix.KindRadixJob, getObject) + controller.HandleObject(radixJob, v1.KindRadixJob, getObject) }, }); err != nil { utilruntime.HandleError(err) @@ -145,7 +144,7 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac return } - controller.HandleObject(job, radix.KindRadixJob, getObject) + controller.HandleObject(job, v1.KindRadixJob, getObject) } }, }); err != nil { diff --git a/radix-operator/registration/controller.go b/radix-operator/registration/controller.go index 9a694304e..516ca5df0 100644 --- a/radix-operator/registration/controller.go +++ b/radix-operator/registration/controller.go @@ -7,7 +7,6 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-operator/pkg/apis/metrics" - "github.com/equinor/radix-operator/pkg/apis/radix" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" informers "github.com/equinor/radix-operator/pkg/client/informers/externalversions" @@ -102,7 +101,7 @@ func NewController(client kubernetes.Interface, namespaceInformer := kubeInformerFactory.Core().V1().Namespaces() if _, err := namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ DeleteFunc: func(obj interface{}) { - controller.HandleObject(obj, radix.KindRadixRegistration, getObject) + controller.HandleObject(obj, v1.KindRadixRegistration, getObject) }, }); err != nil { utilruntime.HandleError(err) @@ -126,7 +125,7 @@ func NewController(client kubernetes.Interface, if isGitDeployKey(newSecret) && newSecret.Namespace != "" { // Resync, as deploy key is updated. Resync is triggered on namespace, since RR not directly own the // secret - controller.HandleObject(namespace, radix.KindRadixRegistration, getObject) + controller.HandleObject(namespace, v1.KindRadixRegistration, getObject) } }, DeleteFunc: func(obj interface{}) { @@ -148,7 +147,7 @@ func NewController(client kubernetes.Interface, if isGitDeployKey(secret) && namespace.Labels[kube.RadixAppLabel] != "" { // Resync, as deploy key is deleted. Resync is triggered on namespace, since RR not directly own the // secret - controller.HandleObject(namespace, radix.KindRadixRegistration, getObject) + controller.HandleObject(namespace, v1.KindRadixRegistration, getObject) } }, }); err != nil { From 3963c007dc08be436bb0ae78e7e39b97b98022bc Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Thu, 14 Dec 2023 16:44:48 +0100 Subject: [PATCH 112/121] Cleanup --- pkg/apis/dnsalias/syncer_test.go | 2 +- pkg/apis/radix/v1/register.go | 2 +- pkg/apis/utils/environment_builder.go | 47 +++++++--------------- pkg/apis/utils/environment_builder_test.go | 2 +- 4 files changed, 18 insertions(+), 35 deletions(-) diff --git a/pkg/apis/dnsalias/syncer_test.go b/pkg/apis/dnsalias/syncer_test.go index 15fea29c7..c4c566c8b 100644 --- a/pkg/apis/dnsalias/syncer_test.go +++ b/pkg/apis/dnsalias/syncer_test.go @@ -201,7 +201,7 @@ func (s *syncerTestSuite) Test_syncer_OnSync() { s.Assert().Equal(expectedIngress.port, service.Port.Number, "rule backend service port") if len(ing.ObjectMeta.OwnerReferences) > 0 { ownerRef := ing.ObjectMeta.OwnerReferences[0] - s.Assert().Equal(radixv1.APIVersion, ownerRef.APIVersion, "ownerRef.APIVersion") + s.Assert().Equal(radixv1.SchemeGroupVersion.Identifier(), ownerRef.APIVersion, "ownerRef.APIVersion") s.Assert().Equal(radixv1.KindRadixDNSAlias, ownerRef.Kind, "ownerRef.Kind") s.Assert().Equal(radixDNSAlias.GetName(), ownerRef.Name, "ownerRef.Name") s.Assert().Equal(radixDNSAlias.GetUID(), ownerRef.UID, "ownerRef.UID") diff --git a/pkg/apis/radix/v1/register.go b/pkg/apis/radix/v1/register.go index 64f2f3538..30d50b68a 100644 --- a/pkg/apis/radix/v1/register.go +++ b/pkg/apis/radix/v1/register.go @@ -82,5 +82,5 @@ const ( // ResourceRadixDNSAliases RadixDNSAliases API resource ResourceRadixDNSAliases = "radixdnsaliases" // ResourceRadixDeployment RadixDeployment API resource - ResourceRadixDeployment = "radixdeployment" + ResourceRadixDeployment = "radixdeployments" ) diff --git a/pkg/apis/utils/environment_builder.go b/pkg/apis/utils/environment_builder.go index 9cfb77daa..48993bbb5 100644 --- a/pkg/apis/utils/environment_builder.go +++ b/pkg/apis/utils/environment_builder.go @@ -4,10 +4,9 @@ import ( "time" "github.com/equinor/radix-operator/pkg/apis/kube" - rx "github.com/equinor/radix-operator/pkg/apis/radix/v1" + radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/uuid" ) // EnvironmentBuilder Handles construction of RE @@ -20,13 +19,13 @@ type EnvironmentBuilder interface { WithReconciledTime(time.Time) EnvironmentBuilder WithUID(types.UID) EnvironmentBuilder WithOwner(owner meta.OwnerReference) EnvironmentBuilder - WithRegistrationOwner(registration *rx.RadixRegistration) EnvironmentBuilder + WithRegistrationOwner(registration *radixv1.RadixRegistration) EnvironmentBuilder WithRegistrationBuilder(builder RegistrationBuilder) EnvironmentBuilder WithOrphaned(isOrphan bool) EnvironmentBuilder - WithEgressConfig(egressRules rx.EgressConfig) EnvironmentBuilder + WithEgressConfig(egressRules radixv1.EgressConfig) EnvironmentBuilder WithResourceVersion(version string) EnvironmentBuilder GetRegistrationBuilder() RegistrationBuilder - BuildRE() *rx.RadixEnvironment + BuildRE() *radixv1.RadixEnvironment } // EnvironmentBuilderStruct Holds instance variables @@ -34,7 +33,7 @@ type EnvironmentBuilderStruct struct { registrationBuilder RegistrationBuilder EnvironmentName string AppName string - EgressConfig rx.EgressConfig + EgressConfig radixv1.EgressConfig Labels map[string]string AppLabel bool CreatedTime *time.Time @@ -94,14 +93,14 @@ func (eb *EnvironmentBuilderStruct) WithOwner(owner meta.OwnerReference) Environ } // WithRegistrationOwner appends new OwnerReference to a RadixRegistration -func (eb *EnvironmentBuilderStruct) WithRegistrationOwner(registration *rx.RadixRegistration) EnvironmentBuilder { +func (eb *EnvironmentBuilderStruct) WithRegistrationOwner(registration *radixv1.RadixRegistration) EnvironmentBuilder { if registration == nil { return eb } trueVar := true return eb.WithOwner(meta.OwnerReference{ - APIVersion: rx.APIVersion, - Kind: rx.KindRadixRegistration, + APIVersion: radixv1.SchemeGroupVersion.Identifier(), + Kind: radixv1.KindRadixRegistration, Name: registration.Name, UID: registration.UID, Controller: &trueVar, @@ -132,13 +131,13 @@ func (eb *EnvironmentBuilderStruct) WithOrphaned(isOrphan bool) EnvironmentBuild } // WithEgressConfig sets the egress configuration for this environment -func (eb *EnvironmentBuilderStruct) WithEgressConfig(egress rx.EgressConfig) EnvironmentBuilder { +func (eb *EnvironmentBuilderStruct) WithEgressConfig(egress radixv1.EgressConfig) EnvironmentBuilder { eb.EgressConfig = egress return eb } // BuildRE builds RE structure based on set variables -func (eb *EnvironmentBuilderStruct) BuildRE() *rx.RadixEnvironment { +func (eb *EnvironmentBuilderStruct) BuildRE() *radixv1.RadixEnvironment { var uniqueName string if eb.AppName == "" { @@ -153,10 +152,10 @@ func (eb *EnvironmentBuilderStruct) BuildRE() *rx.RadixEnvironment { eb.WithRegistrationOwner(eb.registrationBuilder.BuildRR()) } - radixEnvironment := &rx.RadixEnvironment{ + radixEnvironment := &radixv1.RadixEnvironment{ TypeMeta: meta.TypeMeta{ - APIVersion: rx.APIVersion, - Kind: rx.KindRadixEnvironment, + APIVersion: radixv1.SchemeGroupVersion.Identifier(), + Kind: radixv1.KindRadixEnvironment, }, ObjectMeta: meta.ObjectMeta{ Name: uniqueName, @@ -166,12 +165,12 @@ func (eb *EnvironmentBuilderStruct) BuildRE() *rx.RadixEnvironment { OwnerReferences: eb.Owners, Finalizers: []string{kube.RadixEnvironmentFinalizer}, }, - Spec: rx.RadixEnvironmentSpec{ + Spec: radixv1.RadixEnvironmentSpec{ AppName: eb.AppName, EnvName: eb.EnvironmentName, Egress: eb.EgressConfig, }, - Status: rx.RadixEnvironmentStatus{ + Status: radixv1.RadixEnvironmentStatus{ Orphaned: eb.IsOrphan, }, } @@ -203,19 +202,3 @@ func NewEnvironmentBuilder() EnvironmentBuilder { IsOrphan: true, } } - -// ARadixEnvironment constructor for environment builder containing test data -func ARadixEnvironment() EnvironmentBuilder { - now := time.Now() - builder := NewEnvironmentBuilder(). - WithAppName("anyapp"). - WithEnvironmentName("anyenv"). - WithResourceVersion("v1.0.0"). - WithAppLabel(). - WithCreatedTime(now). - WithReconciledTime(now). - WithRegistrationBuilder(ARadixRegistration()). - WithUID(uuid.NewUUID()) - - return builder -} diff --git a/pkg/apis/utils/environment_builder_test.go b/pkg/apis/utils/environment_builder_test.go index b71d4b3d1..365be14bf 100644 --- a/pkg/apis/utils/environment_builder_test.go +++ b/pkg/apis/utils/environment_builder_test.go @@ -19,7 +19,7 @@ func Test_RadixEnvironment_Defaults(t *testing.T) { nilTime := (*meta.Time)(nil) // TypeMeta - assert.Equal(t, v1.APIVersion, re.TypeMeta.APIVersion) + assert.Equal(t, v1.SchemeGroupVersion.Identifier(), re.TypeMeta.APIVersion) assert.Equal(t, v1.KindRadixEnvironment, re.TypeMeta.Kind) // ObjectMeta From a00b19c53bb2fde812f03e7a7155ee82fc7a4883 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 15 Dec 2023 14:16:18 +0100 Subject: [PATCH 113/121] Cleanup --- pkg/apis/alert/alert_test.go | 35 ++-- pkg/apis/application/application_test.go | 49 ++--- pkg/apis/application/rolebinding.go | 4 +- .../applicationconfig_test.go | 7 +- pkg/apis/applicationconfig/imagehubsecret.go | 25 --- pkg/apis/batch/syncer_test.go | 6 +- pkg/apis/deployment/deployment_test.go | 183 ++++++++---------- .../deployment/environmentvariables_test.go | 28 ++- .../oauthproxyresourcemanager_test.go | 100 ++++------ pkg/apis/dnsalias/ingress.go | 56 +++++- pkg/apis/dnsalias/syncer.go | 58 +----- pkg/apis/job/job_steps_test.go | 15 +- pkg/apis/job/job_test.go | 29 ++- pkg/apis/kube/environment_variables_test.go | 34 ++-- pkg/apis/radix/v1/register.go | 7 +- radix-operator/alert/controller_test.go | 45 ++--- radix-operator/application/controller_test.go | 28 ++- radix-operator/common/controller_test.go | 10 +- radix-operator/deployment/controller_test.go | 17 +- radix-operator/job/controller_test.go | 21 +- 20 files changed, 333 insertions(+), 424 deletions(-) diff --git a/pkg/apis/alert/alert_test.go b/pkg/apis/alert/alert_test.go index f7416b15a..33b2b0f8a 100644 --- a/pkg/apis/alert/alert_test.go +++ b/pkg/apis/alert/alert_test.go @@ -106,9 +106,8 @@ func (s *alertTestSuite) Test_OnSync_ResourcesCreated() { ObjectMeta: metav1.ObjectMeta{Name: appName}, Spec: radixv1.RadixRegistrationSpec{AdGroups: []string{"admin"}, ReaderAdGroups: []string{"reader"}}, } - if _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) + s.Require().NoError(err) radixAlert := &radixv1.RadixAlert{ ObjectMeta: metav1.ObjectMeta{Name: alertName, Labels: map[string]string{kube.RadixAppLabel: appName}, UID: alertUID}, Spec: radixv1.RadixAlertSpec{}, @@ -116,7 +115,7 @@ func (s *alertTestSuite) Test_OnSync_ResourcesCreated() { radixAlert, _ = s.radixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), radixAlert, metav1.CreateOptions{}) sut := s.createAlertSyncer(radixAlert) - err := sut.OnSync() + err = sut.OnSync() s.Require().NoError(err) _, err = s.kubeClient.CoreV1().Secrets(namespace).Get(context.Background(), GetAlertSecretName(alertName), metav1.GetOptions{}) @@ -182,13 +181,13 @@ func (s *alertTestSuite) Test_OnSync_Rbac_CreateWithOwnerReference() { } radixalert, _ = s.radixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), radixalert, metav1.CreateOptions{}) rr := &radixv1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}} - if _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) + s.Require().NoError(err) + expectedAlertOwnerRef := s.getRadixAlertAsOwnerReference(radixalert) sut := s.createAlertSyncer(radixalert) - err := sut.OnSync() + err = sut.OnSync() s.Require().NoError(err) actualRoles, _ := s.kubeClient.RbacV1().Roles(namespace).List(context.Background(), metav1.ListOptions{}) @@ -217,9 +216,9 @@ func (s *alertTestSuite) Test_OnSync_Rbac_UpdateWithOwnerReference() { s.Require().NoError(err) } rr := &radixv1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}} - if _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err = s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) + s.Require().NoError(err) + _, err = s.kubeClient.RbacV1().Roles(namespace).Create(context.Background(), &rbacv1.Role{ObjectMeta: metav1.ObjectMeta{Name: getAlertConfigSecretAdminRoleName(alertName)}}, metav1.CreateOptions{}) s.Nil(err) _, err = s.kubeClient.RbacV1().RoleBindings(namespace).Create(context.Background(), &rbacv1.RoleBinding{ObjectMeta: metav1.ObjectMeta{Name: getAlertConfigSecretAdminRoleName(alertName)}}, metav1.CreateOptions{}) @@ -258,12 +257,11 @@ func (s *alertTestSuite) Test_OnSync_Rbac_ConfiguredCorrectly() { } radixalert, _ = s.radixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), radixalert, metav1.CreateOptions{}) rr := &radixv1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}, Spec: radixv1.RadixRegistrationSpec{AdGroups: adminGroups, ReaderAdGroups: readerGroups}} - if _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) + s.Require().NoError(err) sut := s.createAlertSyncer(radixalert) - err := sut.OnSync() + err = sut.OnSync() s.Require().NoError(err) actualAdminRole, _ := s.kubeClient.RbacV1().Roles(namespace).Get(context.Background(), getAlertConfigSecretAdminRoleName(alertName), metav1.GetOptions{}) @@ -310,12 +308,11 @@ func (s *alertTestSuite) Test_OnSync_Secret_RemoveOrphanedKeys() { GetSlackConfigSecretKeyName("orphaned2"): []byte("bar"), }, } - if _, err := s.kubeClient.CoreV1().Secrets(namespace).Create(context.Background(), secret, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err := s.kubeClient.CoreV1().Secrets(namespace).Create(context.Background(), secret, metav1.CreateOptions{}) + s.Require().NoError(err) sut := s.createAlertSyncer(radixalert) - err := sut.OnSync() + err = sut.OnSync() s.Require().NoError(err) actualSecret, _ := s.kubeClient.CoreV1().Secrets(namespace).Get(context.Background(), GetAlertSecretName(alertName), metav1.GetOptions{}) diff --git a/pkg/apis/application/application_test.go b/pkg/apis/application/application_test.go index c31e0f01f..503cb5217 100644 --- a/pkg/apis/application/application_test.go +++ b/pkg/apis/application/application_test.go @@ -98,10 +98,9 @@ func TestOnSync_RegistrationCreated_AppNamespaceWithResourcesCreated(t *testing. // Test appName := "any-app" - if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). - WithName(appName)); err != nil { - require.NoError(t, err) - } + _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). + WithName(appName)) + require.NoError(t, err) ns, err := client.CoreV1().Namespaces().Get(context.TODO(), utils.GetAppNamespace(appName), metav1.GetOptions{}) assert.NoError(t, err) @@ -144,10 +143,9 @@ func TestOnSync_PodSecurityStandardLabelsSetOnNamespace(t *testing.T) { // Test appName := "any-app" - if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). - WithName(appName)); err != nil { - require.NoError(t, err) - } + _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). + WithName(appName)) + require.NoError(t, err) ns, err := client.CoreV1().Namespaces().Get(context.TODO(), utils.GetAppNamespace(appName), metav1.GetOptions{}) assert.NoError(t, err) @@ -172,24 +170,22 @@ func TestOnSync_RegistrationCreated_AppNamespaceReconciled(t *testing.T) { defer os.Clearenv() // Create namespaces manually - if _, err := client.CoreV1().Namespaces().Create( + _, err := client.CoreV1().Namespaces().Create( context.TODO(), &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "any-app-app", }, }, - metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } + metav1.CreateOptions{}) + require.NoError(t, err) label := fmt.Sprintf("%s=%s", kube.RadixAppLabel, "any-app") // Test - if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). - WithName("any-app")); err != nil { - require.NoError(t, err) - } + _, err = applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). + WithName("any-app")) + require.NoError(t, err) namespaces, _ := client.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{ LabelSelector: label, @@ -205,12 +201,11 @@ func TestOnSync_NoUserGroupDefined_DefaultUserGroupSet(t *testing.T) { os.Setenv(defaults.OperatorDefaultUserGroupEnvironmentVariable, defaultRole) // Test - if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). + _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). WithName("any-app"). WithAdGroups([]string{}). - WithReaderAdGroups([]string{})); err != nil { - require.NoError(t, err) - } + WithReaderAdGroups([]string{})) + require.NoError(t, err) rolebindings, _ := client.RbacV1().RoleBindings("any-app-app").List(context.TODO(), metav1.ListOptions{}) assert.ElementsMatch(t, @@ -234,10 +229,9 @@ func TestOnSync_LimitsDefined_LimitsSet(t *testing.T) { os.Setenv(defaults.OperatorAppLimitDefaultRequestMemoryEnvironmentVariable, "256M") // Test - if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). - WithName("any-app")); err != nil { - require.NoError(t, err) - } + _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). + WithName("any-app")) + require.NoError(t, err) limitRanges, _ := client.CoreV1().LimitRanges(utils.GetAppNamespace("any-app")).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 1, len(limitRanges.Items), "Number of limit ranges was not expected") @@ -254,10 +248,9 @@ func TestOnSync_NoLimitsDefined_NoLimitsSet(t *testing.T) { os.Setenv(defaults.OperatorAppLimitDefaultRequestMemoryEnvironmentVariable, "") // Test - if _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). - WithName("any-app")); err != nil { - require.NoError(t, err) - } + _, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration(). + WithName("any-app")) + require.NoError(t, err) limitRanges, _ := client.CoreV1().LimitRanges(utils.GetAppNamespace("any-app")).List(context.TODO(), metav1.ListOptions{}) assert.Equal(t, 0, len(limitRanges.Items), "Number of limit ranges was not expected") diff --git a/pkg/apis/application/rolebinding.go b/pkg/apis/application/rolebinding.go index cc77d520e..a58ae96bd 100644 --- a/pkg/apis/application/rolebinding.go +++ b/pkg/apis/application/rolebinding.go @@ -155,7 +155,7 @@ func (app *Application) pipelineRoleBinding(serviceAccount *corev1.ServiceAccoun rolebinding := &rbacv1.RoleBinding{ TypeMeta: metav1.TypeMeta{ APIVersion: rbacv1.SchemeGroupVersion.Identifier(), - Kind: "RoleBinding", + Kind: k8s.KindRoleBinding, }, ObjectMeta: metav1.ObjectMeta{ Name: defaults.PipelineAppRoleName, @@ -187,7 +187,7 @@ func (app *Application) radixTektonRoleBinding(serviceAccount *corev1.ServiceAcc rolebinding := &rbacv1.RoleBinding{ TypeMeta: metav1.TypeMeta{ APIVersion: rbacv1.SchemeGroupVersion.Identifier(), - Kind: "RoleBinding", + Kind: k8s.KindRoleBinding, }, ObjectMeta: metav1.ObjectMeta{ Name: defaults.RadixTektonAppRoleName, diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index e8d75d1ec..5c5f35992 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -215,13 +215,12 @@ func Test_WithBuildSecretsSet_SecretsCorrectlyAdded(t *testing.T) { tu, client, kubeUtil, radixClient := setupTest() appNamespace := "any-app-app" - if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, + err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). - WithBuildSecrets("secret1", "secret2")); err != nil { - require.NoError(t, err) - } + WithBuildSecrets("secret1", "secret2")) + require.NoError(t, err) secrets, _ := client.CoreV1().Secrets(appNamespace).List(context.TODO(), metav1.ListOptions{}) defaultValue := []byte(defaults.BuildSecretDefaultData) diff --git a/pkg/apis/applicationconfig/imagehubsecret.go b/pkg/apis/applicationconfig/imagehubsecret.go index 6202e06fa..822a56ef2 100644 --- a/pkg/apis/applicationconfig/imagehubsecret.go +++ b/pkg/apis/applicationconfig/imagehubsecret.go @@ -27,31 +27,6 @@ func GetKubeDPrivateImageHubAnnotationValues(appName string) (key, value string) return fmt.Sprintf("%s-sync", defaults.PrivateImageHubSecretName), appName } -// UpdatePrivateImageHubsSecretsPassword updates the private image hub secret -func UpdatePrivateImageHubsSecretsPassword(kubeutil *kube.Kube, appName, server, password string) error { - ns := utils.GetAppNamespace(appName) - secret, _ := kubeutil.GetSecret(ns, defaults.PrivateImageHubSecretName) - if secret == nil { - return fmt.Errorf("private image hub secret does not exist for app %s", appName) - } - - imageHubs, err := GetImageHubSecretValue(secret.Data[corev1.DockerConfigJsonKey]) - if err != nil { - return err - } - - if config, ok := imageHubs[server]; ok { - config.Password = password - imageHubs[server] = config - secretValue, err := GetImageHubsSecretValue(imageHubs) - if err != nil { - return err - } - return ApplyPrivateImageHubSecret(kubeutil, ns, appName, secretValue) - } - return fmt.Errorf("private image hub secret does not contain config for server %s", server) -} - func (app *ApplicationConfig) syncPrivateImageHubSecrets() error { namespace := utils.GetAppNamespace(app.config.Name) secret, err := app.kubeutil.GetSecret(namespace, defaults.PrivateImageHubSecretName) diff --git a/pkg/apis/batch/syncer_test.go b/pkg/apis/batch/syncer_test.go index e897af7bf..de1a98d57 100644 --- a/pkg/apis/batch/syncer_test.go +++ b/pkg/apis/batch/syncer_test.go @@ -71,9 +71,9 @@ func (s *syncerTestSuite) ensurePopulatedEnvVarsConfigMaps(kubeUtil *kube.Kube, } desiredConfigMap.Data[envVarName] = envVarValue } - if err := kubeUtil.ApplyConfigMap(rd.GetNamespace(), initialEnvVarsConfigMap, desiredConfigMap); err != nil { - s.Require().NoError(err) - } + err := kubeUtil.ApplyConfigMap(rd.GetNamespace(), initialEnvVarsConfigMap, desiredConfigMap) + s.Require().NoError(err) + return desiredConfigMap } diff --git a/pkg/apis/deployment/deployment_test.go b/pkg/apis/deployment/deployment_test.go index d4026da69..13df787a4 100644 --- a/pkg/apis/deployment/deployment_test.go +++ b/pkg/apis/deployment/deployment_test.go @@ -926,14 +926,13 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { t.Run("app with component using identity fails if SA exist with missing is-service-account-for-component label", func(t *testing.T) { tu, client, kubeUtil, radixclient, prometheusclient, _ := setupTest() appName, envName, componentName, clientId := "any-app", "any-env", "any-component", "any-client-id" - if _, err := client.CoreV1().ServiceAccounts("any-app-any-env").Create( + _, err := client.CoreV1().ServiceAccounts("any-app-any-env").Create( context.Background(), &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: utils.GetComponentServiceAccountName(componentName), Labels: map[string]string{kube.RadixComponentLabel: componentName}}}, - metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } + metav1.CreateOptions{}) + require.NoError(t, err) - _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( utils.NewDeployComponentBuilder(). WithName(componentName). @@ -949,14 +948,13 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { t.Run("app with component using identity success if SA exist with correct labels", func(t *testing.T) { tu, client, kubeUtil, radixclient, prometheusclient, _ := setupTest() appName, envName, componentName, clientId := "any-app", "any-env", "any-component", "any-client-id" - if _, err := client.CoreV1().ServiceAccounts("any-app-any-env").Create( + _, err := client.CoreV1().ServiceAccounts("any-app-any-env").Create( context.Background(), &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: utils.GetComponentServiceAccountName(componentName), Labels: map[string]string{kube.RadixComponentLabel: componentName, kube.IsServiceAccountForComponent: "true", "any-other-label": "any-value"}}}, - metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } + metav1.CreateOptions{}) + require.NoError(t, err) - _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( utils.NewDeployComponentBuilder(). WithName(componentName). @@ -980,15 +978,14 @@ func TestObjectSynced_ServiceAccountSettingsAndRbac(t *testing.T) { appName, envName, componentName, clientId, anyOtherServiceAccountName := "any-app", "any-env", "any-component", "any-client-id", "any-other-serviceaccount" // A service account that must not be deleted - if _, err := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).Create( + _, err := client.CoreV1().ServiceAccounts(utils.GetEnvironmentNamespace(appName, envName)).Create( context.Background(), &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: anyOtherServiceAccountName, Labels: map[string]string{kube.RadixComponentLabel: "anything"}}}, - metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } + metav1.CreateOptions{}) + require.NoError(t, err) // Deploy component with Azure identity must create custom SA - _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithComponents( utils.NewDeployComponentBuilder(). WithName(componentName). @@ -1581,9 +1578,8 @@ func TestObjectSynced_DeploymentReplicasFromCurrentDeploymentWhenHPAEnabled(t *t // Simulate HPA scaling up comp1 to 3 replicas comp1.Spec.Replicas = pointers.Ptr[int32](3) - if _, err := client.AppsV1().Deployments(envNamespace).Update(context.Background(), comp1, metav1.UpdateOptions{}); err != nil { - require.NoError(t, err) - } + _, err = client.AppsV1().Deployments(envNamespace).Update(context.Background(), comp1, metav1.UpdateOptions{}) + require.NoError(t, err) // Resync existing RD should use replicas from current deployment for HPA enabled component err = applyDeploymentUpdateWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). @@ -2657,9 +2653,8 @@ func TestObjectUpdated_RemoveOneSecret_SecretIsRemoved(t *testing.T) { secretData["a_third_secret"] = []byte(anySecretValue) anyComponentSecret.Data = secretData - if _, err := client.CoreV1().Secrets(envNamespace).Update(context.TODO(), anyComponentSecret, metav1.UpdateOptions{}); err != nil { - require.NoError(t, err) - } + _, err = client.CoreV1().Secrets(envNamespace).Update(context.TODO(), anyComponentSecret, metav1.UpdateOptions{}) + require.NoError(t, err) // Removing one secret from config and therefor from the deployment // should cause it to disappear @@ -3557,16 +3552,15 @@ func Test_JobScheduler_ObjectsGarbageCollected(t *testing.T) { labels[kube.RadixJobTypeLabel] = kube.RadixJobTypeJobSchedule } - if _, err := client.BatchV1().Jobs(namespace).Create(context.TODO(), + _, err := client.BatchV1().Jobs(namespace).Create(context.TODO(), &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ Name: name, Labels: labels, }, }, - metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } + metav1.CreateOptions{}) + require.NoError(t, err) } addSecret := func(client kubernetes.Interface, name, namespace, componentName string) { @@ -3576,16 +3570,15 @@ func Test_JobScheduler_ObjectsGarbageCollected(t *testing.T) { labels[kube.RadixComponentLabel] = componentName } - if _, err := client.CoreV1().Secrets(namespace).Create(context.TODO(), + _, err := client.CoreV1().Secrets(namespace).Create(context.TODO(), &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: name, Labels: labels, }, }, - metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } + metav1.CreateOptions{}) + require.NoError(t, err) } addService := func(client kubernetes.Interface, name, namespace, componentName string) { @@ -3595,16 +3588,15 @@ func Test_JobScheduler_ObjectsGarbageCollected(t *testing.T) { labels[kube.RadixComponentLabel] = componentName } - if _, err := client.CoreV1().Services(namespace).Create(context.TODO(), + _, err := client.CoreV1().Services(namespace).Create(context.TODO(), &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: name, Labels: labels, }, }, - metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } + metav1.CreateOptions{}) + require.NoError(t, err) } t.Run(theory.name, func(t *testing.T) { @@ -3633,9 +3625,8 @@ func Test_JobScheduler_ObjectsGarbageCollected(t *testing.T) { addService(client, "non-job-service1", "app-dev", "") addService(client, "prod-job-service1", "app-prod", "job") - if _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, theory.builder); err != nil { - assert.FailNow(t, fmt.Sprintf("error apply deployment: %v", err)) - } + _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, theory.builder) + require.NoError(t, err, "error apply deployment") // Verify expected jobs kubeJobs, _ := client.BatchV1().Jobs("").List(context.TODO(), metav1.ListOptions{LabelSelector: "item-in-test=true"}) @@ -3770,12 +3761,12 @@ func Test_IngressAnnotations_Called(t *testing.T) { defer os.Unsetenv(defaults.ActiveClusternameEnvironmentVariable) rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http").WithDNSAppAlias(true)).BuildRD() - if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } - if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } + _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) + require.NoError(t, err) + + _, err = radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}) + require.NoError(t, err) + ctrl := gomock.NewController(t) defer ctrl.Finish() annotations1 := ingress.NewMockAnnotationProvider(ctrl) @@ -3793,14 +3784,14 @@ func Test_IngressAnnotations_Called(t *testing.T) { ingressAnnotationProviders: []ingress.AnnotationProvider{annotations1, annotations2}, } - err := syncer.OnSync() - assert.Nil(t, err) + err = syncer.OnSync() + require.NoError(t, err) ingresses, _ := kubeclient.NetworkingV1().Ingresses("").List(context.Background(), metav1.ListOptions{}) assert.Len(t, ingresses.Items, 3) expected := map[string]string{"bar": "y", "baz": "z", "foo": "x"} - for _, ingress := range ingresses.Items { - assert.Equal(t, expected, ingress.GetAnnotations()) + for _, ing := range ingresses.Items { + assert.Equal(t, expected, ing.GetAnnotations()) } } @@ -3809,12 +3800,12 @@ func Test_IngressAnnotations_ReturnError(t *testing.T) { defer teardownTest() rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http")).BuildRD() - if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } - if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } + _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) + require.NoError(t, err) + + _, err = radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}) + require.NoError(t, err) + ctrl := gomock.NewController(t) defer ctrl.Finish() annotations1 := ingress.NewMockAnnotationProvider(ctrl) @@ -3830,7 +3821,7 @@ func Test_IngressAnnotations_ReturnError(t *testing.T) { ingressAnnotationProviders: []ingress.AnnotationProvider{annotations1}, } - err := syncer.OnSync() + err = syncer.OnSync() assert.Error(t, err) } @@ -3839,12 +3830,12 @@ func Test_AuxiliaryResourceManagers_Called(t *testing.T) { defer teardownTest() rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http")).BuildRD() - if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } - if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } + _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) + require.NoError(t, err) + + _, err = radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}) + require.NoError(t, err) + ctrl := gomock.NewController(t) defer ctrl.Finish() auxResource := NewMockAuxiliaryResourceManager(ctrl) @@ -3861,8 +3852,8 @@ func Test_AuxiliaryResourceManagers_Called(t *testing.T) { auxResourceManagers: []AuxiliaryResourceManager{auxResource}, } - err := syncer.OnSync() - assert.Nil(t, err) + err = syncer.OnSync() + assert.NoError(t, err) } func Test_AuxiliaryResourceManagers_Sync_ReturnErr(t *testing.T) { @@ -3870,12 +3861,12 @@ func Test_AuxiliaryResourceManagers_Sync_ReturnErr(t *testing.T) { defer teardownTest() rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http")).BuildRD() - if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } - if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } + _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) + require.NoError(t, err) + + _, err = radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}) + require.NoError(t, err) + ctrl := gomock.NewController(t) defer ctrl.Finish() auxErr := errors.New("an error") @@ -3893,7 +3884,7 @@ func Test_AuxiliaryResourceManagers_Sync_ReturnErr(t *testing.T) { auxResourceManagers: []AuxiliaryResourceManager{auxResource}, } - err := syncer.OnSync() + err = syncer.OnSync() assert.Contains(t, err.Error(), auxErr.Error()) } @@ -3902,12 +3893,12 @@ func Test_AuxiliaryResourceManagers_GarbageCollect_ReturnErr(t *testing.T) { defer teardownTest() rr := utils.NewRegistrationBuilder().WithName("app").BuildRR() rd := utils.NewDeploymentBuilder().WithAppName("app").WithEnvironment("dev").WithComponent(utils.NewDeployComponentBuilder().WithName("comp").WithPublicPort("http")).BuildRD() - if _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } - if _, err := radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } + _, err := radixclient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{}) + require.NoError(t, err) + + _, err = radixclient.RadixV1().RadixDeployments("app-dev").Create(context.Background(), rd, metav1.CreateOptions{}) + require.NoError(t, err) + ctrl := gomock.NewController(t) defer ctrl.Finish() auxErr := errors.New("an error") @@ -3925,7 +3916,7 @@ func Test_AuxiliaryResourceManagers_GarbageCollect_ReturnErr(t *testing.T) { auxResourceManagers: []AuxiliaryResourceManager{auxResource}, } - err := syncer.OnSync() + err = syncer.OnSync() assert.Contains(t, err.Error(), auxErr.Error()) } @@ -4104,33 +4095,25 @@ func TestRadixBatch_IsGarbageCollected(t *testing.T) { } } - if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch1", "job1"), metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } - if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch2", "job1"), metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } - if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch3", "job2"), metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } - if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch4", "job2"), metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } - if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch5", "job3"), metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } - if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch6", "job4"), metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } - if _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch7", ""), metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } - if _, err := radixclient.RadixV1().RadixBatches("other-ns").Create(context.Background(), batchFactory("batch8", "job1"), metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } + _, err := radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch1", "job1"), metav1.CreateOptions{}) + require.NoError(t, err) + _, err = radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch2", "job1"), metav1.CreateOptions{}) + require.NoError(t, err) + _, err = radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch3", "job2"), metav1.CreateOptions{}) + require.NoError(t, err) + _, err = radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch4", "job2"), metav1.CreateOptions{}) + require.NoError(t, err) + _, err = radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch5", "job3"), metav1.CreateOptions{}) + require.NoError(t, err) + _, err = radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch6", "job4"), metav1.CreateOptions{}) + require.NoError(t, err) + _, err = radixclient.RadixV1().RadixBatches(namespace).Create(context.Background(), batchFactory("batch7", ""), metav1.CreateOptions{}) + require.NoError(t, err) + _, err = radixclient.RadixV1().RadixBatches("other-ns").Create(context.Background(), batchFactory("batch8", "job1"), metav1.CreateOptions{}) + require.NoError(t, err) // Test - _, err := applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). + _, err = applyDeploymentWithSync(tu, client, kubeUtil, radixclient, prometheusclient, utils.ARadixDeployment(). WithAppName(appName). WithEnvironment(anyEnvironment). WithJobComponents( diff --git a/pkg/apis/deployment/environmentvariables_test.go b/pkg/apis/deployment/environmentvariables_test.go index 6419020ef..81676a67b 100644 --- a/pkg/apis/deployment/environmentvariables_test.go +++ b/pkg/apis/deployment/environmentvariables_test.go @@ -98,10 +98,9 @@ func Test_getEnvironmentVariablesForRadixOperator(t *testing.T) { "VAR3": "val3", }) }) - if cm, err := testEnv.kubeUtil.GetConfigMap(corev1.NamespaceDefault, "radix-config"); err != nil { - require.NoError(t, err) - require.Equal(t, testClusterName, cm.Data["clustername"]) - } + cm, err := testEnv.kubeUtil.GetConfigMap(corev1.NamespaceDefault, "radix-config") + require.NoError(t, err) + require.Equal(t, testClusterName, cm.Data["clustername"]) envVars, err := GetEnvironmentVariablesForRadixOperator(testEnv.kubeUtil, appName, rd, &rd.Spec.Components[0]) @@ -133,26 +132,25 @@ func Test_RemoveFromConfigMapEnvVarsNotExistingInRadixDeployment(t *testing.T) { defer teardownTest() t.Run("Remove obsolete env-vars from config-maps", func(t *testing.T) { //goland:noinspection GoUnhandledErrorResult - if _, err := testEnv.kubeUtil.CreateConfigMap(namespace, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: kube.GetEnvVarsConfigMapName(componentName)}, Data: map[string]string{ + _, err := testEnv.kubeUtil.CreateConfigMap(namespace, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: kube.GetEnvVarsConfigMapName(componentName)}, Data: map[string]string{ "VAR1": "val1", "OUTDATED_VAR1": "val1z", - }}); err != nil { - require.NoError(t, err) - } + }}) + require.NoError(t, err) + existingEnvVarsMetadataConfigMap := corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: kube.GetEnvVarsMetadataConfigMapName(componentName)}} //goland:noinspection GoUnhandledErrorResult - if err := kube.SetEnvVarsMetadataMapToConfigMap(&existingEnvVarsMetadataConfigMap, + err = kube.SetEnvVarsMetadataMapToConfigMap(&existingEnvVarsMetadataConfigMap, map[string]kube.EnvVarMetadata{ "VAR1": {RadixConfigValue: "orig-val1"}, "OUTDATED_VAR1": {RadixConfigValue: "orig-val1a"}, "OUTDATED_VAR2": {RadixConfigValue: "orig-val2a"}, - }); err != nil { - require.NoError(t, err) - } + }) + require.NoError(t, err) + //goland:noinspection GoUnhandledErrorResult - if _, err := testEnv.kubeUtil.CreateConfigMap(namespace, &existingEnvVarsMetadataConfigMap); err != nil { - require.NoError(t, err) - } + _, err = testEnv.kubeUtil.CreateConfigMap(namespace, &existingEnvVarsMetadataConfigMap) + require.NoError(t, err) rd := testEnv.applyRdComponent(t, appName, envName, componentName, func(componentBuilder utils.DeployComponentBuilder) { componentBuilder.WithEnvironmentVariables(map[string]string{ diff --git a/pkg/apis/deployment/oauthproxyresourcemanager_test.go b/pkg/apis/deployment/oauthproxyresourcemanager_test.go index 61141476c..795362a19 100644 --- a/pkg/apis/deployment/oauthproxyresourcemanager_test.go +++ b/pkg/apis/deployment/oauthproxyresourcemanager_test.go @@ -484,9 +484,8 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxySecret_KeysGarb // Remove redispassword if sessionstoretype is cookie s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(1).Return(&v1.OAuth2{SessionStoreType: v1.SessionStoreCookie}, nil) - if err := sut.Sync(); err != nil { - s.Require().NoError(err) - } + err = sut.Sync() + s.Require().NoError(err) actualSecret, _ = s.kubeClient.CoreV1().Secrets(envNs).Get(context.Background(), secretName, metav1.GetOptions{}) s.Equal( map[string][]byte{ @@ -572,24 +571,18 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate Rules: []networkingv1.IngressRule{{Host: "ing2.public"}}, }, } - if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingServer, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } - if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingServerNoRules, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } - if _, err := s.kubeClient.NetworkingV1().Ingresses("otherns").Create(context.Background(), &ingServerOtherNs, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } - if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingOtherComponent, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } - if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingWeb1, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } - if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingWeb2, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingServer, metav1.CreateOptions{}) + s.Require().NoError(err) + _, err = s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingServerNoRules, metav1.CreateOptions{}) + s.Require().NoError(err) + _, err = s.kubeClient.NetworkingV1().Ingresses("otherns").Create(context.Background(), &ingServerOtherNs, metav1.CreateOptions{}) + s.Require().NoError(err) + _, err = s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingOtherComponent, metav1.CreateOptions{}) + s.Require().NoError(err) + _, err = s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingWeb1, metav1.CreateOptions{}) + s.Require().NoError(err) + _, err = s.kubeClient.NetworkingV1().Ingresses(envNs).Create(context.Background(), &ingWeb2, metav1.CreateOptions{}) + s.Require().NoError(err) rr := utils.NewRegistrationBuilder().WithName(appName).BuildRR() rd := utils.NewDeploymentBuilder(). @@ -610,15 +603,15 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyIngressesCreate expectedIngWebAnnotations := map[string]string{"annotation2-1": "val2-1", "annotation2-2": "val2-2"} s.ingressAnnotationProvider.EXPECT().GetAnnotations(expectedIngWebCall, rd.Namespace).Times(2).Return(expectedIngWebAnnotations, nil) sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []ingress.AnnotationProvider{s.ingressAnnotationProvider}, s.oauth2Config, ""} - err := sut.Sync() - s.Nil(err) + err = sut.Sync() + s.NoError(err) actualIngresses, _ := s.kubeClient.NetworkingV1().Ingresses(corev1.NamespaceAll).List(context.Background(), metav1.ListOptions{}) s.Len(actualIngresses.Items, 9) getIngress := func(name string, ingresses []networkingv1.Ingress) *networkingv1.Ingress { - for _, ingress := range ingresses { - if ingress.Name == name { - return &ingress + for _, ing := range ingresses { + if ing.Name == name { + return &ing } } return nil @@ -677,33 +670,30 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyUninstall() { appName, envName, component1Name, component2Name := "anyapp", "qa", "server", "web" envNs := utils.GetEnvironmentNamespace(appName, envName) - if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create( + _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create( context.Background(), &networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{Name: "ing1", Labels: map[string]string{kube.RadixAppLabel: appName, kube.RadixComponentLabel: component1Name, kube.RadixDefaultAliasLabel: "true"}}, Spec: networkingv1.IngressSpec{Rules: []networkingv1.IngressRule{{Host: "anyhost"}}}}, metav1.CreateOptions{}, - ); err != nil { - s.Require().NoError(err) - } - if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create( + ) + s.Require().NoError(err) + _, err = s.kubeClient.NetworkingV1().Ingresses(envNs).Create( context.Background(), &networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{Name: "ing2", Labels: map[string]string{kube.RadixAppLabel: appName, kube.RadixComponentLabel: component2Name, kube.RadixDefaultAliasLabel: "true"}}, Spec: networkingv1.IngressSpec{Rules: []networkingv1.IngressRule{{Host: "anyhost"}}}}, metav1.CreateOptions{}, - ); err != nil { - s.Require().NoError(err) - } - if _, err := s.kubeClient.NetworkingV1().Ingresses(envNs).Create( + ) + s.Require().NoError(err) + _, err = s.kubeClient.NetworkingV1().Ingresses(envNs).Create( context.Background(), &networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{Name: "ing3", Labels: map[string]string{kube.RadixAppLabel: appName, kube.RadixComponentLabel: component2Name, kube.RadixDefaultAliasLabel: "true"}}, Spec: networkingv1.IngressSpec{Rules: []networkingv1.IngressRule{{Host: "anyhost"}}}}, metav1.CreateOptions{}, - ); err != nil { - s.Require().NoError(err) - } + ) + s.Require().NoError(err) rr := utils.NewRegistrationBuilder().WithName(appName).BuildRR() rd := utils.NewDeploymentBuilder(). @@ -714,8 +704,8 @@ func (s *OAuthProxyResourceManagerTestSuite) Test_Sync_OAuthProxyUninstall() { BuildRD() s.oauth2Config.EXPECT().MergeWith(gomock.Any()).Times(2).Return(&v1.OAuth2{}, nil) sut := &oauthProxyResourceManager{rd, rr, s.kubeUtil, []ingress.AnnotationProvider{}, s.oauth2Config, ""} - err := sut.Sync() - s.Nil(err) + err = sut.Sync() + s.NoError(err) // Bootstrap oauth proxy resources for two components actualDeploys, _ := s.kubeClient.AppsV1().Deployments(envNs).List(context.Background(), metav1.ListOptions{}) @@ -921,9 +911,7 @@ func (s *OAuthProxyResourceManagerTestSuite) addDeployment(name, namespace, appN }, } _, err := s.kubeClient.AppsV1().Deployments(namespace).Create(context.Background(), deploy, metav1.CreateOptions{}) - if err != nil { - s.Require().NoError(err) - } + s.Require().NoError(err) } func (s *OAuthProxyResourceManagerTestSuite) addSecret(name, namespace, appName, auxComponentName, auxComponentType string) { @@ -935,9 +923,7 @@ func (s *OAuthProxyResourceManagerTestSuite) addSecret(name, namespace, appName, }, } _, err := s.kubeClient.CoreV1().Secrets(namespace).Create(context.Background(), secret, metav1.CreateOptions{}) - if err != nil { - s.Require().NoError(err) - } + s.Require().NoError(err) } func (s *OAuthProxyResourceManagerTestSuite) addService(name, namespace, appName, auxComponentName, auxComponentType string) { @@ -949,23 +935,19 @@ func (s *OAuthProxyResourceManagerTestSuite) addService(name, namespace, appName }, } _, err := s.kubeClient.CoreV1().Services(namespace).Create(context.Background(), service, metav1.CreateOptions{}) - if err != nil { - s.Require().NoError(err) - } + s.Require().NoError(err) } func (s *OAuthProxyResourceManagerTestSuite) addIngress(name, namespace, appName, auxComponentName, auxComponentType string) { - ingress := &networkingv1.Ingress{ + ing := &networkingv1.Ingress{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, Labels: s.buildResourceLabels(appName, auxComponentName, auxComponentType), }, } - _, err := s.kubeClient.NetworkingV1().Ingresses(namespace).Create(context.Background(), ingress, metav1.CreateOptions{}) - if err != nil { - s.Require().NoError(err) - } + _, err := s.kubeClient.NetworkingV1().Ingresses(namespace).Create(context.Background(), ing, metav1.CreateOptions{}) + s.Require().NoError(err) } func (s *OAuthProxyResourceManagerTestSuite) addRole(name, namespace, appName, auxComponentName, auxComponentType string) { @@ -977,9 +959,8 @@ func (s *OAuthProxyResourceManagerTestSuite) addRole(name, namespace, appName, a }, } _, err := s.kubeClient.RbacV1().Roles(namespace).Create(context.Background(), role, metav1.CreateOptions{}) - if err != nil { - s.Require().NoError(err) - } + + s.Require().NoError(err) } func (s *OAuthProxyResourceManagerTestSuite) addRoleBinding(name, namespace, appName, auxComponentName, auxComponentType string) { @@ -991,9 +972,8 @@ func (s *OAuthProxyResourceManagerTestSuite) addRoleBinding(name, namespace, app }, } _, err := s.kubeClient.RbacV1().RoleBindings(namespace).Create(context.Background(), rolebinding, metav1.CreateOptions{}) - if err != nil { - s.Require().NoError(err) - } + + s.Require().NoError(err) } func (s *OAuthProxyResourceManagerTestSuite) buildResourceLabels(appName, auxComponentName, auxComponentType string) labels.Set { diff --git a/pkg/apis/dnsalias/ingress.go b/pkg/apis/dnsalias/ingress.go index 9eba31de3..95a85de82 100644 --- a/pkg/apis/dnsalias/ingress.go +++ b/pkg/apis/dnsalias/ingress.go @@ -5,9 +5,15 @@ import ( "fmt" "github.com/equinor/radix-common/utils/slice" + "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" + "github.com/equinor/radix-operator/pkg/apis/defaults" + "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" "github.com/equinor/radix-operator/pkg/apis/ingress" + "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" + "github.com/equinor/radix-operator/pkg/apis/radixvalidators" "github.com/equinor/radix-operator/pkg/apis/utils" + "github.com/equinor/radix-operator/pkg/apis/utils/annotations" radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" "github.com/equinor/radix-operator/pkg/apis/utils/oauth" log "github.com/sirupsen/logrus" @@ -33,7 +39,8 @@ func GetDNSAliasHost(alias, dnsZone string) string { return fmt.Sprintf("%s.%s", alias, dnsZone) } -func (s *syncer) syncIngress(namespace string, radixDeployComponent radixv1.RadixCommonDeployComponent, ingressName string) (*networkingv1.Ingress, error) { +func (s *syncer) syncIngress(namespace string, radixDeployComponent radixv1.RadixCommonDeployComponent) (*networkingv1.Ingress, error) { + ingressName := GetDNSAliasIngressName(s.radixDNSAlias.GetName()) newIngress, err := buildIngress(radixDeployComponent, s.radixDNSAlias, s.dnsConfig, s.oauth2DefaultConfig, s.ingressConfiguration) if err != nil { return nil, err @@ -67,8 +74,8 @@ func (s *syncer) createIngress(radixDNSAlias *radixv1.RadixDNSAlias, ing *networ return CreateRadixDNSAliasIngress(s.kubeClient, radixDNSAlias.Spec.AppName, radixDNSAlias.Spec.Environment, ing) } -func (s *syncer) syncOAuthProxyIngress(deployComponent radixv1.RadixCommonDeployComponent, namespace string, aliasSpec radixv1.RadixDNSAliasSpec, radixDeployComponent radixv1.RadixCommonDeployComponent, ing *networkingv1.Ingress) error { - appName := aliasSpec.AppName +func (s *syncer) syncOAuthProxyIngress(namespace string, ing *networkingv1.Ingress, deployComponent radixv1.RadixCommonDeployComponent) error { + appName := s.radixDNSAlias.Spec.AppName authentication := deployComponent.GetAuthentication() oauthEnabled := authentication != nil && authentication.OAuth2 != nil if !oauthEnabled { @@ -97,3 +104,46 @@ func (s *syncer) deleteOAuthAuxIngresses(deployComponent radixv1.RadixCommonDepl } return s.kubeUtil.DeleteIngresses(slice.PointersOf(oauthAuxIngresses.Items).([]*networkingv1.Ingress)...) } + +func buildIngress(radixDeployComponent radixv1.RadixCommonDeployComponent, radixDNSAlias *radixv1.RadixDNSAlias, dnsConfig *dnsalias.DNSConfig, oauth2Config defaults.OAuth2Config, ingressConfiguration ingress.IngressConfiguration) (*networkingv1.Ingress, error) { + log.Debug("build an ingress for the RadixDNSAlias") + publicPort := getComponentPublicPort(radixDeployComponent) + if publicPort == nil { + return nil, radixvalidators.ComponentForDNSAliasIsNotMarkedAsPublicError(radixDeployComponent.GetName()) + } + aliasName := radixDNSAlias.GetName() + aliasSpec := radixDNSAlias.Spec + ingressName := GetDNSAliasIngressName(aliasName) + hostName := GetDNSAliasHost(aliasName, dnsConfig.DNSZone) + ingressSpec := ingress.GetIngressSpec(hostName, aliasSpec.Component, defaults.TLSSecretName, publicPort.Port) + + namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) + ingressAnnotations := ingress.GetAnnotationProvider(ingressConfiguration, namespace, oauth2Config) + ingressConfig, err := ingress.GetIngressConfig(namespace, aliasSpec.AppName, radixDeployComponent, ingressName, ingressSpec, ingressAnnotations, internal.GetOwnerReferences(radixDNSAlias)) + if err != nil { + return nil, err + } + + ingressConfig.ObjectMeta.Annotations = annotations.Merge(ingressConfig.ObjectMeta.Annotations, annotations.ForManagedByRadixDNSAliasIngress(aliasName)) + ingressConfig.ObjectMeta.Labels[kube.RadixAliasLabel] = aliasName + log.Debugf("built the Ingress %s in the environment %s with a host %s", ingressConfig.GetName(), namespace, hostName) + return ingressConfig, nil +} + +func (s *syncer) deletedIngressesForRadixDNSAlias() error { + aliasSpec := s.radixDNSAlias.Spec + namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) + dnsAliasIngressesSelector := radixlabels.ForDNSAliasIngress(aliasSpec.AppName, aliasSpec.Component, s.radixDNSAlias.GetName()).String() + ingresses, err := s.kubeUtil.KubeClient().NetworkingV1().Ingresses(namespace).List(context.Background(), metav1.ListOptions{LabelSelector: dnsAliasIngressesSelector}) + if err != nil { + return err + } + return s.kubeUtil.DeleteIngresses(slice.PointersOf(ingresses.Items).([]*networkingv1.Ingress)...) +} + +func getComponentPublicPort(component radixv1.RadixCommonDeployComponent) *radixv1.ComponentPort { + if port, ok := slice.FindFirst(component.GetPorts(), func(p radixv1.ComponentPort) bool { return p.Name == component.GetPublicPort() }); ok { + return &port + } + return nil +} diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index bf4d45c57..788a4a9b0 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -1,7 +1,6 @@ package dnsalias import ( - "context" "fmt" "regexp" @@ -9,18 +8,12 @@ import ( "github.com/equinor/radix-common/utils/slice" "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" "github.com/equinor/radix-operator/pkg/apis/defaults" - "github.com/equinor/radix-operator/pkg/apis/dnsalias/internal" "github.com/equinor/radix-operator/pkg/apis/ingress" "github.com/equinor/radix-operator/pkg/apis/kube" radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" - "github.com/equinor/radix-operator/pkg/apis/radixvalidators" "github.com/equinor/radix-operator/pkg/apis/utils" - "github.com/equinor/radix-operator/pkg/apis/utils/annotations" - radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" radixclient "github.com/equinor/radix-operator/pkg/client/clientset/versioned" log "github.com/sirupsen/logrus" - networkingv1 "k8s.io/api/networking/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" ) @@ -74,8 +67,7 @@ func (s *syncer) OnSync() error { } func (s *syncer) syncAlias() error { - aliasName := s.radixDNSAlias.GetName() - log.Debugf("syncAlias RadixDNSAlias %s", aliasName) + log.Debugf("syncAlias RadixDNSAlias %s", s.radixDNSAlias.GetName()) radixDeployComponent, err := s.getRadixDeployComponent() if err != nil { @@ -86,15 +78,14 @@ func (s *syncer) syncAlias() error { } aliasSpec := s.radixDNSAlias.Spec - ingressName := GetDNSAliasIngressName(aliasName) namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) - ing, err := s.syncIngress(namespace, radixDeployComponent, ingressName) + ing, err := s.syncIngress(namespace, radixDeployComponent) if err != nil { return s.getDNSAliasError(err) } - return s.syncOAuthProxyIngress(radixDeployComponent, namespace, aliasSpec, radixDeployComponent, ing) + return s.syncOAuthProxyIngress(namespace, ing, radixDeployComponent) } func (s *syncer) getDNSAliasError(err error) error { @@ -148,46 +139,3 @@ func (s *syncer) handleDeletedRadixDNSAlias() error { return s.kubeUtil.UpdateRadixDNSAlias(updatingAlias) } - -func (s *syncer) deletedIngressesForRadixDNSAlias() error { - aliasSpec := s.radixDNSAlias.Spec - namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) - dnsAliasIngressesSelector := radixlabels.ForDNSAliasIngress(aliasSpec.AppName, aliasSpec.Component, s.radixDNSAlias.GetName()).String() - ingresses, err := s.kubeUtil.KubeClient().NetworkingV1().Ingresses(namespace).List(context.Background(), metav1.ListOptions{LabelSelector: dnsAliasIngressesSelector}) - if err != nil { - return err - } - return s.kubeUtil.DeleteIngresses(slice.PointersOf(ingresses.Items).([]*networkingv1.Ingress)...) -} - -func buildIngress(radixDeployComponent radixv1.RadixCommonDeployComponent, radixDNSAlias *radixv1.RadixDNSAlias, dnsConfig *dnsalias.DNSConfig, oauth2Config defaults.OAuth2Config, ingressConfiguration ingress.IngressConfiguration) (*networkingv1.Ingress, error) { - log.Debug("build an ingress for the RadixDNSAlias") - publicPort := getComponentPublicPort(radixDeployComponent) - if publicPort == nil { - return nil, radixvalidators.ComponentForDNSAliasIsNotMarkedAsPublicError(radixDeployComponent.GetName()) - } - aliasName := radixDNSAlias.GetName() - aliasSpec := radixDNSAlias.Spec - ingressName := GetDNSAliasIngressName(aliasName) - hostName := GetDNSAliasHost(aliasName, dnsConfig.DNSZone) - ingressSpec := ingress.GetIngressSpec(hostName, aliasSpec.Component, defaults.TLSSecretName, publicPort.Port) - - namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) - ingressAnnotations := ingress.GetAnnotationProvider(ingressConfiguration, namespace, oauth2Config) - ingressConfig, err := ingress.GetIngressConfig(namespace, aliasSpec.AppName, radixDeployComponent, ingressName, ingressSpec, ingressAnnotations, internal.GetOwnerReferences(radixDNSAlias)) - if err != nil { - return nil, err - } - - ingressConfig.ObjectMeta.Annotations = annotations.Merge(ingressConfig.ObjectMeta.Annotations, annotations.ForManagedByRadixDNSAliasIngress(aliasName)) - ingressConfig.ObjectMeta.Labels[kube.RadixAliasLabel] = aliasName - log.Debugf("built the Ingress %s in the environment %s with a host %s", ingressConfig.GetName(), namespace, hostName) - return ingressConfig, nil -} - -func getComponentPublicPort(component radixv1.RadixCommonDeployComponent) *radixv1.ComponentPort { - if port, ok := slice.FindFirst(component.GetPorts(), func(p radixv1.ComponentPort) bool { return p.Name == component.GetPublicPort() }); ok { - return &port - } - return nil -} diff --git a/pkg/apis/job/job_steps_test.go b/pkg/apis/job/job_steps_test.go index 2163842e7..abd7d1cc4 100644 --- a/pkg/apis/job/job_steps_test.go +++ b/pkg/apis/job/job_steps_test.go @@ -12,6 +12,7 @@ import ( v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" batchv1 "k8s.io/api/batch/v1" @@ -265,19 +266,15 @@ func (s *RadixJobStepTestSuite) Test_StatusSteps_InitContainers() { } func (s *RadixJobStepTestSuite) testSetStatusOfJobTestScenario(scenario *setStatusOfJobTestScenario) { - if err := s.initScenario(scenario); err != nil { - assert.FailNowf(s.T(), err.Error(), "scenario %s", scenario.name) - } + err := s.initScenario(scenario) + require.NoError(s.T(), err, "scenario %s", scenario.name) job := NewJob(s.kubeClient, s.kubeUtils, s.radixClient, scenario.radixjob, nil) - if err := job.setStatusOfJob(); err != nil { - assert.FailNowf(s.T(), err.Error(), "scenario %s", scenario.name) - } + err = job.setStatusOfJob() + require.NoError(s.T(), err, "scenario %s", scenario.name) actualRj, err := s.radixClient.RadixV1().RadixJobs(scenario.radixjob.Namespace).Get(context.Background(), scenario.radixjob.Name, metav1.GetOptions{}) - if err != nil { - assert.FailNowf(s.T(), err.Error(), "scenario %s", scenario.name) - } + require.NoError(s.T(), err, "scenario %s", scenario.name) assert.Equal(s.T(), scenario.expected.returnsError, err != nil, scenario.name) assert.ElementsMatch(s.T(), scenario.expected.steps, actualRj.Status.Steps, scenario.name) diff --git a/pkg/apis/job/job_test.go b/pkg/apis/job/job_test.go index 28292f7dd..0b4b30c03 100644 --- a/pkg/apis/job/job_test.go +++ b/pkg/apis/job/job_test.go @@ -294,9 +294,9 @@ func (s *RadixJobTestSuite) TestObjectSynced_FirstJobRunning_SecondJobQueued() { // Stopping first job should set second job to running firstJob.Spec.Stop = true - if _, err := s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err = s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}) + s.Require().NoError(err) + err = s.runSync(firstJob, config) s.Require().NoError(err) @@ -317,9 +317,9 @@ func (s *RadixJobTestSuite) TestObjectSynced_FirstJobWaiting_SecondJobQueued() { // Stopping first job should set second job to running firstJob.Spec.Stop = true - if _, err := s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err = s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}) + s.Require().NoError(err) + err = s.runSync(firstJob, config) s.Require().NoError(err) @@ -345,9 +345,8 @@ func (s *RadixJobTestSuite) TestObjectSynced_MultipleJobs_MissingRadixApplicatio // Stopping first job should set second job to running firstJob.Spec.Stop = true - if _, err := s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err = s.radixClient.RadixV1().RadixJobs(firstJob.ObjectMeta.Namespace).Update(context.TODO(), firstJob, metav1.UpdateOptions{}) + s.Require().NoError(err) err = s.runSync(firstJob, config) s.Require().NoError(err) @@ -690,9 +689,9 @@ func (s *RadixJobTestSuite) TestHistoryLimit_EachEnvHasOwnHistory() { WithAppName(appName).WithDeploymentName(rdJob.rdName).WithEnvironment(rdJob.env).WithJobName(rdJob.jobName). WithActiveFrom(testTime)) s.NoError(err) - if err := s.applyJobWithSyncFor(raBuilder, appName, rdJob, config); err != nil { - s.Require().NoError(err) - } + err = s.applyJobWithSyncFor(raBuilder, appName, rdJob, config) + s.Require().NoError(err) + testTime = testTime.Add(time.Hour) } @@ -827,9 +826,9 @@ func (s *RadixJobTestSuite) Test_WildCardJobs() { config := getConfigWithPipelineJobsHistoryLimit(10) testTime := time.Now().Add(time.Hour * -100) raBuilder := scenario.raBuilder.WithAppName(appName) - if _, err := s.testUtils.ApplyApplication(raBuilder); err != nil { - s.Require().NoError(err) - } + _, err := s.testUtils.ApplyApplication(raBuilder) + s.Require().NoError(err) + for _, rdJob := range scenario.existingRadixDeploymentJobs { if rdJob.jobStatus == radixv1.JobSucceeded { _, err := s.testUtils.ApplyDeployment(utils.ARadixDeployment(). diff --git a/pkg/apis/kube/environment_variables_test.go b/pkg/apis/kube/environment_variables_test.go index 57102a276..70852fe84 100644 --- a/pkg/apis/kube/environment_variables_test.go +++ b/pkg/apis/kube/environment_variables_test.go @@ -101,7 +101,7 @@ func Test_GetEnvVarsMetadataConfigMapAndMap(t *testing.T) { namespace := "some-namespace" componentName := "comp1" createEnvVarConfigMapFunc := func(testEnv EnvironmentVariablesTestEnv) { - if err := createConfigMap(testEnv.kubeUtil, namespace, &corev1.ConfigMap{ + err := createConfigMap(testEnv.kubeUtil, namespace, &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "env-vars-" + componentName, Namespace: namespace, @@ -111,12 +111,12 @@ func Test_GetEnvVarsMetadataConfigMapAndMap(t *testing.T) { "VAR2": "val2", "VAR3": "setVal3", }, - }); err != nil { - require.NoError(t, err) - } + }) + require.NoError(t, err) + } createEnvVarMetadataConfigMapFunc := func(testEnv EnvironmentVariablesTestEnv) { - if err := createConfigMap( + err := createConfigMap( testEnv.kubeUtil, namespace, &corev1.ConfigMap{ @@ -133,9 +133,9 @@ func Test_GetEnvVarsMetadataConfigMapAndMap(t *testing.T) { `, }, }, - ); err != nil { - require.NoError(t, err) - } + ) + require.NoError(t, err) + } t.Run("Get existing", func(t *testing.T) { t.Parallel() @@ -213,13 +213,12 @@ func Test_SetEnvVarsMetadataMapToConfigMap(t *testing.T) { }, } - if err := SetEnvVarsMetadataMapToConfigMap(¤tMetadataConfigMap, map[string]EnvVarMetadata{ + err := SetEnvVarsMetadataMapToConfigMap(¤tMetadataConfigMap, map[string]EnvVarMetadata{ "VAR1": {RadixConfigValue: "val1changed"}, "VAR2": {RadixConfigValue: "added"}, // VAR3: removed - }); err != nil { - require.NoError(t, err) - } + }) + require.NoError(t, err) assert.NotNil(t, currentMetadataConfigMap.Data) assert.NotNil(t, currentMetadataConfigMap.Data["metadata"]) @@ -262,17 +261,16 @@ func Test_ApplyEnvVarsMetadataConfigMap(t *testing.T) { t.Run("Save changes", func(t *testing.T) { t.Parallel() testEnv := getEnvironmentVariablesTestEnv() - if _, err := testEnv.kubeclient.CoreV1().ConfigMaps(namespace).Create(context.Background(), &corev1.ConfigMap{ + _, err := testEnv.kubeclient.CoreV1().ConfigMaps(namespace).Create(context.Background(), &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, - }}, metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } - - err := testEnv.kubeUtil.ApplyEnvVarsMetadataConfigMap(namespace, ¤tMetadataConfigMap, metadata) + }}, metav1.CreateOptions{}) + require.NoError(t, err) + err = testEnv.kubeUtil.ApplyEnvVarsMetadataConfigMap(namespace, ¤tMetadataConfigMap, metadata) assert.NoError(t, err) + configMap, err := testEnv.kubeclient.CoreV1().ConfigMaps(namespace).Get(context.Background(), name, metav1.GetOptions{}) assert.NoError(t, err) assert.NotNil(t, configMap) diff --git a/pkg/apis/radix/v1/register.go b/pkg/apis/radix/v1/register.go index 30d50b68a..0e7e4a175 100644 --- a/pkg/apis/radix/v1/register.go +++ b/pkg/apis/radix/v1/register.go @@ -6,9 +6,14 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" ) +const ( + GroupName = "radix.equinor.com" + Version = "v1" +) + // SchemeGroupVersion provides the group version var SchemeGroupVersion = schema.GroupVersion{ - Group: "radix.equinor.com", + Group: GroupName, Version: "v1", } var ( diff --git a/radix-operator/alert/controller_test.go b/radix-operator/alert/controller_test.go index f70cafdbd..a699df373 100644 --- a/radix-operator/alert/controller_test.go +++ b/radix-operator/alert/controller_test.go @@ -29,9 +29,8 @@ func (s *controllerTestSuite) Test_RadixAlertEvents() { s.RadixInformerFactory.Start(s.Stop) s.KubeInformerFactory.Start(s.Stop) go func() { - if err := sut.Run(5, s.Stop); err != nil { - s.Require().NoError(err) - } + err := sut.Run(5, s.Stop) + s.Require().NoError(err) }() // Adding a RadixAlert should trigger sync @@ -46,16 +45,16 @@ func (s *controllerTestSuite) Test_RadixAlertEvents() { // Updating the RadixAlert with changes should trigger a sync s.Handler.EXPECT().Sync(namespace, alertName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) alert.Labels = map[string]string{"foo": "bar"} - if _, err := s.RadixClient.RadixV1().RadixAlerts(namespace).Update(context.TODO(), alert, metav1.UpdateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err = s.RadixClient.RadixV1().RadixAlerts(namespace).Update(context.TODO(), alert, metav1.UpdateOptions{}) + s.Require().NoError(err) + s.WaitForSynced("second call") // Updating the RadixAlert with no changes should not trigger a sync s.Handler.EXPECT().Sync(namespace, alertName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) - if _, err := s.RadixClient.RadixV1().RadixAlerts(namespace).Update(context.TODO(), alert, metav1.UpdateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err = s.RadixClient.RadixV1().RadixAlerts(namespace).Update(context.TODO(), alert, metav1.UpdateOptions{}) + s.Require().NoError(err) + s.WaitForNotSynced("Sync should not be called when updating RadixAlert with no changes") } @@ -73,24 +72,23 @@ func (s *controllerTestSuite) Test_RadixRegistrationEvents() { s.RadixInformerFactory.Start(s.Stop) s.KubeInformerFactory.Start(s.Stop) go func() { - if err := sut.Run(5, s.Stop); err != nil { - s.Require().NoError(err) - } + err := sut.Run(5, s.Stop) + s.Require().NoError(err) }() hasSynced := cache.WaitForCacheSync(s.Stop, s.RadixInformerFactory.Radix().V1().RadixRegistrations().Informer().HasSynced) s.True(hasSynced) // Initial Sync for the two alerts - if _, err := s.RadixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), alert1, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err = s.RadixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), alert1, metav1.CreateOptions{}) + s.Require().NoError(err) + s.Handler.EXPECT().Sync(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("sync of alert1") - if _, err := s.RadixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), alert2, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err = s.RadixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), alert2, metav1.CreateOptions{}) + s.Require().NoError(err) + s.Handler.EXPECT().Sync(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("initial sync of alert2") @@ -98,9 +96,8 @@ func (s *controllerTestSuite) Test_RadixRegistrationEvents() { rr.Spec.AdGroups = []string{"another-admin-group"} rr.ResourceVersion = "2" rr, err = s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}) - if err != nil { - s.Require().NoError(err) - } + s.Require().NoError(err) + s.Handler.EXPECT().Sync(namespace, alert1Name, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("sync on adGroups update") @@ -114,9 +111,9 @@ func (s *controllerTestSuite) Test_RadixRegistrationEvents() { // Update other props on RR should not trigger sync of alert1 rr.Spec.Owner = "owner" rr.ResourceVersion = "4" - if _, err := s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err = s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}) + s.Require().NoError(err) + s.Handler.EXPECT().Sync(namespace, alert1Name, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(0) s.WaitForNotSynced("Sync should not be called when updating other RR props") } diff --git a/radix-operator/application/controller_test.go b/radix-operator/application/controller_test.go index 2cf2a8a97..e3398309f 100644 --- a/radix-operator/application/controller_test.go +++ b/radix-operator/application/controller_test.go @@ -30,15 +30,13 @@ func (s *controllerTestSuite) Test_Controller_Calls_Handler() { s.KubeInformerFactory.Start(s.Stop) go func() { - if err := sut.Run(1, s.Stop); err != nil { - s.Require().NoError(err) - } + err := sut.Run(1, s.Stop) + s.Require().NoError(err) }() ra := utils.ARadixApplication().WithAppName(appName).WithEnvironment("dev", "master").BuildRA() - if _, err := s.RadixClient.RadixV1().RadixApplications(appNamespace).Create(context.TODO(), ra, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err := s.RadixClient.RadixV1().RadixApplications(appNamespace).Create(context.TODO(), ra, metav1.CreateOptions{}) + s.Require().NoError(err) s.Handler.EXPECT().Sync(namespace, appName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("added app") @@ -65,23 +63,23 @@ func (s *controllerTestSuite) Test_Controller_Calls_Handler_On_Admin_Or_Reader_C }() ra := utils.ARadixApplication().WithAppName(appName).WithEnvironment("dev", "master").BuildRA() - if _, err := s.RadixClient.RadixV1().RadixApplications(appNamespace).Create(context.TODO(), ra, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err = s.RadixClient.RadixV1().RadixApplications(appNamespace).Create(context.TODO(), ra, metav1.CreateOptions{}) + s.Require().NoError(err) + s.Handler.EXPECT().Sync(namespace, appName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("added app") rr.Spec.AdGroups = []string{"another-admin-group"} - if _, err := s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err = s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}) + s.Require().NoError(err) + s.Handler.EXPECT().Sync(namespace, appName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("AdGroups changed") rr.Spec.ReaderAdGroups = []string{"another-reader-group"} - if _, err := s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err = s.RadixClient.RadixV1().RadixRegistrations().Update(context.TODO(), rr, metav1.UpdateOptions{}) + s.Require().NoError(err) + s.Handler.EXPECT().Sync(namespace, appName, s.EventRecorder).DoAndReturn(s.SyncedChannelCallback()).Times(1) s.WaitForSynced("ReaderAdGroups changed") } diff --git a/radix-operator/common/controller_test.go b/radix-operator/common/controller_test.go index cdd783fb2..861f555c3 100644 --- a/radix-operator/common/controller_test.go +++ b/radix-operator/common/controller_test.go @@ -78,9 +78,8 @@ func (s *commonControllerTestSuite) Test_SyncSuccess() { s.KubeInformerFactory.Start(stopCh) go func() { - if err := sut.Run(1, stopCh); err != nil { - s.Require().NoError(err) - } + err := sut.Run(1, stopCh) + s.Require().NoError(err) }() doneCh := make(chan struct{}) @@ -125,9 +124,8 @@ func (s *commonControllerTestSuite) Test_RequeueWhenSyncError() { s.KubeInformerFactory.Start(stopCh) go func() { - if err := sut.Run(1, stopCh); err != nil { - s.Require().NoError(err) - } + err := sut.Run(1, stopCh) + s.Require().NoError(err) }() doneCh := make(chan struct{}) diff --git a/radix-operator/deployment/controller_test.go b/radix-operator/deployment/controller_test.go index 94f4c242d..3605094bb 100644 --- a/radix-operator/deployment/controller_test.go +++ b/radix-operator/deployment/controller_test.go @@ -50,7 +50,7 @@ func Test_Controller_Calls_Handler(t *testing.T) { // Setup tu, client, kubeUtil, radixClient, prometheusclient := setupTest() - if _, err := client.CoreV1().Namespaces().Create( + _, err := client.CoreV1().Namespaces().Create( context.TODO(), &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ @@ -61,9 +61,8 @@ func Test_Controller_Calls_Handler(t *testing.T) { }, }, }, - metav1.CreateOptions{}); err != nil { - require.NoError(t, err) - } + metav1.CreateOptions{}) + require.NoError(t, err) stop := make(chan struct{}) synced := make(chan bool) @@ -82,9 +81,8 @@ func Test_Controller_Calls_Handler(t *testing.T) { WithHasSyncedCallback(func(syncedOk bool) { synced <- syncedOk }), ) go func() { - if err := startDeploymentController(client, radixClient, radixInformerFactory, kubeInformerFactory, deploymentHandler, stop); err != nil { - require.NoError(t, err) - } + err := startDeploymentController(client, radixClient, radixInformerFactory, kubeInformerFactory, deploymentHandler, stop) + require.NoError(t, err) }() // Test @@ -106,9 +104,8 @@ func Test_Controller_Calls_Handler(t *testing.T) { // Update deployment should sync. Only actual updates will be handled by the controller noReplicas := 0 rd.Spec.Components[0].Replicas = &noReplicas - if _, err := radixClient.RadixV1().RadixDeployments(rd.ObjectMeta.Namespace).Update(context.TODO(), rd, metav1.UpdateOptions{}); err != nil { - require.NoError(t, err) - } + _, err = radixClient.RadixV1().RadixDeployments(rd.ObjectMeta.Namespace).Update(context.TODO(), rd, metav1.UpdateOptions{}) + require.NoError(t, err) op, ok = <-synced assert.True(t, ok) diff --git a/radix-operator/job/controller_test.go b/radix-operator/job/controller_test.go index 1f7e441dd..af8e1a702 100644 --- a/radix-operator/job/controller_test.go +++ b/radix-operator/job/controller_test.go @@ -95,9 +95,8 @@ func (s *jobTestSuite) Test_Controller_Calls_Handler() { }, ) go func() { - if err := startJobController(s.kubeUtil.KubeClient(), s.kubeUtil.RadixClient(), radixInformerFactory, kubeInformerFactory, jobHandler, stop); err != nil { - s.Require().NoError(err) - } + err := startJobController(s.kubeUtil.KubeClient(), s.kubeUtil.RadixClient(), radixInformerFactory, kubeInformerFactory, jobHandler, stop) + s.Require().NoError(err) }() // Test @@ -114,9 +113,8 @@ func (s *jobTestSuite) Test_Controller_Calls_Handler() { // Update radix job should sync. Controller will skip if an update // changes nothing, except for spec or metadata, labels or annotations rj.Spec.Stop = true - if _, err := s.kubeUtil.RadixClient().RadixV1().RadixJobs(rj.ObjectMeta.Namespace).Update(context.TODO(), rj, metav1.UpdateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err := s.kubeUtil.RadixClient().RadixV1().RadixJobs(rj.ObjectMeta.Namespace).Update(context.TODO(), rj, metav1.UpdateOptions{}) + s.Require().NoError(err) op, ok = <-synced s.True(ok) @@ -130,13 +128,12 @@ func (s *jobTestSuite) Test_Controller_Calls_Handler() { } // Only update of Kubernetes Job is something that the job-controller handles - if _, err := s.kubeUtil.KubeClient().BatchV1().Jobs(rj.ObjectMeta.Namespace).Create(context.TODO(), &childJob, metav1.CreateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err = s.kubeUtil.KubeClient().BatchV1().Jobs(rj.ObjectMeta.Namespace).Create(context.TODO(), &childJob, metav1.CreateOptions{}) + s.Require().NoError(err) + childJob.ObjectMeta.ResourceVersion = "1234" - if _, err := s.kubeUtil.KubeClient().BatchV1().Jobs(rj.ObjectMeta.Namespace).Update(context.TODO(), &childJob, metav1.UpdateOptions{}); err != nil { - s.Require().NoError(err) - } + _, err = s.kubeUtil.KubeClient().BatchV1().Jobs(rj.ObjectMeta.Namespace).Update(context.TODO(), &childJob, metav1.UpdateOptions{}) + s.Require().NoError(err) op, ok = <-synced s.True(ok) From 965263d06e920dec26bfa1343c0b2c058b518ad9 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 15 Dec 2023 14:31:22 +0100 Subject: [PATCH 114/121] Cleanup --- .../applicationconfig_test.go | 61 ++++++++----------- pkg/apis/environment/environment_test.go | 32 ++++++---- pkg/apis/job/job_test.go | 5 +- pkg/apis/kube/environment_variables_test.go | 31 +++++----- radix-operator/application/controller_test.go | 5 +- radix-operator/common/controller_test.go | 35 +++++------ radix-operator/deployment/controller_test.go | 10 +-- radix-operator/deployment/handler_test.go | 27 ++++---- radix-operator/job/controller_test.go | 6 +- .../registration/controller_test.go | 11 +--- 10 files changed, 99 insertions(+), 124 deletions(-) diff --git a/pkg/apis/applicationconfig/applicationconfig_test.go b/pkg/apis/applicationconfig/applicationconfig_test.go index 5c5f35992..fbd4788e2 100644 --- a/pkg/apis/applicationconfig/applicationconfig_test.go +++ b/pkg/apis/applicationconfig/applicationconfig_test.go @@ -239,13 +239,12 @@ func Test_WithBuildSecretsSet_SecretsCorrectlyAdded(t *testing.T) { assert.True(t, roleBindingByNameExists("radix-app-admin-build-secrets", rolebindings)) assert.True(t, roleBindingByNameExists("pipeline-build-secrets", rolebindings)) - if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, + err = applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). - WithBuildSecrets("secret4", "secret5", "secret6")); err != nil { - require.NoError(t, err) - } + WithBuildSecrets("secret4", "secret5", "secret6")) + require.NoError(t, err) secrets, _ = client.CoreV1().Secrets(appNamespace).List(context.TODO(), metav1.ListOptions{}) buildSecrets = getSecretByName(defaults.BuildSecretsName, secrets) @@ -328,23 +327,21 @@ func Test_SubPipelineServiceAccountsCorrectlyDeleted(t *testing.T) { func Test_WithBuildSecretsDeleted_SecretsCorrectlyDeleted(t *testing.T) { tu, client, kubeUtil, radixClient := setupTest() - if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, + err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). - WithBuildSecrets("secret1", "secret2")); err != nil { - require.NoError(t, err) - } + WithBuildSecrets("secret1", "secret2")) + require.NoError(t, err) // Delete secret appNamespace := "any-app-app" - if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, + err = applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). - WithBuildSecrets("secret2")); err != nil { - require.NoError(t, err) - } + WithBuildSecrets("secret2")) + require.NoError(t, err) secrets, _ := client.CoreV1().Secrets(appNamespace).List(context.TODO(), metav1.ListOptions{}) defaultValue := []byte(defaults.BuildSecretDefaultData) @@ -356,13 +353,12 @@ func Test_WithBuildSecretsDeleted_SecretsCorrectlyDeleted(t *testing.T) { assert.Equal(t, defaultValue, buildSecrets.Data["secret2"]) // Delete secret - if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, + err = applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). - WithBuildSecrets()); err != nil { - require.NoError(t, err) - } + WithBuildSecrets()) + require.NoError(t, err) // Secret is deleted secrets, _ = client.CoreV1().Secrets(appNamespace).List(context.TODO(), metav1.ListOptions{}) @@ -382,13 +378,12 @@ func Test_WithBuildSecretsDeleted_SecretsCorrectlyDeleted(t *testing.T) { func Test_AppReaderBuildSecretsRoleAndRoleBindingExists(t *testing.T) { tu, client, kubeUtil, radixClient := setupTest() - if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, + err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). WithEnvironment("dev", "master"). - WithBuildSecrets("secret1", "secret2")); err != nil { - require.NoError(t, err) - } + WithBuildSecrets("secret1", "secret2")) + require.NoError(t, err) roles, _ := client.RbacV1().Roles("any-app-app").List(context.TODO(), metav1.ListOptions{}) assert.True(t, roleByNameExists("radix-app-reader-build-secrets", roles)) @@ -397,12 +392,11 @@ func Test_AppReaderBuildSecretsRoleAndRoleBindingExists(t *testing.T) { assert.True(t, roleBindingByNameExists("radix-app-reader-build-secrets", rolebindings)) // Delete secret and verify that role and rolebinding is deleted - if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, + err = applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithAppName("any-app"). - WithEnvironment("dev", "master")); err != nil { - require.NoError(t, err) - } + WithEnvironment("dev", "master")) + require.NoError(t, err) roles, _ = client.RbacV1().Roles("any-app-app").List(context.TODO(), metav1.ListOptions{}) assert.False(t, roleByNameExists("radix-app-reader-build-secrets", roles)) @@ -415,13 +409,12 @@ func Test_AppReaderPrivateImageHubRoleAndRoleBindingExists(t *testing.T) { tu, client, kubeUtil, radixClient := setupTest() adminGroups, readerGroups := []string{"admin1", "admin2"}, []string{"reader1", "reader2"} - if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, + err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). WithRadixRegistration(utils.ARadixRegistration().WithAdGroups(adminGroups).WithReaderAdGroups(readerGroups)). WithAppName("any-app"). - WithEnvironment("dev", "master")); err != nil { - require.NoError(t, err) - } + WithEnvironment("dev", "master")) + require.NoError(t, err) type testSpec struct { roleName string @@ -568,11 +561,10 @@ func Test_WithPrivateImageHubSet_SecretsCorrectly_Delete(t *testing.T) { func Test_RadixEnvironment(t *testing.T) { tu, client, kubeUtil, radixClient := setupTest() - if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, + err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixApplication(). - WithAppName("any-app")); err != nil { - require.NoError(t, err) - } + WithAppName("any-app")) + require.NoError(t, err) rr, _ := radixClient.RadixV1().RadixRegistrations().Get(context.TODO(), "any-app", metav1.GetOptions{}) @@ -625,9 +617,8 @@ func Test_UseBuildKit(t *testing.T) { if testScenario.useBuildKit != nil { ra = ra.WithBuildKit(testScenario.useBuildKit) } - if err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, ra); err != nil { - require.NoError(t, err) - } + err := applyApplicationWithSync(tu, client, kubeUtil, radixClient, ra) + require.NoError(t, err) raAfterSync, _ := radixClient.RadixV1().RadixApplications(utils.GetAppNamespace(testScenario.appName)).Get(context.TODO(), testScenario.appName, metav1.GetOptions{}) diff --git a/pkg/apis/environment/environment_test.go b/pkg/apis/environment/environment_test.go index f02724d88..95da15123 100644 --- a/pkg/apis/environment/environment_test.go +++ b/pkg/apis/environment/environment_test.go @@ -52,7 +52,7 @@ func setupTest() (test.Utils, kubernetes.Interface, *kube.Kube, radixclient.Inte return handlerTestUtils, fakekube, kubeUtil, fakeradix } -func newEnv(client kubernetes.Interface, kubeUtil *kube.Kube, radixclient radixclient.Interface, radixEnvFileName string) (*v1.RadixRegistration, *v1.RadixEnvironment, Environment) { +func newEnv(client kubernetes.Interface, kubeUtil *kube.Kube, radixclient radixclient.Interface, radixEnvFileName string) (*v1.RadixRegistration, *v1.RadixEnvironment, Environment, error) { rr, _ := utils.GetRadixRegistrationFromFile(regConfigFileName) re, _ := utils.GetRadixEnvironmentFromFile(radixEnvFileName) logger := logrus.WithFields(logrus.Fields{"environmentName": namespaceName}) @@ -60,15 +60,16 @@ func newEnv(client kubernetes.Interface, kubeUtil *kube.Kube, radixclient radixc env, _ := NewEnvironment(client, kubeUtil, radixclient, re, rr, nil, logger, &nw) // register instance with radix-client so UpdateStatus() can find it if _, err := radixclient.RadixV1().RadixEnvironments().Create(context.TODO(), re, metav1.CreateOptions{}); err != nil { - panic(err) + return nil, nil, env, err } - return rr, re, env + return rr, re, env, nil } func Test_Create_Namespace(t *testing.T) { _, client, kubeUtil, radixclient := setupTest() defer os.Clearenv() - rr, _, env := newEnv(client, kubeUtil, radixclient, envConfigFileName) + rr, _, env, err := newEnv(client, kubeUtil, radixclient, envConfigFileName) + require.NoError(t, err) sync(t, &env) @@ -94,7 +95,8 @@ func Test_Create_Namespace(t *testing.T) { func Test_DeleteEnvironment_Deleted(t *testing.T) { _, client, kubeUtil, radixclient := setupTest() defer os.Clearenv() - _, _, env := newEnv(client, kubeUtil, radixclient, envConfigFileName) + _, _, env, err := newEnv(client, kubeUtil, radixclient, envConfigFileName) + require.NoError(t, err) sync(t, &env) @@ -120,12 +122,13 @@ func Test_DeleteEnvironment_Deleted(t *testing.T) { func Test_DeleteEnvironment_DeletedDNSAlias(t *testing.T) { _, client, kubeUtil, radixclient := setupTest() defer os.Clearenv() - _, _, env := newEnv(client, kubeUtil, radixclient, envConfigFileName) + _, _, env, err := newEnv(client, kubeUtil, radixclient, envConfigFileName) + require.NoError(t, err) sync(t, &env) alias1Name := "alias1" - err := createRadixDNSAliasForEnvironment(radixclient, alias1Name) + err = createRadixDNSAliasForEnvironment(radixclient, alias1Name) require.NoError(t, err) dnsAlias, err := radixclient.RadixV1().RadixDNSAliases().Get(context.Background(), alias1Name, metav1.GetOptions{}) require.NoError(t, err) @@ -166,7 +169,8 @@ func Test_Create_Namespace_PodSecurityStandardLabels(t *testing.T) { os.Setenv(defaults.PodSecurityStandardWarnLevelEnvironmentVariable, "warnLvl") os.Setenv(defaults.PodSecurityStandardWarnVersionEnvironmentVariable, "warnVer") defer os.Clearenv() - rr, _, env := newEnv(client, kubeUtil, radixclient, envConfigFileName) + rr, _, env, err := newEnv(client, kubeUtil, radixclient, envConfigFileName) + require.NoError(t, err) sync(t, &env) @@ -198,7 +202,8 @@ func Test_Create_Namespace_PodSecurityStandardLabels(t *testing.T) { func Test_Create_EgressRules(t *testing.T) { _, client, kubeUtil, radixclient := setupTest() defer os.Clearenv() - rr, _, env := newEnv(client, kubeUtil, radixclient, egressRuleEnvConfigFileName) + rr, _, env, err := newEnv(client, kubeUtil, radixclient, egressRuleEnvConfigFileName) + require.NoError(t, err) sync(t, &env) @@ -219,7 +224,8 @@ func Test_Create_EgressRules(t *testing.T) { func Test_Create_RoleBinding(t *testing.T) { _, client, kubeUtil, radixclient := setupTest() defer os.Clearenv() - rr, _, env := newEnv(client, kubeUtil, radixclient, envConfigFileName) + rr, _, env, err := newEnv(client, kubeUtil, radixclient, envConfigFileName) + require.NoError(t, err) sync(t, &env) @@ -244,7 +250,8 @@ func Test_Create_RoleBinding(t *testing.T) { func Test_Create_LimitRange(t *testing.T) { _, client, kubeUtil, radixclient := setupTest() defer os.Clearenv() - _, _, env := newEnv(client, kubeUtil, radixclient, envConfigFileName) + _, _, env, err := newEnv(client, kubeUtil, radixclient, envConfigFileName) + require.NoError(t, err) sync(t, &env) @@ -264,7 +271,8 @@ func Test_Create_LimitRange(t *testing.T) { func Test_Orphaned_Status(t *testing.T) { _, client, kubeUtil, radixclient := setupTest() defer os.Clearenv() - _, _, env := newEnv(client, kubeUtil, radixclient, envConfigFileName) + _, _, env, err := newEnv(client, kubeUtil, radixclient, envConfigFileName) + require.NoError(t, err) env.appConfig = nil sync(t, &env) diff --git a/pkg/apis/job/job_test.go b/pkg/apis/job/job_test.go index 0b4b30c03..88139b87e 100644 --- a/pkg/apis/job/job_test.go +++ b/pkg/apis/job/job_test.go @@ -700,9 +700,8 @@ func (s *RadixJobTestSuite) TestHistoryLimit_EachEnvHasOwnHistory() { WithEnvironment(scenario.testingRadixDeploymentJob.env). WithActiveFrom(testTime)) s.NoError(err) - if err := s.applyJobWithSyncFor(raBuilder, appName, scenario.testingRadixDeploymentJob, config); err != nil { - s.Require().NoError(err) - } + err = s.applyJobWithSyncFor(raBuilder, appName, scenario.testingRadixDeploymentJob, config) + s.Require().NoError(err) radixJobList, err := s.radixClient.RadixV1().RadixJobs(appNamespace).List(context.TODO(), metav1.ListOptions{}) s.NoError(err) diff --git a/pkg/apis/kube/environment_variables_test.go b/pkg/apis/kube/environment_variables_test.go index 70852fe84..428584575 100644 --- a/pkg/apis/kube/environment_variables_test.go +++ b/pkg/apis/kube/environment_variables_test.go @@ -302,7 +302,7 @@ func Test_GetEnvVarsConfigMapAndMetadataMap(t *testing.T) { t.Run("Get existing", func(t *testing.T) { t.Parallel() testEnv := getEnvironmentVariablesTestEnv() - if err := createConfigMap(testEnv.kubeUtil, namespace, &corev1.ConfigMap{ + err := createConfigMap(testEnv.kubeUtil, namespace, &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "env-vars-" + componentName, Namespace: namespace, @@ -312,10 +312,10 @@ func Test_GetEnvVarsConfigMapAndMetadataMap(t *testing.T) { "VAR2": "val2", "VAR3": "setVal3", }, - }); err != nil { - require.NoError(t, err) - } - if err := createConfigMap( + }) + require.NoError(t, err) + + err = createConfigMap( testEnv.kubeUtil, namespace, &corev1.ConfigMap{ @@ -332,9 +332,9 @@ func Test_GetEnvVarsConfigMapAndMetadataMap(t *testing.T) { `, }, }, - ); err != nil { - require.NoError(t, err) - } + ) + require.NoError(t, err) + envVarsConfigMap, envVarsMetadataConfigMap, metadataMap, err := testEnv.kubeUtil.GetEnvVarsConfigMapAndMetadataMap(namespace, componentName) assert.NoError(t, err) assert.NotNil(t, envVarsConfigMap) @@ -380,7 +380,7 @@ func Test_GetOrCreateEnvVarsConfigMapAndMetadataMap(t *testing.T) { t.Run("Get existing", func(t *testing.T) { t.Parallel() testEnv := getEnvironmentVariablesTestEnv() - if err := createConfigMap(testEnv.kubeUtil, namespace, &corev1.ConfigMap{ + err := createConfigMap(testEnv.kubeUtil, namespace, &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "env-vars-" + componentName, Namespace: namespace, @@ -390,10 +390,10 @@ func Test_GetOrCreateEnvVarsConfigMapAndMetadataMap(t *testing.T) { "VAR2": "val2", "VAR3": "setVal3", }, - }); err != nil { - require.NoError(t, err) - } - if err := createConfigMap( + }) + require.NoError(t, err) + + err = createConfigMap( testEnv.kubeUtil, namespace, &corev1.ConfigMap{ @@ -410,9 +410,8 @@ func Test_GetOrCreateEnvVarsConfigMapAndMetadataMap(t *testing.T) { `, }, }, - ); err != nil { - require.NoError(t, err) - } + ) + require.NoError(t, err) envVarsConfigMap, envVarsMetadataConfigMap, err := testEnv.kubeUtil.GetOrCreateEnvVarsConfigMapAndMetadataMap(namespace, appName, componentName) diff --git a/radix-operator/application/controller_test.go b/radix-operator/application/controller_test.go index e3398309f..0a0f0b3ec 100644 --- a/radix-operator/application/controller_test.go +++ b/radix-operator/application/controller_test.go @@ -57,9 +57,8 @@ func (s *controllerTestSuite) Test_Controller_Calls_Handler_On_Admin_Or_Reader_C s.KubeInformerFactory.Start(s.Stop) go func() { - if err := sut.Run(1, s.Stop); err != nil { - s.Require().NoError(err) - } + err := sut.Run(1, s.Stop) + s.Require().NoError(err) }() ra := utils.ARadixApplication().WithAppName(appName).WithEnvironment("dev", "master").BuildRA() diff --git a/radix-operator/common/controller_test.go b/radix-operator/common/controller_test.go index 861f555c3..835f1660f 100644 --- a/radix-operator/common/controller_test.go +++ b/radix-operator/common/controller_test.go @@ -169,9 +169,8 @@ func (s *commonControllerTestSuite) Test_ForgetWhenLockKeyAndIdentifierError() { s.KubeInformerFactory.Start(stopCh) go func() { - if err := sut.Run(1, stopCh); err != nil { - s.Require().NoError(err) - } + err := sut.Run(1, stopCh) + s.Require().NoError(err) }() doneCh := make(chan struct{}) @@ -212,9 +211,8 @@ func (s *commonControllerTestSuite) Test_SkipItemWhenNil() { s.KubeInformerFactory.Start(stopCh) go func() { - if err := sut.Run(1, stopCh); err != nil { - s.Require().NoError(err) - } + err := sut.Run(1, stopCh) + s.Require().NoError(err) }() doneCh := make(chan struct{}) @@ -253,9 +251,8 @@ func (s *commonControllerTestSuite) Test_SkipItemWhenEmpty() { s.KubeInformerFactory.Start(stopCh) go func() { - if err := sut.Run(1, stopCh); err != nil { - s.Require().NoError(err) - } + err := sut.Run(1, stopCh) + s.Require().NoError(err) }() doneCh := make(chan struct{}) @@ -295,9 +292,8 @@ func (s *commonControllerTestSuite) Test_QuitRunWhenShutdownTrue() { doneCh := make(chan struct{}) go func() { - if err := sut.Run(1, stopCh); err != nil { - s.Require().NoError(err) - } + err := sut.Run(1, stopCh) + s.Require().NoError(err) close(doneCh) }() @@ -335,10 +331,9 @@ func (s *commonControllerTestSuite) Test_QuitRunWhenShuttingDownTrue() { doneCh := make(chan struct{}) go func() { - if err := sut.Run(1, stopCh); err != nil { - s.Require().NoError(err) - } + err := sut.Run(1, stopCh) close(doneCh) + s.Require().NoError(err) }() queue.On("ShuttingDown").Return(true).Times(1) @@ -377,9 +372,8 @@ func (s *commonControllerTestSuite) Test_RequeueWhenLocked() { s.KubeInformerFactory.Start(stopCh) go func() { - if err := sut.Run(1, stopCh); err != nil { - s.Require().NoError(err) - } + err := sut.Run(1, stopCh) + s.Require().NoError(err) }() doneCh := make(chan struct{}) @@ -435,9 +429,8 @@ func (s *commonControllerTestSuite) Test_ProcessParallell() { queue.On("ShuttingDown").Return(false) go func() { - if err := sut.Run(threadiness, stopCh); err != nil { - s.Require().NoError(err) - } + err := sut.Run(threadiness, stopCh) + s.Require().NoError(err) }() for i := 0; i < len(testItems); i++ { diff --git a/radix-operator/deployment/controller_test.go b/radix-operator/deployment/controller_test.go index 3605094bb..a8aca7ac6 100644 --- a/radix-operator/deployment/controller_test.go +++ b/radix-operator/deployment/controller_test.go @@ -124,9 +124,8 @@ func Test_Controller_Calls_Handler(t *testing.T) { }) for _, aservice := range services.Items { - if err := client.CoreV1().Services(rd.ObjectMeta.Namespace).Delete(context.TODO(), aservice.Name, metav1.DeleteOptions{}); err != nil { - require.NoError(t, err) - } + err := client.CoreV1().Services(rd.ObjectMeta.Namespace).Delete(context.TODO(), aservice.Name, metav1.DeleteOptions{}) + require.NoError(t, err) op, ok = <-synced assert.True(t, ok) @@ -155,8 +154,5 @@ func startDeploymentController(client kubernetes.Interface, radixClient radixcli kubeInformerFactory.Start(stop) radixInformerFactory.Start(stop) - if err := controller.Run(4, stop); err != nil { - return err - } - return nil + return controller.Run(4, stop) } diff --git a/radix-operator/deployment/handler_test.go b/radix-operator/deployment/handler_test.go index afe141946..3f8915fdd 100644 --- a/radix-operator/deployment/handler_test.go +++ b/radix-operator/deployment/handler_test.go @@ -63,36 +63,35 @@ func (s *handlerSuite) Test_Sync() { appName := "any-app" namespace := "any-ns" - if err := s.radixClient.Tracker().Add( + err := s.radixClient.Tracker().Add( &radixv1.RadixDeployment{ ObjectMeta: v1.ObjectMeta{Name: inactiveRdName, Namespace: namespace}, Status: radixv1.RadixDeployStatus{Condition: radixv1.DeploymentInactive}, }, - ); err != nil { - s.Require().NoError(err) - } - if err := s.radixClient.Tracker().Add( + ) + s.Require().NoError(err) + + err = s.radixClient.Tracker().Add( &radixv1.RadixDeployment{ ObjectMeta: v1.ObjectMeta{Name: activeRdMissingRrName, Namespace: namespace}, Status: radixv1.RadixDeployStatus{Condition: radixv1.DeploymentActive}, }, - ); err != nil { - s.Require().NoError(err) - } + ) + s.Require().NoError(err) + activeRd := &radixv1.RadixDeployment{ ObjectMeta: v1.ObjectMeta{Name: activeRdName, Namespace: namespace}, Spec: radixv1.RadixDeploymentSpec{AppName: appName}, Status: radixv1.RadixDeployStatus{Condition: radixv1.DeploymentActive}, } - if err := s.radixClient.Tracker().Add(activeRd); err != nil { - s.Require().NoError(err) - } + err = s.radixClient.Tracker().Add(activeRd) + s.Require().NoError(err) + rr := &radixv1.RadixRegistration{ ObjectMeta: v1.ObjectMeta{Name: appName}, } - if err := s.radixClient.Tracker().Add(rr); err != nil { - s.Require().NoError(err) - } + err = s.radixClient.Tracker().Add(rr) + s.Require().NoError(err) s.Run("non-existing RD should not call factory method", func() { ctrl := gomock.NewController(s.T()) diff --git a/radix-operator/job/controller_test.go b/radix-operator/job/controller_test.go index af8e1a702..3a76dd76a 100644 --- a/radix-operator/job/controller_test.go +++ b/radix-operator/job/controller_test.go @@ -149,9 +149,5 @@ func startJobController(client kubernetes.Interface, radixClient radixclient.Int kubeInformerFactory.Start(stop) radixInformerFactory.Start(stop) - if err := controller.Run(4, stop); err != nil { - return err - } - - return nil + return controller.Run(4, stop) } diff --git a/radix-operator/registration/controller_test.go b/radix-operator/registration/controller_test.go index f52811e70..d1594263f 100644 --- a/radix-operator/registration/controller_test.go +++ b/radix-operator/registration/controller_test.go @@ -54,9 +54,8 @@ func Test_Controller_Calls_Handler(t *testing.T) { }, ) go func() { - if err := startRegistrationController(client, radixClient, radixInformerFactory, kubeInformerFactory, registrationHandler, stop); err != nil { - require.NoError(t, err) - } + err := startRegistrationController(client, radixClient, radixInformerFactory, kubeInformerFactory, registrationHandler, stop) + require.NoError(t, err) }() // Test @@ -137,9 +136,5 @@ func startRegistrationController(client kubernetes.Interface, radixClient radixc kubeInformerFactory.Start(stop) radixInformerFactory.Start(stop) - if err := controller.Run(5, stop); err != nil { - return err - } - - return nil + return controller.Run(5, stop) } From 334123788f452d637559e5cce28d42909d3933c0 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 15 Dec 2023 14:35:18 +0100 Subject: [PATCH 115/121] Cleanup --- pkg/apis/dnsalias/syncer.go | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/pkg/apis/dnsalias/syncer.go b/pkg/apis/dnsalias/syncer.go index 788a4a9b0..44ccc2576 100644 --- a/pkg/apis/dnsalias/syncer.go +++ b/pkg/apis/dnsalias/syncer.go @@ -2,7 +2,6 @@ package dnsalias import ( "fmt" - "regexp" commonUtils "github.com/equinor/radix-common/utils" "github.com/equinor/radix-common/utils/slice" @@ -35,11 +34,8 @@ type syncer struct { ingressAnnotationProviders []ingress.AnnotationProvider } -var admissionWebhookErrorExpression *regexp.Regexp - // NewSyncer is the constructor for RadixDNSAlias syncer func NewSyncer(kubeClient kubernetes.Interface, kubeUtil *kube.Kube, radixClient radixclient.Interface, dnsConfig *dnsalias.DNSConfig, ingressConfiguration ingress.IngressConfiguration, oauth2Config defaults.OAuth2Config, ingressAnnotationProviders []ingress.AnnotationProvider, radixDNSAlias *radixv1.RadixDNSAlias) Syncer { - admissionWebhookErrorExpression = regexp.MustCompile(`admission webhook "validate.nginx.ingress.kubernetes.io" denied the request: host "(.*?)" and path "(.*?)" is already defined in ingress (.*?)/(.*?)$`) return &syncer{ kubeClient: kubeClient, radixClient: radixClient, @@ -82,20 +78,11 @@ func (s *syncer) syncAlias() error { ing, err := s.syncIngress(namespace, radixDeployComponent) if err != nil { - return s.getDNSAliasError(err) + return err } - return s.syncOAuthProxyIngress(namespace, ing, radixDeployComponent) } -func (s *syncer) getDNSAliasError(err error) error { - if admissionWebhookErrorMatcher := admissionWebhookErrorExpression.FindStringSubmatch(err.Error()); len(admissionWebhookErrorMatcher) == 5 { - log.Error(err) - return fmt.Errorf("DNS alias %s cannot be used, because the host %s with the path %s is already in use", s.radixDNSAlias.GetName(), admissionWebhookErrorMatcher[1], admissionWebhookErrorMatcher[2]) - } - return err -} - func (s *syncer) getRadixDeployComponent() (radixv1.RadixCommonDeployComponent, error) { aliasSpec := s.radixDNSAlias.Spec namespace := utils.GetEnvironmentNamespace(aliasSpec.AppName, aliasSpec.Environment) From 59d48357d953300bcbc9a1faf8e04b80b422225d Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 15 Dec 2023 14:54:58 +0100 Subject: [PATCH 116/121] Cleanup --- Makefile | 4 ++++ charts/radix-operator/templates/radixdnsalias.yaml | 2 +- charts/radix-operator/values.yaml | 2 ++ pipeline-runner/steps/promotion_test.go | 2 -- pkg/apis/deployment/radixcomponent.go | 10 ---------- pkg/apis/radix/config.go | 1 - pkg/apis/radix/v1/radixdeploytypes.go | 10 ---------- pkg/apis/radix/v1/radixdnsaliastypes.go | 2 +- pkg/apis/radix/v1/zz_generated.deepcopy.go | 5 ----- 9 files changed, 8 insertions(+), 30 deletions(-) delete mode 100644 pkg/apis/radix/config.go diff --git a/Makefile b/Makefile index 6492f4d20..0fd62a321 100644 --- a/Makefile +++ b/Makefile @@ -160,4 +160,8 @@ delete-temp-crds: staticcheck: staticcheck `go list ./... | grep -v "pkg/client"` && go vet `go list ./... | grep -v "pkg/client"` +.PHONY: lint +lint: + golangci-lint run + diff --git a/charts/radix-operator/templates/radixdnsalias.yaml b/charts/radix-operator/templates/radixdnsalias.yaml index 8ad524e3e..90f4731cd 100644 --- a/charts/radix-operator/templates/radixdnsalias.yaml +++ b/charts/radix-operator/templates/radixdnsalias.yaml @@ -22,7 +22,7 @@ spec: name: Application type: string - jsonPath: .status.condition - name: Condition + name: State type: string - jsonPath: .metadata.creationTimestamp name: Age diff --git a/charts/radix-operator/values.yaml b/charts/radix-operator/values.yaml index c11ae1224..a0f724eff 100644 --- a/charts/radix-operator/values.yaml +++ b/charts/radix-operator/values.yaml @@ -31,6 +31,8 @@ reservedDNSAlias: - prometheus - www - app + - playground + - dev appAliasBaseURL: app.dev.radix.equinor.com dnsZone: dev.radix.equinor.com diff --git a/pipeline-runner/steps/promotion_test.go b/pipeline-runner/steps/promotion_test.go index a40a57a5d..27fa44895 100644 --- a/pipeline-runner/steps/promotion_test.go +++ b/pipeline-runner/steps/promotion_test.go @@ -308,8 +308,6 @@ func TestPromote_PromoteToOtherEnvironment_NewStateIsExpected(t *testing.T) { assert.Equal(t, "mysql", rds.Items[0].Spec.Components[0].EnvironmentVariables["DB_TYPE"]) assert.Equal(t, "my-db-prod", rds.Items[0].Spec.Components[0].EnvironmentVariables["DB_NAME"]) assert.Equal(t, anyExternalDNSAlias, rds.Items[0].Spec.Components[0].DNSExternalAlias[0]) - assert.Contains(t, rds.Items[0].Spec.Components[0].DNSAlias, anyDNSAlias1) - assert.Contains(t, rds.Items[0].Spec.Components[0].DNSAlias, anyDNSAlias2) assert.True(t, rds.Items[0].Spec.Components[0].DNSAppAlias) assert.Len(t, rds.Items[0].Spec.Components[0].Secrets, 1) assert.Equal(t, "DEPLOYAPPSECRET", rds.Items[0].Spec.Components[0].Secrets[0]) diff --git a/pkg/apis/deployment/radixcomponent.go b/pkg/apis/deployment/radixcomponent.go index 587f51b00..43293da9f 100644 --- a/pkg/apis/deployment/radixcomponent.go +++ b/pkg/apis/deployment/radixcomponent.go @@ -58,7 +58,6 @@ func GetRadixComponentsForEnv(radixApplication *v1.RadixApplication, env string, deployComponent.Resources = getRadixCommonComponentResources(&radixComponent, environmentSpecificConfig) deployComponent.EnvironmentVariables = getRadixCommonComponentEnvVars(&radixComponent, environmentSpecificConfig, defaultEnvVars) deployComponent.AlwaysPullImageOnDeploy = getRadixComponentAlwaysPullImageOnDeployFlag(&radixComponent, environmentSpecificConfig) - deployComponent.DNSAlias = getDNSAliasForComponentEnvironment(radixApplication, componentName, env) deployComponent.DNSExternalAlias = getExternalDNSAliasForComponentEnvironment(radixApplication, componentName, env) deployComponent.SecretRefs = getRadixCommonComponentRadixSecretRefs(&radixComponent, environmentSpecificConfig) deployComponent.PublicPort = getRadixComponentPort(&radixComponent) @@ -143,15 +142,6 @@ func getRadixComponentPort(radixComponent *v1.RadixComponent) string { return radixComponent.PublicPort } -func getDNSAliasForComponentEnvironment(radixApplication *v1.RadixApplication, component, env string) []string { - return slice.Reduce(radixApplication.Spec.DNSAlias, make([]string, 0), func(acc []string, dnsAlias v1.DNSAlias) []string { - if dnsAlias.Component == component && dnsAlias.Environment == env { - acc = append(acc, dnsAlias.Alias) - } - return acc - }) -} - func getExternalDNSAliasForComponentEnvironment(radixApplication *v1.RadixApplication, component, env string) []string { return slice.Reduce(radixApplication.Spec.DNSExternalAlias, make([]string, 0), func(acc []string, externalAlias v1.ExternalAlias) []string { if externalAlias.Component == component && externalAlias.Environment == env { diff --git a/pkg/apis/radix/config.go b/pkg/apis/radix/config.go deleted file mode 100644 index a751fe77d..000000000 --- a/pkg/apis/radix/config.go +++ /dev/null @@ -1 +0,0 @@ -package radix diff --git a/pkg/apis/radix/v1/radixdeploytypes.go b/pkg/apis/radix/v1/radixdeploytypes.go index 86e5e9991..3482b7a6e 100644 --- a/pkg/apis/radix/v1/radixdeploytypes.go +++ b/pkg/apis/radix/v1/radixdeploytypes.go @@ -97,7 +97,6 @@ type RadixDeployComponent struct { SecretRefs RadixSecretRefs `json:"secretRefs,omitempty" yaml:"secretRefs,omitempty"` IngressConfiguration []string `json:"ingressConfiguration,omitempty" yaml:"ingressConfiguration,omitempty"` DNSAppAlias bool `json:"dnsAppAlias,omitempty" yaml:"dnsAppAlias,omitempty"` - DNSAlias []string `json:"dnsAlias,omitempty" yaml:"dnsAlias,omitempty"` DNSExternalAlias []string `json:"dnsExternalAlias,omitempty" yaml:"dnsExternalAlias,omitempty"` Monitoring bool `json:"monitoring" yaml:"monitoring"` MonitoringConfig MonitoringConfig `json:"monitoringConfig,omitempty" yaml:"monitoringConfig,omitempty"` @@ -178,10 +177,6 @@ func (deployComponent *RadixDeployComponent) GetDNSExternalAlias() []string { return deployComponent.DNSExternalAlias } -func (deployComponent *RadixDeployComponent) GetDNSAlias() []string { - return deployComponent.DNSAlias -} - func (deployComponent *RadixDeployComponent) IsDNSAppAlias() bool { return deployComponent.DNSAppAlias } @@ -287,10 +282,6 @@ func (deployJobComponent *RadixDeployJobComponent) GetDNSExternalAlias() []strin return nil } -func (deployJobComponent *RadixDeployJobComponent) GetDNSAlias() []string { - return nil -} - func (deployJobComponent *RadixDeployJobComponent) IsDNSAppAlias() bool { return false } @@ -388,7 +379,6 @@ type RadixCommonDeployComponent interface { GetHorizontalScaling() *RadixHorizontalScaling GetPublicPort() string IsPublic() bool - GetDNSAlias() []string GetDNSExternalAlias() []string IsDNSAppAlias() bool GetIngressConfiguration() []string diff --git a/pkg/apis/radix/v1/radixdnsaliastypes.go b/pkg/apis/radix/v1/radixdnsaliastypes.go index fddb76180..04233a242 100644 --- a/pkg/apis/radix/v1/radixdnsaliastypes.go +++ b/pkg/apis/radix/v1/radixdnsaliastypes.go @@ -6,7 +6,7 @@ import meta "k8s.io/apimachinery/pkg/apis/meta/v1" // +genclient:nonNamespaced // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +kubebuilder:printcolumn:name="Application",type="string",JSONPath=".spec.appName" -// +kubebuilder:printcolumn:name="Condition",type="string",JSONPath=".status.condition" +// +kubebuilder:printcolumn:name="State",type="string",JSONPath=".status.condition" // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" // +kubebuilder:resource:path=radixdnsaliases,scope=Cluster,shortName=rda // +kubebuilder:subresource:status diff --git a/pkg/apis/radix/v1/zz_generated.deepcopy.go b/pkg/apis/radix/v1/zz_generated.deepcopy.go index 73dc82155..560811d31 100644 --- a/pkg/apis/radix/v1/zz_generated.deepcopy.go +++ b/pkg/apis/radix/v1/zz_generated.deepcopy.go @@ -1369,11 +1369,6 @@ func (in *RadixDeployComponent) DeepCopyInto(out *RadixDeployComponent) { *out = make([]string, len(*in)) copy(*out, *in) } - if in.DNSAlias != nil { - in, out := &in.DNSAlias, &out.DNSAlias - *out = make([]string, len(*in)) - copy(*out, *in) - } if in.DNSExternalAlias != nil { in, out := &in.DNSExternalAlias, &out.DNSExternalAlias *out = make([]string, len(*in)) From 3bb3dd3b89b4577d4b36996f36439cc1b3499aba Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Fri, 15 Dec 2023 16:05:13 +0100 Subject: [PATCH 117/121] Changed status column title --- charts/radix-operator/templates/radixdnsalias.yaml | 2 +- pkg/apis/radix/v1/radixdnsaliastypes.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/radix-operator/templates/radixdnsalias.yaml b/charts/radix-operator/templates/radixdnsalias.yaml index 90f4731cd..8c00d4611 100644 --- a/charts/radix-operator/templates/radixdnsalias.yaml +++ b/charts/radix-operator/templates/radixdnsalias.yaml @@ -22,7 +22,7 @@ spec: name: Application type: string - jsonPath: .status.condition - name: State + name: Status type: string - jsonPath: .metadata.creationTimestamp name: Age diff --git a/pkg/apis/radix/v1/radixdnsaliastypes.go b/pkg/apis/radix/v1/radixdnsaliastypes.go index 04233a242..4c5fa6f28 100644 --- a/pkg/apis/radix/v1/radixdnsaliastypes.go +++ b/pkg/apis/radix/v1/radixdnsaliastypes.go @@ -6,7 +6,7 @@ import meta "k8s.io/apimachinery/pkg/apis/meta/v1" // +genclient:nonNamespaced // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +kubebuilder:printcolumn:name="Application",type="string",JSONPath=".spec.appName" -// +kubebuilder:printcolumn:name="State",type="string",JSONPath=".status.condition" +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.condition" // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" // +kubebuilder:resource:path=radixdnsaliases,scope=Cluster,shortName=rda // +kubebuilder:subresource:status From e04bc8f8ec38c33f49fff364a9698d8a900047d2 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 18 Dec 2023 13:19:51 +0100 Subject: [PATCH 118/121] Cleanup --- pkg/apis/application/roles.go | 2 +- pkg/apis/radix/v1/register.go | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/pkg/apis/application/roles.go b/pkg/apis/application/roles.go index 92a86a10f..a9f7f0f79 100644 --- a/pkg/apis/application/roles.go +++ b/pkg/apis/application/roles.go @@ -21,7 +21,7 @@ func (app *Application) buildRRClusterRole(clusterRoleName string, verbs []strin func (app *Application) buildRadixDNSAliasClusterRole(roleNamePrefix string) *rbacv1.ClusterRole { clusterRoleName := fmt.Sprintf("%s-%s", roleNamePrefix, app.registration.Name) - return app.buildClusterRole(clusterRoleName, rbacv1.PolicyRule{APIGroups: []string{"radix.equinor.com"}, + return app.buildClusterRole(clusterRoleName, rbacv1.PolicyRule{APIGroups: []string{v1.SchemeGroupVersion.Group}, Resources: []string{v1.ResourceRadixDNSAliases}, Verbs: []string{"list"}, }) diff --git a/pkg/apis/radix/v1/register.go b/pkg/apis/radix/v1/register.go index 0e7e4a175..f9cffd162 100644 --- a/pkg/apis/radix/v1/register.go +++ b/pkg/apis/radix/v1/register.go @@ -8,7 +8,6 @@ import ( const ( GroupName = "radix.equinor.com" - Version = "v1" ) // SchemeGroupVersion provides the group version @@ -62,10 +61,6 @@ func addKnownTypes(scheme *runtime.Scheme) error { } const ( - - // APIVersion API version for Radix objects - APIVersion = "radix.equinor.com/v1" - // KindRadixRegistration RadixRegistration object Kind KindRadixRegistration = "RadixRegistration" // KindRadixEnvironment RadixEnvironment object Kind @@ -86,6 +81,4 @@ const ( ResourceRadixRegistrations = "radixregistrations" // ResourceRadixDNSAliases RadixDNSAliases API resource ResourceRadixDNSAliases = "radixdnsaliases" - // ResourceRadixDeployment RadixDeployment API resource - ResourceRadixDeployment = "radixdeployments" ) From 6795b6498be20c79c8942edd641eeed760c08a51 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 18 Dec 2023 13:36:34 +0100 Subject: [PATCH 119/121] Controllers fail with panic, when creating informers with error --- radix-operator/alert/controller.go | 4 ++-- radix-operator/application/controller.go | 4 ++-- radix-operator/deployment/controller.go | 4 ++-- radix-operator/environment/controller.go | 12 ++++++------ radix-operator/job/controller.go | 6 +++--- radix-operator/registration/controller.go | 4 ++-- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/radix-operator/alert/controller.go b/radix-operator/alert/controller.go index 7a0a6b4e7..363429fad 100644 --- a/radix-operator/alert/controller.go +++ b/radix-operator/alert/controller.go @@ -94,7 +94,7 @@ func NewController(client kubernetes.Interface, metrics.CustomResourceDeleted(crType) }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } if _, err := registrationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ @@ -125,7 +125,7 @@ func NewController(client kubernetes.Interface, } }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } return controller diff --git a/radix-operator/application/controller.go b/radix-operator/application/controller.go index 1877de9e3..25518b3e1 100644 --- a/radix-operator/application/controller.go +++ b/radix-operator/application/controller.go @@ -93,7 +93,7 @@ func NewController(client kubernetes.Interface, metrics.CustomResourceDeleted(crType) }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } if _, err := registrationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: func(old, cur interface{}) { @@ -118,7 +118,7 @@ func NewController(client kubernetes.Interface, metrics.CustomResourceUpdated(crType) }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } return controller diff --git a/radix-operator/deployment/controller.go b/radix-operator/deployment/controller.go index 4f66248f9..9fcfa67fc 100644 --- a/radix-operator/deployment/controller.go +++ b/radix-operator/deployment/controller.go @@ -133,7 +133,7 @@ func NewController(client kubernetes.Interface, controller.HandleObject(obj, v1.KindRadixDeployment, getObject) }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } if _, err := registrationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ @@ -171,7 +171,7 @@ func NewController(client kubernetes.Interface, } }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } return controller diff --git a/radix-operator/environment/controller.go b/radix-operator/environment/controller.go index f052c7458..247b7e1ac 100644 --- a/radix-operator/environment/controller.go +++ b/radix-operator/environment/controller.go @@ -99,7 +99,7 @@ func NewController(client kubernetes.Interface, metrics.CustomResourceDeleted(crType) }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } namespaceInformer := kubeInformerFactory.Core().V1().Namespaces() @@ -109,7 +109,7 @@ func NewController(client kubernetes.Interface, controller.HandleObject(obj, v1.KindRadixEnvironment, getOwner) }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } rolebindingInformer := kubeInformerFactory.Rbac().V1().RoleBindings() @@ -119,7 +119,7 @@ func NewController(client kubernetes.Interface, controller.HandleObject(obj, v1.KindRadixEnvironment, getOwner) }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } limitrangeInformer := kubeInformerFactory.Core().V1().LimitRanges() @@ -129,7 +129,7 @@ func NewController(client kubernetes.Interface, controller.HandleObject(obj, v1.KindRadixEnvironment, getOwner) }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } if _, err := registrationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ @@ -164,7 +164,7 @@ func NewController(client kubernetes.Interface, } }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } if _, err := applicationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ @@ -203,7 +203,7 @@ func NewController(client kubernetes.Interface, } }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } return controller diff --git a/radix-operator/job/controller.go b/radix-operator/job/controller.go index 85ef02e50..92f644de4 100644 --- a/radix-operator/job/controller.go +++ b/radix-operator/job/controller.go @@ -98,7 +98,7 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac metrics.CustomResourceDeleted(crType) }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } if _, err := kubernetesJobInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ @@ -121,7 +121,7 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac controller.HandleObject(radixJob, v1.KindRadixJob, getObject) }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } if _, err := podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ @@ -148,7 +148,7 @@ func NewController(client kubernetes.Interface, radixClient radixclient.Interfac } }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } return controller diff --git a/radix-operator/registration/controller.go b/radix-operator/registration/controller.go index 516ca5df0..061741155 100644 --- a/radix-operator/registration/controller.go +++ b/radix-operator/registration/controller.go @@ -95,7 +95,7 @@ func NewController(client kubernetes.Interface, metrics.CustomResourceDeleted(crType) }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } namespaceInformer := kubeInformerFactory.Core().V1().Namespaces() @@ -104,7 +104,7 @@ func NewController(client kubernetes.Interface, controller.HandleObject(obj, v1.KindRadixRegistration, getObject) }, }); err != nil { - utilruntime.HandleError(err) + panic(err) } secretInformer := kubeInformerFactory.Core().V1().Secrets() From 9fc9d0cc439bef77b19e8b8840ffdea17b7c234d Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 18 Dec 2023 13:55:39 +0100 Subject: [PATCH 120/121] Fixed of review commented issues --- pipeline-runner/pipelines/app_test.go | 4 ++- pipeline-runner/steps/deploy_test.go | 3 +- pkg/apis/application/application_test.go | 21 +++++++------ pkg/apis/application/secrets_test.go | 10 +++--- pkg/apis/dnsalias/ingress.go | 2 -- pkg/apis/kube/kube.go | 10 +++--- pkg/apis/test/utils.go | 17 +++++----- pkg/apis/utils/annotations/annotations.go | 5 --- .../utils/annotations/annotations_test.go | 6 ---- pkg/apis/utils/application_builder.go | 31 +++---------------- pkg/apis/utils/environment_builder_test.go | 3 +- radix-operator/dnsalias/controller.go | 23 ++++++-------- 12 files changed, 50 insertions(+), 85 deletions(-) diff --git a/pipeline-runner/pipelines/app_test.go b/pipeline-runner/pipelines/app_test.go index 4792cce94..fdc5c5c17 100644 --- a/pipeline-runner/pipelines/app_test.go +++ b/pipeline-runner/pipelines/app_test.go @@ -11,6 +11,7 @@ import ( radix "github.com/equinor/radix-operator/pkg/client/clientset/versioned/fake" monitoring "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" kubernetes "k8s.io/client-go/kubernetes/fake" secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake" ) @@ -21,7 +22,8 @@ func setupTest(t *testing.T) (*kubernetes.Clientset, *radix.Clientset, *secretpr radixclient := radix.NewSimpleClientset() secretproviderclient := secretproviderfake.NewSimpleClientset() testUtils := commonTest.NewTestUtils(kubeclient, radixclient, secretproviderclient) - testUtils.CreateClusterPrerequisites("AnyClusterName", "0.0.0.0", "anysubid") + err := testUtils.CreateClusterPrerequisites("AnyClusterName", "0.0.0.0", "anysubid") + require.NoError(t, err) return kubeclient, radixclient, secretproviderclient, testUtils } diff --git a/pipeline-runner/steps/deploy_test.go b/pipeline-runner/steps/deploy_test.go index 148ebf4c0..97f40462d 100644 --- a/pipeline-runner/steps/deploy_test.go +++ b/pipeline-runner/steps/deploy_test.go @@ -38,7 +38,8 @@ func setupTest(t *testing.T) (*kubernetes.Clientset, *kube.Kube, *radix.Clientse radixclient := radix.NewSimpleClientset() secretproviderclient := secretproviderfake.NewSimpleClientset() testUtils := commonTest.NewTestUtils(kubeclient, radixclient, secretproviderclient) - testUtils.CreateClusterPrerequisites("AnyClusterName", "0.0.0.0", "anysubid") + err := testUtils.CreateClusterPrerequisites("AnyClusterName", "0.0.0.0", "anysubid") + require.NoError(t, err) kubeUtil, _ := kube.New(kubeclient, radixclient, secretproviderclient) return kubeclient, kubeUtil, radixclient, testUtils diff --git a/pkg/apis/application/application_test.go b/pkg/apis/application/application_test.go index 503cb5217..859f65afe 100644 --- a/pkg/apis/application/application_test.go +++ b/pkg/apis/application/application_test.go @@ -24,19 +24,20 @@ import ( secretproviderfake "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/fake" ) -func setupTest() (test.Utils, kubernetes.Interface, *kube.Kube, radixclient.Interface) { +func setupTest(t *testing.T) (test.Utils, kubernetes.Interface, *kube.Kube, radixclient.Interface) { client := fake.NewSimpleClientset() radixClient := fakeradix.NewSimpleClientset() secretproviderclient := secretproviderfake.NewSimpleClientset() kubeUtil, _ := kube.New(client, radixClient, secretproviderclient) handlerTestUtils := test.NewTestUtils(client, radixClient, secretproviderclient) - handlerTestUtils.CreateClusterPrerequisites("AnyClusterName", "0.0.0.0", "anysubid") + err := handlerTestUtils.CreateClusterPrerequisites("AnyClusterName", "0.0.0.0", "anysubid") + require.NoError(t, err) return handlerTestUtils, client, kubeUtil, radixClient } func TestOnSync_CorrectRRScopedClusterRoles_CorrectClusterRoleBindings(t *testing.T) { // Setup - tu, client, kubeUtil, radixClient := setupTest() + tu, client, kubeUtil, radixClient := setupTest(t) defer os.Clearenv() // Test @@ -68,7 +69,7 @@ func TestOnSync_CorrectRRScopedClusterRoles_CorrectClusterRoleBindings(t *testin func TestOnSync_CorrectRoleBindings_AppNamespace(t *testing.T) { // Setup - tu, client, kubeUtil, radixClient := setupTest() + tu, client, kubeUtil, radixClient := setupTest(t) defer os.Clearenv() // Test @@ -93,7 +94,7 @@ func TestOnSync_CorrectRoleBindings_AppNamespace(t *testing.T) { func TestOnSync_RegistrationCreated_AppNamespaceWithResourcesCreated(t *testing.T) { // Setup - tu, client, kubeUtil, radixClient := setupTest() + tu, client, kubeUtil, radixClient := setupTest(t) defer os.Clearenv() // Test @@ -131,7 +132,7 @@ func TestOnSync_RegistrationCreated_AppNamespaceWithResourcesCreated(t *testing. func TestOnSync_PodSecurityStandardLabelsSetOnNamespace(t *testing.T) { // Setup - tu, client, kubeUtil, radixClient := setupTest() + tu, client, kubeUtil, radixClient := setupTest(t) defer os.Clearenv() os.Setenv(defaults.PodSecurityStandardAppNamespaceEnforceLevelEnvironmentVariable, "enforceAppNsLvl") os.Setenv(defaults.PodSecurityStandardEnforceLevelEnvironmentVariable, "enforceLvl") @@ -166,7 +167,7 @@ func TestOnSync_PodSecurityStandardLabelsSetOnNamespace(t *testing.T) { func TestOnSync_RegistrationCreated_AppNamespaceReconciled(t *testing.T) { // Setup - tu, client, kubeUtil, radixClient := setupTest() + tu, client, kubeUtil, radixClient := setupTest(t) defer os.Clearenv() // Create namespaces manually @@ -195,7 +196,7 @@ func TestOnSync_RegistrationCreated_AppNamespaceReconciled(t *testing.T) { func TestOnSync_NoUserGroupDefined_DefaultUserGroupSet(t *testing.T) { // Setup - tu, client, kubeUtil, radixClient := setupTest() + tu, client, kubeUtil, radixClient := setupTest(t) defaultRole := "9876-54321-09876" defer os.Clearenv() os.Setenv(defaults.OperatorDefaultUserGroupEnvironmentVariable, defaultRole) @@ -222,7 +223,7 @@ func TestOnSync_NoUserGroupDefined_DefaultUserGroupSet(t *testing.T) { func TestOnSync_LimitsDefined_LimitsSet(t *testing.T) { // Setup - tu, client, kubeUtil, radixClient := setupTest() + tu, client, kubeUtil, radixClient := setupTest(t) defer os.Clearenv() os.Setenv(defaults.OperatorAppLimitDefaultMemoryEnvironmentVariable, "300M") os.Setenv(defaults.OperatorAppLimitDefaultRequestCPUEnvironmentVariable, "0.25") @@ -241,7 +242,7 @@ func TestOnSync_LimitsDefined_LimitsSet(t *testing.T) { func TestOnSync_NoLimitsDefined_NoLimitsSet(t *testing.T) { // Setup - tu, client, kubeUtil, radixClient := setupTest() + tu, client, kubeUtil, radixClient := setupTest(t) defer os.Clearenv() os.Setenv(defaults.OperatorAppLimitDefaultMemoryEnvironmentVariable, "") os.Setenv(defaults.OperatorAppLimitDefaultRequestCPUEnvironmentVariable, "") diff --git a/pkg/apis/application/secrets_test.go b/pkg/apis/application/secrets_test.go index f00aef3a6..d95903bac 100644 --- a/pkg/apis/application/secrets_test.go +++ b/pkg/apis/application/secrets_test.go @@ -19,7 +19,7 @@ const somePublicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDpMmE/GGn1U86URGIWy func TestOnSync_PublicKeyCmExists_NothingChanges(t *testing.T) { // Setup - tu, client, kubeUtil, radixClient := setupTest() + tu, client, kubeUtil, radixClient := setupTest(t) defer os.Clearenv() // Test @@ -62,7 +62,7 @@ func TestOnSync_PublicKeyCmExists_NothingChanges(t *testing.T) { func TestOnSync_PublicKeyCmDoesNotExist_NewKeyIsGenerated(t *testing.T) { // Setup - tu, client, kubeUtil, radixClient := setupTest() + tu, client, kubeUtil, radixClient := setupTest(t) defer os.Clearenv() // Test @@ -100,7 +100,7 @@ func TestOnSync_PublicKeyCmDoesNotExist_NewKeyIsGenerated(t *testing.T) { func TestOnSync_PublicKeyCmDoesNotExist_KeyIsCopiedFromRR(t *testing.T) { // Setup - tu, client, kubeUtil, radixClient := setupTest() + tu, client, kubeUtil, radixClient := setupTest(t) defer os.Clearenv() // Test @@ -135,7 +135,7 @@ func TestOnSync_PublicKeyCmDoesNotExist_KeyIsCopiedFromRR(t *testing.T) { func TestOnSync_PublicKeyInCmIsEmpty_KeyIsCopiedFromRR(t *testing.T) { // Setup - tu, client, kubeUtil, radixClient := setupTest() + tu, client, kubeUtil, radixClient := setupTest(t) defer os.Clearenv() // Test @@ -181,7 +181,7 @@ func TestOnSync_PublicKeyInCmIsEmpty_KeyIsCopiedFromRR(t *testing.T) { func TestOnSync_PrivateKeySecretIsUpdatedManually_PublicKeyIsUpdated(t *testing.T) { // Setup - tu, client, kubeUtil, radixClient := setupTest() + tu, client, kubeUtil, radixClient := setupTest(t) defer os.Clearenv() // Test diff --git a/pkg/apis/dnsalias/ingress.go b/pkg/apis/dnsalias/ingress.go index 95a85de82..9f19e8351 100644 --- a/pkg/apis/dnsalias/ingress.go +++ b/pkg/apis/dnsalias/ingress.go @@ -13,7 +13,6 @@ import ( radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/radixvalidators" "github.com/equinor/radix-operator/pkg/apis/utils" - "github.com/equinor/radix-operator/pkg/apis/utils/annotations" radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels" "github.com/equinor/radix-operator/pkg/apis/utils/oauth" log "github.com/sirupsen/logrus" @@ -124,7 +123,6 @@ func buildIngress(radixDeployComponent radixv1.RadixCommonDeployComponent, radix return nil, err } - ingressConfig.ObjectMeta.Annotations = annotations.Merge(ingressConfig.ObjectMeta.Annotations, annotations.ForManagedByRadixDNSAliasIngress(aliasName)) ingressConfig.ObjectMeta.Labels[kube.RadixAliasLabel] = aliasName log.Debugf("built the Ingress %s in the environment %s with a host %s", ingressConfig.GetName(), namespace, hostName) return ingressConfig, nil diff --git a/pkg/apis/kube/kube.go b/pkg/apis/kube/kube.go index 96414f236..a987f4acb 100644 --- a/pkg/apis/kube/kube.go +++ b/pkg/apis/kube/kube.go @@ -26,14 +26,16 @@ const ( RadixDeploymentNameAnnotation = "radix-deployment-name" RadixDeploymentPromotedFromDeploymentAnnotation = "radix.equinor.com/radix-deployment-promoted-from-deployment" RadixDeploymentPromotedFromEnvironmentAnnotation = "radix.equinor.com/radix-deployment-promoted-from-environment" - ManagedByRadixDNSAliasIngressAnnotation = "radix.equinor.com/managed-by-radix-dns-alias" - RadixEnvironmentFinalizer = "radix.equinor.com/environment-finalizer" - RadixDNSAliasFinalizer = "radix.equinor.com/dnsalias-finalizer" - // See https://github.com/equinor/radix-velero-plugin/blob/master/velero-plugins/deployment/restore.go RestoredStatusAnnotation = "equinor.com/velero-restored-status" ) +// Radix Finalizers +const ( + RadixEnvironmentFinalizer = "radix.equinor.com/environment-finalizer" + RadixDNSAliasFinalizer = "radix.equinor.com/dnsalias-finalizer" +) + // Radix Labels const ( K8sAppLabel = "k8s-app" diff --git a/pkg/apis/test/utils.go b/pkg/apis/test/utils.go index 06eb97ca2..9254139f8 100644 --- a/pkg/apis/test/utils.go +++ b/pkg/apis/test/utils.go @@ -104,7 +104,7 @@ func (tu *Utils) ApplyApplication(applicationBuilder utils.ApplicationBuilder) ( WithEnvironmentName(env.Name). WithRegistrationOwner(rr). WithOrphaned(false)); err != nil { - panic(err) + return nil, err } } @@ -139,7 +139,7 @@ func (tu *Utils) ApplyApplicationUpdate(applicationBuilder utils.ApplicationBuil WithAppLabel(). WithEnvironmentName(env.Name). WithRegistrationOwner(rr)); err != nil { - panic(err) + return nil, err } } @@ -197,7 +197,7 @@ func (tu *Utils) ApplyDeploymentUpdate(deploymentBuilder utils.DeploymentBuilder func (tu *Utils) ApplyJob(jobBuilder utils.JobBuilder) (*radixv1.RadixJob, error) { if jobBuilder.GetApplicationBuilder() != nil { if _, err := tu.ApplyApplication(jobBuilder.GetApplicationBuilder()); err != nil { - panic(err) + return nil, err } } @@ -285,7 +285,7 @@ func SetRequiredEnvironmentVariables() { } // CreateClusterPrerequisites Will do the needed setup which is part of radix boot -func (tu *Utils) CreateClusterPrerequisites(clustername, egressIps, subscriptionId string) { +func (tu *Utils) CreateClusterPrerequisites(clustername, egressIps, subscriptionId string) error { SetRequiredEnvironmentVariables() if _, err := tu.client.CoreV1().Secrets(corev1.NamespaceDefault).Create( @@ -301,10 +301,10 @@ func (tu *Utils) CreateClusterPrerequisites(clustername, egressIps, subscription }, }, metav1.CreateOptions{}); err != nil { - panic(err) + return err } - if _, err := tu.client.CoreV1().ConfigMaps(corev1.NamespaceDefault).Create( + _, err := tu.client.CoreV1().ConfigMaps(corev1.NamespaceDefault).Create( context.TODO(), &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ @@ -317,9 +317,8 @@ func (tu *Utils) CreateClusterPrerequisites(clustername, egressIps, subscription "subscriptionId": subscriptionId, }, }, - metav1.CreateOptions{}); err != nil { - panic(err) - } + metav1.CreateOptions{}) + return err } // CreateAppNamespace Helper method to creat app namespace diff --git a/pkg/apis/utils/annotations/annotations.go b/pkg/apis/utils/annotations/annotations.go index 820cfde27..0fdf0b088 100644 --- a/pkg/apis/utils/annotations/annotations.go +++ b/pkg/apis/utils/annotations/annotations.go @@ -53,11 +53,6 @@ func ForClusterAutoscalerSafeToEvict(safeToEvict bool) map[string]string { return map[string]string{clusterAutoscaleSafeToEvictAnnotation: fmt.Sprint(safeToEvict)} } -// ForManagedByRadixDNSAliasIngress returns annotation with a name of a RadixDNSAlias, managed an ingresses -func ForManagedByRadixDNSAliasIngress(dnsAliasName string) map[string]string { - return map[string]string{kube.ManagedByRadixDNSAliasIngressAnnotation: dnsAliasName} -} - func forAzureWorkloadIdentityClientId(clientId string) map[string]string { return map[string]string{azureWorkloadIdentityClientIdAnnotation: clientId} } diff --git a/pkg/apis/utils/annotations/annotations_test.go b/pkg/apis/utils/annotations/annotations_test.go index 4975495e3..b3e8da4c1 100644 --- a/pkg/apis/utils/annotations/annotations_test.go +++ b/pkg/apis/utils/annotations/annotations_test.go @@ -50,9 +50,3 @@ func Test_ForClusterAutoscalerSafeToEvict(t *testing.T) { expected = map[string]string{"cluster-autoscaler.kubernetes.io/safe-to-evict": "true"} assert.Equal(t, expected, actual) } - -func Test_ForManagedByRadixDNSAliasIngress(t *testing.T) { - actual := ForManagedByRadixDNSAliasIngress("test-alias") - expected := map[string]string{"radix.equinor.com/managed-by-radix-dns-alias": "test-alias"} - assert.Equal(t, expected, actual) -} diff --git a/pkg/apis/utils/application_builder.go b/pkg/apis/utils/application_builder.go index 2d5742770..9726a9843 100644 --- a/pkg/apis/utils/application_builder.go +++ b/pkg/apis/utils/application_builder.go @@ -1,8 +1,6 @@ package utils import ( - "strings" - radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-operator/pkg/apis/utils/numbers" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,15 +47,15 @@ func (ap *ApplicationBuilderStruct) WithBuildKit(useBuildKit *bool) ApplicationB ap.useBuildKit = useBuildKit return ap } -func (ap *ApplicationBuilderStruct) WithBuildCache(useBuilCache *bool) ApplicationBuilder { - ap.useBuildCache = useBuilCache +func (ap *ApplicationBuilderStruct) WithBuildCache(useBuildCache *bool) ApplicationBuilder { + ap.useBuildCache = useBuildCache return ap } // WithPrivateImageRegistry adds a private image hub to application func (ap *ApplicationBuilderStruct) WithPrivateImageRegistry(server, username, email string) ApplicationBuilder { if ap.privateImageHubs == nil { - ap.privateImageHubs = radixv1.PrivateImageHubEntries(map[string]*radixv1.RadixPrivateImageHubCredential{}) + ap.privateImageHubs = map[string]*radixv1.RadixPrivateImageHubCredential{} } ap.privateImageHubs[server] = &radixv1.RadixPrivateImageHubCredential{ @@ -121,28 +119,7 @@ func (ap *ApplicationBuilderStruct) WithDNSAppAlias(env, component string) Appli // WithDNSAlias Sets alias for env and component to be the DNS alias like "my-alias.radix.equinor.com" or "my-alias..radix.equinor.com" func (ap *ApplicationBuilderStruct) WithDNSAlias(dnsAliases ...radixv1.DNSAlias) ApplicationBuilder { - var dnsAliasesToAppend []radixv1.DNSAlias - for _, dnsAlias := range dnsAliases { - foundExistingAlias := false - for i := 0; i < len(ap.dnsAliases); i++ { - if strings.EqualFold(dnsAlias.Alias, ap.dnsAliases[i].Alias) { - ap.dnsAliases[i].Alias = dnsAlias.Alias - ap.dnsAliases[i].Environment = dnsAlias.Environment - ap.dnsAliases[i].Component = dnsAlias.Component - foundExistingAlias = true - break - } - } - if foundExistingAlias { - continue - } - dnsAliasesToAppend = append(dnsAliasesToAppend, radixv1.DNSAlias{ - Alias: dnsAlias.Alias, - Environment: dnsAlias.Environment, - Component: dnsAlias.Component, - }) - } - ap.dnsAliases = append(ap.dnsAliases, dnsAliasesToAppend...) + ap.dnsAliases = dnsAliases return ap } diff --git a/pkg/apis/utils/environment_builder_test.go b/pkg/apis/utils/environment_builder_test.go index 365be14bf..3b0fe4d61 100644 --- a/pkg/apis/utils/environment_builder_test.go +++ b/pkg/apis/utils/environment_builder_test.go @@ -27,8 +27,7 @@ func Test_RadixEnvironment_Defaults(t *testing.T) { assert.Equal(t, minTime, re.ObjectMeta.CreationTimestamp) assert.Equal(t, (*int64)(nil), re.ObjectMeta.DeletionGracePeriodSeconds) assert.Equal(t, nilTime, re.ObjectMeta.DeletionTimestamp) - assert.Len(t, re.ObjectMeta.Finalizers, 1) - assert.Equal(t, re.ObjectMeta.Finalizers[0], kube.RadixEnvironmentFinalizer) + assert.ElementsMatch(t, re.ObjectMeta.Finalizers, []string{kube.RadixEnvironmentFinalizer}) assert.Equal(t, "", re.ObjectMeta.GenerateName) assert.Equal(t, int64(0), re.ObjectMeta.Generation) assert.Len(t, re.ObjectMeta.Labels, 0) diff --git a/radix-operator/dnsalias/controller.go b/radix-operator/dnsalias/controller.go index bef0178db..526fb10b2 100644 --- a/radix-operator/dnsalias/controller.go +++ b/radix-operator/dnsalias/controller.go @@ -70,7 +70,7 @@ func NewController(kubeClient kubernetes.Interface, } func addEventHandlersForIngresses(ingressInformer networkinginformersv1.IngressInformer, controller *common.Controller) { - _, err := ingressInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := ingressInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: func(oldObj, newObj interface{}) { oldIng := oldObj.(metav1.Object) newIng := newObj.(metav1.Object) @@ -90,14 +90,13 @@ func addEventHandlersForIngresses(ingressInformer networkinginformersv1.IngressI logger.Debugf("deleted Ingress %s", ing.GetName()) controller.HandleObject(ing, radixv1.KindRadixDNSAlias, getOwner) // restore ingress if RadixDNSAlias exist }, - }) - if err != nil { - logger.Errorf("failed to add an event hanflers to the ingressInformer") + }); err != nil { + panic(err) } } func addEventHandlersForRadixDeployments(radixDeploymentInformer radixinformersv1.RadixDeploymentInformer, controller *common.Controller, radixClient radixclient.Interface) { - _, err := radixDeploymentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := radixDeploymentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { rd := cur.(*radixv1.RadixDeployment) enqueueRadixDNSAliasesForRadixDeployment(controller, radixClient, rd) @@ -111,14 +110,13 @@ func addEventHandlersForRadixDeployments(radixDeploymentInformer radixinformersv rd := newRD.(*radixv1.RadixDeployment) enqueueRadixDNSAliasesForRadixDeployment(controller, radixClient, rd) }, - }) - if err != nil { - logger.Errorf("failed to add an event hanflers to the radixDeploymentInformer") + }); err != nil { + panic(err) } } func addEventHandlersForRadixDNSAliases(radixDNSAliasInformer radixinformersv1.RadixDNSAliasInformer, controller *common.Controller) { - _, err := radixDNSAliasInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + if _, err := radixDNSAliasInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { alias := cur.(*radixv1.RadixDNSAlias) logger.Debugf("added RadixDNSAlias %s", alias.GetName()) @@ -156,9 +154,8 @@ func addEventHandlersForRadixDNSAliases(radixDNSAliasInformer radixinformersv1.R } metrics.CustomResourceDeleted(radixv1.KindRadixDNSAlias) }, - }) - if err != nil { - logger.Errorf("failed to add an event hanflers to the radixDNSAliasInformer") + }); err != nil { + panic(err) } } @@ -175,7 +172,7 @@ func enqueueRadixDNSAliasesForRadixDeployment(controller *common.Controller, rad for _, radixDNSAlias := range radixDNSAliases { logger.Debugf("re-sync RadixDNSAlias %s", radixDNSAlias.GetName()) if _, err := controller.Enqueue(&radixDNSAlias); err != nil { - logger.Errorf("failed to re-sync RadixDNSAlias %s. Error: %v", radixDNSAlias.GetName(), err) + logger.Errorf("failed to enqueue RadixDNSAlias %s. Error: %v", radixDNSAlias.GetName(), err) } } } From 300eb87c8561f4ef41970f427b82bd1bcac43b76 Mon Sep 17 00:00:00 2001 From: Sergey Smolnikov Date: Mon, 18 Dec 2023 14:03:46 +0100 Subject: [PATCH 121/121] Fixed of review commented issues --- pkg/apis/radixvalidators/validate_rr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/apis/radixvalidators/validate_rr.go b/pkg/apis/radixvalidators/validate_rr.go index d2deeee27..55ced4bc8 100644 --- a/pkg/apis/radixvalidators/validate_rr.go +++ b/pkg/apis/radixvalidators/validate_rr.go @@ -19,7 +19,7 @@ const ( ) var ( - ErrInvalidRadixConfigFullName = fmt.Errorf("invalid file name for radixconfig. See https://www.radix.equinor.com/references/reference-radix-config/ for more information") + ErrInvalidRadixConfigFullName = stderrors.New("invalid file name for radixconfig. See https://www.radix.equinor.com/references/reference-radix-config/ for more information") requiredRadixRegistrationValidators []RadixRegistrationValidator = []RadixRegistrationValidator{ validateRadixRegistrationAppName,