Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
4c56edb
feat: add control plane parity spec types
ThomasK33 Feb 13, 2026
6d7dff8
docs: add Helm chart parity tracking document
ThomasK33 Feb 13, 2026
604bafa
chore: add gateway api scheme support
ThomasK33 Feb 13, 2026
4be5f85
feat: reconcile service accounts and workspace RBAC
ThomasK33 Feb 13, 2026
5589950
feat: reconcile ingress and httproute exposure
ThomasK33 Feb 13, 2026
7ec62f6
chore: regenerate CRD manifests and API docs
ThomasK33 Feb 13, 2026
df0ac70
test: expand controller reconciliation coverage
ThomasK33 Feb 13, 2026
cd3acb8
chore: promote apiextensions-apiserver to direct dependency
ThomasK33 Feb 13, 2026
34d36b3
docs: avoid inline HTML in API reference
ThomasK33 Feb 13, 2026
8e8c866
docs: whitelist tolerations in cspell
ThomasK33 Feb 13, 2026
0d0fa25
fix: cleanup workspace RBAC and TLS status URL
ThomasK33 Feb 13, 2026
1c6151d
fix: avoid duplicate TLS service ports on 443
ThomasK33 Feb 13, 2026
ad2266b
fix: include custom service port in default access URL
ThomasK33 Feb 13, 2026
48f17f7
fix: requeue gateway exposure to repair httproute drift
ThomasK33 Feb 13, 2026
f9e0171
fix: requeue cross-namespace workspace RBAC drift
ThomasK33 Feb 13, 2026
fe3f93c
fix: sanitize secret-derived volume names
ThomasK33 Feb 13, 2026
d628c36
fix: prevent secret-name collisions in volume naming
ThomasK33 Feb 13, 2026
4334487
fix: harden serviceaccount and RBAC cleanup ownership
ThomasK33 Feb 13, 2026
4d8f55a
chore: apply gofumpt formatting in service account test
ThomasK33 Feb 13, 2026
8310b07
fix: use internal HTTP URL for operator SDK calls
ThomasK33 Feb 13, 2026
2e2b2b4
fix: use HTTPS SDK URL when TLS service port is 443
ThomasK33 Feb 13, 2026
70a76f9
fix: respect envFrom access URL and probe defaults
ThomasK33 Feb 13, 2026
7da89f9
fix: make probe enabled defaults explicit
ThomasK33 Feb 13, 2026
e03e128
fix: preserve explicit false for RBAC flags
ThomasK33 Feb 13, 2026
f018167
fix: allow workspace deletecollection RBAC grants
ThomasK33 Feb 13, 2026
fbd4d04
fix: detach managed serviceaccounts by owner
ThomasK33 Feb 13, 2026
123ae53
fix: require gateway parentRefs for HTTPRoute exposure
ThomasK33 Feb 13, 2026
349e676
fix: require gateway parentRefs and retry without CRDs
ThomasK33 Feb 13, 2026
e3c54c3
fix: only honor envFrom when access URL is present
ThomasK33 Feb 13, 2026
76e6e35
fix: harden envFrom access URL detection
ThomasK33 Feb 13, 2026
a7f24f3
fix: validate envFrom sources and ignore configmap binary data
ThomasK33 Feb 13, 2026
1039b16
fix: harden workspace RBAC naming and finalization
ThomasK33 Feb 13, 2026
c3b0743
fix: scope workspace RBAC resource names per control plane
ThomasK33 Feb 13, 2026
bc7bd3d
fix: route gateway HTTPRoute traffic to HTTP service port
ThomasK33 Feb 13, 2026
4269470
fix: deduplicate cert secret volumes for shared names
ThomasK33 Feb 13, 2026
d4b5038
fix: watch envFrom sources and normalize cert mount collisions
ThomasK33 Feb 13, 2026
73bada5
fix: keep in-cluster SDK URL on HTTP
ThomasK33 Feb 13, 2026
0a5f061
fix: align ingress and gateway watches with HTTPRoute
ThomasK33 Feb 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
"cnpg",
"pooler",
"finalizer",
"superfences"
"superfences",
"tolerations"
],
"ignorePaths": [
".git/**",
Expand Down
57 changes: 57 additions & 0 deletions api/v1alpha1/codercontrolplane_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,63 @@ type CoderControlPlaneSpec struct {
// control plane is ready and re-uploads when the Secret value changes.
// +optional
LicenseSecretRef *SecretKeySelector `json:"licenseSecretRef,omitempty"`

// ServiceAccount configures the ServiceAccount for the control plane pod.
// +kubebuilder:default={}
ServiceAccount ServiceAccountSpec `json:"serviceAccount,omitempty"`
// RBAC configures namespace-scoped RBAC for workspace provisioning.
// +kubebuilder:default={}
RBAC RBACSpec `json:"rbac,omitempty"`

// Resources sets resource requests/limits for the control plane container.
// +optional
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`
// SecurityContext sets the container security context.
// +optional
SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"`
// PodSecurityContext sets the pod-level security context.
// +optional
PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"`

// TLS configures Coder built-in TLS.
// +kubebuilder:default={}
TLS TLSSpec `json:"tls,omitempty"`

// ReadinessProbe configures the readiness probe for the control plane container.
// +kubebuilder:default={enabled:true}
ReadinessProbe ProbeSpec `json:"readinessProbe,omitempty"`
// LivenessProbe configures the liveness probe for the control plane container.
// +kubebuilder:default={enabled:false}
LivenessProbe ProbeSpec `json:"livenessProbe,omitempty"`

// EnvUseClusterAccessURL injects a default CODER_ACCESS_URL when not explicitly set.
// +kubebuilder:default=true
EnvUseClusterAccessURL *bool `json:"envUseClusterAccessURL,omitempty"`

// Expose configures external exposure via Ingress or Gateway API.
// +optional
Expose *ExposeSpec `json:"expose,omitempty"`

// +kubebuilder:validation:XValidation:rule="self.all(e, !(has(e.configMapRef) && has(e.secretRef)))",message="each envFrom entry may specify at most one of configMapRef or secretRef"
// EnvFrom injects environment variables from ConfigMaps/Secrets.
EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"`
// Volumes are additional volumes to add to the pod.
Volumes []corev1.Volume `json:"volumes,omitempty"`
// VolumeMounts are additional volume mounts for the control plane container.
VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"`
// Certs configures additional CA certificate mounts.
// +kubebuilder:default={}
Certs CertsSpec `json:"certs,omitempty"`

// NodeSelector constrains pod scheduling to nodes matching labels.
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
// Tolerations are applied to the control plane pod.
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
// Affinity configures pod affinity/anti-affinity rules.
// +optional
Affinity *corev1.Affinity `json:"affinity,omitempty"`
// TopologySpreadConstraints control pod topology spread.
TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"`
}

// OperatorAccessSpec configures the controller-managed coderd operator user.
Expand Down
133 changes: 132 additions & 1 deletion api/v1alpha1/types_shared.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package v1alpha1

import corev1 "k8s.io/api/core/v1"
import (
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
)

const (
// DefaultTokenSecretKey is the default key used for proxy session tokens.
Expand Down Expand Up @@ -28,3 +31,131 @@ type SecretKeySelector struct {
// Key is the key inside the Secret data map.
Key string `json:"key,omitempty"`
}

// ServiceAccountSpec configures the ServiceAccount used by the Coder pod.
type ServiceAccountSpec struct {
// DisableCreate skips ServiceAccount creation (use an existing SA).
// +kubebuilder:default=false
DisableCreate bool `json:"disableCreate,omitempty"`
// Name overrides the ServiceAccount name. Defaults to the CoderControlPlane name.
Name string `json:"name,omitempty"`
// Annotations are applied to the managed ServiceAccount.
Annotations map[string]string `json:"annotations,omitempty"`
// Labels are applied to the managed ServiceAccount.
Labels map[string]string `json:"labels,omitempty"`
}

// RBACSpec configures namespace-scoped RBAC for workspace provisioning.
type RBACSpec struct {
// WorkspacePerms enables Role/RoleBinding creation for workspace resources.
// When omitted, the default is true.
// +kubebuilder:default=true
WorkspacePerms *bool `json:"workspacePerms,omitempty"`
// EnableDeployments grants apps/deployments permissions (only when WorkspacePerms is true).
// When omitted, the default is true.
// +kubebuilder:default=true
EnableDeployments *bool `json:"enableDeployments,omitempty"`
// ExtraRules are appended to the managed Role rules.
ExtraRules []rbacv1.PolicyRule `json:"extraRules,omitempty"`
// WorkspaceNamespaces lists additional namespaces for Role/RoleBinding creation.
WorkspaceNamespaces []string `json:"workspaceNamespaces,omitempty"`
}

// TLSSpec configures Coder built-in TLS.
type TLSSpec struct {
// SecretNames lists TLS secrets to mount for built-in TLS.
// When non-empty, TLS is enabled on the Coder control plane.
SecretNames []string `json:"secretNames,omitempty"`
}

// ProbeSpec configures a Kubernetes probe with an enable toggle.
type ProbeSpec struct {
// Enabled toggles the probe on or off.
// When omitted, readiness defaults to enabled while liveness defaults to disabled.
Enabled *bool `json:"enabled,omitempty"`
// InitialDelaySeconds is the delay before the probe starts.
// +kubebuilder:default=0
InitialDelaySeconds int32 `json:"initialDelaySeconds,omitempty"`
// PeriodSeconds controls how often the probe is performed.
PeriodSeconds *int32 `json:"periodSeconds,omitempty"`
// TimeoutSeconds is the probe timeout.
TimeoutSeconds *int32 `json:"timeoutSeconds,omitempty"`
// SuccessThreshold is the minimum consecutive successes for the probe to be considered successful.
SuccessThreshold *int32 `json:"successThreshold,omitempty"`
// FailureThreshold is the minimum consecutive failures for the probe to be considered failed.
FailureThreshold *int32 `json:"failureThreshold,omitempty"`
}

// ExposeSpec configures external exposure for the control plane.
// At most one of Ingress or Gateway may be set.
// +kubebuilder:validation:XValidation:rule="!(has(self.ingress) && has(self.gateway))",message="only one of ingress or gateway may be set"
type ExposeSpec struct {
// Ingress configures a networking.k8s.io/v1 Ingress.
// +optional
Ingress *IngressExposeSpec `json:"ingress,omitempty"`
// Gateway configures a gateway.networking.k8s.io/v1 HTTPRoute.
// +optional
Gateway *GatewayExposeSpec `json:"gateway,omitempty"`
}

// IngressExposeSpec defines Ingress exposure configuration.
type IngressExposeSpec struct {
// ClassName is the Ingress class name.
ClassName *string `json:"className,omitempty"`
// Host is the primary hostname for the Ingress rule.
Host string `json:"host"`
// WildcardHost is an optional wildcard hostname (e.g., for workspace apps).
WildcardHost string `json:"wildcardHost,omitempty"`
// Annotations are applied to the managed Ingress.
Annotations map[string]string `json:"annotations,omitempty"`
// TLS configures TLS termination at the Ingress.
// +optional
TLS *IngressTLSExposeSpec `json:"tls,omitempty"`
}

// IngressTLSExposeSpec defines TLS configuration for the Ingress.
type IngressTLSExposeSpec struct {
// SecretName is the TLS Secret for the primary host.
SecretName string `json:"secretName,omitempty"`
// WildcardSecretName is the TLS Secret for the wildcard host.
WildcardSecretName string `json:"wildcardSecretName,omitempty"`
}

// GatewayExposeSpec defines Gateway API (HTTPRoute) exposure configuration.
type GatewayExposeSpec struct {
// Host is the primary hostname for the HTTPRoute.
Host string `json:"host"`
// WildcardHost is an optional wildcard hostname.
WildcardHost string `json:"wildcardHost,omitempty"`
// ParentRefs are Gateways that the HTTPRoute attaches to.
// At least one parentRef is required when gateway exposure is configured.
// +kubebuilder:validation:MinItems=1
ParentRefs []GatewayParentRef `json:"parentRefs"`
}

// GatewayParentRef identifies a Gateway for HTTPRoute attachment.
type GatewayParentRef struct {
// Name is the Gateway name.
Name string `json:"name"`
// Namespace is the Gateway namespace.
// +optional
Namespace *string `json:"namespace,omitempty"`
// SectionName is the listener name within the Gateway.
// +optional
SectionName *string `json:"sectionName,omitempty"`
}

// CertsSpec configures additional CA certificate mounts.
type CertsSpec struct {
// Secrets lists Secret key selectors for CA certificates.
// Each is mounted at `/etc/ssl/certs/{name}.crt`.
Secrets []CertSecretSelector `json:"secrets,omitempty"`
}

// CertSecretSelector identifies a key within a Secret for CA cert mounting.
type CertSecretSelector struct {
// Name is the Secret name.
Name string `json:"name"`
// Key is the key within the Secret data map.
Key string `json:"key"`
}
Loading
Loading