From fa1e933636fbda1fa7e34b53b299e14add2a72a9 Mon Sep 17 00:00:00 2001 From: jenkins Date: Sun, 28 Jun 2026 17:33:33 -0300 Subject: [PATCH] Deploy Veles 0.4.5 public feedback --- .../oneoffs/veles-realm-ensure-job.yaml | 69 ++++++++++++++- services/veles/backend-deployment.yaml | 6 +- services/veles/configmap.yaml | 2 +- services/veles/feedback-mirror-cronjob.yaml | 84 +++++++++++++++++++ services/veles/frontend-deployment.yaml | 2 +- services/veles/kustomization.yaml | 1 + services/veles/retention-cronjob.yaml | 2 +- services/veles/serviceaccounts.yaml | 9 ++ 8 files changed, 166 insertions(+), 9 deletions(-) create mode 100644 services/veles/feedback-mirror-cronjob.yaml diff --git a/services/keycloak/oneoffs/veles-realm-ensure-job.yaml b/services/keycloak/oneoffs/veles-realm-ensure-job.yaml index 2b27db42c..c48b46c74 100644 --- a/services/keycloak/oneoffs/veles-realm-ensure-job.yaml +++ b/services/keycloak/oneoffs/veles-realm-ensure-job.yaml @@ -67,6 +67,8 @@ spec: value: no-reply-veles@bstein.dev - name: KEYCLOAK_SMTP_FROM_NAME value: Veles + - name: VELES_PUBLIC_REPLAY_USERS + value: veles-dev,daniel-test,viktor-test command: ["/bin/sh", "-c"] args: - | @@ -186,7 +188,7 @@ spec: if status not in (200, 204): raise SystemExit(f"Realm update failed: status={status} body={body}") - def ensure_group(name): + def find_group(name): status, groups = request( "GET", f"{base_url}/admin/realms/{realm}/groups?search={urllib.parse.quote(name)}", @@ -194,14 +196,75 @@ spec: ) if status != 200: raise SystemExit(f"Group search failed for {name}: status={status}") - if any(group.get("name") == name for group in groups or []): - return + for group in groups or []: + if group.get("name") == name: + return group + return None + + def ensure_group(name): + group = find_group(name) + if group: + return group status, body = request("POST", f"{base_url}/admin/realms/{realm}/groups", token, {"name": name}) if status not in (201, 204, 409): raise SystemExit(f"Group create failed for {name}: status={status} body={body}") + group = find_group(name) + if not group: + raise SystemExit(f"Group missing after create for {name}") + return group + + def find_user(username): + encoded = urllib.parse.quote(username) + for query in (f"username={encoded}&exact=true", f"email={encoded}&exact=true", f"search={encoded}"): + status, users = request( + "GET", + f"{base_url}/admin/realms/{realm}/users?{query}", + token, + ) + if status != 200: + raise SystemExit(f"User search failed for {username}: status={status}") + for user in users or []: + candidates = { + str(user.get("username") or "").casefold(), + str(user.get("email") or "").casefold(), + } + if username.casefold() in candidates: + return user + return None + + def ensure_user_group(username, group): + user = find_user(username) + if not user: + print(f"WARNING: Veles public replay user {username!r} not found; skipping membership") + return + user_id = user.get("id") + group_id = group.get("id") + if not user_id or not group_id: + raise SystemExit(f"Missing id for user/group membership: user={username}") + status, memberships = request( + "GET", + f"{base_url}/admin/realms/{realm}/users/{user_id}/groups", + token, + ) + if status != 200: + raise SystemExit(f"User group lookup failed for {username}: status={status}") + if any(item.get("id") == group_id for item in memberships or []): + return + status, body = request( + "PUT", + f"{base_url}/admin/realms/{realm}/users/{user_id}/groups/{group_id}", + token, + ) + if status not in (200, 204): + raise SystemExit(f"User group update failed for {username}: status={status} body={body}") ensure_group("alpha") ensure_group("admin") + public_replay_group = ensure_group("public-replay") + for username in os.environ.get("VELES_PUBLIC_REPLAY_USERS", "").split(","): + username = username.strip() + if username: + ensure_user_group(username, public_replay_group) status, clients = request( "GET", diff --git a/services/veles/backend-deployment.yaml b/services/veles/backend-deployment.yaml index eb29b1ab2..a3a356587 100644 --- a/services/veles/backend-deployment.yaml +++ b/services/veles/backend-deployment.yaml @@ -17,7 +17,7 @@ spec: labels: app: veles-backend annotations: - veles.bstein.dev/redeploy: "2026-06-28-0.4.4-commander-bugfixes" + veles.bstein.dev/redeploy: "2026-06-28-0.4.5-public-feedback-replay" vault.hashicorp.com/agent-inject: "true" vault.hashicorp.com/agent-init-first: "true" vault.hashicorp.com/agent-pre-populate-only: "true" @@ -58,7 +58,7 @@ spec: type: RuntimeDefault initContainers: - name: database-init - image: registry.bstein.dev/veles/veles-backend:0.4.4 # {"$imagepolicy": "veles:veles-backend"} + image: registry.bstein.dev/veles/veles-backend:0.4.5 # {"$imagepolicy": "veles:veles-backend"} imagePullPolicy: Always command: ["/bin/sh", "-c"] args: @@ -80,7 +80,7 @@ spec: memory: 512Mi containers: - name: backend - image: registry.bstein.dev/veles/veles-backend:0.4.4 # {"$imagepolicy": "veles:veles-backend"} + image: registry.bstein.dev/veles/veles-backend:0.4.5 # {"$imagepolicy": "veles:veles-backend"} imagePullPolicy: Always command: ["/bin/sh", "-c"] args: diff --git a/services/veles/configmap.yaml b/services/veles/configmap.yaml index 2d33dc4c3..c9c159b27 100644 --- a/services/veles/configmap.yaml +++ b/services/veles/configmap.yaml @@ -18,7 +18,7 @@ data: VELES_OIDC_REQUIRED_GROUPS: alpha,veles-tester,admin VELES_OIDC_ADMIN_GROUPS: admin VELES_NAMESPACE: veles - VELES_SIM_IMAGE: registry.bstein.dev/veles/veles-sim-worker:0.4.4 # {"$imagepolicy": "veles:veles-sim-worker"} + VELES_SIM_IMAGE: registry.bstein.dev/veles/veles-sim-worker:0.4.5 # {"$imagepolicy": "veles:veles-sim-worker"} VELES_SIM_SERVICE_ACCOUNT: veles-sim VELES_SIM_PRIORITY_CLASS: veles-sim VELES_SIM_NODE_SELECTOR: veles.bstein.dev/node-pool=oceanus,kubernetes.io/arch=amd64 diff --git a/services/veles/feedback-mirror-cronjob.yaml b/services/veles/feedback-mirror-cronjob.yaml new file mode 100644 index 000000000..8873c9c54 --- /dev/null +++ b/services/veles/feedback-mirror-cronjob.yaml @@ -0,0 +1,84 @@ +# services/veles/feedback-mirror-cronjob.yaml +apiVersion: batch/v1 +kind: CronJob +metadata: + name: veles-feedback-mirror + namespace: veles + labels: + app: veles-feedback-mirror +spec: + schedule: "*/15 * * * *" + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 1 + failedJobsHistoryLimit: 3 + jobTemplate: + spec: + template: + metadata: + labels: + app: veles-feedback-mirror + spec: + restartPolicy: Never + serviceAccountName: veles-feedback-mirror + automountServiceAccountToken: false + priorityClassName: veles-core + nodeSelector: + veles.bstein.dev/node-pool: oceanus + kubernetes.io/arch: amd64 + tolerations: + - key: veles.bstein.dev/simulation + operator: Equal + value: "true" + effect: NoSchedule + securityContext: + fsGroup: 10001 + fsGroupChangePolicy: OnRootMismatch + seccompProfile: + type: RuntimeDefault + containers: + - name: mirror + image: registry.bstein.dev/veles/veles-backend:0.4.5 # {"$imagepolicy": "veles:veles-backend"} + imagePullPolicy: IfNotPresent + command: ["/bin/sh", "-c"] + args: + - | + set -eu + if [ -z "${GITEA_TOKEN:-}" ]; then + echo "No GITEA_TOKEN configured for feedback mirror; leaving existing mirror untouched." + exit 0 + fi + exec veles-feedback-mirror \ + --api-base-url "${VELES_FEEDBACK_GITEA_API_URL:-https://scm.bstein.dev/api/v1}" \ + --repo "${VELES_FEEDBACK_REPO:-veles-alpha/feedback}" \ + --output "${VELES_FEEDBACK_MIRROR_PATH:-/data/veles-artifacts/artifacts/feedback/issues.json}" + envFrom: + - configMapRef: + name: veles-config + env: + - name: GITEA_TOKEN + valueFrom: + secretKeyRef: + name: veles-feedback-mirror + key: GITEA_TOKEN + optional: true + volumeMounts: + - name: artifacts + mountPath: /data/veles-artifacts + resources: + requests: + cpu: 25m + memory: 128Mi + limits: + cpu: 200m + memory: 384Mi + securityContext: + runAsNonRoot: true + runAsUser: 10001 + runAsGroup: 10001 + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + volumes: + - name: artifacts + persistentVolumeClaim: + claimName: veles-artifacts diff --git a/services/veles/frontend-deployment.yaml b/services/veles/frontend-deployment.yaml index 0bd52c65f..c28049d94 100644 --- a/services/veles/frontend-deployment.yaml +++ b/services/veles/frontend-deployment.yaml @@ -48,7 +48,7 @@ spec: type: RuntimeDefault containers: - name: frontend - image: registry.bstein.dev/veles/veles-frontend:0.4.4 # {"$imagepolicy": "veles:veles-frontend"} + image: registry.bstein.dev/veles/veles-frontend:0.4.5 # {"$imagepolicy": "veles:veles-frontend"} imagePullPolicy: Always ports: - name: http diff --git a/services/veles/kustomization.yaml b/services/veles/kustomization.yaml index 764438c1e..dd4fa3481 100644 --- a/services/veles/kustomization.yaml +++ b/services/veles/kustomization.yaml @@ -18,6 +18,7 @@ resources: - backend-deployment.yaml - frontend-deployment.yaml - retention-cronjob.yaml + - feedback-mirror-cronjob.yaml - image.yaml - ingress.yaml - oneoffs/veles-secrets-ensure-job.yaml diff --git a/services/veles/retention-cronjob.yaml b/services/veles/retention-cronjob.yaml index aefd9c7e7..5dbc7e6f1 100644 --- a/services/veles/retention-cronjob.yaml +++ b/services/veles/retention-cronjob.yaml @@ -37,7 +37,7 @@ spec: type: RuntimeDefault containers: - name: retention - image: registry.bstein.dev/veles/veles-backend:0.4.4 # {"$imagepolicy": "veles:veles-backend"} + image: registry.bstein.dev/veles/veles-backend:0.4.5 # {"$imagepolicy": "veles:veles-backend"} imagePullPolicy: IfNotPresent command: ["veles-hygiene"] args: ["--prune-artifacts"] diff --git a/services/veles/serviceaccounts.yaml b/services/veles/serviceaccounts.yaml index c14ff0f8d..54b360c0c 100644 --- a/services/veles/serviceaccounts.yaml +++ b/services/veles/serviceaccounts.yaml @@ -35,6 +35,15 @@ imagePullSecrets: --- apiVersion: v1 kind: ServiceAccount +metadata: + name: veles-feedback-mirror + namespace: veles +automountServiceAccountToken: false +imagePullSecrets: + - name: harbor-regcred +--- +apiVersion: v1 +kind: ServiceAccount metadata: name: veles-vault-sync namespace: veles