diff --git a/library/common-test/tests/ingress/cert_manager_test.yaml b/library/common-test/tests/ingress/cert_manager_test.yaml index 020d1e9c..937bc14f 100644 --- a/library/common-test/tests/ingress/cert_manager_test.yaml +++ b/library/common-test/tests/ingress/cert_manager_test.yaml @@ -12,6 +12,15 @@ tests: operator: &operator verify: enabled: false + service: &service + my-service: + enabled: true + primary: true + ports: + main: + enabled: true + primary: true + port: 80 ingress: my-ingress: enabled: true @@ -27,7 +36,7 @@ tests: paths: - path: /test-path asserts: - - documentIndex: &ingressDoc 0 + - documentIndex: &ingressDoc 1 isKind: of: Ingress - documentIndex: *ingressDoc @@ -48,6 +57,7 @@ tests: - it: should pass with ingress created without cert manager annotations when cert manager false set: operator: *operator + service: *service ingress: my-ingress: enabled: true @@ -73,6 +83,7 @@ tests: - it: should fail with missing clusterIssuer set: operator: *operator + service: *service ingress: my-ingress1: enabled: true @@ -88,6 +99,7 @@ tests: - it: should fail with clusterIssuer not a string set: operator: *operator + service: *service ingress: my-ingress1: enabled: true diff --git a/library/common-test/tests/ingress/homepage_test.yaml b/library/common-test/tests/ingress/homepage_test.yaml index 8d9b8270..1ad45c69 100644 --- a/library/common-test/tests/ingress/homepage_test.yaml +++ b/library/common-test/tests/ingress/homepage_test.yaml @@ -18,6 +18,17 @@ tests: operator: &operator verify: enabled: false + service: &service + my-service: + enabled: true + primary: true + ports: + main: + enabled: true + primary: true + port: 80 + someHost: test-host + somePath: /test-path ingress: my-ingress1: enabled: true @@ -27,10 +38,10 @@ tests: enabled: false homepage: enabled: true - hosts: &hosts - - host: test-host + hosts: + - host: "{{ .Values.someHost }}" paths: - - path: /test-path + - path: "{{ .Values.somePath }}" my-ingress2: enabled: true integrations: @@ -51,9 +62,12 @@ tests: custom: some-key: some-value some-other-key: some-other-value - hosts: *hosts + hosts: &hosts + - host: test-host + paths: + - path: /test-path asserts: - - documentIndex: &ingressDoc 0 + - documentIndex: &ingressDoc 1 isKind: of: Ingress - documentIndex: *ingressDoc @@ -74,7 +88,7 @@ tests: equal: path: metadata.namespace value: test-release-namespace - - documentIndex: &otherIngressDoc 1 + - documentIndex: &otherIngressDoc 2 isKind: of: Ingress - documentIndex: *otherIngressDoc @@ -105,6 +119,7 @@ tests: - it: should fail with podSelector not a slice set: operator: *operator + service: *service ingress: my-ingress1: enabled: true @@ -121,6 +136,7 @@ tests: - it: should fail with custom widget not a map set: operator: *operator + service: *service ingress: my-ingress1: enabled: true diff --git a/library/common-test/tests/ingress/metadata_test.yaml b/library/common-test/tests/ingress/metadata_test.yaml index a72b2125..ad3fc5f7 100644 --- a/library/common-test/tests/ingress/metadata_test.yaml +++ b/library/common-test/tests/ingress/metadata_test.yaml @@ -23,6 +23,15 @@ tests: operator: &operator verify: enabled: false + service: &service + my-service: + enabled: true + primary: true + ports: + main: + enabled: true + primary: true + port: 80 ingress: my-ingress1: enabled: true @@ -46,7 +55,7 @@ tests: integrations: *integrations hosts: *hosts asserts: - - documentIndex: &ingressDoc 0 + - documentIndex: &ingressDoc 1 isKind: of: Ingress - documentIndex: *ingressDoc @@ -81,7 +90,7 @@ tests: equal: path: metadata.namespace value: test-release-namespace - - documentIndex: &otherIngressDoc 1 + - documentIndex: &otherIngressDoc 2 isKind: of: Ingress - documentIndex: *otherIngressDoc @@ -111,6 +120,7 @@ tests: set: key: some-namespace operator: *operator + service: *service ingress: my-ingress1: enabled: true @@ -119,7 +129,7 @@ tests: integrations: *integrations hosts: *hosts asserts: - - documentIndex: &IngressDoc 0 + - documentIndex: *ingressDoc equal: path: metadata.namespace value: some-namespace @@ -130,6 +140,7 @@ tests: global: namespace: "{{ .Values.key }}" operator: *operator + service: *service ingress: my-ingress1: enabled: true @@ -149,6 +160,7 @@ tests: global: namespace: global-namespace operator: *operator + service: *service ingress: my-ingress1: enabled: true @@ -168,6 +180,7 @@ tests: iAmNotEmpty: true namespace: ix-namespace operator: *operator + service: *service ingress: my-ingress1: enabled: true diff --git a/library/common-test/tests/ingress/name_test.yaml b/library/common-test/tests/ingress/name_test.yaml index 3fb3ed26..6f36ded8 100644 --- a/library/common-test/tests/ingress/name_test.yaml +++ b/library/common-test/tests/ingress/name_test.yaml @@ -10,6 +10,15 @@ tests: operator: verify: enabled: false + service: + my-service: + enabled: true + primary: true + ports: + main: + enabled: true + primary: true + port: 80 ingress: my-ingress1: enabled: true @@ -26,7 +35,7 @@ tests: expandObjectName: false hosts: *hosts asserts: - - documentIndex: &ingressDoc 0 + - documentIndex: &ingressDoc 1 isKind: of: Ingress - documentIndex: *ingressDoc @@ -36,7 +45,7 @@ tests: equal: path: metadata.name value: test-release-name-common-test - - documentIndex: &otherIngressDoc 1 + - documentIndex: &otherIngressDoc 2 isKind: of: Ingress - documentIndex: *otherIngressDoc @@ -46,7 +55,7 @@ tests: equal: path: metadata.name value: test-release-name-common-test-my-ingress2 - - documentIndex: &thirdIngressDoc 2 + - documentIndex: &thirdIngressDoc 3 isKind: of: Ingress - documentIndex: *thirdIngressDoc diff --git a/library/common-test/tests/ingress/rules_test.yaml b/library/common-test/tests/ingress/rules_test.yaml new file mode 100644 index 00000000..221c773c --- /dev/null +++ b/library/common-test/tests/ingress/rules_test.yaml @@ -0,0 +1,123 @@ +suite: ingress - rules test +templates: + - common.yaml +chart: + appVersion: &appVer v9.9.9 +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should pass with ingress created with ingressClassName + set: + operator: &operator + verify: + enabled: false + service: + my-service: + enabled: true + primary: true + ports: + main: + enabled: true + primary: true + port: 80 + ingress: + my-ingress: + enabled: true + primary: true + ingressClassName: some-class + hosts: &hosts + - host: test-host + paths: + - path: /test-path + integrations: &integrations + traefik: + enabled: false + asserts: + - documentIndex: &ingressDoc 1 + isKind: + of: Ingress + - documentIndex: *ingressDoc + equal: + path: metadata.name + value: test-release-name-common-test + - documentIndex: *ingressDoc + equal: + path: spec.ingressClassName + value: some-class + + - it: should pass with ingress created with rules + set: + operator: &operator + verify: + enabled: false + service: + my-service: + enabled: true + primary: true + ports: + main: + enabled: true + primary: true + port: 80 + someHost: test-host + somePath: /test-path + someType: Exact + ingress: + my-ingress: + enabled: true + primary: true + hosts: &hosts + - host: "{{ .Values.someHost }}" + paths: + - path: "{{ .Values.somePath }}" + pathType: "{{ .Values.someType }}" + - host: test-other-host + paths: + - path: /test-other-path + - path: /test-other-path2 + overrideService: + name: other-service + port: 8080 + integrations: &integrations + traefik: + enabled: false + asserts: + - documentIndex: &ingressDoc 1 + isKind: + of: Ingress + - documentIndex: *ingressDoc + equal: + path: metadata.name + value: test-release-name-common-test + - documentIndex: *ingressDoc + equal: + path: spec.rules + value: + - host: test-host + http: + paths: + - path: /test-path + pathType: Exact + backend: + service: + name: test-release-name-common-test + port: + number: 80 + - host: test-other-host + http: + paths: + - path: /test-other-path + pathType: Prefix + backend: + service: + name: test-release-name-common-test + port: + number: 80 + - path: /test-other-path2 + pathType: Prefix + backend: + service: + name: other-service + port: + number: 8080 diff --git a/library/common-test/tests/ingress/traefik_test.yaml b/library/common-test/tests/ingress/traefik_test.yaml index 92c113c0..2eb69a5f 100644 --- a/library/common-test/tests/ingress/traefik_test.yaml +++ b/library/common-test/tests/ingress/traefik_test.yaml @@ -12,6 +12,15 @@ tests: operator: &operator verify: enabled: false + service: &service + my-service: + enabled: true + primary: true + ports: + main: + enabled: true + primary: true + port: 80 ingress: my-ingress: enabled: true @@ -21,7 +30,7 @@ tests: paths: - path: /test-path asserts: - - documentIndex: &ingressDoc 0 + - documentIndex: &ingressDoc 1 isKind: of: Ingress - documentIndex: *ingressDoc @@ -42,6 +51,7 @@ tests: - it: should pass with ingress created without traefik annotations when traefik false set: operator: *operator + service: *service ingress: my-ingress: enabled: true @@ -65,6 +75,7 @@ tests: - it: should replace local fixedMiddlewares when allowCors true set: operator: *operator + service: *service ingress: my-ingress: enabled: true @@ -94,6 +105,7 @@ tests: - it: should replace global fixedMiddlewares when allowCors true set: operator: *operator + service: *service ingress: my-ingress: enabled: true @@ -121,6 +133,7 @@ tests: - it: should replace global fixedMiddlewares when local fixedMiddlewares is defined set: operator: *operator + service: *service ingress: my-ingress: enabled: true @@ -149,6 +162,7 @@ tests: - it: should override default entrypoint(s) set: operator: *operator + service: *service ingress: my-ingress: enabled: true @@ -178,6 +192,7 @@ tests: - it: should not contain fixed middlewares when global is disabled set: operator: *operator + service: *service global: traefik: enableFixedMiddlewares: false @@ -202,6 +217,7 @@ tests: - it: should not contain fixed middlewares when local is disabled set: operator: *operator + service: *service global: traefik: enableFixedMiddlewares: true @@ -231,6 +247,7 @@ tests: enabled: false traefik: namespace: some-ns + service: *service ingress: my-ingress: enabled: true @@ -264,6 +281,8 @@ tests: enabled: false traefik: namespace: some-ns + someclass: some-class + service: *service ingress: my-ingress: enabled: true @@ -271,7 +290,7 @@ tests: integrations: traefik: enabled: true - ingressClassName: some-class + ingressClassName: "{{ .Values.someclass }}" hosts: *hosts asserts: - documentIndex: *ingressDoc @@ -295,6 +314,7 @@ tests: enabled: false traefik: namespace: some-ns + service: *service global: ixChartContext: imNotEmpty: true @@ -326,6 +346,7 @@ tests: - it: should add the defined middlewares to the ingress set: operator: *operator + service: *service ingress: my-ingress: enabled: true @@ -359,6 +380,7 @@ tests: - it: should fail with entrypoint not a slice set: operator: *operator + service: *service ingress: my-ingress1: enabled: true @@ -375,6 +397,7 @@ tests: - it: should fail with middlewares not a slice set: operator: *operator + service: *service ingress: my-ingress1: enabled: true @@ -391,6 +414,7 @@ tests: - it: should fail with fixedMiddlewares not a slice set: operator: *operator + service: *service ingress: my-ingress1: enabled: true @@ -407,6 +431,7 @@ tests: - it: should fail with duplicate middlewares set: operator: *operator + service: *service ingress: my-ingress1: enabled: true @@ -424,6 +449,7 @@ tests: - it: should fail with duplicate entrypoints set: operator: *operator + service: *service ingress: my-ingress1: enabled: true diff --git a/library/common-test/tests/ingress/validation_test.yaml b/library/common-test/tests/ingress/validation_test.yaml index a9315bfa..b5540b8a 100644 --- a/library/common-test/tests/ingress/validation_test.yaml +++ b/library/common-test/tests/ingress/validation_test.yaml @@ -10,6 +10,15 @@ tests: operator: &operator verify: enabled: false + service: &service + my-service: + enabled: true + primary: true + ports: + main: + enabled: true + primary: true + port: 80 ingress: my-ingress: enabled: false @@ -21,6 +30,7 @@ tests: - it: should fail with name longer than 253 characters set: operator: *operator + service: *service ingress: my-ing: enabled: true @@ -38,6 +48,7 @@ tests: - it: should fail with name starting with underscore set: operator: *operator + service: *service ingress: my-ing: enabled: true @@ -52,6 +63,7 @@ tests: - it: should fail with namespace longer than 63 characters set: operator: *operator + service: *service ingress: my-ingress: enabled: true @@ -68,6 +80,16 @@ tests: ixChartContext: iAmNotEmpty: true operator: *operator + service: + my-service: + enabled: true + primary: true + namespace: ix-namespace + ports: + main: + enabled: true + primary: true + port: 80 ingress: my-ingress: enabled: true @@ -340,3 +362,117 @@ tests: asserts: - failedTemplate: errorMessage: Ingress - Expected non-empty [hosts.paths.overrideService.port] + + - it: should fail if targeted service does not exist + set: + operator: *operator + ingress: + my-ingress: + enabled: true + primary: true + targetSelector: + my-service: my-port + hosts: + - host: test-host + paths: + - path: /test-path + asserts: + - failedTemplate: + errorMessage: Ingress - Expected targeted service [my-service] to exist + + - it: should fail if targeted service is not enabled + set: + operator: *operator + service: + my-service: + enabled: false + primary: true + ports: + my-port: + enabled: true + primary: true + port: 80 + ingress: + my-ingress: + enabled: true + primary: true + targetSelector: + my-service: my-port + hosts: + - host: test-host + paths: + - path: /test-path + asserts: + - failedTemplate: + errorMessage: Ingress - Expected targeted service [my-service] to be enabled + + - it: should fail without primary service or a targetSelector + set: + operator: *operator + ingress: + my-ingress: + enabled: true + primary: true + hosts: + - host: test-host + paths: + - path: /test-path + asserts: + - failedTemplate: + errorMessage: Ingress - Expected [targetSelector] or a primary service to exist + + - it: should fail if the targeted service does not have the targeted port + set: + operator: *operator + service: + my-service: + enabled: true + primary: true + ports: + my-other-port: + enabled: true + primary: true + port: 80 + ingress: + my-ingress: + enabled: true + primary: true + targetSelector: + my-service: my-port + hosts: + - host: test-host + paths: + - path: /test-path + asserts: + - failedTemplate: + errorMessage: Ingress - Expected targeted service [my-service] to have port [my-port] + + - it: should fail if the targeted service port is not enabled + set: + operator: *operator + service: + my-service: + enabled: true + primary: true + ports: + my-port: + enabled: false + primary: true + port: 80 + my-other-port: + enabled: true + primary: true + port: 80 + ingress: + my-ingress: + enabled: true + primary: true + targetSelector: + my-service: my-port + hosts: + - host: test-host + paths: + - path: /test-path + asserts: + - failedTemplate: + errorMessage: Ingress - Expected targeted service port [my-port] to be enabled diff --git a/library/common/templates/class/_ingress.tpl b/library/common/templates/class/_ingress.tpl index ca126cde..bd9f5205 100644 --- a/library/common/templates/class/_ingress.tpl +++ b/library/common/templates/class/_ingress.tpl @@ -11,7 +11,8 @@ objectData: The object data to be used to render the Ingress. {{- $rootCtx := .rootCtx -}} {{- $objectData := .objectData -}} - {{/* TODO: fetch the selected service or fallback to primary */}} + {{- /* TODO: UT */}} + {{- $svcData := (include "tc.v1.common.lib.ingress.targetSelector" (dict "rootCtx" $rootCtx "objectData" $objectData) | fromYaml) -}} {{- if not (hasKey $objectData "integrations") -}} {{- $_ := set $objectData "integrations" dict -}} @@ -40,29 +41,25 @@ metadata: {{- . | nindent 4 }} {{- end }} spec: - {{- /* TODO: UT */}} {{- if $objectData.ingressClassName }} - ingressClassName: {{ $objectData.ingressClassName }} + ingressClassName: {{ tpl $objectData.ingressClassName $rootCtx }} {{- end }} rules: {{- range $h := $objectData.hosts }} - - host: {{ $h.host }} + - host: {{ tpl $h.host $rootCtx }} http: paths: {{- range $p := $h.paths -}} - {{- $serviceName := "TODO:!" -}} - {{- $servicePort := "TODO:!" -}} {{- with $p.overrideService -}} - {{- $serviceName = .name -}} - {{- $servicePort = .port -}} + {{- $svcData = (dict "name" .name "port" .port) -}} {{- end }} - - path: {{ $p.path }} - pathType: {{ $p.pathType | default "Prefix" }} + - path: {{ tpl $p.path $rootCtx }} + pathType: {{ tpl ($p.pathType | default "Prefix") $rootCtx }} backend: service: - name: {{ $serviceName }} + name: {{ $svcData.name }} port: - number: {{ $servicePort }} + number: {{ $svcData.port }} {{- end -}} {{- end }} diff --git a/library/common/templates/lib/ingress/_targetSelector.tpl b/library/common/templates/lib/ingress/_targetSelector.tpl new file mode 100644 index 00000000..17115631 --- /dev/null +++ b/library/common/templates/lib/ingress/_targetSelector.tpl @@ -0,0 +1,85 @@ +{{/* Returns the selected service or fallback to primary */}} +{{- define "tc.v1.common.lib.ingress.targetSelector" -}} + {{- $rootCtx := .rootCtx -}} + {{- $objectData := .objectData -}} + + {{- $selectedService := (dict "name" "" "port" 0) -}} + {{- $svcData := dict -}} + {{- $portData := dict -}} + {{- $svcName := "" -}} + {{- $portName := "" -}} + + {{- if $objectData.targetSelector -}} + {{/* We have validation that only 1 key is allowed */}} + {{- $svcName = ($objectData.targetSelector | keys | mustFirst) -}} + {{- $portName = (get $objectData.targetSelector $svcName) -}} + {{- $svcData = (get $rootCtx.Values.service $svcName) -}} + + {{- if not $svcData -}} + {{- fail (printf "Ingress - Expected targeted service [%s] to exist" $svcName) -}} + {{- end -}} + + {{- $enabled := (include "tc.v1.common.lib.util.enabled" (dict + "rootCtx" $rootCtx "objectData" $svcData + "name" $svcName "caller" "Ingress" + "key" "ingress")) -}} + + {{- if ne $enabled "true" -}} + {{- fail (printf "Ingress - Expected targeted service [%s] to be enabled" $svcName) -}} + {{- end -}} + + {{- else -}} + {{/* Find the primary service */}} + {{- range $name, $service := $rootCtx.Values.service -}} + + {{- $enabled := (include "tc.v1.common.lib.util.enabled" (dict + "rootCtx" $rootCtx "objectData" $service + "name" $name "caller" "Ingress" + "key" "ingress")) -}} + + {{/* Check if its enabled */}} + {{- if eq $enabled "true" -}} + + {{- if $service.primary -}} + {{- $svcName = $name -}} + {{- $svcData = $service -}} + + {{/* Find the primary port */}} + {{- range $name, $port := $svcData.ports -}} + {{- if $port.primary -}} + {{- $portName = $name -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if not $svcData -}} + {{- fail "Ingress - Expected [targetSelector] or a primary service to exist" -}} + {{- end -}} + + {{- end -}} + + {{- $portData = (get $svcData.ports $portName) -}} + {{- if not $portData -}} + {{- fail (printf "Ingress - Expected targeted service [%s] to have port [%s]" $svcName $portName) -}} + {{- end -}} + + {{- $enabled := (include "tc.v1.common.lib.util.enabled" (dict + "rootCtx" $rootCtx "objectData" $portData + "name" $portName "caller" "Ingress" + "key" "ingress")) -}} + + {{- if ne $enabled "true" -}} + {{- fail (printf "Ingress - Expected targeted service port [%s] to be enabled" $portName) -}} + {{- end -}} + + {{- $expandedSvcName := include "tc.v1.common.lib.chart.names.fullname" $rootCtx -}} + {{- if not $svcData.primary -}} + {{- $expandedSvcName = printf "%s-%s" $expandedSvcName $svcName -}} + {{- end -}} + + {{- $selectedService = (dict "name" $expandedSvcName "port" (tpl ($portData.port | toString) $rootCtx)) -}} + + {{- $selectedService | toYaml -}} +{{- end -}} diff --git a/library/common/templates/lib/ingress/integrations/_homepage.tpl b/library/common/templates/lib/ingress/integrations/_homepage.tpl index 92c6c611..94863efb 100644 --- a/library/common/templates/lib/ingress/integrations/_homepage.tpl +++ b/library/common/templates/lib/ingress/integrations/_homepage.tpl @@ -19,8 +19,8 @@ {{- if not $url -}} {{- $fHost := $objectData.hosts | mustFirst -}} {{- $fPath := $fHost.paths | mustFirst -}} - {{- $host := $fHost.host -}} - {{- $path := $fPath.path -}} + {{- $host := tpl $fHost.host $rootCtx -}} + {{- $path := tpl $fPath.path $rootCtx -}} {{- $url = printf "https://%s/%s" $host ($path | trimPrefix "/") -}} {{- end -}} diff --git a/library/common/templates/lib/ingress/integrations/_traefik.tpl b/library/common/templates/lib/ingress/integrations/_traefik.tpl index ee6600a6..4dcef8dd 100644 --- a/library/common/templates/lib/ingress/integrations/_traefik.tpl +++ b/library/common/templates/lib/ingress/integrations/_traefik.tpl @@ -67,7 +67,7 @@ {{- end -}} {{- if $traefik.ingressClassName -}} - {{- $midNamespace = $traefik.ingressClassName -}} + {{- $midNamespace = tpl $traefik.ingressClassName $rootCtx -}} {{/* On SCALE prepend with ix- */}} {{- if $rootCtx.Values.global.ixChartContext -}}