diff --git a/.gitignore b/.gitignore index 468bf057..2b35956a 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,7 @@ spicy-secrets/** tilt_config.json .local-data/ -.helm-cache/ \ No newline at end of file +.helm-cache/ + +# Script related stuff +**/.gradle \ No newline at end of file diff --git a/README.MD b/README.MD index fbe070e4..3a235d32 100644 --- a/README.MD +++ b/README.MD @@ -52,13 +52,14 @@ kubectl apply -f app-set-test.yaml Many apps will fail to start, because the lack the secrets that will be generated by infisical. But infiscal needs be setup too. We use the cloud edition, but there is also a self hosted one we do not cover here. -For our stack you need to create a service token in the web ui and add this as a secret in all affected namespaces: +For our stack you need to create a machine identity in the web ui and add its credentials as a secret in all affected namespaces: ```sh -for namespace in "faf-apps faf-ops argocd"; do -kubectl create secret generic "infisical-service-token" \ +for namespace in faf-apps faf-ops argocd replay-mounter; do + kubectl create secret generic infisical-machine-identity \ -n "$namespace" \ - --from-literal=infisicalToken= + --from-literal=clientId= \ + --from-literal=clientSecret= done ``` diff --git a/apps/ory-hydra/templates/config.yaml b/apps/ory-hydra/templates/config.yaml index 9aa1ccb7..b2ccdc14 100644 --- a/apps/ory-hydra/templates/config.yaml +++ b/apps/ory-hydra/templates/config.yaml @@ -9,8 +9,9 @@ data: URLS_SELF_ISSUER: "https://hydra.{{.Values.baseDomain}}" URLS_LOGIN: "https://user.{{.Values.baseDomain}}/oauth2/login" URLS_CONSENT: "https://user.{{.Values.baseDomain}}/oauth2/consent" + URLS_DEVICE_VERIFICATION: "https://user.{{.Values.baseDomain}}/oauth2/device-login" STRATEGIES_ACCESS_TOKEN: "jwt" OAUTH2_CLIENT_CREDENTIALS_DEFAULT_GRANT_ALLOWED_SCOPE: "true" # These are only used for mariadb init script, it is redundant in the DSN secret! Don't forget to also create a secret for DB_PASSWORD DB_USER: "hydra" - DB_NAME: "ory-hydra" + DB_NAME: "ory-hydra" \ No newline at end of file diff --git a/cluster/argocd/Chart.yaml b/cluster/argocd/Chart.yaml index 4b83efb0..13fc9de7 100644 --- a/cluster/argocd/Chart.yaml +++ b/cluster/argocd/Chart.yaml @@ -3,5 +3,5 @@ name: argocd version: 1.0.0 dependencies: - name: argo-cd - version: 9.4.10 + version: 9.4.15 repository: https://argoproj.github.io/argo-helm diff --git a/cluster/argocd/templates/secret.yaml b/cluster/argocd/templates/secret.yaml index 93336a83..d3178277 100644 --- a/cluster/argocd/templates/secret.yaml +++ b/cluster/argocd/templates/secret.yaml @@ -11,8 +11,8 @@ spec: secretName: infisical-machine-identity secretNamespace: argocd secretsScope: - projectSlug: {{.Values.infisical.projectSlug}} - envSlug: {{.Values.infisical.envSlug}} + projectSlug: {{ index .Values "infisical-secret" "projectSlug" }} + envSlug: {{ index .Values "infisical-secret" "envSlug" }} secretsPath: "/argocd" managedSecretReference: secretName: dex-github diff --git a/cluster/namespaces.yaml b/cluster/namespaces.yaml index 5b72ac64..45cf6299 100644 --- a/cluster/namespaces.yaml +++ b/cluster/namespaces.yaml @@ -19,4 +19,10 @@ metadata: apiVersion: v1 kind: Namespace metadata: - name: traefik \ No newline at end of file + name: traefik + +--- +apiVersion: v1 +kind: Namespace +metadata: + name: replay-mounter \ No newline at end of file diff --git a/cluster/replay-mounter/Chart.yaml b/cluster/replay-mounter/Chart.yaml new file mode 100644 index 00000000..b8b0eb31 --- /dev/null +++ b/cluster/replay-mounter/Chart.yaml @@ -0,0 +1,9 @@ +apiVersion: v2 +name: replay-mounter +version: 1.0.0 +description: CIFS/SMB mount watchdog for the faf-replays hostPath PV + +dependencies: + - name: infisical-secret + version: 1.0.0 + repository: file://../../common/infisical-secret diff --git a/cluster/replay-mounter/templates/daemonset.yaml b/cluster/replay-mounter/templates/daemonset.yaml new file mode 100644 index 00000000..e733212f --- /dev/null +++ b/cluster/replay-mounter/templates/daemonset.yaml @@ -0,0 +1,102 @@ +{{- if .Values.cifsMount.enabled }} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: replay-mounter + namespace: replay-mounter +spec: + selector: + matchLabels: + app: replay-mounter + template: + metadata: + labels: + app: replay-mounter + spec: + nodeSelector: + openebs.io/nodeid: {{ .Values.zfs.nodeId }} + terminationGracePeriodSeconds: 30 + containers: + - name: replay-mounter + image: {{ .Values.cifsMount.image }} + securityContext: + privileged: true + env: + - name: CIFS_SERVER + valueFrom: + secretKeyRef: + name: {{ .Values.cifsMount.credentialsSecret }} + key: CIFS_SERVER + - name: CIFS_USERNAME + valueFrom: + secretKeyRef: + name: {{ .Values.cifsMount.credentialsSecret }} + key: CIFS_USERNAME + - name: CIFS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.cifsMount.credentialsSecret }} + key: CIFS_PASSWORD + - name: MOUNT_TARGET + value: "{{ .Values.cifsMount.mountPath }}" + volumeMounts: + - name: host-base + mountPath: "{{ .Values.cifsMount.hostBasePath }}" + mountPropagation: Bidirectional + command: + - /bin/sh + - -c + - | + echo "Installing cifs-utils..." + apk add --no-cache cifs-utils + echo "cifs-utils installed." + + cleanup() { + echo "Shutting down, unmounting $MOUNT_TARGET..." + umount "$MOUNT_TARGET" 2>/dev/null || \ + umount -l "$MOUNT_TARGET" 2>/dev/null || true + exit 0 + } + trap cleanup TERM INT + + mount_cifs() { + mkdir -p "$MOUNT_TARGET" + echo "Mounting $CIFS_SERVER -> $MOUNT_TARGET..." + mount -t cifs "$CIFS_SERVER" "$MOUNT_TARGET" \ + -o "username=$CIFS_USERNAME,password=$CIFS_PASSWORD,{{ .Values.cifsMount.mountOptions }}" + } + + is_mounted() { grep -q " $MOUNT_TARGET cifs " /proc/mounts; } + is_alive() { timeout 5 ls "$MOUNT_TARGET" > /dev/null 2>&1; } + + if is_mounted; then + echo "Mount already present, skipping initial mount." + else + echo "Mount not present, mounting..." + until mount_cifs; do echo "Mount failed, retrying in 10s..."; sleep 10; done + echo "Mount successful." + fi + + echo "Entering watchdog loop (30s interval)..." + # is_mounted catches a fully gone mount (umount); + # is_alive catches a dead connection (soft mount returns error instead of hanging) + while true; do + sleep 30 & + wait $! + if ! is_mounted; then + echo "Watchdog: mount gone, remounting..." + mount_cifs || true + elif ! is_alive; then + echo "Watchdog: mount unreachable, remounting..." + umount -l "$MOUNT_TARGET" 2>/dev/null || true + mount_cifs || true + else + echo "Watchdog: mount healthy at $(date -Iseconds)." + fi + done + volumes: + - name: host-base + hostPath: + path: "{{ .Values.cifsMount.hostBasePath }}" + type: Directory +{{- end }} diff --git a/cluster/replay-mounter/values-prod.yaml b/cluster/replay-mounter/values-prod.yaml new file mode 100644 index 00000000..1937f5d1 --- /dev/null +++ b/cluster/replay-mounter/values-prod.yaml @@ -0,0 +1,2 @@ +cifsMount: + enabled: true diff --git a/cluster/replay-mounter/values-test.yaml b/cluster/replay-mounter/values-test.yaml new file mode 100644 index 00000000..1937f5d1 --- /dev/null +++ b/cluster/replay-mounter/values-test.yaml @@ -0,0 +1,2 @@ +cifsMount: + enabled: true diff --git a/cluster/replay-mounter/values.yaml b/cluster/replay-mounter/values.yaml new file mode 100644 index 00000000..5c01889c --- /dev/null +++ b/cluster/replay-mounter/values.yaml @@ -0,0 +1,14 @@ +cifsMount: + enabled: false + mountPath: "/opt/faf/data/replays-old" + hostBasePath: "/opt/faf/data" # parent dir shared via Bidirectional propagation + credentialsSecret: "cifs-credentials" + mountOptions: "ro,soft,vers=3.0,uid=1000,gid=1000,file_mode=0644,dir_mode=0755" + image: "alpine:3.21" + +# zfs.nodeId injected from config/prod.yaml +# infisical-secret.enabled injected from config/prod.yaml +infisical-secret: + name: cifs-credentials + secretNamespace: replay-mounter # namespace where infisical-machine-identity lives + overrideSecretPath: "/replay-mounter"