---
# yaml-language-server: $schema=https://taskfile.dev/schema.json
version: '3'

# Taskfile used to manage certain VolSync tasks for a given application, limitations are as followed.
#   1. Fluxtomization, HelmRelease, PVC, ReplicationSource all have the same name (e.g. plex)
#   2. ReplicationSource and ReplicationDestination are a Restic repository
#   3. Each application only has one PVC that is being replicated

vars:
  VOLSYNC_RESOURCES_DIR: '{{.ROOT_DIR}}/.taskfiles/volsync/resources'

tasks:

  state-*:
    desc: Suspend or resume Volsync [CLUSTER=main]
    cmds:
      - flux --namespace flux-system {{.STATE}} kustomization volsync
      - flux --namespace volsync-system {{.STATE}} helmrelease volsync
      - kubectl --namespace volsync-system scale deployment volsync --replicas {{if eq .STATE "suspend"}}0{{else}}1{{end}}
    vars:
      STATE: '{{index .MATCH 0}}'
    requires:
      vars: [CLUSTER]
    preconditions:
      - '[[ "{{.STATE}}" == "suspend" || "{{.STATE}}" == "resume" ]]'
      - which flux kubectl

  unlock:
    desc: Unlock all restic source repos [CLUSTER=main]
    cmds:
      - for: { var: SOURCES, split: "\n" }
        cmd: kubectl --namespace {{splitList "," .ITEM | first}} patch --field-manager=flux-client-side-apply replicationsources {{splitList "," .ITEM | last}} --type merge --patch "{\"spec\":{\"restic\":{\"unlock\":\"{{now | unixEpoch}}\"}}}"
    vars:
      SOURCES:
        sh: kubectl get replicationsources --all-namespaces --no-headers --output=jsonpath='{range .items[*]}{.metadata.namespace},{.metadata.name}{"\n"}{end}'
    requires:
      vars: [CLUSTER]
    preconditions:
      - which kubectl

  snapshot:
    desc: Snapshot an app [CLUSTER=main] [NS=default] [APP=required]
    cmds:
      - kubectl --namespace {{.NS}} patch replicationsources {{.APP}} --type merge -p '{"spec":{"trigger":{"manual":"{{now | unixEpoch}}"}}}'
      - until kubectl --namespace {{.NS}} get job/{{.JOB}} &>/dev/null; do sleep 5; done
      - kubectl --namespace {{.NS}} wait job/{{.JOB}} --for=condition=complete --timeout=120m
    vars:
      NS: '{{.NS | default "default"}}'
      JOB: volsync-src-{{.APP}}
    requires:
      vars: [CLUSTER, APP]
    preconditions:
      - kubectl --namespace {{.NS}} get replicationsources {{.APP}}
      - which kubectl

  restore:
    desc: Restore an app [CLUSTER=main] [NS=default] [APP=required] [PREVIOUS=required]
    cmds:
      # Suspend
      - flux --namespace flux-system suspend kustomization {{.APP}}
      - flux --namespace {{.NS}} suspend helmrelease {{.APP}}
      - kubectl --namespace {{.NS}} scale {{.CONTROLLER}}/{{.APP}} --replicas 0
      - kubectl --namespace {{.NS}} wait pod --for=delete --selector="app.kubernetes.io/name={{.APP}}" --timeout=5m
      # Restore
      - minijinja-cli {{.VOLSYNC_RESOURCES_DIR}}/replicationdestination.yaml.j2 | kubectl apply --server-side --filename -
      - until kubectl --namespace {{.NS}} get job/volsync-dst-{{.APP}}-manual &>/dev/null; do sleep 5; done
      - kubectl --namespace {{.NS}} wait job/volsync-dst-{{.APP}}-manual --for=condition=complete --timeout=120m
      - kubectl --namespace {{.NS}} delete replicationdestination {{.APP}}-manual
      # Resume
      - flux --namespace flux-system resume kustomization {{.APP}}
      - flux --namespace {{.NS}} resume helmrelease {{.APP}}
      - flux --namespace {{.NS}} reconcile helmrelease {{.APP}} --force
      - kubectl --namespace {{.NS}} wait pod --for=condition=ready --selector="app.kubernetes.io/name={{.APP}}" --timeout=5m
    vars:
      NS: '{{.NS | default "default"}}'
      CONTROLLER:
        sh: kubectl --namespace {{.NS}} get deployment {{.APP}} &>/dev/null && echo deployment || echo statefulset
    env:
      NS: '{{.NS}}'
      APP: '{{.APP}}'
      PREVIOUS: '{{.PREVIOUS}}'
      CLAIM:
        sh: kubectl --namespace {{.NS}} get replicationsources/{{.APP}} --output=jsonpath="{.spec.sourcePVC}"
      ACCESS_MODES:
        sh: kubectl --namespace {{.NS}} get replicationsources/{{.APP}} --output=jsonpath="{.spec.restic.accessModes}"
      STORAGE_CLASS_NAME:
        sh: kubectl --namespace {{.NS}} get replicationsources/{{.APP}} --output=jsonpath="{.spec.restic.storageClassName}"
      PUID:
        sh: kubectl --namespace {{.NS}} get replicationsources/{{.APP}} --output=jsonpath="{.spec.restic.moverSecurityContext.runAsUser}"
      PGID:
        sh: kubectl --namespace {{.NS}} get replicationsources/{{.APP}} --output=jsonpath="{.spec.restic.moverSecurityContext.runAsGroup}"
    requires:
      vars: [CLUSTER, APP, PREVIOUS]
    preconditions:
      - test -f {{.VOLSYNC_RESOURCES_DIR}}/replicationdestination.yaml.j2
      - which flux kubectl minijinja-cli