Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f2d5d296e2 | |||
| afc44ebbf8 | |||
| 1ef1c0e456 | |||
| f182211601 | |||
| 5d46d3ada0 | |||
| e98dd8b0a2 | |||
| 90a9aad15d | |||
| 4f4b4286dc | |||
| 1cc2ec2e92 | |||
| b3cc9b0975 | |||
| a6f19e23c6 | |||
| ec41528f1e | |||
| 23f16bc7a8 | |||
| 229d8e5389 | |||
| 69983fa321 | |||
| 9c2bc1223f | |||
| a31c259909 | |||
| 2230aae540 | |||
| 037d4d8994 | |||
| 55ee4b27be | |||
| 3e903a2d76 | |||
| 884f5730a3 | |||
| 5129786b77 | |||
| 297bc50184 | |||
| cf673e379d | |||
| 4863dcd8a8 | |||
| b73f3b45ea | |||
| 8bc8dae266 | |||
| fed4229c9e |
@@ -1,6 +1,6 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
name: pieced-operator
|
name: pieced-operator
|
||||||
description: PieCed IT tenant lifecycle operator
|
description: PieCed IT tenant lifecycle operator
|
||||||
version: 0.1.14
|
version: 0.1.43
|
||||||
appVersion: "0.1.14"
|
appVersion: "0.1.43"
|
||||||
type: application
|
type: application
|
||||||
|
|||||||
@@ -87,6 +87,18 @@ spec:
|
|||||||
suspend:
|
suspend:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: Stops reconciliation without deleting resources.
|
description: Stops reconciliation without deleting resources.
|
||||||
|
openClawImage:
|
||||||
|
type: object
|
||||||
|
description: >
|
||||||
|
Per-tenant override for the OpenClaw container image
|
||||||
|
tag. When unset, the operator uses the platform
|
||||||
|
default from the pieced-openclaw-config ConfigMap.
|
||||||
|
Set by platform admins via the portal; customer-
|
||||||
|
facing onboarding does not expose this field.
|
||||||
|
properties:
|
||||||
|
tag:
|
||||||
|
type: string
|
||||||
|
description: Image tag (e.g. "2026.4.22").
|
||||||
status:
|
status:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@@ -123,6 +135,25 @@ spec:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
|
suspendedAt:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
warnings:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- source
|
||||||
|
properties:
|
||||||
|
source:
|
||||||
|
type: string
|
||||||
|
reason:
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
since:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
observedGeneration:
|
observedGeneration:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{{/*
|
||||||
|
Platform-wide default OpenClaw image tag. Used by the operator when a
|
||||||
|
PiecedTenant has no explicit `spec.openClawImage.tag` override.
|
||||||
|
|
||||||
|
Tag-only by design — see internal/openclawconfig/loader.go for
|
||||||
|
rationale (single image-selector field avoids SSA field-ownership
|
||||||
|
ambiguity). For reproducibility-critical deployments, pin by using
|
||||||
|
an immutable release tag.
|
||||||
|
|
||||||
|
If `defaultTag` is empty (or this ConfigMap doesn't exist), the
|
||||||
|
operator falls back to a hardcoded built-in version.
|
||||||
|
|
||||||
|
Tenants without an `openClawImage` override automatically follow
|
||||||
|
changes to this ConfigMap on the next reconcile — the operator
|
||||||
|
watches it and re-enqueues affected tenants.
|
||||||
|
*/}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: pieced-openclaw-config
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: pieced-operator
|
||||||
|
data:
|
||||||
|
defaultTag: {{ .Values.openClaw.defaultTag | quote }}
|
||||||
@@ -8,9 +8,17 @@ metadata:
|
|||||||
app.kubernetes.io/name: pieced-operator
|
app.kubernetes.io/name: pieced-operator
|
||||||
rules:
|
rules:
|
||||||
# --- PiecedTenant CRD ---
|
# --- PiecedTenant CRD ---
|
||||||
|
# `delete` is required so the operator can self-initiate the post-
|
||||||
|
# 60-day cleanup of suspended tenants (Bug 37b). Without it, the
|
||||||
|
# `r.Delete(ctx, tenant)` call in the suspend block fails with a
|
||||||
|
# 403 every reconcile cycle while the tenant sits past its
|
||||||
|
# retention window. Until then this verb wasn't strictly needed —
|
||||||
|
# the customer/portal initiated CR deletes, and the operator's
|
||||||
|
# finalizer ran cleanup; only with operator-initiated deletion did
|
||||||
|
# the missing verb become a problem.
|
||||||
- apiGroups: ["pieced.ch"]
|
- apiGroups: ["pieced.ch"]
|
||||||
resources: ["piecedtenants"]
|
resources: ["piecedtenants"]
|
||||||
verbs: ["get", "list", "watch", "update", "patch"]
|
verbs: ["get", "list", "watch", "update", "patch", "delete"]
|
||||||
- apiGroups: ["pieced.ch"]
|
- apiGroups: ["pieced.ch"]
|
||||||
resources: ["piecedtenants/status"]
|
resources: ["piecedtenants/status"]
|
||||||
verbs: ["get", "update", "patch"]
|
verbs: ["get", "update", "patch"]
|
||||||
@@ -34,29 +42,34 @@ rules:
|
|||||||
verbs: ["create", "patch"]
|
verbs: ["create", "patch"]
|
||||||
|
|
||||||
# --- Capsule Tenant ---
|
# --- Capsule Tenant ---
|
||||||
|
# `patch` is required for server-side apply (SSA) — controller-runtime's
|
||||||
|
# `client.Apply` uses HTTP PATCH with content-type application/apply-patch+yaml.
|
||||||
|
# We keep `update` for backwards-compat in case any code path still does
|
||||||
|
# replace-style writes (currently none). Same applies to all unstructured
|
||||||
|
# resources below.
|
||||||
- apiGroups: ["capsule.clastix.io"]
|
- apiGroups: ["capsule.clastix.io"]
|
||||||
resources: ["tenants"]
|
resources: ["tenants"]
|
||||||
verbs: ["get", "list", "watch", "create", "update", "delete"]
|
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||||
|
|
||||||
# --- ESO SecretStore ---
|
# --- ESO SecretStore ---
|
||||||
- apiGroups: ["external-secrets.io"]
|
- apiGroups: ["external-secrets.io"]
|
||||||
resources: ["secretstores"]
|
resources: ["secretstores"]
|
||||||
verbs: ["get", "list", "watch", "create", "update", "delete"]
|
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||||
|
|
||||||
# --- ESO ExternalSecret ---
|
# --- ESO ExternalSecret ---
|
||||||
- apiGroups: ["external-secrets.io"]
|
- apiGroups: ["external-secrets.io"]
|
||||||
resources: ["externalsecrets"]
|
resources: ["externalsecrets"]
|
||||||
verbs: ["get", "list", "watch", "create", "update", "delete"]
|
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||||
|
|
||||||
# --- Cilium CiliumNetworkPolicy ---
|
# --- Cilium CiliumNetworkPolicy ---
|
||||||
- apiGroups: ["cilium.io"]
|
- apiGroups: ["cilium.io"]
|
||||||
resources: ["ciliumnetworkpolicies"]
|
resources: ["ciliumnetworkpolicies"]
|
||||||
verbs: ["get", "list", "watch", "create", "update", "delete"]
|
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||||
|
|
||||||
# --- OpenClaw OpenClawInstance ---
|
# --- OpenClaw OpenClawInstance ---
|
||||||
- apiGroups: ["openclaw.rocks"]
|
- apiGroups: ["openclaw.rocks"]
|
||||||
resources: ["openclawinstances"]
|
resources: ["openclawinstances"]
|
||||||
verbs: ["get", "list", "watch", "create", "update", "delete"]
|
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||||
|
|
||||||
# --- Leader election (coordination) ---
|
# --- Leader election (coordination) ---
|
||||||
- apiGroups: ["coordination.k8s.io"]
|
- apiGroups: ["coordination.k8s.io"]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
image:
|
image:
|
||||||
repository: registry.c5ai.ch/pieced/pieced-operator
|
repository: registry.c5ai.ch/pieced/pieced-operator
|
||||||
tag: "0.1.14"
|
tag: "0.1.43"
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
imagePullSecrets:
|
imagePullSecrets:
|
||||||
@@ -56,3 +56,23 @@ serviceAccount:
|
|||||||
# Network policy — restrict operator egress to only what it needs
|
# Network policy — restrict operator egress to only what it needs
|
||||||
networkPolicy:
|
networkPolicy:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
|
# OpenClaw image default (Feature: per-tenant version overrides).
|
||||||
|
#
|
||||||
|
# Materialised as the `pieced-openclaw-config` ConfigMap, which the
|
||||||
|
# operator reads on every reconcile. Per-tenant overrides set via the
|
||||||
|
# portal (PiecedTenant.spec.openClawImage.tag) take precedence over
|
||||||
|
# this default for the affected tenants.
|
||||||
|
#
|
||||||
|
# We support tag-only (not digest) by design — a single image-selector
|
||||||
|
# field avoids SSA field-ownership ambiguity when switching values,
|
||||||
|
# and the downstream OpenClaw operator handles a tag-only image spec
|
||||||
|
# unambiguously. For reproducibility-critical deployments, pin by
|
||||||
|
# using an immutable release tag.
|
||||||
|
#
|
||||||
|
# Empty defaultTag falls back to the operator's built-in version.
|
||||||
|
# Admins can edit this value at runtime via the portal admin UI;
|
||||||
|
# the resulting ConfigMap edits trigger reconciles for every tenant
|
||||||
|
# that doesn't have its own override.
|
||||||
|
openClaw:
|
||||||
|
defaultTag: "2026.4.22"
|
||||||
|
|||||||
Reference in New Issue
Block a user