Add Veles deployment IaC
This commit is contained in:
parent
87e8146d5f
commit
a1139cd3f6
@ -28,33 +28,3 @@ spec:
|
||||
- veles-postgres
|
||||
retain: 8
|
||||
concurrency: 1
|
||||
---
|
||||
apiVersion: longhorn.io/v1beta2
|
||||
kind: RecurringJob
|
||||
metadata:
|
||||
name: veles-artifacts-backup
|
||||
namespace: longhorn-system
|
||||
spec:
|
||||
name: veles-artifacts-backup
|
||||
cron: "45 5 * * *"
|
||||
task: backup
|
||||
groups:
|
||||
- veles
|
||||
- veles-artifacts
|
||||
retain: 7
|
||||
concurrency: 1
|
||||
---
|
||||
apiVersion: longhorn.io/v1beta2
|
||||
kind: RecurringJob
|
||||
metadata:
|
||||
name: veles-artifacts-snapshot
|
||||
namespace: longhorn-system
|
||||
spec:
|
||||
name: veles-artifacts-snapshot
|
||||
cron: "15 */6 * * *"
|
||||
task: snapshot
|
||||
groups:
|
||||
- veles
|
||||
- veles-artifacts
|
||||
retain: 8
|
||||
concurrency: 1
|
||||
|
||||
@ -15,7 +15,6 @@ parameters:
|
||||
fsType: ext4
|
||||
replicaAutoBalance: disabled
|
||||
dataLocality: strict-local
|
||||
recurringJobSelector: '[{"name":"veles-artifacts-backup","isGroup":false},{"name":"veles-artifacts-snapshot","isGroup":false}]'
|
||||
reclaimPolicy: Retain
|
||||
allowVolumeExpansion: true
|
||||
volumeBindingMode: WaitForFirstConsumer
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
# services/keycloak/oneoffs/veles-gitea-oidc-secret-ensure-job.yaml
|
||||
# One-off job for sso/veles-gitea-oidc-secret-ensure-5.
|
||||
# Purpose: create/update the Veles realm Gitea OIDC client and write the
|
||||
# matching Gitea auth-source secret to Vault.
|
||||
# Keep suspended until the Vault policy change has reconciled, then unsuspend once.
|
||||
# One-off job for sso/veles-gitea-oidc-secret-ensure-1.
|
||||
# Purpose: create/update the Keycloak veles realm Gitea OIDC client, ensure the
|
||||
# veles-tester group exists, and write the client secret to Vault for Gitea.
|
||||
# Run by setting spec.suspend to false, reconcile, then set it back to true.
|
||||
# Safe to delete the finished Job/pod; it should not run continuously.
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: veles-gitea-oidc-secret-ensure-5
|
||||
name: veles-gitea-oidc-secret-ensure-1
|
||||
namespace: sso
|
||||
spec:
|
||||
suspend: true
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
# services/keycloak/oneoffs/veles-realm-ensure-job.yaml
|
||||
# One-off job for sso/veles-realm-ensure-4.
|
||||
# One-off job for sso/veles-realm-ensure-2.
|
||||
# Purpose: create the Veles realm, groups, OIDC client, SMTP settings, and Vault client secret.
|
||||
# Keep suspended until Veles Vault paths/policies have reconciled, then unsuspend once.
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: veles-realm-ensure-4
|
||||
name: veles-realm-ensure-2
|
||||
namespace: sso
|
||||
spec:
|
||||
suspend: true
|
||||
@ -157,7 +157,7 @@ spec:
|
||||
create_payload = {
|
||||
"realm": realm,
|
||||
"enabled": True,
|
||||
"registrationAllowed": True,
|
||||
"registrationAllowed": False,
|
||||
"resetPasswordAllowed": True,
|
||||
"verifyEmail": True,
|
||||
"loginWithEmailAllowed": True,
|
||||
@ -174,7 +174,7 @@ spec:
|
||||
realm_rep.update(
|
||||
{
|
||||
"enabled": True,
|
||||
"registrationAllowed": True,
|
||||
"registrationAllowed": False,
|
||||
"resetPasswordAllowed": True,
|
||||
"verifyEmail": True,
|
||||
"loginWithEmailAllowed": True,
|
||||
@ -194,77 +194,14 @@ spec:
|
||||
)
|
||||
if status != 200:
|
||||
raise SystemExit(f"Group search failed for {name}: status={status}")
|
||||
for group in groups or []:
|
||||
if group.get("name") == name:
|
||||
return group["id"]
|
||||
if any(group.get("name") == name for group in groups or []):
|
||||
return
|
||||
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}")
|
||||
status, groups = request(
|
||||
"GET",
|
||||
f"{base_url}/admin/realms/{realm}/groups?search={urllib.parse.quote(name)}",
|
||||
token,
|
||||
)
|
||||
if status != 200:
|
||||
raise SystemExit(f"Group lookup failed after create for {name}: status={status}")
|
||||
for group in groups or []:
|
||||
if group.get("name") == name:
|
||||
return group["id"]
|
||||
raise SystemExit(f"Group {name} not found after create")
|
||||
|
||||
def ensure_role(name):
|
||||
status, role = request("GET", f"{base_url}/admin/realms/{realm}/roles/{urllib.parse.quote(name)}", token)
|
||||
if status == 404:
|
||||
status, body = request("POST", f"{base_url}/admin/realms/{realm}/roles", token, {"name": name})
|
||||
if status not in (201, 204, 409):
|
||||
raise SystemExit(f"Role create failed for {name}: status={status} body={body}")
|
||||
status, role = request(
|
||||
"GET",
|
||||
f"{base_url}/admin/realms/{realm}/roles/{urllib.parse.quote(name)}",
|
||||
token,
|
||||
)
|
||||
if status != 200 or not isinstance(role, dict):
|
||||
raise SystemExit(f"Role lookup failed for {name}: status={status}")
|
||||
return role
|
||||
|
||||
def ensure_group_role(group_id, role):
|
||||
status, mappings = request(
|
||||
"GET",
|
||||
f"{base_url}/admin/realms/{realm}/groups/{group_id}/role-mappings/realm",
|
||||
token,
|
||||
)
|
||||
if status != 200:
|
||||
raise SystemExit(f"Group role mapping lookup failed: status={status}")
|
||||
if any(mapping.get("name") == role["name"] for mapping in mappings or []):
|
||||
return
|
||||
status, body = request(
|
||||
"POST",
|
||||
f"{base_url}/admin/realms/{realm}/groups/{group_id}/role-mappings/realm",
|
||||
token,
|
||||
[role],
|
||||
)
|
||||
if status not in (200, 204):
|
||||
raise SystemExit(f"Group role mapping failed for {role['name']}: status={status} body={body}")
|
||||
|
||||
def ensure_default_group(group_id, name):
|
||||
status, groups = request("GET", f"{base_url}/admin/realms/{realm}/default-groups", token)
|
||||
if status != 200:
|
||||
raise SystemExit(f"Default group lookup failed: status={status}")
|
||||
for group in groups or []:
|
||||
if group.get("id") == group_id or group.get("name") == name:
|
||||
return
|
||||
status, body = request("PUT", f"{base_url}/admin/realms/{realm}/default-groups/{group_id}", token)
|
||||
if status not in (200, 204):
|
||||
raise SystemExit(f"Default group update failed for {name}: status={status} body={body}")
|
||||
|
||||
alpha_group_id = ensure_group("alpha")
|
||||
admin_group_id = ensure_group("admin")
|
||||
alpha_role = ensure_role("alpha")
|
||||
admin_role = ensure_role("admin")
|
||||
ensure_group_role(alpha_group_id, alpha_role)
|
||||
ensure_group_role(admin_group_id, alpha_role)
|
||||
ensure_group_role(admin_group_id, admin_role)
|
||||
ensure_default_group(alpha_group_id, "alpha")
|
||||
ensure_group("alpha")
|
||||
ensure_group("admin")
|
||||
|
||||
status, clients = request(
|
||||
"GET",
|
||||
@ -336,7 +273,6 @@ spec:
|
||||
raise SystemExit(f"Mapper lookup failed: status={status}")
|
||||
mapper_id = next((mapper.get("id") for mapper in mappers or [] if mapper.get("name") == "groups"), None)
|
||||
if mapper_id:
|
||||
mapper_payload["id"] = mapper_id
|
||||
status, body = request(
|
||||
"PUT",
|
||||
f"{base_url}/admin/realms/{realm}/clients/{client_uuid}/protocol-mappers/models/{mapper_id}",
|
||||
|
||||
241
services/keycloak/scripts/veles_gitea_oidc_secret_ensure.sh
Executable file → Normal file
241
services/keycloak/scripts/veles_gitea_oidc_secret_ensure.sh
Executable file → Normal file
@ -9,8 +9,7 @@ CLIENT_ID="${KEYCLOAK_CLIENT_ID:-gitea}"
|
||||
PUBLIC_BASE_URL="${GITEA_PUBLIC_BASE_URL:-https://scm.bstein.dev}"
|
||||
AUTH_SOURCE_NAME="${GITEA_AUTH_SOURCE_NAME:-veles}"
|
||||
TESTER_GROUP="${VELES_GITEA_TESTER_GROUP:-veles-tester}"
|
||||
VAULT_SECRET_PATH="${VAULT_SECRET_PATH:-gitea/gitea-veles-oidc}"
|
||||
GROUP_TEAM_MAP="${GITEA_GROUP_TEAM_MAP:-{\"veles-tester\":{\"veles-alpha\":[\"testers\"]}}}"
|
||||
VAULT_SECRET_PATH="${VAULT_SECRET_PATH:-kv/data/atlas/gitea/gitea-veles-oidc}"
|
||||
|
||||
ACCESS_TOKEN=""
|
||||
for attempt in 1 2 3 4 5 6 7 8 9 10; do
|
||||
@ -20,7 +19,6 @@ for attempt in 1 2 3 4 5 6 7 8 9 10; do
|
||||
echo "Waiting for Keycloak to be reachable (attempt ${attempt})" >&2
|
||||
sleep $((attempt * 2))
|
||||
done
|
||||
|
||||
for attempt in 1 2 3 4 5; do
|
||||
TOKEN_JSON="$(curl -sS -X POST "$KC_URL/realms/master/protocol/openid-connect/token" \
|
||||
-H 'Content-Type: application/x-www-form-urlencoded' \
|
||||
@ -44,198 +42,21 @@ ensure_group() {
|
||||
group_name="$1"
|
||||
groups="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/groups?search=$(printf '%s' "${group_name}" | jq -sRr @uri)" || true)"
|
||||
group_id="$(echo "$groups" | jq -r --arg name "$group_name" '.[]? | select(.name == $name) | .id' | head -n1 || true)"
|
||||
if [ -n "$group_id" ] && [ "$group_id" != "null" ]; then
|
||||
printf '%s' "$group_id"
|
||||
if echo "$groups" | jq -e --arg name "$group_name" '.[]? | select(.name == $name)' >/dev/null 2>&1; then
|
||||
return
|
||||
fi
|
||||
status="$(curl -sS -o /tmp/keycloak-group-create.json -w "%{http_code}" -X POST \
|
||||
status="$(curl -sS -o /dev/null -w "%{http_code}" -X POST \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "$(jq -nc --arg name "$group_name" '{name:$name}')" \
|
||||
"${KC_URL}/admin/realms/${REALM}/groups")"
|
||||
if [ "$status" != "201" ] && [ "$status" != "204" ] && [ "$status" != "409" ]; then
|
||||
echo "Keycloak group create failed for ${group_name} (status ${status})" >&2
|
||||
cat /tmp/keycloak-group-create.json >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
groups="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/groups?search=$(printf '%s' "${group_name}" | jq -sRr @uri)" || true)"
|
||||
group_id="$(echo "$groups" | jq -r --arg name "$group_name" '.[]? | select(.name == $name) | .id' | head -n1 || true)"
|
||||
if [ -z "$group_id" ] || [ "$group_id" = "null" ]; then
|
||||
echo "Keycloak group ${group_name} not found after create" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf '%s' "$group_id"
|
||||
}
|
||||
|
||||
ensure_role() {
|
||||
role_name="$1"
|
||||
role="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/roles/$(printf '%s' "${role_name}" | jq -sRr @uri)" || true)"
|
||||
if echo "$role" | jq -e --arg name "$role_name" '.name == $name' >/dev/null 2>&1; then
|
||||
printf '%s' "$role"
|
||||
return
|
||||
fi
|
||||
status="$(curl -sS -o /tmp/keycloak-role-create.json -w "%{http_code}" -X POST \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "$(jq -nc --arg name "$role_name" '{name:$name}')" \
|
||||
"${KC_URL}/admin/realms/${REALM}/roles")"
|
||||
if [ "$status" != "201" ] && [ "$status" != "204" ] && [ "$status" != "409" ]; then
|
||||
echo "Keycloak role create failed for ${role_name} (status ${status})" >&2
|
||||
cat /tmp/keycloak-role-create.json >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
role="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/roles/$(printf '%s' "${role_name}" | jq -sRr @uri)" || true)"
|
||||
if ! echo "$role" | jq -e --arg name "$role_name" '.name == $name' >/dev/null 2>&1; then
|
||||
echo "Keycloak role ${role_name} not found after create" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf '%s' "$role"
|
||||
}
|
||||
|
||||
ensure_group_role() {
|
||||
group_id="$1"
|
||||
role_json="$2"
|
||||
role_name="$(echo "$role_json" | jq -r '.name')"
|
||||
mappings="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/groups/${group_id}/role-mappings/realm" || true)"
|
||||
if echo "$mappings" | jq -e --arg name "$role_name" '.[]? | select(.name == $name)' >/dev/null 2>&1; then
|
||||
return
|
||||
fi
|
||||
status="$(curl -sS -o /tmp/keycloak-group-role.json -w "%{http_code}" -X POST \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "[$role_json]" \
|
||||
"${KC_URL}/admin/realms/${REALM}/groups/${group_id}/role-mappings/realm")"
|
||||
if [ "$status" != "200" ] && [ "$status" != "204" ]; then
|
||||
echo "Keycloak group role mapping failed for ${role_name} (status ${status})" >&2
|
||||
cat /tmp/keycloak-group-role.json >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_mapper() {
|
||||
client_uuid="$1"
|
||||
mapper_name="$2"
|
||||
mapper_payload="$3"
|
||||
mappers="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/clients/${client_uuid}/protocol-mappers/models" || true)"
|
||||
mapper_id="$(echo "$mappers" | jq -r --arg name "$mapper_name" '.[]? | select(.name == $name) | .id' | head -n1 || true)"
|
||||
if [ -n "$mapper_id" ] && [ "$mapper_id" != "null" ]; then
|
||||
mapper_payload="$(echo "$mapper_payload" | jq --arg id "$mapper_id" '. + {id:$id}')"
|
||||
status="$(curl -sS -o /tmp/keycloak-mapper.json -w "%{http_code}" -X PUT \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "${mapper_payload}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/clients/${client_uuid}/protocol-mappers/models/${mapper_id}")"
|
||||
else
|
||||
status="$(curl -sS -o /tmp/keycloak-mapper.json -w "%{http_code}" -X POST \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "${mapper_payload}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/clients/${client_uuid}/protocol-mappers/models")"
|
||||
fi
|
||||
if [ "$status" != "200" ] && [ "$status" != "201" ] && [ "$status" != "204" ]; then
|
||||
echo "Keycloak mapper ensure failed for ${mapper_name} (status ${status})" >&2
|
||||
cat /tmp/keycloak-mapper.json >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_client_scope() {
|
||||
scope_name="$1"
|
||||
scopes="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/client-scopes?search=$(printf '%s' "${scope_name}" | jq -sRr @uri)" || true)"
|
||||
scope_id="$(echo "$scopes" | jq -r --arg name "$scope_name" '.[]? | select(.name == $name) | .id' | head -n1 || true)"
|
||||
if [ -n "$scope_id" ] && [ "$scope_id" != "null" ]; then
|
||||
printf '%s' "$scope_id"
|
||||
return
|
||||
fi
|
||||
|
||||
scope_payload="$(jq -nc --arg name "$scope_name" '{name:$name,protocol:"openid-connect",attributes:{"include.in.token.scope":"true","display.on.consent.screen":"false"}}')"
|
||||
status="$(curl -sS -o /tmp/keycloak-client-scope-create.json -w "%{http_code}" -X POST \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "${scope_payload}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/client-scopes")"
|
||||
if [ "$status" != "201" ] && [ "$status" != "204" ] && [ "$status" != "409" ]; then
|
||||
echo "Keycloak client scope create failed for ${scope_name} (status ${status})" >&2
|
||||
cat /tmp/keycloak-client-scope-create.json >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
scopes="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/client-scopes?search=$(printf '%s' "${scope_name}" | jq -sRr @uri)" || true)"
|
||||
scope_id="$(echo "$scopes" | jq -r --arg name "$scope_name" '.[]? | select(.name == $name) | .id' | head -n1 || true)"
|
||||
if [ -z "$scope_id" ] || [ "$scope_id" = "null" ]; then
|
||||
echo "Keycloak client scope ${scope_name} not found after create" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf '%s' "$scope_id"
|
||||
}
|
||||
|
||||
ensure_scope_mapper() {
|
||||
scope_id="$1"
|
||||
mapper_name="$2"
|
||||
mapper_payload="$3"
|
||||
mappers="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/client-scopes/${scope_id}/protocol-mappers/models" || true)"
|
||||
mapper_id="$(echo "$mappers" | jq -r --arg name "$mapper_name" '.[]? | select(.name == $name) | .id' | head -n1 || true)"
|
||||
if [ -n "$mapper_id" ] && [ "$mapper_id" != "null" ]; then
|
||||
mapper_payload="$(echo "$mapper_payload" | jq --arg id "$mapper_id" '. + {id:$id}')"
|
||||
status="$(curl -sS -o /tmp/keycloak-scope-mapper.json -w "%{http_code}" -X PUT \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "${mapper_payload}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/client-scopes/${scope_id}/protocol-mappers/models/${mapper_id}")"
|
||||
else
|
||||
status="$(curl -sS -o /tmp/keycloak-scope-mapper.json -w "%{http_code}" -X POST \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "${mapper_payload}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/client-scopes/${scope_id}/protocol-mappers/models")"
|
||||
fi
|
||||
if [ "$status" != "200" ] && [ "$status" != "201" ] && [ "$status" != "204" ]; then
|
||||
echo "Keycloak client-scope mapper ensure failed for ${mapper_name} (status ${status})" >&2
|
||||
cat /tmp/keycloak-scope-mapper.json >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_client_optional_scope() {
|
||||
client_uuid="$1"
|
||||
scope_id="$2"
|
||||
scope_name="$3"
|
||||
default_scopes="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/clients/${client_uuid}/default-client-scopes" || true)"
|
||||
optional_scopes="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/clients/${client_uuid}/optional-client-scopes" || true)"
|
||||
|
||||
if echo "$default_scopes" | jq -e --arg name "$scope_name" '.[]? | select(.name == $name)' >/dev/null 2>&1 \
|
||||
|| echo "$optional_scopes" | jq -e --arg name "$scope_name" '.[]? | select(.name == $name)' >/dev/null 2>&1; then
|
||||
return
|
||||
fi
|
||||
|
||||
status="$(curl -sS -o /dev/null -w "%{http_code}" -X PUT \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/clients/${client_uuid}/optional-client-scopes/${scope_id}")"
|
||||
if [ "$status" != "200" ] && [ "$status" != "201" ] && [ "$status" != "204" ]; then
|
||||
status="$(curl -sS -o /dev/null -w "%{http_code}" -X POST \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/clients/${client_uuid}/optional-client-scopes/${scope_id}")"
|
||||
if [ "$status" != "200" ] && [ "$status" != "201" ] && [ "$status" != "204" ]; then
|
||||
echo "Failed to attach ${scope_name} client scope to ${CLIENT_ID} (status ${status})" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
TESTER_GROUP_ID="$(ensure_group "${TESTER_GROUP}")"
|
||||
TESTER_ROLE="$(ensure_role "${TESTER_GROUP}")"
|
||||
ensure_group_role "${TESTER_GROUP_ID}" "${TESTER_ROLE}"
|
||||
ensure_group "${TESTER_GROUP}"
|
||||
|
||||
CLIENT_QUERY="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/clients?clientId=$(printf '%s' "${CLIENT_ID}" | jq -sRr @uri)" || true)"
|
||||
@ -245,17 +66,16 @@ client_payload="$(jq -nc \
|
||||
--arg client_id "${CLIENT_ID}" \
|
||||
--arg root_url "${PUBLIC_BASE_URL}" \
|
||||
--arg callback "${PUBLIC_BASE_URL}/user/oauth2/${AUTH_SOURCE_NAME}/callback" \
|
||||
'{clientId:$client_id,enabled:true,protocol:"openid-connect",publicClient:false,standardFlowEnabled:true,implicitFlowEnabled:false,directAccessGrantsEnabled:false,serviceAccountsEnabled:false,redirectUris:[$callback],webOrigins:[$root_url],rootUrl:$root_url,baseUrl:"/",attributes:{"pkce.code.challenge.method":"","post.logout.redirect.uris":($root_url + "/*")}}')"
|
||||
'{clientId:$client_id,enabled:true,protocol:"openid-connect",publicClient:false,standardFlowEnabled:true,implicitFlowEnabled:false,directAccessGrantsEnabled:false,serviceAccountsEnabled:false,redirectUris:[$callback],webOrigins:[$root_url],rootUrl:$root_url,baseUrl:"/",attributes:{"pkce.code.challenge.method":"S256","post.logout.redirect.uris":($root_url + "/*")}}')"
|
||||
|
||||
if [ -z "$CLIENT_UUID" ] || [ "$CLIENT_UUID" = "null" ]; then
|
||||
status="$(curl -sS -o /tmp/keycloak-client-create.json -w "%{http_code}" -X POST \
|
||||
status="$(curl -sS -o /dev/null -w "%{http_code}" -X POST \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "${client_payload}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/clients")"
|
||||
if [ "$status" != "201" ] && [ "$status" != "204" ] && [ "$status" != "409" ]; then
|
||||
echo "Keycloak client create failed for ${CLIENT_ID} (status ${status})" >&2
|
||||
cat /tmp/keycloak-client-create.json >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
CLIENT_QUERY="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
@ -268,26 +88,38 @@ if [ -z "$CLIENT_UUID" ] || [ "$CLIENT_UUID" = "null" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
status="$(curl -sS -o /tmp/keycloak-client-update.json -w "%{http_code}" -X PUT \
|
||||
status="$(curl -sS -o /dev/null -w "%{http_code}" -X PUT \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "${client_payload}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/clients/${CLIENT_UUID}")"
|
||||
if [ "$status" != "200" ] && [ "$status" != "204" ]; then
|
||||
echo "Keycloak client update failed for ${CLIENT_ID} (status ${status})" >&2
|
||||
cat /tmp/keycloak-client-update.json >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
groups_mapper_payload="$(jq -nc \
|
||||
mapper_payload="$(jq -nc \
|
||||
'{name:"groups",protocol:"openid-connect",protocolMapper:"oidc-group-membership-mapper",consentRequired:false,config:{"full.path":"false","id.token.claim":"true","access.token.claim":"true","userinfo.token.claim":"true","claim.name":"groups","jsonType.label":"String"}}')"
|
||||
roles_mapper_payload="$(jq -nc \
|
||||
'{name:"roles",protocol:"openid-connect",protocolMapper:"oidc-usermodel-realm-role-mapper",consentRequired:false,config:{"multivalued":"true","id.token.claim":"true","access.token.claim":"true","userinfo.token.claim":"true","claim.name":"roles","jsonType.label":"String"}}')"
|
||||
ensure_mapper "${CLIENT_UUID}" groups "${groups_mapper_payload}"
|
||||
ensure_mapper "${CLIENT_UUID}" roles "${roles_mapper_payload}"
|
||||
GROUPS_SCOPE_ID="$(ensure_client_scope groups)"
|
||||
ensure_scope_mapper "${GROUPS_SCOPE_ID}" groups "${groups_mapper_payload}"
|
||||
ensure_client_optional_scope "${CLIENT_UUID}" "${GROUPS_SCOPE_ID}" groups
|
||||
mappers="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/clients/${CLIENT_UUID}/protocol-mappers/models" || true)"
|
||||
MAPPER_ID="$(echo "$mappers" | jq -r '.[]? | select(.name == "groups") | .id' | head -n1 || true)"
|
||||
if [ -n "$MAPPER_ID" ] && [ "$MAPPER_ID" != "null" ]; then
|
||||
status="$(curl -sS -o /dev/null -w "%{http_code}" -X PUT \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "${mapper_payload}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/clients/${CLIENT_UUID}/protocol-mappers/models/${MAPPER_ID}")"
|
||||
else
|
||||
status="$(curl -sS -o /dev/null -w "%{http_code}" -X POST \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "${mapper_payload}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/clients/${CLIENT_UUID}/protocol-mappers/models")"
|
||||
fi
|
||||
if [ "$status" != "200" ] && [ "$status" != "201" ] && [ "$status" != "204" ]; then
|
||||
echo "Keycloak groups mapper ensure failed (status ${status})" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CLIENT_SECRET="$(curl -sS -H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
"${KC_URL}/admin/realms/${REALM}/clients/${CLIENT_UUID}/client-secret" | jq -r '.value' 2>/dev/null || true)"
|
||||
@ -310,21 +142,16 @@ fi
|
||||
payload="$(jq -nc \
|
||||
--arg client_id "${CLIENT_ID}" \
|
||||
--arg client_secret "${CLIENT_SECRET}" \
|
||||
--arg discovery_url "${PUBLIC_BASE_URL}" \
|
||||
--arg issuer "https://sso.bstein.dev/realms/${REALM}" \
|
||||
--arg auto_discovery_url "https://sso.bstein.dev/realms/${REALM}/.well-known/openid-configuration" \
|
||||
--arg auth_source_name "${AUTH_SOURCE_NAME}" \
|
||||
--arg tester_group "${TESTER_GROUP}" \
|
||||
--arg group_team_map "${GROUP_TEAM_MAP}" \
|
||||
'{data:{client_id:$client_id,client_secret:$client_secret,issuer:$issuer,openid_auto_discovery_url:$auto_discovery_url,auth_source_name:$auth_source_name,required_claim_name:"groups",required_claim_value:$tester_group,group_claim_name:"groups",restricted_group:$tester_group,group_team_map:$group_team_map}}')"
|
||||
--arg group_team_map "{\"${TESTER_GROUP}\":{\"veles-alpha\":[\"testers\"]}}" \
|
||||
'{data:{client_id:$client_id,client_secret:$client_secret,issuer:$issuer,openid_auto_discovery_url:$auto_discovery_url,auth_source_name:$auth_source_name,required_claim_name:"groups",required_claim_value:$tester_group,group_claim_name:"groups",restricted_group:$tester_group,group_team_map:$group_team_map,gitea_base_url:$discovery_url}}')"
|
||||
|
||||
write_status="$(curl -sS -o /tmp/veles-gitea-oidc-write.json -w "%{http_code}" -X POST \
|
||||
-H "X-Vault-Token: ${vault_token}" \
|
||||
curl -sS -X POST -H "X-Vault-Token: ${vault_token}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "${payload}" "${vault_addr}/v1/kv/data/atlas/${VAULT_SECRET_PATH}")"
|
||||
if [ "${write_status}" != "200" ] && [ "${write_status}" != "204" ]; then
|
||||
echo "Vault write failed for ${VAULT_SECRET_PATH} (status ${write_status})" >&2
|
||||
cat /tmp/veles-gitea-oidc-write.json >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
-d "${payload}" "${vault_addr}/v1/${VAULT_SECRET_PATH}" >/dev/null
|
||||
|
||||
echo "Veles Gitea OIDC client ready in Keycloak and Vault"
|
||||
echo "Veles realm Gitea OIDC client ready"
|
||||
|
||||
@ -7,11 +7,26 @@ metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: veles
|
||||
app.kubernetes.io/component: artifacts
|
||||
veles.bstein.dev/backup: longhorn
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: veles-oceanus-artifacts
|
||||
resources:
|
||||
requests:
|
||||
storage: 200Gi
|
||||
storage: 500Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: veles-engine-cache
|
||||
namespace: veles
|
||||
labels:
|
||||
app.kubernetes.io/name: veles
|
||||
app.kubernetes.io/component: engine-cache
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: veles-oceanus-artifacts
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Gi
|
||||
|
||||
@ -16,11 +16,30 @@ spec:
|
||||
metadata:
|
||||
labels:
|
||||
app: veles-backend
|
||||
annotations:
|
||||
vault.hashicorp.com/agent-inject: "true"
|
||||
vault.hashicorp.com/agent-pre-populate-only: "true"
|
||||
vault.hashicorp.com/role: "veles"
|
||||
vault.hashicorp.com/agent-inject-secret-veles-env.sh: "kv/data/atlas/veles/veles-db"
|
||||
vault.hashicorp.com/agent-inject-template-veles-env.sh: |
|
||||
{{- with secret "kv/data/atlas/veles/veles-db" }}
|
||||
export DATABASE_URL="{{ .Data.data.DATABASE_URL }}"
|
||||
export VELES_DATABASE_USER="{{ .Data.data.POSTGRES_USER }}"
|
||||
export VELES_DATABASE_PASSWORD="{{ .Data.data.POSTGRES_PASSWORD }}"
|
||||
{{- end }}
|
||||
{{- with secret "kv/data/atlas/veles/veles-oidc" }}
|
||||
export VELES_OIDC_CLIENT_SECRET="{{ .Data.data.client_secret }}"
|
||||
{{- end }}
|
||||
{{- with secret "kv/data/atlas/veles/app-secrets" }}
|
||||
export VELES_SESSION_SECRET="{{ .Data.data.VELES_SESSION_SECRET }}"
|
||||
export VELES_BYOK_ENCRYPTION_KEY="{{ .Data.data.VELES_BYOK_ENCRYPTION_KEY }}"
|
||||
{{- end }}
|
||||
spec:
|
||||
serviceAccountName: veles-backend
|
||||
priorityClassName: veles-core
|
||||
nodeSelector:
|
||||
veles.bstein.dev/node-pool: oceanus
|
||||
kubernetes.io/arch: amd64
|
||||
tolerations:
|
||||
- key: veles.bstein.dev/simulation
|
||||
operator: Equal
|
||||
@ -32,41 +51,46 @@ spec:
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
initContainers:
|
||||
- name: migrate-db
|
||||
image: registry.bstein.dev/veles/veles-backend:0.3.15 # {"$imagepolicy": "veles:veles-backend"}
|
||||
- name: database-init
|
||||
image: registry.bstein.dev/veles/veles-backend:0.3.16 # {"$imagepolicy": "veles:veles-backend"}
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["veles-db"]
|
||||
args: ["--init", "--json"]
|
||||
command: ["/bin/sh", "-c"]
|
||||
args:
|
||||
- |
|
||||
set -eu
|
||||
if [ -f /vault/secrets/veles-env.sh ]; then
|
||||
. /vault/secrets/veles-env.sh
|
||||
fi
|
||||
exec veles-db --init --wait-seconds 120 --bootstrap-meta --content-root /opt/veles-content
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: veles-app-config
|
||||
- secretRef:
|
||||
name: veles-runtime-secrets
|
||||
name: veles-config
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
cpu: 50m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
cpu: 250m
|
||||
memory: 512Mi
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 10001
|
||||
runAsGroup: 10001
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
containers:
|
||||
- name: backend
|
||||
image: registry.bstein.dev/veles/veles-backend:0.3.15 # {"$imagepolicy": "veles:veles-backend"}
|
||||
image: registry.bstein.dev/veles/veles-backend:0.3.16 # {"$imagepolicy": "veles:veles-backend"}
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: VELES_SIM_IMAGE
|
||||
value: registry.bstein.dev/veles/veles-sim-worker:0.3.15 # {"$imagepolicy": "veles:veles-sim-worker"}
|
||||
command: ["/bin/sh", "-c"]
|
||||
args:
|
||||
- |
|
||||
set -eu
|
||||
if [ -f /vault/secrets/veles-env.sh ]; then
|
||||
. /vault/secrets/veles-env.sh
|
||||
fi
|
||||
exec veles-web --host 0.0.0.0 --port 8796 --no-resume-queued
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8796
|
||||
protocol: TCP
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: veles-config
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /api/v1/ready
|
||||
@ -79,18 +103,13 @@ spec:
|
||||
port: http
|
||||
initialDelaySeconds: 20
|
||||
periodSeconds: 20
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: veles-app-config
|
||||
- secretRef:
|
||||
name: veles-runtime-secrets
|
||||
resources:
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
cpu: "1"
|
||||
memory: 2Gi
|
||||
memory: 1Gi
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 10001
|
||||
|
||||
@ -2,55 +2,44 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: veles-app-config
|
||||
name: veles-config
|
||||
namespace: veles
|
||||
data:
|
||||
VELES_ENV: alpha
|
||||
VELES_PROFILE: cluster
|
||||
VELES_AUTH_MODE: oidc
|
||||
VELES_SIM_RUNNER: kubernetes-job
|
||||
VELES_PUBLIC_URL: https://veles.bstein.dev
|
||||
VELES_PUBLIC_BASE_URL: https://veles.bstein.dev
|
||||
VELES_BACKEND_HTTP_PORT: "8796"
|
||||
VELES_FRONTEND_HTTP_PORT: "8080"
|
||||
VELES_ALPHA_LABEL: ALPHA
|
||||
VELES_OIDC_ISSUER_URL: https://sso.bstein.dev/realms/veles
|
||||
VELES_OIDC_ISSUER: https://sso.bstein.dev/realms/veles
|
||||
VELES_OIDC_CLIENT_ID: veles-web
|
||||
VELES_OIDC_ALLOWED_GROUPS: alpha,admin
|
||||
VELES_OIDC_REQUIRED_GROUPS: alpha,admin
|
||||
VELES_OIDC_ALLOWED_GROUPS: alpha,veles-tester,admin
|
||||
VELES_OIDC_REQUIRED_GROUPS: alpha,veles-tester,admin
|
||||
VELES_OIDC_ADMIN_GROUPS: admin
|
||||
VELES_OIDC_GROUPS_CLAIM: groups
|
||||
VELES_OIDC_ROLES_CLAIM: realm_access.roles
|
||||
VELES_DATABASE_HOST: veles-postgres.veles.svc.cluster.local
|
||||
VELES_DATABASE_PORT: "5432"
|
||||
VELES_DATABASE_NAME: veles
|
||||
VELES_ARTIFACTS_PATH: /data/veles-artifacts
|
||||
VELES_ARTIFACTS_MODE: rwo-backend-owned
|
||||
VELES_LOG_ROOT: /data/veles-artifacts/logs
|
||||
VELES_REPORT_ROOT: /data/veles-artifacts/reports
|
||||
VELES_ARTIFACT_ROOT: /data/veles-artifacts/artifacts
|
||||
VELES_RETENTION_DAYS: "30"
|
||||
VELES_SIM_NAMESPACE: veles
|
||||
VELES_NAMESPACE: veles
|
||||
VELES_SIM_IMAGE: registry.bstein.dev/veles/veles-sim-worker:0.3.15 # {"$imagepolicy": "veles:veles-sim-worker"}
|
||||
VELES_SIM_IMAGE: registry.bstein.dev/veles/veles-sim-worker:0.3.16 # {"$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
|
||||
VELES_SIM_TOLERATIONS: veles.bstein.dev/simulation=true:NoSchedule
|
||||
VELES_SIM_TOLERATION_KEY: veles.bstein.dev/simulation
|
||||
VELES_SIM_TOLERATION_VALUE: "true"
|
||||
VELES_SIM_ACTIVE_DEADLINE_SECONDS: "7200"
|
||||
VELES_SIM_TTL_SECONDS: "3600"
|
||||
VELES_SIM_CPU_REQUEST: 500m
|
||||
VELES_SIM_CPU_LIMIT: "2"
|
||||
VELES_SIM_MEMORY_REQUEST: 1Gi
|
||||
VELES_SIM_MEMORY_LIMIT: 4Gi
|
||||
VELES_SIM_ARTIFACT_PVC: veles-artifacts
|
||||
VELES_SIM_ARTIFACT_MOUNT_PATH: /data/veles-artifacts
|
||||
VELES_SIM_FS_GROUP: "10001"
|
||||
VELES_MAX_ACTIVE_SIMS_PER_USER: "1"
|
||||
VELES_MAX_ACTIVE_SIMS_GLOBAL: "4"
|
||||
VELES_RETENTION_NODE_SELECTOR: veles.bstein.dev/simulation=true
|
||||
VELES_RETENTION_TOLERATION_KEY: veles.bstein.dev/simulation
|
||||
VELES_RETENTION_TOLERATION_VALUE: "true"
|
||||
VELES_LOG_RETENTION_DAYS: "30"
|
||||
VELES_RETENTION_DAYS: "30"
|
||||
VELES_LOG_ROOT: /data/veles-artifacts/logs
|
||||
VELES_REPORT_ROOT: /data/veles-artifacts/reports
|
||||
VELES_ARTIFACT_ROOT: /data/veles-artifacts/artifacts
|
||||
VELES_SIM_ARTIFACT_PVC: veles-artifacts
|
||||
VELES_SIM_ARTIFACT_MOUNT_PATH: /data/veles-artifacts
|
||||
VELES_SIM_ENGINE_PVC: veles-engine-cache
|
||||
VELES_SIM_ENGINE_MOUNT_PATH: /engine
|
||||
VELES_SIM_CODEX_CLI_SECRET_PROVIDER_CLASS: veles-codex-cli
|
||||
VELES_SIM_CODEX_CLI_MOUNT_PATH: /home/veles/.codex
|
||||
VELES_SIM_CODEX_CLI_HOME: /home/veles/.codex
|
||||
|
||||
@ -19,6 +19,7 @@ spec:
|
||||
spec:
|
||||
serviceAccountName: veles-frontend
|
||||
priorityClassName: veles-core
|
||||
automountServiceAccountToken: false
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
@ -43,12 +44,11 @@ spec:
|
||||
values: ["rpi5"]
|
||||
securityContext:
|
||||
fsGroup: 101
|
||||
fsGroupChangePolicy: OnRootMismatch
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: frontend
|
||||
image: registry.bstein.dev/veles/veles-frontend:0.3.15 # {"$imagepolicy": "veles:veles-frontend"}
|
||||
image: registry.bstein.dev/veles/veles-frontend:0.3.16 # {"$imagepolicy": "veles:veles-frontend"}
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
@ -66,20 +66,15 @@ spec:
|
||||
port: http
|
||||
initialDelaySeconds: 20
|
||||
periodSeconds: 20
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: veles-app-config
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
cpu: 250m
|
||||
memory: 256Mi
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 101
|
||||
runAsGroup: 101
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
|
||||
@ -18,12 +18,9 @@ metadata:
|
||||
spec:
|
||||
imageRepositoryRef:
|
||||
name: veles-backend
|
||||
filterTags:
|
||||
pattern: '^(?P<version>\d+\.\d+\.\d+)$'
|
||||
extract: '$version'
|
||||
policy:
|
||||
semver:
|
||||
range: ">=0.1.0"
|
||||
range: ">=0.1.0-0"
|
||||
---
|
||||
apiVersion: image.toolkit.fluxcd.io/v1
|
||||
kind: ImageRepository
|
||||
@ -44,12 +41,9 @@ metadata:
|
||||
spec:
|
||||
imageRepositoryRef:
|
||||
name: veles-frontend
|
||||
filterTags:
|
||||
pattern: '^(?P<version>\d+\.\d+\.\d+)$'
|
||||
extract: '$version'
|
||||
policy:
|
||||
semver:
|
||||
range: ">=0.1.0"
|
||||
range: ">=0.1.0-0"
|
||||
---
|
||||
apiVersion: image.toolkit.fluxcd.io/v1
|
||||
kind: ImageRepository
|
||||
@ -70,9 +64,6 @@ metadata:
|
||||
spec:
|
||||
imageRepositoryRef:
|
||||
name: veles-sim-worker
|
||||
filterTags:
|
||||
pattern: '^(?P<version>\d+\.\d+\.\d+)$'
|
||||
extract: '$version'
|
||||
policy:
|
||||
semver:
|
||||
range: ">=0.1.0"
|
||||
range: ">=0.1.0-0"
|
||||
|
||||
@ -17,6 +17,7 @@ resources:
|
||||
- services.yaml
|
||||
- backend-deployment.yaml
|
||||
- frontend-deployment.yaml
|
||||
- retention-cronjob.yaml
|
||||
- image.yaml
|
||||
- ingress.yaml
|
||||
- oneoffs/veles-secrets-ensure-job.yaml
|
||||
|
||||
@ -46,7 +46,7 @@ spec:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: postgres
|
||||
image: postgres:15
|
||||
image: postgres:17
|
||||
ports:
|
||||
- name: postgres
|
||||
containerPort: 5432
|
||||
@ -62,13 +62,15 @@ spec:
|
||||
value: veles
|
||||
resources:
|
||||
requests:
|
||||
cpu: "2"
|
||||
memory: 8Gi
|
||||
cpu: "1"
|
||||
memory: 2Gi
|
||||
limits:
|
||||
cpu: "4"
|
||||
memory: 16Gi
|
||||
memory: 8Gi
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
volumeMounts:
|
||||
- name: postgres-data
|
||||
mountPath: /var/lib/postgresql/data
|
||||
@ -83,4 +85,4 @@ spec:
|
||||
storageClassName: veles-oceanus-db
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Gi
|
||||
storage: 200Gi
|
||||
|
||||
@ -13,7 +13,7 @@ spec:
|
||||
pods: "60"
|
||||
count/jobs.batch: "100"
|
||||
persistentvolumeclaims: "8"
|
||||
requests.storage: 300Gi
|
||||
requests.storage: 1Ti
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ResourceQuota
|
||||
|
||||
67
services/veles/retention-cronjob.yaml
Normal file
67
services/veles/retention-cronjob.yaml
Normal file
@ -0,0 +1,67 @@
|
||||
# services/veles/retention-cronjob.yaml
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: veles-retention
|
||||
namespace: veles
|
||||
labels:
|
||||
app: veles-retention
|
||||
spec:
|
||||
schedule: "17 4 * * *"
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 1
|
||||
failedJobsHistoryLimit: 3
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: veles-retention
|
||||
spec:
|
||||
restartPolicy: Never
|
||||
serviceAccountName: veles-retention
|
||||
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: retention
|
||||
image: registry.bstein.dev/veles/veles-backend:0.3.16 # {"$imagepolicy": "veles:veles-backend"}
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["veles-hygiene"]
|
||||
args: ["--prune-artifacts"]
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: veles-config
|
||||
volumeMounts:
|
||||
- name: artifacts
|
||||
mountPath: /data/veles-artifacts
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 250m
|
||||
memory: 512Mi
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 10001
|
||||
runAsGroup: 10001
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
volumes:
|
||||
- name: artifacts
|
||||
persistentVolumeClaim:
|
||||
claimName: veles-artifacts
|
||||
@ -13,22 +13,22 @@ spec:
|
||||
- objectName: "harbor-pull__dockerconfigjson"
|
||||
secretPath: "kv/data/atlas/shared/harbor-pull"
|
||||
secretKey: "dockerconfigjson"
|
||||
- objectName: "veles-db__DATABASE_URL"
|
||||
- objectName: "veles-db__database-url"
|
||||
secretPath: "kv/data/atlas/veles/veles-db"
|
||||
secretKey: "DATABASE_URL"
|
||||
- objectName: "veles-db__POSTGRES_USER"
|
||||
- objectName: "veles-db__user"
|
||||
secretPath: "kv/data/atlas/veles/veles-db"
|
||||
secretKey: "POSTGRES_USER"
|
||||
- objectName: "veles-db__POSTGRES_PASSWORD"
|
||||
- objectName: "veles-db__password"
|
||||
secretPath: "kv/data/atlas/veles/veles-db"
|
||||
secretKey: "POSTGRES_PASSWORD"
|
||||
- objectName: "veles-oidc__client_secret"
|
||||
- objectName: "veles-oidc__client-secret"
|
||||
secretPath: "kv/data/atlas/veles/veles-oidc"
|
||||
secretKey: "client_secret"
|
||||
- objectName: "veles-app-secrets__VELES_SESSION_SECRET"
|
||||
- objectName: "veles-app__session-secret"
|
||||
secretPath: "kv/data/atlas/veles/app-secrets"
|
||||
secretKey: "VELES_SESSION_SECRET"
|
||||
- objectName: "veles-app-secrets__VELES_BYOK_ENCRYPTION_KEY"
|
||||
- objectName: "veles-app__byok-encryption-key"
|
||||
secretPath: "kv/data/atlas/veles/app-secrets"
|
||||
secretKey: "VELES_BYOK_ENCRYPTION_KEY"
|
||||
secretObjects:
|
||||
@ -40,15 +40,31 @@ spec:
|
||||
- secretName: veles-runtime-secrets
|
||||
type: Opaque
|
||||
data:
|
||||
- objectName: veles-db__DATABASE_URL
|
||||
- objectName: veles-db__database-url
|
||||
key: DATABASE_URL
|
||||
- objectName: veles-db__POSTGRES_USER
|
||||
- objectName: veles-db__user
|
||||
key: VELES_DATABASE_USER
|
||||
- objectName: veles-db__POSTGRES_PASSWORD
|
||||
- objectName: veles-db__password
|
||||
key: VELES_DATABASE_PASSWORD
|
||||
- objectName: veles-oidc__client_secret
|
||||
- objectName: veles-oidc__client-secret
|
||||
key: VELES_OIDC_CLIENT_SECRET
|
||||
- objectName: veles-app-secrets__VELES_SESSION_SECRET
|
||||
- objectName: veles-app__session-secret
|
||||
key: VELES_SESSION_SECRET
|
||||
- objectName: veles-app-secrets__VELES_BYOK_ENCRYPTION_KEY
|
||||
- objectName: veles-app__byok-encryption-key
|
||||
key: VELES_BYOK_ENCRYPTION_KEY
|
||||
---
|
||||
apiVersion: secrets-store.csi.x-k8s.io/v1
|
||||
kind: SecretProviderClass
|
||||
metadata:
|
||||
name: veles-codex-cli
|
||||
namespace: veles
|
||||
spec:
|
||||
provider: vault
|
||||
parameters:
|
||||
vaultAddress: "http://vault.vault.svc.cluster.local:8200"
|
||||
roleName: "veles-sim"
|
||||
objects: |
|
||||
- objectName: "auth.json"
|
||||
secretPath: "kv/data/atlas/veles/codex-cli"
|
||||
secretKey: "auth.json"
|
||||
filePermission: "0440"
|
||||
|
||||
@ -12,6 +12,7 @@ kind: ServiceAccount
|
||||
metadata:
|
||||
name: veles-frontend
|
||||
namespace: veles
|
||||
automountServiceAccountToken: false
|
||||
imagePullSecrets:
|
||||
- name: harbor-regcred
|
||||
---
|
||||
@ -25,6 +26,15 @@ imagePullSecrets:
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: veles-retention
|
||||
namespace: veles
|
||||
automountServiceAccountToken: false
|
||||
imagePullSecrets:
|
||||
- name: harbor-regcred
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: veles-vault-sync
|
||||
namespace: veles
|
||||
|
||||
@ -11,7 +11,7 @@ spec:
|
||||
- name: http
|
||||
port: 80
|
||||
protocol: TCP
|
||||
targetPort: http
|
||||
targetPort: 8796
|
||||
selector:
|
||||
app: veles-backend
|
||||
---
|
||||
@ -27,6 +27,6 @@ spec:
|
||||
- name: http
|
||||
port: 80
|
||||
protocol: TCP
|
||||
targetPort: http
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: veles-frontend
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user