Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@
"codertemplate",
"codertemplates",
"aibridge",
"aigateway",
"stakater",
"coderaigatewaykey",
"coderaigatewaykeys",
"coderaiprovider",
"coderaiproviders",
"codertemplatetest",
Expand Down
19 changes: 3 additions & 16 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ jobs:
- 'api/v1alpha1/**'
- 'internal/controller/codertemplatetest*'
- 'internal/controller/coderaiprovider*'
- 'internal/controller/coderaigatewaykey*'
- 'internal/controller/owned_secret.go'
- 'internal/controller/reserved_secret_names.go'
# Shared Coder access that CoderTemplateTest and later pool controllers call.
- 'internal/controller/controlplane_access.go'
- 'internal/controller/coder_access.go'
Expand Down Expand Up @@ -156,22 +159,6 @@ jobs:
exit 1
fi

- name: Verify the dormant CoderAIGatewayKey CRD is not installed
# Remove this step when the CoderAIGatewayKey controller ships (#156).
run: |
# grep exits 1 when nothing matches. Any other status (for example a missing file) fails the step.
status=0
# The third pattern matches the CRD path entry in config/default/kustomization.yaml.
grep -n -E '^[[:space:]]+kind: CoderAIGatewayKey$|coderaigatewaykeys\.coder\.com|coder\.com_coderaigatewaykeys\.yaml' \
dist/install.yaml config/default/kustomization.yaml config/crd/bases/*.yaml || status=$?
if [[ "${status}" -eq 0 ]]; then
echo "assertion failed: the CoderAIGatewayKey CRD must not ship before its controller" >&2
exit 1
elif [[ "${status}" -ne 1 ]]; then
echo "assertion failed: the CoderAIGatewayKey CRD guard could not read the install manifests (grep exit ${status})" >&2
exit 1
fi

- name: Verify the dormant CoderMCPServer CRD is not installed
# Remove this step when the CoderMCPServer controller ships (#155).
run: |
Expand Down
11 changes: 6 additions & 5 deletions api/v1alpha1/coderaigatewaykey_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ type AIGatewaySpec struct {
// controller creates no key. Setting it back to false stops new keys and
// rotations. The current key of each CoderAIGatewayKey stays until that
// object is deleted.
//
// This field has no effect yet: the CoderAIGatewayKey controller is not
// shipped.
// +optional
AllowKeys bool `json:"allowKeys,omitempty"`
}
Expand Down Expand Up @@ -237,8 +234,12 @@ type CoderAIGatewayKeyStatus struct {
// CoderAIGatewayKey manages a Coder AI Gateway key for standalone AI Gateway
// replicas and stores it in a Secret that this object owns. A gateway key
// lets its holder load the API key of every enabled AI provider, so write
// access to this kind is admin-only. Deleting the object revokes every key
// that it created at once, and gateways that use them stop within a minute.
// access to this kind is admin-only. Deleting the object deletes every key
// that it created in Coder: after the 5-minute settle window of its last key
// create, and only while the control plane can reach Coder. A failed
// deletion keeps the object and retries. When the control plane is gone, the
// object goes and its keys stay valid in Coder. A gateway stops within a
// minute after its key is deleted.
type CoderAIGatewayKey struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Expand Down
3 changes: 1 addition & 2 deletions api/v1alpha1/codercontrolplane_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,7 @@ type CoderControlPlaneSpec struct {
MCPServers *MCPServersSpec `json:"mcpServers,omitempty"`

// AIGateway configures CoderAIGatewayKey objects that use this control
// plane. It has no effect yet: the CoderAIGatewayKey controller is not
// shipped.
// plane.
// +optional
AIGateway *AIGatewaySpec `json:"aiGateway,omitempty"`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@ spec:
CoderAIGatewayKey manages a Coder AI Gateway key for standalone AI Gateway
replicas and stores it in a Secret that this object owns. A gateway key
lets its holder load the API key of every enabled AI provider, so write
access to this kind is admin-only. Deleting the object revokes every key
that it created at once, and gateways that use them stop within a minute.
access to this kind is admin-only. Deleting the object deletes every key
that it created in Coder: after the 5-minute settle window of its last key
create, and only while the control plane can reach Coder. A failed
deletion keeps the object and retries. When the control plane is gone, the
object goes and its keys stay valid in Coder. A gateway stops within a
minute after its key is deleted.
properties:
apiVersion:
description: |-
Expand Down
6 changes: 1 addition & 5 deletions config/crd/bases/coder.com_codercontrolplanes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -954,8 +954,7 @@ spec:
aiGateway:
description: |-
AIGateway configures CoderAIGatewayKey objects that use this control
plane. It has no effect yet: the CoderAIGatewayKey controller is not
shipped.
plane.
properties:
allowKeys:
description: |-
Expand All @@ -967,9 +966,6 @@ spec:
controller creates no key. Setting it back to false stops new keys and
rotations. The current key of each CoderAIGatewayKey stays until that
object is deleted.

This field has no effect yet: the CoderAIGatewayKey controller is not
shipped.
type: boolean
type: object
certs:
Expand Down
1 change: 1 addition & 0 deletions config/default/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace-coder-system.yaml
- ../crd/bases/coder.com_coderaigatewaykeys.yaml
- ../crd/bases/coder.com_coderaiproviders.yaml
- ../crd/bases/coder.com_codercontrolplanes.yaml
- ../crd/bases/coder.com_coderprovisioners.yaml
Expand Down
14 changes: 8 additions & 6 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,6 @@ rules:
- coder.com
resources:
- coderaigatewaykeys
- codermcpservers
verbs:
- list
- apiGroups:
- coder.com
resources:
- coderaiproviders
verbs:
- get
Expand All @@ -100,6 +94,7 @@ rules:
- apiGroups:
- coder.com
resources:
- coderaigatewaykeys/finalizers
- coderaiproviders/finalizers
- codercontrolplanes/finalizers
- coderprovisioners/finalizers
Expand All @@ -110,6 +105,7 @@ rules:
- apiGroups:
- coder.com
resources:
- coderaigatewaykeys/status
- coderaiproviders/status
verbs:
- get
Expand Down Expand Up @@ -139,6 +135,12 @@ rules:
- get
- patch
- update
- apiGroups:
- coder.com
resources:
- codermcpservers
verbs:
- list
- apiGroups:
- coder.com
resources:
Expand Down
24 changes: 24 additions & 0 deletions config/samples/coder_v1alpha1_coderaigatewaykey.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Keeps one Coder AI Gateway key in an owned Secret and rotates it. See
# docs/how-to/manage-ai-gateway-keys.md.
#
# Prerequisites:
# - A Coder Premium license with the AI Gateway enabled.
# - CoderControlPlane codercontrolplane-sample with status.operatorAccessReady
# true and spec.aiGateway.allowKeys true.
# - No Secret named coder-ai-gateway-key in the namespace: the operator
# creates it.
apiVersion: coder.com/v1alpha1
kind: CoderAIGatewayKey
metadata:
name: gateway
namespace: coder
spec:
# Immutable.
controlPlaneRef:
name: codercontrolplane-sample
# Immutable. The key goes into data key "key".
secretName: coder-ai-gateway-key
rotation:
intervalSeconds: 2592000
gracePeriodSeconds: 3600
consumerWaitSeconds: 86400
Loading
Loading