Skip to content

Comments

Add secretRef and configMapRef support on ServiceContext#3232

Merged
michaeljguarino merged 4 commits intomasterfrom
service-context-configmap-secret-ref
Feb 19, 2026
Merged

Add secretRef and configMapRef support on ServiceContext#3232
michaeljguarino merged 4 commits intomasterfrom
service-context-configmap-secret-ref

Conversation

@michaeljguarino
Copy link
Member

This should give us the ability to take config maps and secrets and publish them to service context. Useful for combining with things like ASO, and crossplane.

Test Plan

unit test

Checklist

  • If required, I have updated the Plural documentation accordingly.
  • I have added tests to cover my changes.
  • I have added a meaningful title and summary to convey the impact of this PR to a user.

Plural Flow: console

@michaeljguarino michaeljguarino requested a review from a team February 18, 2026 16:40
@michaeljguarino michaeljguarino added the enhancement New feature or request label Feb 18, 2026
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 18, 2026

Greptile Summary

Adds configMapRef and secretRef fields to the ServiceContext CRD, allowing users to merge data from Kubernetes ConfigMaps and Secrets into the service context configuration JSON. This is useful for integrating outputs from infrastructure-as-code tools like ASO and Crossplane into service contexts.

  • Extends ServiceContextSpec with optional ConfigMapRef (ObjectReference) and SecretRef (SecretReference) fields
  • Controller sync method now fetches and merges ConfigMap/Secret data into the configuration JSON before saving to the Console API
  • Adds watch handlers (OnSecretChange, OnConfigMapChange) so that changes to referenced Secrets/ConfigMaps trigger ServiceContext reconciliation via owner-ref annotations
  • Includes a comprehensive unit test validating merged configuration output and owner annotation propagation
  • Issue: Inconsistent namespace fallback — ConfigMapRef falls back to the ServiceContext's namespace when omitted, but SecretRef falls back to "default" (via utils.GetSecret)

Confidence Score: 3/5

  • Generally safe but has an inconsistent namespace fallback between ConfigMap and Secret references that could cause unexpected behavior in non-default namespaces.
  • The core feature logic is sound and well-tested, but the inconsistent namespace resolution between ConfigMapRef (falls back to ServiceContext namespace) and SecretRef (falls back to "default" namespace) is a behavioral bug that could cause secrets to be fetched from the wrong namespace in production.
  • Pay close attention to go/controller/internal/controller/servicecontext_controller.go — the SecretRef namespace fallback is inconsistent with ConfigMapRef.

Important Files Changed

Filename Overview
go/controller/api/v1alpha1/servicecontext_types.go Adds ConfigMapRef (ObjectReference) and SecretRef (SecretReference) fields to ServiceContextSpec. Clean type additions with proper kubebuilder tags.
go/controller/internal/controller/servicecontext_controller.go Core logic for merging ConfigMap/Secret data into service context configuration. Has inconsistent namespace fallback between ConfigMap (uses SC namespace) and Secret (uses "default" via utils.GetSecret). New OnConfigMapChange handler added.
go/controller/internal/controller/servicecontext_controller_test.go Good test covering merged configuration from ConfigMap, Secret, and existing Configuration. Verifies owner annotations are set correctly.
go/controller/config/crd/bases/deployments.plural.sh_servicecontexts.yaml CRD schema updated with configMapRef and secretRef properties. Generated from types.
go/controller/docs/api.md API documentation updated with new configMapRef and secretRef fields.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[ServiceContext Reconcile] --> B{handleExisting & DriftDetect?}
    B -->|Skip sync| C[Mark ReadOnly & Requeue]
    B -->|Proceed| D[sync]
    D --> E[Parse spec.configuration JSON]
    E --> F{configMapRef set?}
    F -->|Yes| G[Fetch ConfigMap]
    G --> H[AddOwnerRefAnnotation to ConfigMap]
    H --> I[Merge ConfigMap data into config]
    F -->|No| J{secretRef set?}
    I --> J
    J -->|Yes| K[Fetch Secret]
    K --> L[AddOwnerRefAnnotation to Secret]
    L --> M[Merge Secret data into config]
    J -->|No| N[Marshal merged JSON]
    M --> N
    N --> O[SaveServiceContext to Console API]

    P[Secret Changes] --> Q[OnSecretChange Watch]
    Q --> R[GetOwnerRefsAnnotationRequests]
    R --> A

    S[ConfigMap Changes] --> T[OnConfigMapChange Watch]
    T --> R
Loading

Last reviewed commit: 312612f

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

11 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines 147 to 150
if sc.Spec.SecretRef != nil {
secret, err := utils.GetSecret(ctx, r.Client, sc.Spec.SecretRef)
if err != nil {
return nil, fmt.Errorf("failed to get secret %s/%s: %w", sc.Spec.SecretRef.Namespace, sc.Spec.SecretRef.Name, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent namespace fallback for SecretRef

When SecretRef.Namespace is empty, utils.GetSecret falls back to "default" (see go/controller/internal/utils/kubernetes.go:193), whereas the ConfigMapRef handling above (line 128-129) falls back to sc.GetNamespace() (the ServiceContext's own namespace). This inconsistency means that if a user omits the namespace on both refs, the ConfigMap is looked up in the ServiceContext's namespace but the Secret is looked up in "default".

The ConfigMap behavior (falling back to the owner's namespace) is the more intuitive and correct approach. Consider either adding a namespace fallback before calling GetSecret, or updating GetSecret to accept the fallback namespace:

Suggested change
if sc.Spec.SecretRef != nil {
secret, err := utils.GetSecret(ctx, r.Client, sc.Spec.SecretRef)
if err != nil {
return nil, fmt.Errorf("failed to get secret %s/%s: %w", sc.Spec.SecretRef.Namespace, sc.Spec.SecretRef.Name, err)
if sc.Spec.SecretRef != nil {
ref := sc.Spec.SecretRef
if ref.Namespace == "" {
ref = &corev1.SecretReference{Name: ref.Name, Namespace: sc.GetNamespace()}
}
secret, err := utils.GetSecret(ctx, r.Client, ref)

@michaeljguarino michaeljguarino force-pushed the service-context-configmap-secret-ref branch from 312612f to f4ba9d7 Compare February 18, 2026 16:47
This should give us the ability to take config maps and secrets and publish them to service context.  Useful for combining with things like ASO, and crossplane.
@michaeljguarino michaeljguarino force-pushed the service-context-configmap-secret-ref branch from f4ba9d7 to 8e64174 Compare February 18, 2026 16:52
@michaeljguarino michaeljguarino force-pushed the service-context-configmap-secret-ref branch from c4b98d4 to 64a9a50 Compare February 19, 2026 13:11
@michaeljguarino michaeljguarino force-pushed the service-context-configmap-secret-ref branch from 38745c1 to 914e78e Compare February 19, 2026 15:36
@michaeljguarino michaeljguarino force-pushed the service-context-configmap-secret-ref branch from 95447e4 to 8f6fffd Compare February 19, 2026 17:19
@michaeljguarino michaeljguarino merged commit c63ea80 into master Feb 19, 2026
29 of 31 checks passed
@michaeljguarino michaeljguarino deleted the service-context-configmap-secret-ref branch February 19, 2026 17:46
@greptile-apps greptile-apps bot mentioned this pull request Feb 19, 2026
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants