Skip to content

Commit 9323120

Browse files
committed
fix: address code review comments for telemetry operator
Signed-off-by: Bella Khizgiyaev <bkhizgiy@redhat.com> Assisted-by: claude-4.6-opus
1 parent 1ad03a5 commit 9323120

5 files changed

Lines changed: 159 additions & 127 deletions

File tree

controller/deploy/operator/internal/controller/jumpstarter/certificates.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ func (r *JumpstarterReconciler) reconcileRouterCertificate(ctx context.Context,
378378

379379
// reconcileTelemetryCertificate creates the TLS certificate for the telemetry service.
380380
func (r *JumpstarterReconciler) reconcileTelemetryCertificate(ctx context.Context, js *operatorv1alpha1.Jumpstarter, issuerRef cmmeta.ObjectReference) error {
381-
certName := GetTelemetryCertSecretName(js)
381+
certName := getTelemetryCertSecretName(js)
382382
includeInternalNames := !isExternalIssuer(js)
383383
dnsNames := r.collectTelemetryDNSNames(js, includeInternalNames)
384384
return r.reconcileServerCertificate(ctx, js, issuerRef, certName, "telemetry", dnsNames, nil)

controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,7 +1312,8 @@ func (r *JumpstarterReconciler) buildConfig(ctx context.Context, jumpstarter *op
13121312
Keys: jumpstarter.Spec.DeprecatedLabels.Keys,
13131313
}
13141314

1315-
// Telemetry configuration
1315+
// Telemetry configuration.
1316+
// Certificate is intentionally omitted until the telemetry binary supports TLS serving.
13161317
if jumpstarter.Spec.Telemetry != nil && jumpstarter.Spec.Telemetry.Enabled {
13171318
t := jumpstarter.Spec.Telemetry
13181319
telemetryCfg := &config.Telemetry{
@@ -1322,17 +1323,6 @@ func (r *JumpstarterReconciler) buildConfig(ctx context.Context, jumpstarter *op
13221323
if t.Logging.Filter.MinSeverity != "" {
13231324
telemetryCfg.Logging.Filter.MinSeverity = t.Logging.Filter.MinSeverity
13241325
}
1325-
// Resolve the CA certificate for TLS verification by exporters.
1326-
// When cert-manager is enabled in self-signed mode, read it from the CA secret.
1327-
// When an external issuer is used, use its CA bundle if provided.
1328-
if jumpstarter.Spec.CertManager.Enabled {
1329-
caCert, err := r.resolveTelemetryCA(ctx, jumpstarter)
1330-
if err != nil {
1331-
logf.FromContext(ctx).V(1).Info("Telemetry CA not yet available, will retry", "error", err)
1332-
} else if caCert != "" {
1333-
telemetryCfg.Certificate = caCert
1334-
}
1335-
}
13361326
cfg.Telemetry = telemetryCfg
13371327
}
13381328

controller/deploy/operator/internal/controller/jumpstarter/suite_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ var _ = BeforeSuite(func() {
7070

7171
By("bootstrapping test environment")
7272
testEnv = &envtest.Environment{
73-
CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")},
73+
CRDDirectoryPaths: []string{
74+
filepath.Join("..", "..", "..", "config", "crd", "bases"),
75+
},
7476
ErrorIfCRDPathMissing: true,
7577
}
7678

controller/deploy/operator/internal/controller/jumpstarter/telemetry.go

Lines changed: 66 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ import (
2020
"context"
2121
"fmt"
2222

23+
certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
2324
appsv1 "k8s.io/api/apps/v1"
2425
corev1 "k8s.io/api/core/v1"
2526
"k8s.io/apimachinery/pkg/api/errors"
27+
"k8s.io/apimachinery/pkg/api/meta"
2628
"k8s.io/apimachinery/pkg/api/resource"
2729
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2830
"k8s.io/apimachinery/pkg/util/intstr"
@@ -39,6 +41,7 @@ const (
3941
telemetryCertSuffix = "-telemetry-tls"
4042
telemetryServiceName = "jumpstarter-telemetry"
4143
telemetryComponentApp = "jumpstarter-telemetry"
44+
telemetrySASuffix = "-telemetry"
4245
)
4346

4447
// reconcileTelemetryDeploymentStage reconciles only the telemetry Deployment (and cleanup).
@@ -49,13 +52,48 @@ func (r *JumpstarterReconciler) reconcileTelemetryDeploymentStage(ctx context.Co
4952
return r.cleanupTelemetry(ctx, jumpstarter)
5053
}
5154

55+
if err := r.reconcileTelemetryServiceAccount(ctx, jumpstarter); err != nil {
56+
return fmt.Errorf("failed to reconcile telemetry service account: %w", err)
57+
}
58+
5259
if err := r.reconcileTelemetryDeployment(ctx, jumpstarter); err != nil {
5360
return fmt.Errorf("failed to reconcile telemetry deployment: %w", err)
5461
}
5562

5663
return nil
5764
}
5865

66+
// reconcileTelemetryServiceAccount creates a dedicated, no-RBAC ServiceAccount for
67+
// the telemetry pod. The telemetry binary has no need for Kubernetes API access;
68+
// giving it the controller-manager SA would grant it far more privilege than required.
69+
func (r *JumpstarterReconciler) reconcileTelemetryServiceAccount(ctx context.Context, jumpstarter *operatorv1alpha1.Jumpstarter) error {
70+
log := logf.FromContext(ctx)
71+
saName := jumpstarter.Name + telemetrySASuffix
72+
73+
desired := &corev1.ServiceAccount{
74+
ObjectMeta: metav1.ObjectMeta{
75+
Name: saName,
76+
Namespace: jumpstarter.Namespace,
77+
Labels: telemetryLabels(jumpstarter),
78+
},
79+
}
80+
81+
existing := &corev1.ServiceAccount{}
82+
existing.Name = saName
83+
existing.Namespace = jumpstarter.Namespace
84+
85+
op, err := controllerutil.CreateOrUpdate(ctx, r.Client, existing, func() error {
86+
existing.Labels = desired.Labels
87+
return controllerutil.SetControllerReference(jumpstarter, existing, r.Scheme)
88+
})
89+
if err != nil {
90+
return err
91+
}
92+
93+
log.V(1).Info("Telemetry ServiceAccount reconciled", "name", saName, "operation", op)
94+
return nil
95+
}
96+
5997
// reconcileTelemetryServiceStage reconciles only the telemetry ClusterIP Service.
6098
// It is called from the Services/networking stage of the reconcile loop.
6199
func (r *JumpstarterReconciler) reconcileTelemetryServiceStage(ctx context.Context, jumpstarter *operatorv1alpha1.Jumpstarter) error {
@@ -73,7 +111,7 @@ func (r *JumpstarterReconciler) reconcileTelemetryServiceStage(ctx context.Conte
73111
// reconcileTelemetryDeployment creates or updates the telemetry Deployment.
74112
func (r *JumpstarterReconciler) reconcileTelemetryDeployment(ctx context.Context, jumpstarter *operatorv1alpha1.Jumpstarter) error {
75113
log := logf.FromContext(ctx)
76-
desiredDeployment := r.createTelemetryDeployment(jumpstarter)
114+
desiredDeployment := createTelemetryDeployment(jumpstarter)
77115

78116
existingDeployment := &appsv1.Deployment{}
79117
existingDeployment.Name = desiredDeployment.Name
@@ -175,6 +213,7 @@ func (r *JumpstarterReconciler) reconcileTelemetryService(ctx context.Context, j
175213
}
176214

177215
existingService.Labels = desiredService.Labels
216+
existingService.Spec.Type = desiredService.Spec.Type
178217
existingService.Spec.Selector = desiredService.Spec.Selector
179218
existingService.Spec.Ports = desiredService.Spec.Ports
180219
return controllerutil.SetControllerReference(jumpstarter, existingService, r.Scheme)
@@ -192,7 +231,7 @@ func (r *JumpstarterReconciler) reconcileTelemetryService(ctx context.Context, j
192231
}
193232

194233
// createTelemetryDeployment builds the desired Deployment for the telemetry service.
195-
func (r *JumpstarterReconciler) createTelemetryDeployment(jumpstarter *operatorv1alpha1.Jumpstarter) *appsv1.Deployment {
234+
func createTelemetryDeployment(jumpstarter *operatorv1alpha1.Jumpstarter) *appsv1.Deployment {
196235
t := jumpstarter.Spec.Telemetry
197236
labels := telemetryLabels(jumpstarter)
198237

@@ -201,51 +240,6 @@ func (r *JumpstarterReconciler) createTelemetryDeployment(jumpstarter *operatorv
201240
replicas = *t.Replicas
202241
}
203242

204-
envVars := []corev1.EnvVar{
205-
{
206-
Name: "CONTROLLER_KEY",
207-
ValueFrom: &corev1.EnvVarSource{
208-
SecretKeyRef: &corev1.SecretKeySelector{
209-
LocalObjectReference: corev1.LocalObjectReference{
210-
Name: "jumpstarter-controller-secret",
211-
},
212-
Key: "key",
213-
},
214-
},
215-
},
216-
}
217-
218-
var volumeMounts []corev1.VolumeMount
219-
var volumes []corev1.Volume
220-
221-
// Add TLS certificate mount when cert-manager is enabled
222-
var tlsSecretName string
223-
if jumpstarter.Spec.CertManager.Enabled {
224-
tlsSecretName = GetTelemetryCertSecretName(jumpstarter)
225-
}
226-
227-
if tlsSecretName != "" {
228-
envVars = append(envVars,
229-
corev1.EnvVar{Name: "EXTERNAL_CERT_PEM", Value: "/tls/tls.crt"},
230-
corev1.EnvVar{Name: "EXTERNAL_KEY_PEM", Value: "/tls/tls.key"},
231-
)
232-
volumeMounts = append(volumeMounts, corev1.VolumeMount{
233-
Name: "tls-certs",
234-
MountPath: "/tls",
235-
ReadOnly: true,
236-
})
237-
defaultMode := int32(420)
238-
volumes = append(volumes, corev1.Volume{
239-
Name: "tls-certs",
240-
VolumeSource: corev1.VolumeSource{
241-
Secret: &corev1.SecretVolumeSource{
242-
SecretName: tlsSecretName,
243-
DefaultMode: &defaultMode,
244-
},
245-
},
246-
})
247-
}
248-
249243
return &appsv1.Deployment{
250244
ObjectMeta: metav1.ObjectMeta{
251245
Name: fmt.Sprintf("%s-telemetry", jumpstarter.Name),
@@ -283,8 +277,6 @@ func (r *JumpstarterReconciler) createTelemetryDeployment(jumpstarter *operatorv
283277
Args: []string{
284278
fmt.Sprintf("--grpc-bind=:%d", telemetryPort),
285279
},
286-
Env: envVars,
287-
VolumeMounts: volumeMounts,
288280
Ports: []corev1.ContainerPort{
289281
{
290282
ContainerPort: int32(telemetryPort),
@@ -327,23 +319,22 @@ func (r *JumpstarterReconciler) createTelemetryDeployment(jumpstarter *operatorv
327319
},
328320
},
329321
},
330-
Volumes: volumes,
331322
SecurityContext: &corev1.PodSecurityContext{
332323
RunAsNonRoot: boolPtr(true),
333324
SeccompProfile: &corev1.SeccompProfile{
334325
Type: corev1.SeccompProfileTypeRuntimeDefault,
335326
},
336327
},
337-
ServiceAccountName: fmt.Sprintf("%s-controller-manager", jumpstarter.Name),
328+
ServiceAccountName: jumpstarter.Name + telemetrySASuffix,
338329
},
339330
},
340331
},
341332
}
342333
}
343334

344335
// cleanupTelemetry removes telemetry resources when telemetry is disabled.
345-
// Owned resources (Deployment, Service) are deleted; the CR's garbage collection
346-
// will handle removing any cert-manager Certificate.
336+
// GC cannot remove the cert-manager Certificate while the Jumpstarter CR still
337+
// exists (GC only fires when the owner is deleted), so it is deleted explicitly.
347338
func (r *JumpstarterReconciler) cleanupTelemetry(ctx context.Context, jumpstarter *operatorv1alpha1.Jumpstarter) error {
348339
log := logf.FromContext(ctx)
349340

@@ -368,11 +359,31 @@ func (r *JumpstarterReconciler) cleanupTelemetry(ctx context.Context, jumpstarte
368359
log.Info("Deleted telemetry service", "name", telemetryServiceName)
369360
}
370361

362+
certName := getTelemetryCertSecretName(jumpstarter)
363+
cert := &certmanagerv1.Certificate{}
364+
cert.Name = certName
365+
cert.Namespace = jumpstarter.Namespace
366+
if err := r.Delete(ctx, cert); err != nil && !errors.IsNotFound(err) && !meta.IsNoMatchError(err) {
367+
return fmt.Errorf("failed to delete telemetry certificate: %w", err)
368+
} else if err == nil {
369+
log.Info("Deleted telemetry certificate", "name", certName)
370+
}
371+
372+
saName := jumpstarter.Name + telemetrySASuffix
373+
sa := &corev1.ServiceAccount{}
374+
sa.Name = saName
375+
sa.Namespace = jumpstarter.Namespace
376+
if err := r.Delete(ctx, sa); err != nil && !errors.IsNotFound(err) {
377+
return fmt.Errorf("failed to delete telemetry service account: %w", err)
378+
} else if err == nil {
379+
log.Info("Deleted telemetry service account", "name", saName)
380+
}
381+
371382
return nil
372383
}
373384

374-
// GetTelemetryCertSecretName returns the name of the telemetry TLS secret.
375-
func GetTelemetryCertSecretName(js *operatorv1alpha1.Jumpstarter) string {
385+
// getTelemetryCertSecretName returns the name of the telemetry TLS secret.
386+
func getTelemetryCertSecretName(js *operatorv1alpha1.Jumpstarter) string {
376387
return js.Name + telemetryCertSuffix
377388
}
378389

0 commit comments

Comments
 (0)