Skip to content

Commit d38bf70

Browse files
committed
fix: respect envFrom access URL and probe defaults
1 parent 4c07e60 commit d38bf70

2 files changed

Lines changed: 109 additions & 2 deletions

File tree

internal/controller/codercontrolplane_controller.go

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,10 @@ func buildProbe(spec coderv1alpha1.ProbeSpec, path, portName string) *corev1.Pro
731731
},
732732
},
733733
InitialDelaySeconds: spec.InitialDelaySeconds,
734+
PeriodSeconds: 10,
735+
TimeoutSeconds: 1,
736+
SuccessThreshold: 1,
737+
FailureThreshold: 3,
734738
}
735739
if spec.PeriodSeconds != nil {
736740
probe.PeriodSeconds = *spec.PeriodSeconds
@@ -755,6 +759,16 @@ func (r *CoderControlPlaneReconciler) reconcileDeployment(ctx context.Context, c
755759

756760
deployment := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: coderControlPlane.Name, Namespace: coderControlPlane.Namespace}}
757761

762+
injectClusterAccessURL := coderControlPlane.Spec.EnvUseClusterAccessURL == nil || *coderControlPlane.Spec.EnvUseClusterAccessURL
763+
accessURLConfiguredViaEnvFrom := false
764+
if injectClusterAccessURL {
765+
var err error
766+
accessURLConfiguredViaEnvFrom, err = envFromMayDefineEnvVar(coderControlPlane.Spec.EnvFrom, "CODER_ACCESS_URL")
767+
if err != nil {
768+
return nil, err
769+
}
770+
}
771+
758772
_, err := controllerutil.CreateOrUpdate(ctx, r.Client, deployment, func() error {
759773
labels := controlPlaneLabels(coderControlPlane.Name)
760774
deployment.Labels = maps.Clone(labels)
@@ -795,12 +809,12 @@ func (r *CoderControlPlaneReconciler) reconcileDeployment(ctx context.Context, c
795809
}
796810

797811
tlsEnabled := controlPlaneTLSEnabled(coderControlPlane)
798-
if coderControlPlane.Spec.EnvUseClusterAccessURL == nil || *coderControlPlane.Spec.EnvUseClusterAccessURL {
812+
if injectClusterAccessURL {
799813
configuredAccessURL, err := findEnvVar(coderControlPlane.Spec.ExtraEnv, "CODER_ACCESS_URL")
800814
if err != nil {
801815
return err
802816
}
803-
if configuredAccessURL == nil {
817+
if configuredAccessURL == nil && !accessURLConfiguredViaEnvFrom {
804818
scheme := "http"
805819
accessURLPort := coderControlPlane.Spec.Service.Port
806820
if accessURLPort == 0 {
@@ -2039,6 +2053,40 @@ func (r *CoderControlPlaneReconciler) resolvePostgresURLFromExtraEnv(
20392053
return r.readSecretValue(ctx, coderControlPlane.Namespace, secretRef.Name, secretRef.Key)
20402054
}
20412055

2056+
func envFromMayDefineEnvVar(envFromSources []corev1.EnvFromSource, envVarName string) (bool, error) {
2057+
if strings.TrimSpace(envVarName) == "" {
2058+
return false, fmt.Errorf("assertion failed: environment variable name must not be empty")
2059+
}
2060+
2061+
for i := range envFromSources {
2062+
envFromSource := envFromSources[i]
2063+
if envFromSource.ConfigMapRef != nil && envFromSource.SecretRef != nil {
2064+
return false, fmt.Errorf("assertion failed: envFrom[%d] must not set both configMapRef and secretRef", i)
2065+
}
2066+
2067+
prefix := strings.TrimSpace(envFromSource.Prefix)
2068+
if prefix != "" && !strings.HasPrefix(envVarName, prefix) {
2069+
continue
2070+
}
2071+
2072+
if envFromSource.ConfigMapRef != nil {
2073+
if strings.TrimSpace(envFromSource.ConfigMapRef.Name) == "" {
2074+
return false, fmt.Errorf("assertion failed: envFrom[%d].configMapRef.name must not be empty", i)
2075+
}
2076+
return true, nil
2077+
}
2078+
2079+
if envFromSource.SecretRef != nil {
2080+
if strings.TrimSpace(envFromSource.SecretRef.Name) == "" {
2081+
return false, fmt.Errorf("assertion failed: envFrom[%d].secretRef.name must not be empty", i)
2082+
}
2083+
return true, nil
2084+
}
2085+
}
2086+
2087+
return false, nil
2088+
}
2089+
20422090
func findEnvVar(envVars []corev1.EnvVar, name string) (*corev1.EnvVar, error) {
20432091
if strings.TrimSpace(name) == "" {
20442092
return nil, fmt.Errorf("assertion failed: environment variable name must not be empty")

internal/controller/codercontrolplane_controller_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2823,6 +2823,53 @@ func TestReconcile_DeploymentAlignment(t *testing.T) {
28232823
}
28242824
})
28252825

2826+
t.Run("EnvFromAccessURLTakesPrecedence", func(t *testing.T) {
2827+
configMap := &corev1.ConfigMap{
2828+
ObjectMeta: metav1.ObjectMeta{Name: "test-deployment-alignment-envfrom-access-url", Namespace: "default"},
2829+
Data: map[string]string{
2830+
"CODER_ACCESS_URL": "https://envfrom.example.test",
2831+
},
2832+
}
2833+
if err := k8sClient.Create(ctx, configMap); err != nil {
2834+
t.Fatalf("create configmap: %v", err)
2835+
}
2836+
t.Cleanup(func() {
2837+
_ = k8sClient.Delete(ctx, configMap)
2838+
})
2839+
2840+
cp := &coderv1alpha1.CoderControlPlane{
2841+
ObjectMeta: metav1.ObjectMeta{Name: "test-deployment-alignment-envfrom-access-url", Namespace: "default"},
2842+
Spec: coderv1alpha1.CoderControlPlaneSpec{
2843+
Image: "test-deployment-alignment:latest",
2844+
EnvFrom: []corev1.EnvFromSource{{
2845+
ConfigMapRef: &corev1.ConfigMapEnvSource{
2846+
LocalObjectReference: corev1.LocalObjectReference{Name: configMap.Name},
2847+
},
2848+
}},
2849+
},
2850+
}
2851+
if err := k8sClient.Create(ctx, cp); err != nil {
2852+
t.Fatalf("create control plane: %v", err)
2853+
}
2854+
t.Cleanup(func() {
2855+
_ = k8sClient.Delete(ctx, cp)
2856+
})
2857+
2858+
r := &controller.CoderControlPlaneReconciler{Client: k8sClient, Scheme: scheme}
2859+
if _, err := r.Reconcile(ctx, ctrl.Request{NamespacedName: types.NamespacedName{Name: cp.Name, Namespace: cp.Namespace}}); err != nil {
2860+
t.Fatalf("reconcile control plane: %v", err)
2861+
}
2862+
2863+
deployment := &appsv1.Deployment{}
2864+
if err := k8sClient.Get(ctx, types.NamespacedName{Name: cp.Name, Namespace: cp.Namespace}, deployment); err != nil {
2865+
t.Fatalf("get deployment: %v", err)
2866+
}
2867+
container := deployment.Spec.Template.Spec.Containers[0]
2868+
if countEnvVar(container.Env, "CODER_ACCESS_URL") != 0 {
2869+
t.Fatalf("expected operator to skip default CODER_ACCESS_URL when envFrom is configured, got %v", container.Env)
2870+
}
2871+
})
2872+
28262873
t.Run("ResourcesAndSecurityContextsApplied", func(t *testing.T) {
28272874
runAsUser := int64(1001)
28282875
allowPrivilegeEscalation := false
@@ -2921,6 +2968,18 @@ func TestReconcile_ProbeConfiguration(t *testing.T) {
29212968
if container.ReadinessProbe.HTTPGet.Port != intstr.FromString("http") {
29222969
t.Fatalf("expected readiness probe port name %q, got %#v", "http", container.ReadinessProbe.HTTPGet.Port)
29232970
}
2971+
if container.ReadinessProbe.PeriodSeconds != 10 {
2972+
t.Fatalf("expected readiness probe default periodSeconds=10, got %d", container.ReadinessProbe.PeriodSeconds)
2973+
}
2974+
if container.ReadinessProbe.TimeoutSeconds != 1 {
2975+
t.Fatalf("expected readiness probe default timeoutSeconds=1, got %d", container.ReadinessProbe.TimeoutSeconds)
2976+
}
2977+
if container.ReadinessProbe.SuccessThreshold != 1 {
2978+
t.Fatalf("expected readiness probe default successThreshold=1, got %d", container.ReadinessProbe.SuccessThreshold)
2979+
}
2980+
if container.ReadinessProbe.FailureThreshold != 3 {
2981+
t.Fatalf("expected readiness probe default failureThreshold=3, got %d", container.ReadinessProbe.FailureThreshold)
2982+
}
29242983
})
29252984

29262985
t.Run("LivenessProbeDisabled", func(t *testing.T) {

0 commit comments

Comments
 (0)