diff --git a/operator/api/apps/v1/postgresservice_types.go b/operator/api/apps/v1/postgresservice_types.go index e6695222..58882b51 100644 --- a/operator/api/apps/v1/postgresservice_types.go +++ b/operator/api/apps/v1/postgresservice_types.go @@ -209,6 +209,7 @@ type IntegrationTests struct { PgNodeQty int `json:"pgNodeQty,omitempty"` PodLabels map[string]string `json:"podLabels,omitempty"` Affinity v1.Affinity `json:"affinity,omitempty"` + MonitoredImages string `json:"monitoredImages,omitempty"` } // ExternalDataBase defines the desired state of ExternalDataBase diff --git a/operator/api/patroni/v1/patronicore_types.go b/operator/api/patroni/v1/patronicore_types.go index 1c672f6a..09a3eba3 100644 --- a/operator/api/patroni/v1/patronicore_types.go +++ b/operator/api/patroni/v1/patronicore_types.go @@ -188,6 +188,7 @@ type IntegrationTests struct { PgNodeQty int `json:"pgNodeQty,omitempty"` PodLabels map[string]string `json:"podLabels,omitempty"` Affinity v1.Affinity `json:"affinity,omitempty"` + MonitoredImages string `json:"monitoredImages,omitempty"` } type Policies struct { diff --git a/operator/charts/patroni-core/crds/netcracker.com_patronicores.yaml b/operator/charts/patroni-core/crds/netcracker.com_patronicores.yaml index 2d37f6ca..5017993a 100644 --- a/operator/charts/patroni-core/crds/netcracker.com_patronicores.yaml +++ b/operator/charts/patroni-core/crds/netcracker.com_patronicores.yaml @@ -1019,6 +1019,8 @@ spec: type: object image: type: string + monitoredImages: + type: string pgNodeQty: type: integer podLabels: @@ -2636,9 +2638,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- diff --git a/operator/charts/patroni-core/templates/_helpers.tpl b/operator/charts/patroni-core/templates/_helpers.tpl index e5c2ce41..116c3f45 100644 --- a/operator/charts/patroni-core/templates/_helpers.tpl +++ b/operator/charts/patroni-core/templates/_helpers.tpl @@ -175,4 +175,12 @@ Init container section for postgres-operator {{- end }} {{- define "patroni-tests.monitoredImages" -}} + {{- printf "deployment patroni-core-operator patroni-core-operator %s, " (include "find_image" (dict "deployName" "patroni_core" "SERVICE_NAME" "patroni-core" "vals" .Values "default" .Values.operator.image)) -}} + {{- if .Values.patroni.install -}} + {{- $replicas := int .Values.patroni.replicas -}} + {{- range $i := until $replicas -}} + {{- $node := add $i 1 -}} + {{- printf "statefulset pg-%s-node%d pg-%s-node%d %s, " $.Values.patroni.clusterName $node $.Values.patroni.clusterName $node (include "find_image" (dict "deployName" "pg_patroni" "SERVICE_NAME" "pg_patroni" "vals" $.Values "default" $.Values.patroni.dockerImage)) -}} + {{- end -}} + {{- end -}} {{- end -}} diff --git a/operator/charts/patroni-core/templates/cr.yaml b/operator/charts/patroni-core/templates/cr.yaml index 4643ab0c..1c1fd98d 100644 --- a/operator/charts/patroni-core/templates/cr.yaml +++ b/operator/charts/patroni-core/templates/cr.yaml @@ -221,6 +221,7 @@ spec: {{ toYaml .Values.podLabels | nindent 6 }} {{- end }} image: {{ template "find_image" (dict "deployName" "postgres_operator_tests" "SERVICE_NAME" "postgres_operator_tests" "vals" .Values "default" .Values.tests.dockerImage) }} + monitoredImages: {{ include "patroni-tests.monitoredImages" . | quote }} {{ if .Values.tests.resources }} resources: {{ toYaml .Values.tests.resources | indent 6 }} @@ -233,15 +234,24 @@ spec: cpu: 150m memory: 256Mi {{ end }} -{{- $runTestScenarios := .Values.tests.runTestScenarios }} -{{- if or (eq (lower $runTestScenarios) "full") (eq (lower $runTestScenarios) "basic") }} - runTestScenarios: {{.Values.tests.runTestScenarios}} -{{- else if index .Values.tests.testScenarios (printf "%s" $runTestScenarios) }} +{{- $runTestScenarios := lower .Values.tests.runTestScenarios }} +{{- if or (eq $runTestScenarios "full") (eq $runTestScenarios "basic") }} + runTestScenarios: {{ $runTestScenarios }} +{{- else if eq $runTestScenarios "custom" }} + runTestScenarios: custom + {{- if .Values.tests.testList }} testList: - {{- range (index .Values.tests.testScenarios (printf "%s" $runTestScenarios)) }} + {{- range .Values.tests.testList }} - {{ . }} - {{- end }} -{{ end }} + {{- end }} + {{- end }} +{{- else if hasKey .Values.tests.testScenarios .Values.tests.runTestScenarios }} + runTestScenarios: custom + testList: + {{- range (index .Values.tests.testScenarios .Values.tests.runTestScenarios) }} + - {{ . }} + {{- end }} +{{- end }} pgNodeQty: {{ ( include "postgres.replicasCount" . ) }} {{ end }} {{ if .Values.runTestsOnly }} diff --git a/operator/charts/patroni-services/crds/netcracker.com_patroniservices.yaml b/operator/charts/patroni-services/crds/netcracker.com_patroniservices.yaml index 436e2cc3..c9fb5086 100644 --- a/operator/charts/patroni-services/crds/netcracker.com_patroniservices.yaml +++ b/operator/charts/patroni-services/crds/netcracker.com_patroniservices.yaml @@ -3555,6 +3555,8 @@ spec: type: object image: type: string + monitoredImages: + type: string pgNodeQty: type: integer podLabels: @@ -6139,9 +6141,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- diff --git a/operator/charts/patroni-services/templates/_helpers.tpl b/operator/charts/patroni-services/templates/_helpers.tpl index 0b3deca1..40d8269c 100644 --- a/operator/charts/patroni-services/templates/_helpers.tpl +++ b/operator/charts/patroni-services/templates/_helpers.tpl @@ -376,6 +376,24 @@ Return namespace for gateway {{- end -}} {{- define "supplementary-tests.monitoredImages" -}} + {{- if .Values.deployDescriptor -}} + {{- printf "deployment postgres-operator patroni-services %s, " (include "find_image" (dict "deployName" "postgres_operator" "SERVICE_NAME" "patroni-services" "vals" .Values "default" "not_found")) -}} + {{- if (eq (include "monitoring.install" .) "true") -}} + {{- printf "deployment monitoring-collector monitoring-collector %s, " (include "find_image" (dict "deployName" "pg_patroni_metric_collector" "SERVICE_NAME" "pg_patroni_metric_collector" "vals" .Values "default" "not_found")) -}} + {{- end -}} + {{- if .Values.backupDaemon.install -}} + {{- printf "deployment postgres-backup-daemon postgres-backup-daemon %s, " (include "find_image" (dict "deployName" "postgres_backup_daemon" "SERVICE_NAME" "postgres_backup_daemon" "vals" .Values "default" "not_found")) -}} + {{- end -}} + {{- if .Values.dbaas.install -}} + {{- printf "deployment dbaas-postgres-adapter dbaas-postgres-adapter %s, " (include "find_image" (dict "deployName" "postgresql_dbaas_adapter" "SERVICE_NAME" "postgresql_dbaas_adapter" "vals" .Values "default" "not_found")) -}} + {{- end -}} + {{- if .Values.powaUI.install -}} + {{- printf "deployment powa-ui powa-ui %s, " (include "find_image" (dict "deployName" "powa_ui_docker" "SERVICE_NAME" "powa_ui_docker" "vals" .Values "default" "not_found")) -}} + {{- end -}} + {{- if .Values.connectionPooler.install -}} + {{- printf "deployment connection-puller connection-puller %s, " (include "find_image" (dict "deployName" "pgbouncer" "SERVICE_NAME" "pgbouncer" "vals" .Values "default" "not_found")) -}} + {{- end -}} + {{- end -}} {{- end -}} {{/* diff --git a/operator/charts/patroni-services/templates/cr.yaml b/operator/charts/patroni-services/templates/cr.yaml index d397a2b5..3b41c4f6 100644 --- a/operator/charts/patroni-services/templates/cr.yaml +++ b/operator/charts/patroni-services/templates/cr.yaml @@ -401,6 +401,7 @@ spec: {{ toYaml .Values.podLabels | nindent 6 }} {{- end }} image: {{ template "find_image" (dict "deployName" "postgres_operator_tests" "SERVICE_NAME" "postgres_operator_tests" "vals" .Values "default" .Values.tests.dockerImage) }} + monitoredImages: {{ include "supplementary-tests.monitoredImages" . | quote }} {{ if .Values.tests.resources }} resources: {{ toYaml .Values.tests.resources | indent 6 }} @@ -413,15 +414,24 @@ spec: cpu: 150m memory: 256Mi {{ end }} -{{- $runTestScenarios := .Values.tests.runTestScenarios }} -{{- if or (eq (lower $runTestScenarios) "full") (eq (lower $runTestScenarios) "basic") }} - runTestScenarios: {{.Values.tests.runTestScenarios}} -{{- else if index .Values.tests.testScenarios (printf "%s" $runTestScenarios) }} +{{- $runTestScenarios := lower .Values.tests.runTestScenarios }} +{{- if or (eq $runTestScenarios "full") (eq $runTestScenarios "basic") }} + runTestScenarios: {{ $runTestScenarios }} +{{- else if eq $runTestScenarios "custom" }} + runTestScenarios: custom + {{- if .Values.tests.testList }} testList: - {{- range (index .Values.tests.testScenarios (printf "%s" $runTestScenarios)) }} + {{- range .Values.tests.testList }} - {{ . }} - {{- end }} -{{ end }} + {{- end }} + {{- end }} +{{- else if hasKey .Values.tests.testScenarios .Values.tests.runTestScenarios }} + runTestScenarios: custom + testList: + {{- range (index .Values.tests.testScenarios .Values.tests.runTestScenarios) }} + - {{ . }} + {{- end }} +{{- end }} pgNodeQty: {{ default "1" .Values.patroni.replicas }} {{ end }} {{ if .Values.runTestsOnly }} diff --git a/operator/charts/patroni-services/templates/tests/tests-config.yaml b/operator/charts/patroni-services/templates/tests/tests-config.yaml index cd0c087c..62afb167 100644 --- a/operator/charts/patroni-services/templates/tests/tests-config.yaml +++ b/operator/charts/patroni-services/templates/tests/tests-config.yaml @@ -6,9 +6,5 @@ metadata: labels: app: patroni-tests data: - {{- if include "supplementary-tests.monitoredImages" . }} - dd_images: {{ include "supplementary-tests.monitoredImages" . }} - {{ else }} - dd_images: "" - {{ end }} + dd_images: {{ (.Values.tests.ddImages | default (include "supplementary-tests.monitoredImages" .) | default "") | quote }} {{- end }} diff --git a/operator/pkg/deployment/tests.go b/operator/pkg/deployment/tests.go index ecd2e663..fe097341 100644 --- a/operator/pkg/deployment/tests.go +++ b/operator/pkg/deployment/tests.go @@ -34,24 +34,21 @@ var ( func NewIntegrationTestsPod(cr *v1.PatroniServices, cluster *patroniv1.PatroniClusterSettings) *corev1.Pod { testsSpec := cr.Spec.IntegrationTests - tastsTags := "" + var testsTags string pgHost := cluster.PostgresServiceName - if strings.ToLower(testsSpec.RunTestScenarios) == "full" { + scenario := strings.ToLower(testsSpec.RunTestScenarios) + if scenario == "full" { if cr.Spec.BackupDaemon != nil && cr.Spec.BackupDaemon.Resources != nil { - tastsTags = "backup*ORdbaas*" + testsTags = "backup*ORdbaas*" } - } else { - if strings.ToLower(testsSpec.RunTestScenarios) == "basic" { - if cr.Spec.BackupDaemon != nil && cr.Spec.BackupDaemon.Resources != nil { - tastsTags = "backup_basic" - } - } else { - if testsSpec.TestList != nil { - tastsTags = strings.Join(testsSpec.TestList, "OR") - r := regexp.MustCompile(`\s+`) - tastsTags = r.ReplaceAllString(tastsTags, "_") - } + } else if scenario == "basic" { + if cr.Spec.BackupDaemon != nil && cr.Spec.BackupDaemon.Resources != nil { + testsTags = "backup_basic" } + } else if scenario == "custom" && testsSpec.TestList != nil { + testsTags = strings.Join(testsSpec.TestList, "OR") + r := regexp.MustCompile(`\s+`) + testsTags = r.ReplaceAllString(testsTags, "_") } dockerImage := testsSpec.DockerImage name := "integration-robot-tests" @@ -75,7 +72,7 @@ func NewIntegrationTestsPod(cr *v1.PatroniServices, cluster *patroniv1.PatroniCl Image: dockerImage, ImagePullPolicy: cr.Spec.ImagePullPolicy, SecurityContext: util.GetDefaultSecurityContext(), - Args: []string{"robot", "-i", tastsTags, "/test_runs/"}, + Args: []string{"robot", "-i", testsTags, "/test_runs/"}, Env: []corev1.EnvVar{ { Name: "POSTGRES_USER", @@ -105,7 +102,7 @@ func NewIntegrationTestsPod(cr *v1.PatroniServices, cluster *patroniv1.PatroniCl }, { Name: "TESTS_TAGS", - Value: tastsTags, + Value: testsTags, }, { Name: "PG_HOST", @@ -127,6 +124,10 @@ func NewIntegrationTestsPod(cr *v1.PatroniServices, cluster *patroniv1.PatroniCl }, }, }, + { + Name: "MONITORED_IMAGES", + Value: testsSpec.MonitoredImages, + }, }, VolumeMounts: []corev1.VolumeMount{}, }, @@ -149,25 +150,23 @@ func NewIntegrationTestsPod(cr *v1.PatroniServices, cluster *patroniv1.PatroniCl func NewCoreIntegrationTests(cr *patroniv1.PatroniCore, cluster *patroniv1.PatroniClusterSettings) *corev1.Pod { testsSpec := cr.Spec.IntegrationTests - tastsTags := "" + var testsTags string pgHost := cluster.PostgresServiceName + scenario := strings.ToLower(testsSpec.RunTestScenarios) if cr.Spec.Patroni.StandbyCluster != nil { pgHost = fmt.Sprintf("pg-%s-external", cluster.ClusterName) } if strings.ToLower(cr.Spec.Patroni.Dcs.Type) != "kubernetes" { - tastsTags = "patroni_simple" + testsTags = "patroni_simple" } else { - if strings.ToLower(testsSpec.RunTestScenarios) == "full" { - tastsTags = "patroni*" - } else { - if strings.ToLower(testsSpec.RunTestScenarios) == "basic" { - tastsTags = "patroni_basic" - } else { - if testsSpec.TestList != nil { - r := regexp.MustCompile(`\s+`) - tastsTags = r.ReplaceAllString(tastsTags, "_") - } - } + if scenario == "full" { + testsTags = "patroni*" + } else if scenario == "basic" { + testsTags = "patroni_basic" + } else if scenario == "custom" && len(testsSpec.TestList) > 0 { + testsTags = strings.Join(testsSpec.TestList, "OR") + r := regexp.MustCompile(`\s+`) + testsTags = r.ReplaceAllString(testsTags, "_") } } dockerImage := testsSpec.DockerImage @@ -192,7 +191,7 @@ func NewCoreIntegrationTests(cr *patroniv1.PatroniCore, cluster *patroniv1.Patro Image: dockerImage, ImagePullPolicy: cr.Spec.ImagePullPolicy, SecurityContext: util.GetDefaultSecurityContext(), - Args: []string{"robot", "-i", tastsTags, "/test_runs/"}, + Args: []string{"robot", "-i", testsTags, "/test_runs/"}, Env: []corev1.EnvVar{ { Name: "POSTGRES_USER", @@ -226,7 +225,7 @@ func NewCoreIntegrationTests(cr *patroniv1.PatroniCore, cluster *patroniv1.Patro }, { Name: "TESTS_TAGS", - Value: tastsTags, + Value: testsTags, }, { Name: "PG_HOST", @@ -248,6 +247,10 @@ func NewCoreIntegrationTests(cr *patroniv1.PatroniCore, cluster *patroniv1.Patro }, }, }, + { + Name: "MONITORED_IMAGES", + Value: testsSpec.MonitoredImages, + }, }, VolumeMounts: []corev1.VolumeMount{}, }, diff --git a/tests/robot/image_tests/image_tests.robot b/tests/robot/image_tests/image_tests.robot index 74d03332..5c8cd640 100644 --- a/tests/robot/image_tests/image_tests.robot +++ b/tests/robot/image_tests/image_tests.robot @@ -1,28 +1,38 @@ +*** Variables *** +${MONITORED_IMAGES} %{MONITORED_IMAGES} + *** Settings *** Library String Library Collections Resource ../Lib/lib.robot *** Keywords *** -Compare Images From Resources With Dd - [Arguments] ${dd_images} - ${stripped_resources}= Strip String ${dd_images} characters=, mode=right - @{list_resources} = Split String ${stripped_resources} , +Get Image Tag + [Arguments] ${image} + @{parts}= Split String ${image} : + ${length}= Get Length ${parts} + Run Keyword If ${length} > 1 Return From Keyword ${parts}[${length-1}] + Fail Image has no tag: ${image} + +Compare Images From Resources + [Arguments] ${images} + @{list_resources}= Split String ${images} , FOR ${resource} IN @{list_resources} - ${type} ${name} ${container_name} ${image}= Split String ${resource} - ${resource_image}= Get Image From Resource ${type} ${name} ${container_name} - Should Be Equal ${resource_image} ${image} + ${resource}= Strip String ${resource} + Continue For Loop If '${resource}' == '' + + ${type} ${name} ${container_name} ${image}= Split String ${resource} + ${resource_image}= Get Image From Resource ${type} ${name} ${container_name} + + ${expected_tag}= Get Image Tag ${image} + ${actual_tag}= Get Image Tag ${resource_image} + + Log To Console \n[COMPARE] ${resource}: Expected tag=${expected_tag}, Actual tag=${actual_tag} + Run Keyword And Continue On Failure Should Be Equal ${actual_tag} ${expected_tag} END *** Test Cases *** -Test Hardcoded Images For Core Services +Test Hardcoded Images [Tags] patroni basic check_pg_images - ${dd_images}= Get Dd Images From Config Map patroni-tests-config - Skip If '${dd_images}' == '${None}' There is no dd, not possible to check case! - Compare Images From Resources With Dd ${dd_images} - -Test Hardcoded Images For Supplementary Services - [Tags] backup basic check_pg_images - ${dd_images}= Get Dd Images From Config Map supplementary-tests-config - Skip If '${dd_images}' == '${None}' There is no dd, not possible to check case! - Compare Images From Resources With Dd ${dd_images} + Skip If '${MONITORED_IMAGES}' == '${None}' or '${MONITORED_IMAGES}' == '' There are no monitored images + Compare Images From Resources ${MONITORED_IMAGES}