diff --git a/pkg/api/consts.go b/pkg/api/consts.go index 3dc4754d1f..335d4c84f2 100644 --- a/pkg/api/consts.go +++ b/pkg/api/consts.go @@ -1,8 +1,9 @@ package api const ( - LatestTag = "latest" - RawTag = "raw" - InternalFlagPrefix = "internal.operator.dynatrace.com/" - AnnotationSecretHash = InternalFlagPrefix + "secret-hash" + LatestTag = "latest" + RawTag = "raw" + InternalFlagPrefix = "internal.operator.dynatrace.com/" + AnnotationSecretHash = InternalFlagPrefix + "secret-hash" + AnnotationTelemetryServiceSecretHash = InternalFlagPrefix + "ts-secret-hash" ) diff --git a/pkg/controllers/dynakube/otelc/statefulset/reconciler.go b/pkg/controllers/dynakube/otelc/statefulset/reconciler.go index 273e6ee6be..5f488528bf 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/reconciler.go +++ b/pkg/controllers/dynakube/otelc/statefulset/reconciler.go @@ -127,24 +127,42 @@ func (r *Reconciler) buildTemplateAnnotations(ctx context.Context) (map[string]s templateAnnotations = r.dk.Spec.Templates.OpenTelemetryCollector.Annotations } + tlsSecretHash, err := r.calculateSecretHash(ctx, r.dk.ExtensionsTLSSecretName()) + if err != nil { + return nil, err + } + + templateAnnotations[api.AnnotationSecretHash] = tlsSecretHash + + if r.dk.TelemetryService().IsEnabled() && r.dk.TelemetryService().Spec.TlsRefName != "" { + tlsSecretHash, err = r.calculateSecretHash(ctx, r.dk.TelemetryService().Spec.TlsRefName) + if err != nil { + return nil, err + } + + templateAnnotations[api.AnnotationTelemetryServiceSecretHash] = tlsSecretHash + } + + return templateAnnotations, nil +} + +func (r *Reconciler) calculateSecretHash(ctx context.Context, secretName string) (string, error) { query := k8ssecret.Query(r.client, r.client, log) tlsSecret, err := query.Get(ctx, types.NamespacedName{ - Name: r.dk.ExtensionsTLSSecretName(), + Name: secretName, Namespace: r.dk.Namespace, }) if err != nil { - return nil, err + return "", err } tlsSecretHash, err := hasher.GenerateHash(tlsSecret.Data) if err != nil { - return nil, err + return "", err } - templateAnnotations[api.AnnotationSecretHash] = tlsSecretHash - - return templateAnnotations, nil + return tlsSecretHash, nil } func getReplicas(dk *dynakube.DynaKube) int32 { diff --git a/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go b/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go index de5be03f5d..cbcf8d82e2 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go +++ b/pkg/controllers/dynakube/otelc/statefulset/reconciler_test.go @@ -8,6 +8,7 @@ import ( "github.com/Dynatrace/dynatrace-operator/pkg/api" "github.com/Dynatrace/dynatrace-operator/pkg/api/scheme/fake" "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube" + "github.com/Dynatrace/dynatrace-operator/pkg/api/v1beta3/dynakube/telemetryservice" "github.com/Dynatrace/dynatrace-operator/pkg/consts" "github.com/Dynatrace/dynatrace-operator/pkg/util/conditions" "github.com/Dynatrace/dynatrace-operator/pkg/util/kubeobjects/node" @@ -27,9 +28,10 @@ import ( ) const ( - testDynakubeName = "dynakube" - testNamespaceName = "dynatrace" - testOtelPullSecret = "otelc-pull-secret" + testDynakubeName = "dynakube" + testNamespaceName = "dynatrace" + testOtelPullSecret = "otelc-pull-secret" + testTelemetryServiceSecret = "test-ts-secret" ) func TestReconcile(t *testing.T) { @@ -503,6 +505,45 @@ func TestVolumes(t *testing.T) { assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) }) + + t.Run("volumes and volume mounts with telemetry service custom TLS certificate", func(t *testing.T) { + dk := getTestDynakube() + dk.Spec.TelemetryService = &telemetryservice.Spec{ + TlsRefName: testTelemetryServiceSecret, + } + + tlsSecret := getTLSSecret(dk.TelemetryService().Spec.TlsRefName, dk.Namespace, "crt", "key") + statefulSet := getStatefulset(t, dk, &tlsSecret) + + expectedVolume := corev1.Volume{ + Name: customTlsCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.TelemetryService().Spec.TlsRefName, + Items: []corev1.KeyToPath{ + { + Key: consts.TLSCrtDataName, + Path: consts.TLSCrtDataName, + }, + { + Key: consts.TLSKeyDataName, + Path: consts.TLSKeyDataName, + }, + }, + }, + }, + } + + assert.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume) + + expectedVolumeMount := corev1.VolumeMount{ + Name: customTlsCertVolumeName, + MountPath: customTlsCertMountPath, + ReadOnly: true, + } + + assert.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount) + }) } func getTestDynakube() *dynakube.DynaKube { @@ -519,10 +560,15 @@ func getTestDynakube() *dynakube.DynaKube { } } -func getStatefulset(t *testing.T, dk *dynakube.DynaKube) *appsv1.StatefulSet { +func getStatefulset(t *testing.T, dk *dynakube.DynaKube, objs ...client.Object) *appsv1.StatefulSet { mockK8sClient := fake.NewClient(dk) mockK8sClient = mockTLSSecret(t, mockK8sClient, dk) + for _, obj := range objs { + err := mockK8sClient.Create(context.Background(), obj) + require.NoError(t, err) + } + err := NewReconciler(mockK8sClient, mockK8sClient, dk).Reconcile(context.Background()) require.NoError(t, err) diff --git a/pkg/controllers/dynakube/otelc/statefulset/volumes.go b/pkg/controllers/dynakube/otelc/statefulset/volumes.go index 5b6a9c9957..64058081e6 100644 --- a/pkg/controllers/dynakube/otelc/statefulset/volumes.go +++ b/pkg/controllers/dynakube/otelc/statefulset/volumes.go @@ -13,6 +13,9 @@ const ( caCertsVolumeName = "cacerts" trustedCAsFile = "rootca.pem" + + customTlsCertVolumeName = "telemetry-custom-tls" + customTlsCertMountPath = "/tls/custom/telemetry" ) func setVolumes(dk *dynakube.DynaKube) func(o *appsv1.StatefulSet) { @@ -67,6 +70,27 @@ func setVolumes(dk *dynakube.DynaKube) func(o *appsv1.StatefulSet) { }, }, }) + + if dk.TelemetryService().IsEnabled() && dk.TelemetryService().Spec.TlsRefName != "" { + o.Spec.Template.Spec.Volumes = append(o.Spec.Template.Spec.Volumes, corev1.Volume{ + Name: customTlsCertVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: dk.TelemetryService().Spec.TlsRefName, + Items: []corev1.KeyToPath{ + { + Key: consts.TLSCrtDataName, + Path: consts.TLSCrtDataName, + }, + { + Key: consts.TLSKeyDataName, + Path: consts.TLSKeyDataName, + }, + }, + }, + }, + }) + } } } @@ -89,5 +113,13 @@ func buildContainerVolumeMounts(dk *dynakube.DynaKube) []corev1.VolumeMount { ReadOnly: true, }) + if dk.TelemetryService().IsEnabled() && dk.TelemetryService().Spec.TlsRefName != "" { + vm = append(vm, corev1.VolumeMount{ + Name: customTlsCertVolumeName, + MountPath: customTlsCertMountPath, + ReadOnly: true, + }) + } + return vm }