From 663cb0fa9250d862e313b65079f6792b03a042d6 Mon Sep 17 00:00:00 2001 From: Robert Cerven Date: Wed, 30 Oct 2024 21:30:28 +0100 Subject: [PATCH] create temporary config map with CA certificate based on one in build-service namespace if it exists, so renovate pod can mount it and use it against gitlab.cee.redhat.com KFLUXBUGS-1744 Signed-off-by: Robert Cerven --- ...onent_dependency_update_controller_test.go | 80 +++++++++++++------ controllers/renovate_util.go | 72 ++++++++++++++++- controllers/suite_util_test.go | 13 +++ 3 files changed, 139 insertions(+), 26 deletions(-) diff --git a/controllers/component_dependency_update_controller_test.go b/controllers/component_dependency_update_controller_test.go index a285dbba..66f01636 100644 --- a/controllers/component_dependency_update_controller_test.go +++ b/controllers/component_dependency_update_controller_test.go @@ -92,6 +92,9 @@ var _ = Describe("Component nudge controller", func() { } createSCMSecret(imageRepoSecretKey, imageRepoSecretData, v1.SecretTypeDockerConfigJson, map[string]string{}) + caConfigMapKey := types.NamespacedName{Name: "trusted-ca", Namespace: BuildServiceNamespaceName} + createCAConfigMap(caConfigMapKey) + serviceAccountKey := types.NamespacedName{Name: buildPipelineServiceAccountName, Namespace: UserNamespace} sa := waitServiceAccount(serviceAccountKey) sa.Secrets = []v1.ObjectReference{{Name: "dockerconfigjsonsecret"}} @@ -216,17 +219,40 @@ var _ = Describe("Component nudge controller", func() { // check that renovate config was created renovateConfigsCreated := len(getRenovateConfigMapList()) // check that renovate pipeline run was created - renovatePipelinesCreated := getRenovatePipelineRunCount() - return renovatePipelinesCreated == 1 && renovateConfigsCreated == 1 && failureCount == 0 + renovatePipelinesCreated := len(getRenovatePipelineRunList()) + return renovatePipelinesCreated == 1 && renovateConfigsCreated == 2 && failureCount == 0 }, timeout, interval).WithTimeout(ensureTimeout).Should(BeTrue()) renovateConfigMaps := getRenovateConfigMapList() - Expect(len(renovateConfigMaps)).Should(Equal(1)) + Expect(len(renovateConfigMaps)).Should(Equal(2)) + renovateConfigMapFound := false + renovateCaConfigMapFound := false + for _, renovateConfig := range renovateConfigMaps { - for _, renovateConfigData := range renovateConfig.Data { - Expect(strings.Contains(renovateConfigData, `"username": "image_repo_username"`)).Should(BeTrue()) + if strings.HasPrefix(renovateConfig.ObjectMeta.Name, "renovate-pipeline") { + renovateConfigMapFound = true + + for _, renovateConfigData := range renovateConfig.Data { + Expect(strings.Contains(renovateConfigData, `"username": "image_repo_username"`)).Should(BeTrue()) + } + } + if strings.HasPrefix(renovateConfig.ObjectMeta.Name, "renovate-ca") { + renovateCaConfigMapFound = true + Expect(renovateConfig.Data).Should(Equal(map[string]string{CaConfigMapKey: "someCAcertdata"})) + } + } + Expect(renovateCaConfigMapFound && renovateConfigMapFound).Should(BeTrue()) + + renovatePipelines := getRenovatePipelineRunList() + Expect(len(renovatePipelines)).Should(Equal(1)) + caMounted := false + for _, volumeMount := range renovatePipelines[0].Spec.PipelineSpec.Tasks[0].TaskSpec.TaskSpec.Steps[0].VolumeMounts { + if volumeMount.Name == CaVolumeMountName { + caMounted = true + break } } + Expect(caMounted).Should(BeTrue()) }) It("Test build performs nudge on success, image repository partial auth", func() { @@ -268,15 +294,17 @@ var _ = Describe("Component nudge controller", func() { // check that renovate config was created renovateConfigsCreated := len(getRenovateConfigMapList()) // check that renovate pipeline run was created - renovatePipelinesCreated := getRenovatePipelineRunCount() - return renovatePipelinesCreated == 1 && renovateConfigsCreated == 1 && failureCount == 0 + renovatePipelinesCreated := len(getRenovatePipelineRunList()) + return renovatePipelinesCreated == 1 && renovateConfigsCreated == 2 && failureCount == 0 }, timeout, interval).WithTimeout(ensureTimeout).Should(BeTrue()) renovateConfigMaps := getRenovateConfigMapList() - Expect(len(renovateConfigMaps)).Should(Equal(1)) + Expect(len(renovateConfigMaps)).Should(Equal(2)) for _, renovateConfig := range renovateConfigMaps { - for _, renovateConfigData := range renovateConfig.Data { - Expect(strings.Contains(renovateConfigData, `"username": "image_repo_username_partial"`)).Should(BeTrue()) + if strings.HasPrefix(renovateConfig.ObjectMeta.Name, "renovate-pipeline") { + for _, renovateConfigData := range renovateConfig.Data { + Expect(strings.Contains(renovateConfigData, `"username": "image_repo_username_partial"`)).Should(BeTrue()) + } } } }) @@ -336,15 +364,17 @@ var _ = Describe("Component nudge controller", func() { // check that renovate config was created renovateConfigsCreated := len(getRenovateConfigMapList()) // check that renovate pipeline run was created - renovatePipelinesCreated := getRenovatePipelineRunCount() - return renovatePipelinesCreated == 1 && renovateConfigsCreated == 1 && failureCount == 0 + renovatePipelinesCreated := len(getRenovatePipelineRunList()) + return renovatePipelinesCreated == 1 && renovateConfigsCreated == 2 && failureCount == 0 }, timeout, interval).WithTimeout(ensureTimeout).Should(BeTrue()) renovateConfigMaps := getRenovateConfigMapList() - Expect(len(renovateConfigMaps)).Should(Equal(1)) + Expect(len(renovateConfigMaps)).Should(Equal(2)) for _, renovateConfig := range renovateConfigMaps { - for _, renovateConfigData := range renovateConfig.Data { - Expect(strings.Contains(renovateConfigData, `"username": "image_repo_username_2"`)).Should(BeTrue()) + if strings.HasPrefix(renovateConfig.ObjectMeta.Name, "renovate-pipeline") { + for _, renovateConfigData := range renovateConfig.Data { + Expect(strings.Contains(renovateConfigData, `"username": "image_repo_username_2"`)).Should(BeTrue()) + } } } }) @@ -380,9 +410,9 @@ var _ = Describe("Component nudge controller", func() { // check that renovate config was created renovateConfigsCreated := len(getRenovateConfigMapList()) // check that renovate pipeline run was created - renovatePipelinesCreated := getRenovatePipelineRunCount() + renovatePipelinesCreated := len(getRenovatePipelineRunList()) - return renovatePipelinesCreated == 1 && renovateConfigsCreated == 1 && failureCount == 0 + return renovatePipelinesCreated == 1 && renovateConfigsCreated == 2 && failureCount == 0 }, timeout, interval).WithTimeout(ensureTimeout).Should(BeTrue()) }) @@ -430,9 +460,9 @@ var _ = Describe("Component nudge controller", func() { // check that renovate config was created renovateConfigsCreated := len(getRenovateConfigMapList()) // check that renovate pipeline run was created - renovatePipelinesCreated := getRenovatePipelineRunCount() + renovatePipelinesCreated := len(getRenovatePipelineRunList()) - return renovatePipelinesCreated == 1 && renovateConfigsCreated == 1 + return renovatePipelinesCreated == 1 && renovateConfigsCreated == 2 }, timeout, interval).WithTimeout(ensureTimeout).Should(BeTrue()) }) @@ -470,7 +500,7 @@ var _ = Describe("Component nudge controller", func() { // check that multiple nudgeerror event were reported failureCount := getRenovateFailedEventCount() // check that no renovate pipeline run was created - renovatePipelinesCreated := getRenovatePipelineRunCount() + renovatePipelinesCreated := len(getRenovatePipelineRunList()) return renovatePipelinesCreated == 0 && failureCount == 3 }, timeout, interval).WithTimeout(ensureTimeout).Should(BeTrue()) @@ -603,7 +633,7 @@ func getRenovateConfigMapList() []v1.ConfigMap { err := k8sClient.List(context.TODO(), configMapList, &client.ListOptions{Namespace: UserNamespace}) Expect(err).ToNot(HaveOccurred()) for _, configMap := range configMapList.Items { - if strings.HasPrefix(configMap.ObjectMeta.Name, "renovate-pipeline") { + if strings.HasPrefix(configMap.ObjectMeta.Name, "renovate-") { log.Info(configMap.ObjectMeta.Name) renovateConfigMapList = append(renovateConfigMapList, configMap) } @@ -611,18 +641,18 @@ func getRenovateConfigMapList() []v1.ConfigMap { return renovateConfigMapList } -func getRenovatePipelineRunCount() int { - renovatePipelinesCreated := 0 +func getRenovatePipelineRunList() []tektonapi.PipelineRun { prList := &tektonapi.PipelineRunList{} + renovatePipelinesList := []tektonapi.PipelineRun{} err := k8sClient.List(context.TODO(), prList, &client.ListOptions{Namespace: UserNamespace}) Expect(err).ToNot(HaveOccurred()) for _, pipelineRun := range prList.Items { if strings.HasPrefix(pipelineRun.ObjectMeta.Name, "renovate-pipeline") { log.Info(pipelineRun.ObjectMeta.Name) - renovatePipelinesCreated += 1 + renovatePipelinesList = append(renovatePipelinesList, pipelineRun) } } - return renovatePipelinesCreated + return renovatePipelinesList } func getRenovateFailedEventCount() int { diff --git a/controllers/renovate_util.go b/controllers/renovate_util.go index db4395f6..2a863099 100644 --- a/controllers/renovate_util.go +++ b/controllers/renovate_util.go @@ -33,6 +33,11 @@ const ( RenovateImageEnvName = "RENOVATE_IMAGE" DefaultRenovateImageUrl = "quay.io/redhat-appstudio/renovate:v37.74.1" DefaultRenovateUser = "red-hat-konflux" + CaConfigMapLabel = "config.openshift.io/inject-trusted-cabundle" + CaConfigMapKey = "ca-bundle.crt" + CaFilePath = "tls-ca-bundle.pem" + CaMountPath = "/etc/pki/ca-trust/extracted/pem" + CaVolumeMountName = "trusted-ca" ) type renovateRepository struct { @@ -369,7 +374,9 @@ func (u ComponentDependenciesUpdater) CreateRenovaterPipeline(ctx context.Contex return nil } timestamp := time.Now().Unix() - name := fmt.Sprintf("renovate-pipeline-%d-%s", timestamp, RandomString(5)) + nameSuffix := fmt.Sprintf("%d-%s", timestamp, RandomString(5)) + name := fmt.Sprintf("renovate-pipeline-%s", nameSuffix) + caConfigMapName := fmt.Sprintf("renovate-ca-%s", nameSuffix) secretTokens := map[string]string{} configmaps := map[string]string{} renovateCmds := []string{} @@ -393,6 +400,21 @@ func (u ComponentDependenciesUpdater) CreateRenovaterPipeline(ctx context.Contex if len(renovateCmds) == 0 { return nil } + + allCaConfigMaps := &corev1.ConfigMapList{} + opts := client.ListOption(&client.MatchingLabels{ + CaConfigMapLabel: "true", + }) + + if err := u.Client.List(ctx, allCaConfigMaps, client.InNamespace(BuildServiceNamespaceName), opts); err != nil { + return fmt.Errorf("failed to list config maps with label %s in %s namespace: %w", CaConfigMapLabel, BuildServiceNamespaceName, err) + } + caConfigData := "" + if len(allCaConfigMaps.Items) > 0 { + log.Info("will use CA config map", "name", allCaConfigMaps.Items[0].ObjectMeta.Name) + caConfigData = allCaConfigMaps.Items[0].Data[CaConfigMapKey] + } + secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -407,6 +429,19 @@ func (u ComponentDependenciesUpdater) CreateRenovaterPipeline(ctx context.Contex }, Data: configmaps, } + + var caConfigMap *corev1.ConfigMap + if caConfigData != "" { + configMapData := map[string]string{CaConfigMapKey: caConfigData} + caConfigMap = &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: caConfigMapName, + Namespace: namespace, + }, + Data: configMapData, + } + } + trueBool := true falseBool := false renovateImageUrl := os.Getenv(RenovateImageEnvName) @@ -469,6 +504,31 @@ func (u ComponentDependenciesUpdater) CreateRenovaterPipeline(ctx context.Contex }, }, } + + if caConfigData != "" { + caVolume := corev1.Volume{ + Name: CaVolumeMountName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{Name: caConfigMapName}, + Items: []corev1.KeyToPath{ + { + Key: CaConfigMapKey, + Path: CaFilePath, + }, + }, + }, + }, + } + caVolumeMount := corev1.VolumeMount{ + Name: CaVolumeMountName, + MountPath: CaMountPath, + ReadOnly: true, + } + pipelineRun.Spec.PipelineSpec.Tasks[0].TaskSpec.TaskSpec.Volumes = append(pipelineRun.Spec.PipelineSpec.Tasks[0].TaskSpec.TaskSpec.Volumes, caVolume) + pipelineRun.Spec.PipelineSpec.Tasks[0].TaskSpec.TaskSpec.Steps[0].VolumeMounts = append(pipelineRun.Spec.PipelineSpec.Tasks[0].TaskSpec.TaskSpec.Steps[0].VolumeMounts, caVolumeMount) + } + if debug { pipelineRun.Spec.PipelineSpec.Tasks[0].TaskSpec.Steps[0].Env = append(pipelineRun.Spec.PipelineSpec.Tasks[0].TaskSpec.Steps[0].Env, corev1.EnvVar{Name: "LOG_LEVEL", Value: "debug"}) } @@ -483,6 +543,16 @@ func (u ComponentDependenciesUpdater) CreateRenovaterPipeline(ctx context.Contex if err := controllerutil.SetOwnerReference(pipelineRun, secret, u.Scheme); err != nil { return err } + + if caConfigData != "" { + if err := controllerutil.SetOwnerReference(pipelineRun, caConfigMap, u.Scheme); err != nil { + return err + } + if err := u.Client.Create(ctx, caConfigMap); err != nil { + return err + } + } + if err := u.Client.Create(ctx, secret); err != nil { return err } diff --git a/controllers/suite_util_test.go b/controllers/suite_util_test.go index a897f568..ff0f09d2 100644 --- a/controllers/suite_util_test.go +++ b/controllers/suite_util_test.go @@ -579,6 +579,19 @@ func createBuildPipelineConfigMap(configMapKey types.NamespacedName, pipelineBun } } +func createCAConfigMap(configMapKey types.NamespacedName) { + configMapData := map[string]string{CaConfigMapKey: "someCAcertdata"} + + caConfigMap := corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{Name: configMapKey.Name, Namespace: configMapKey.Namespace, Labels: map[string]string{CaConfigMapLabel: "true"}}, + Data: configMapData, + } + + if err := k8sClient.Create(ctx, &caConfigMap); err != nil && !k8sErrors.IsAlreadyExists(err) { + Fail(err.Error()) + } +} + func waitServiceAccount(serviceAccountKey types.NamespacedName) corev1.ServiceAccount { serviceAccount := corev1.ServiceAccount{} Eventually(func() bool {