diff --git a/assets/auto-deploy-app/templates/_helpers.tpl b/assets/auto-deploy-app/templates/_helpers.tpl index fba1d91bb46bf720951694be205fe8af7bf7a754..30d6a13be2c28038a22cd7a243a61047ab29e7c5 100644 --- a/assets/auto-deploy-app/templates/_helpers.tpl +++ b/assets/auto-deploy-app/templates/_helpers.tpl @@ -104,7 +104,7 @@ helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version| replace "+" "_" }}" app.kubernetes.io/managed-by: {{ .Release.Service }} app.kubernetes.io/instance: {{ .Release.Name }} {{- if .Values.extraLabels }} -{{- toYaml $.Values.extraLabels }} +{{ toYaml $.Values.extraLabels }} {{- end }} {{- end -}} diff --git a/assets/auto-deploy-app/test/templates/cronjob_test.go b/assets/auto-deploy-app/test/templates/cronjob_test.go index a9517a6e95726278f5cd0f2fda996bc2aaca75ea..81ac65a8090012ecb644567299dd5a1a3bd45176 100644 --- a/assets/auto-deploy-app/test/templates/cronjob_test.go +++ b/assets/auto-deploy-app/test/templates/cronjob_test.go @@ -22,6 +22,7 @@ func TestCronjobMeta(t *testing.T) { ExpectedName string ExpectedRelease string + ExpectedLabels map[string]string }{ { CaseName: "default", @@ -34,6 +35,23 @@ func TestCronjobMeta(t *testing.T) { }, ExpectedName: "production", ExpectedRelease: "production", + ExpectedLabels: nil, + }, + { + CaseName: "extraLabels", + Release: "production", + Values: map[string]string{ + "cronjobs.job1.command[0]": "echo", + "cronjobs.job1.args[0]": "hello", + "cronjobs.job2.command[0]": "echo", + "cronjobs.job2.args[0]": "hello", + "extraLabels.firstLabel": "expected-label", + }, + ExpectedName: "production", + ExpectedRelease: "production", + ExpectedLabels: map[string]string{ + "firstLabel": "expected-label", + }, }, { CaseName: "overriden release", @@ -47,6 +65,7 @@ func TestCronjobMeta(t *testing.T) { }, ExpectedName: "productionOverridden", ExpectedRelease: "production", + ExpectedLabels: nil, }, } { t.Run(tc.CaseName, func(t *testing.T) { @@ -81,7 +100,7 @@ func TestCronjobMeta(t *testing.T) { "app.gitlab.com/env": "prod", }, cronjob.Annotations) - require.Equal(t, map[string]string{ + ExpectedLabels := map[string]string{ "app": tc.ExpectedName, "chart": chartName, "heritage": "Helm", @@ -92,7 +111,9 @@ func TestCronjobMeta(t *testing.T) { "helm.sh/chart": chartName, "app.kubernetes.io/managed-by": "Helm", "app.kubernetes.io/instance": tc.ExpectedRelease, - }, cronjob.Labels) + } + mergeStringMap(ExpectedLabels, tc.ExpectedLabels) + require.Equal(t, ExpectedLabels, cronjob.Labels) require.Equal(t, map[string]string{ "app.gitlab.com/app": "auto-devops-examples/minimal-ruby-app", diff --git a/assets/auto-deploy-app/test/templates/db_initialize_job_test.go b/assets/auto-deploy-app/test/templates/db_initialize_job_test.go index a585aa367d28690e7afb9fd01200579a6bd49650..d283c123254e87dbcd63ec6100c8bb3652c6063c 100644 --- a/assets/auto-deploy-app/test/templates/db_initialize_job_test.go +++ b/assets/auto-deploy-app/test/templates/db_initialize_job_test.go @@ -170,3 +170,79 @@ func TestInitializeDatabaseImagePullSecrets(t *testing.T) { }) } } + +func TestInitializeDatabaseLabels(t *testing.T) { + releaseName := "initialize-application-database-labels" + + for _, tc := range []struct { + CaseName string + Values map[string]string + Release string + ExpectedLabels map[string]string + Template string + }{ + { + CaseName: "no label", + Release: "production", + Values: map[string]string{ + "application.initializeCommand": "echo initialize", + }, + ExpectedLabels: nil, + Template: "templates/db-initialize-job.yaml", + }, + { + CaseName: "one label", + Release: "production", + Values: map[string]string{ + "application.initializeCommand": "echo initialize", + "extraLabels.firstLabel": "expected-label", + }, + ExpectedLabels: map[string]string{ + "firstLabel": "expected-label", + }, + Template: "templates/db-initialize-job.yaml", + }, + { + CaseName: "multiple labels", + Release: "production", + Values: map[string]string{ + "application.initializeCommand": "echo initialize", + "extraLabels.firstLabel": "expected-label", + "extraLabels.secondLabel": "expected-label", + }, + ExpectedLabels: map[string]string{ + "firstLabel": "expected-label", + "secondLabel": "expected-label", + }, + Template: "templates/db-initialize-job.yaml", + }, + } { + t.Run(tc.CaseName, func(t *testing.T) { + namespaceName := "minimal-ruby-app-" + strings.ToLower(random.UniqueId()) + + values := map[string]string{} + + mergeStringMap(values, tc.Values) + + options := &helm.Options{ + SetValues: values, + KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName), + } + + output, err := helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{tc.Template}) + + if err != nil { + t.Error(err) + return + } + + deployment := new(appsV1.Deployment) + helm.UnmarshalK8SYaml(t, output, &deployment) + + for key, value := range tc.ExpectedLabels { + require.Equal(t, deployment.ObjectMeta.Labels[key], value) + require.Equal(t, deployment.Spec.Template.ObjectMeta.Labels[key], value) + } + }) + } +} diff --git a/assets/auto-deploy-app/test/templates/db_migrate_hook_test.go b/assets/auto-deploy-app/test/templates/db_migrate_hook_test.go index 61f7fc3d668a8a9c5c67e7733039e2b8243abd2a..58191654a76e09cc7e3bf3518876d59f49224284 100644 --- a/assets/auto-deploy-app/test/templates/db_migrate_hook_test.go +++ b/assets/auto-deploy-app/test/templates/db_migrate_hook_test.go @@ -170,3 +170,79 @@ func TestMigrateDatabaseImagePullSecrets(t *testing.T) { }) } } + +func TestMigrateDatabaseLabels(t *testing.T) { + releaseName := "migrate-application-database-labels" + + for _, tc := range []struct { + CaseName string + Values map[string]string + Release string + ExpectedLabels map[string]string + Template string + }{ + { + CaseName: "no label", + Release: "production", + Values: map[string]string{ + "application.migrateCommand": "echo migrate", + }, + ExpectedLabels: nil, + Template: "templates/db-migrate-hook.yaml", + }, + { + CaseName: "one label", + Release: "production", + Values: map[string]string{ + "application.migrateCommand": "echo migrate", + "extraLabels.firstLabel": "expected-label", + }, + ExpectedLabels: map[string]string{ + "firstLabel": "expected-label", + }, + Template: "templates/db-migrate-hook.yaml", + }, + { + CaseName: "multiple labels", + Release: "production", + Values: map[string]string{ + "application.migrateCommand": "echo migrate", + "extraLabels.firstLabel": "expected-label", + "extraLabels.secondLabel": "expected-label", + }, + ExpectedLabels: map[string]string{ + "firstLabel": "expected-label", + "secondLabel": "expected-label", + }, + Template: "templates/db-migrate-hook.yaml", + }, + } { + t.Run(tc.CaseName, func(t *testing.T) { + namespaceName := "minimal-ruby-app-" + strings.ToLower(random.UniqueId()) + + values := map[string]string{} + + mergeStringMap(values, tc.Values) + + options := &helm.Options{ + SetValues: values, + KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName), + } + + output, err := helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{tc.Template}) + + if err != nil { + t.Error(err) + return + } + + deployment := new(appsV1.Deployment) + helm.UnmarshalK8SYaml(t, output, &deployment) + + for key, value := range tc.ExpectedLabels { + require.Equal(t, deployment.ObjectMeta.Labels[key], value) + require.Equal(t, deployment.Spec.Template.ObjectMeta.Labels[key], value) + } + }) + } +} diff --git a/assets/auto-deploy-app/test/templates/deployment_test.go b/assets/auto-deploy-app/test/templates/deployment_test.go index 1ccdf2a9c1c0332f572e4b4348f58aae89bbc06b..3509be81959fa545c632b34656b6dba84f9f55f1 100644 --- a/assets/auto-deploy-app/test/templates/deployment_test.go +++ b/assets/auto-deploy-app/test/templates/deployment_test.go @@ -21,6 +21,7 @@ func TestDeploymentTemplate(t *testing.T) { CaseName string Release string Values map[string]string + ExpectedLabels map[string]string ExpectedErrorRegexp *regexp.Regexp @@ -37,12 +38,29 @@ func TestDeploymentTemplate(t *testing.T) { ExpectedName: "productionOverridden", ExpectedRelease: "production", ExpectedStrategyType: appsV1.DeploymentStrategyType(""), - }, { + ExpectedLabels: nil, + }, + { + CaseName: "extraLabel", + Release: "production", + Values: map[string]string{ + "releaseOverride": "productionOverridden", + "extraLabels.firstLabel": "expected-label", + }, + ExpectedName: "productionOverridden", + ExpectedRelease: "production", + ExpectedStrategyType: appsV1.DeploymentStrategyType(""), + ExpectedLabels: map[string]string{ + "firstLabel": "expected-label", + }, + }, + { // See https://github.com/helm/helm/issues/6006 CaseName: "long release name", Release: strings.Repeat("r", 80), ExpectedErrorRegexp: regexp.MustCompile("Error: release name .* length must not be longer than 53"), + ExpectedLabels: nil, }, { CaseName: "strategyType", @@ -53,6 +71,7 @@ func TestDeploymentTemplate(t *testing.T) { ExpectedName: "production", ExpectedRelease: "production", ExpectedStrategyType: appsV1.RecreateDeploymentStrategyType, + ExpectedLabels: nil, }, } { t.Run(tc.CaseName, func(t *testing.T) { @@ -91,7 +110,8 @@ func TestDeploymentTemplate(t *testing.T) { "app.gitlab.com/app": "auto-devops-examples/minimal-ruby-app", "app.gitlab.com/env": "prod", }, deployment.Annotations) - require.Equal(t, map[string]string{ + + ExpectedLabels := map[string]string{ "app": tc.ExpectedName, "chart": chartName, "heritage": "Helm", @@ -102,25 +122,17 @@ func TestDeploymentTemplate(t *testing.T) { "helm.sh/chart": chartName, "app.kubernetes.io/managed-by": "Helm", "app.kubernetes.io/instance": tc.ExpectedRelease, - }, deployment.Labels) + } + mergeStringMap(ExpectedLabels, tc.ExpectedLabels) + + require.Equal(t, ExpectedLabels, deployment.Labels) require.Equal(t, map[string]string{ "app.gitlab.com/app": "auto-devops-examples/minimal-ruby-app", "app.gitlab.com/env": "prod", "checksum/application-secrets": "", }, deployment.Spec.Template.Annotations) - require.Equal(t, map[string]string{ - "app": tc.ExpectedName, - "chart": chartName, - "heritage": "Helm", - "release": tc.ExpectedRelease, - "tier": "web", - "track": "stable", - "app.kubernetes.io/name": tc.ExpectedName, - "helm.sh/chart": chartName, - "app.kubernetes.io/managed-by": "Helm", - "app.kubernetes.io/instance": tc.ExpectedRelease, - }, deployment.Spec.Template.Labels) + require.Equal(t, ExpectedLabels, deployment.Spec.Template.Labels) }) } diff --git a/assets/auto-deploy-app/test/templates/hpa_test.go b/assets/auto-deploy-app/test/templates/hpa_test.go index 7b5739b2bf9df8494750692eb303beba1276df4c..fcf248805efdd1b980ed9e2a6f4a430d92c15e0e 100644 --- a/assets/auto-deploy-app/test/templates/hpa_test.go +++ b/assets/auto-deploy-app/test/templates/hpa_test.go @@ -23,25 +23,47 @@ func TestHPA_AutoscalingV1(t *testing.T) { expectedMinReplicas int32 expectedMaxReplicas int32 expectedTargetCPU int32 + ExpectedLabels map[string]string expectedErrorRegexp *regexp.Regexp }{ { name: "defaults", expectedErrorRegexp: regexp.MustCompile("Error: could not find template templates/hpa.yaml in chart"), + ExpectedLabels: nil, }, { name: "with hpa enabled, no requests", values: map[string]string{"hpa.enabled": "true"}, expectedErrorRegexp: regexp.MustCompile("Error: could not find template templates/hpa.yaml in chart"), + ExpectedLabels: nil, }, { name: "with hpa enabled and requests defined", - values: map[string]string{"hpa.enabled": "true", "resources.requests.cpu": "500"}, + values: map[string]string{ + "hpa.enabled": "true", + "resources.requests.cpu": "500", + }, expectedName: "hpa-test-auto-deploy", expectedMinReplicas: 1, expectedMaxReplicas: 5, expectedTargetCPU: 80, + ExpectedLabels: nil, + }, + { + name: "with hpa enabled and requests, label defined", + values: map[string]string{ + "hpa.enabled": "true", + "resources.requests.cpu": "500", + "extraLabels.firstLabel": "expected-label", + }, + expectedName: "hpa-test-auto-deploy", + expectedMinReplicas: 1, + expectedMaxReplicas: 5, + expectedTargetCPU: 80, + ExpectedLabels: map[string]string{ + "firstLabel": "expected-label", + }, }, } @@ -59,6 +81,9 @@ func TestHPA_AutoscalingV1(t *testing.T) { require.Equal(t, tc.expectedMinReplicas, *hpa.Spec.MinReplicas) require.Equal(t, tc.expectedMaxReplicas, hpa.Spec.MaxReplicas) require.Equal(t, tc.expectedTargetCPU, *hpa.Spec.TargetCPUUtilizationPercentage) + for key, value := range tc.ExpectedLabels { + require.Equal(t, hpa.ObjectMeta.Labels[key], value) + } }) } } diff --git a/assets/auto-deploy-app/test/templates/service_account_test.go b/assets/auto-deploy-app/test/templates/service_account_test.go index 41701749aaa2fff2ca622d9c5669e0fc4bfbc7a0..81a6a0417fa51379a7d06d9fd0ffc092fe5e74e8 100644 --- a/assets/auto-deploy-app/test/templates/service_account_test.go +++ b/assets/auto-deploy-app/test/templates/service_account_test.go @@ -23,13 +23,15 @@ func TestServiceAccountTemplate(t *testing.T) { ExpectedName string ExpectedAnnotations map[string]string + ExpectedLabels map[string]string }{ { CaseName: "not created by default", Values: map[string]string{}, ExpectedErrorRegexp: regexp.MustCompile( "Error: could not find template templates/service-account.yaml in chart", - ), + ), + ExpectedLabels: nil, }, { CaseName: "not created if createNew is set to false", @@ -39,6 +41,7 @@ func TestServiceAccountTemplate(t *testing.T) { ExpectedErrorRegexp: regexp.MustCompile( "Error: could not find template templates/service-account.yaml in chart", ), + ExpectedLabels: nil, }, { CaseName: "no annotations", @@ -48,6 +51,7 @@ func TestServiceAccountTemplate(t *testing.T) { }, ExpectedName: "anAccountName", ExpectedAnnotations: nil, + ExpectedLabels: nil, }, { CaseName: "with annotations", @@ -62,6 +66,20 @@ func TestServiceAccountTemplate(t *testing.T) { "key1": "value1", "key2": "value2", }, + ExpectedLabels: nil, + }, + { + CaseName: "with labels", + Values: map[string]string{ + "serviceAccount.createNew": "true", + "serviceAccount.name": "anAccountName", + "extraLabels.firstLabel": "expected-label", + }, + ExpectedName: "anAccountName", + ExpectedAnnotations: nil, + ExpectedLabels: map[string]string{ + "firstLabel": "expected-label", + }, }, } { t.Run(tc.CaseName, func(t *testing.T) { @@ -99,6 +117,9 @@ func TestServiceAccountTemplate(t *testing.T) { require.Equal(t, tc.ExpectedName, serviceAccount.Name) require.Equal(t, tc.ExpectedAnnotations, serviceAccount.Annotations) + for key, value := range tc.ExpectedLabels { + require.Equal(t, serviceAccount.ObjectMeta.Labels[key], value) + } }) } } diff --git a/assets/auto-deploy-app/test/templates/service_test.go b/assets/auto-deploy-app/test/templates/service_test.go index 8d2bb263bc35e2933e319e7e2dc47caa833796bd..df49825e857ae01eafd6cdba3d4ce2efa42f860f 100644 --- a/assets/auto-deploy-app/test/templates/service_test.go +++ b/assets/auto-deploy-app/test/templates/service_test.go @@ -104,6 +104,22 @@ func TestServiceTemplate_DifferentTracks(t *testing.T) { expectedLabels: map[string]string{"app": "production-canary", "release": "production-canary", "track": "canary"}, expectedSelector: map[string]string{"app": "production-canary", "tier": "web", "track": "canary"}, }, + { + name: "with canary track and labels", + releaseName: "production-canary", + values: map[string]string{ + "application.track": "canary", + "extraLabels.firstLabel": "expected-label", + }, + expectedName: "production-canary-auto-deploy", + expectedLabels: map[string]string{ + "app": "production-canary", + "release": "production-canary", + "track": "canary", + "firstLabel": "expected-label", + }, + expectedSelector: map[string]string{"app": "production-canary", "tier": "web", "track": "canary"}, + }, } for _, tc := range tcs { diff --git a/assets/auto-deploy-app/test/templates/workerdeployment_test.go b/assets/auto-deploy-app/test/templates/workerdeployment_test.go index 996bb8c9bcda5f350181b667276cc92e17900adc..154b1c86a859f4417d470a930797d076f2eed97b 100644 --- a/assets/auto-deploy-app/test/templates/workerdeployment_test.go +++ b/assets/auto-deploy-app/test/templates/workerdeployment_test.go @@ -419,12 +419,13 @@ func TestWorkerDeploymentTemplate(t *testing.T) { }) } - // podAnnotations + // podAnnotations & labels for _, tc := range []struct { CaseName string Values map[string]string Release string ExpectedPodAnnotations map[string]string + ExpectedPodLabels map[string]string }{ { CaseName: "one podAnnotations", @@ -437,6 +438,11 @@ func TestWorkerDeploymentTemplate(t *testing.T) { "checksum/application-secrets": "", "firstAnnotation": "expected-annotation", }, + ExpectedPodLabels: map[string]string{ + "release": "production", + "tier": "worker", + "track": "stable", + }, }, { CaseName: "multiple podAnnotations", @@ -451,16 +457,48 @@ func TestWorkerDeploymentTemplate(t *testing.T) { "firstAnnotation": "expected-annotation", "secondAnnotation": "expected-annotation", }, + ExpectedPodLabels: nil, + }, + { + CaseName: "one label", + Release: "production", + Values: map[string]string{ + "workers.worker1.labels.firstLabel": "expected-label", + "workers.worker1.command[0]": "echo", + }, + ExpectedPodAnnotations: map[string]string{ + "checksum/application-secrets": "", + }, + ExpectedPodLabels: map[string]string{ + "firstLabel": "expected-label", + }, }, { - CaseName: "no podAnnotations", + CaseName: "multiple labels", Release: "production", Values: map[string]string{ + "workers.worker1.labels.firstLabel": "expected-label", + "workers.worker1.labels.secondLabel": "expected-label", "workers.worker1.command[0]": "echo", }, ExpectedPodAnnotations: map[string]string{ "checksum/application-secrets": "", }, + ExpectedPodLabels: map[string]string{ + "firstLabel": "expected-label", + "secondLabel": "expected-label", + }, + }, + { + CaseName: "no podAnnotations & labels", + Release: "production", + Values: map[string]string{ + "workers.worker1.command[0]": "echo", + }, + ExpectedPodAnnotations: map[string]string{ + "checksum/application-secrets": "", + }, + ExpectedPodLabels: nil, }, } { t.Run(tc.CaseName, func(t *testing.T) { @@ -488,6 +526,9 @@ func TestWorkerDeploymentTemplate(t *testing.T) { for i := range deployments.Items { deployment := deployments.Items[i] require.Equal(t, tc.ExpectedPodAnnotations, deployment.Spec.Template.ObjectMeta.Annotations) + for key, value := range tc.ExpectedPodLabels { + require.Equal(t, deployment.Spec.Template.ObjectMeta.Labels[key], value) + } } }) }