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

tasks:
  bootstrap:
    desc: Bootstrap Talos
    summary: |
      Args:
        CONTROLLER: Controller node to run command against (required)
    prompt: Bootstrap Talos on the '{{.K8S_CLUSTER}}' cluster... continue?
    cmds:
      - task: bootstrap-etcd
        vars: &vars
          CONTROLLER: "{{.CONTROLER}}"
      - task: fetch-kubeconfig
        vars: *vars
      - task: bootstrap-integrations
        vars: *vars
    requires:
      vars:
        - K8S_CLUSTER
        - CONTROLLER

  bootstrap-etcd:
    desc: Bootstrap Etcd
    cmd: until talosctl --nodes {{.CONTROLLER}} bootstrap; do sleep 10; done
    requires:
      vars:
        - CONTROLLER

  bootstrap-integrations:
    desc: Bootstrap core integrations needed for Talos
    cmds:
      - until kubectl wait --for=condition=Ready=False nodes --all --timeout=600s; do sleep 10; done
      - helmfile --kube-context {{.K8S_CLUSTER}} --file {{.K8S_CLUSTER_DIR}}/bootstrap/helmfile.yaml apply --skip-diff-on-install --suppress-diff
      - until kubectl wait --for=condition=Ready nodes --all --timeout=600s; do sleep 10; done
    requires:
      vars:
        - K8S_CLUSTER
    preconditions:
      - which helmfile
      - sh: kubectl config get-contexts {{.K8S_CLUSTER}}
        msg: "Kubectl context {{.K8S_CLUSTER}} not found"
      - test -f {{.K8S_CLUSTER_DIR}}/bootstrap/helmfile.yaml

  fetch-kubeconfig:
    desc: Fetch kubeconfig from Talos controllers
    cmd: |
      talosctl kubeconfig --nodes {{.CONTROLLER}} \
        --force --force-context-name {{.K8S_CLUSTER}} {{.K8S_CLUSTER_DIR}}
    requires:
      vars:
        - K8S_CLUSTER

  generate-clusterconfig:
    desc: Generate clusterconfig for Talos
    preconditions:
      - which test talhelper
      - test -f {{.K8S_CLUSTER_DIR}}/bootstrap/talos/talsecret.sops.yaml
      - test -f {{.K8S_CLUSTER_DIR}}/bootstrap/talos/talconfig.yaml
    requires:
      vars:
        - K8S_CLUSTER
    cmds:
      - talhelper genconfig
        --env-file {{.K8S_CLUSTER_DIR}}/bootstrap/talos/talenv.sops.yaml
        --secret-file {{.K8S_CLUSTER_DIR}}/bootstrap/talos/talsecret.sops.yaml
        --config-file {{.K8S_CLUSTER_DIR}}/bootstrap/talos/talconfig.yaml
        --out-dir {{.K8S_CLUSTER_DIR}}/bootstrap/talos/clusterconfig

  apply-clusterconfig:
    desc: Apply clusterconfig for a Talos cluster
    vars:
      CLUSTERCONFIG_FILES:
        sh: ls {{.K8S_CLUSTER_DIR}}/bootstrap/talos/clusterconfig/*.yaml
    preconditions:
      - which ls
      - test -f "${TALOSCONFIG}"
    requires:
      vars:
        - K8S_CLUSTER
    cmds:
      - for:
          var: CLUSTERCONFIG_FILES
        task: _apply-machineconfig
        vars:
          FILENAME: "{{.ITEM}}"
          HOSTNAME: |-
            {{ trimPrefix (printf "%s-" .K8S_CLUSTER) (base .ITEM) | trimSuffix ".yaml" }}
          DRY_RUN: "{{ .DRY_RUN }}"
          INSECURE: "{{ .INSECURE }}"

  apply-node:
    desc: Apply Talos config to a node [NODE=required]
    preconditions:
      - which talosctl
      - test -f "${TALOSCONFIG}"
      - talosctl --nodes {{.NODE}} get machineconfig
    requires:
      vars:
        - K8S_CLUSTER
        - NODE
    vars:
      FILE:
        sh: ls {{.K8S_CLUSTER_DIR}}/bootstrap/talos/clusterconfig/{{.K8S_CLUSTER}}-{{.NODE}}*.yaml
    cmds:
      - task: _apply-machineconfig
        vars:
          FILENAME: "{{.FILE}}"
          HOSTNAME: "{{.NODE}}"
      - talosctl --nodes {{.NODE}} health --wait-timeout=10m --server=false

  upgrade-node:
    desc: Upgrade Talos on a single node [NODE=required]
    preconditions:
      - which talosctl
      - test -f "${TALOSCONFIG}"
      - talosctl --nodes {{.NODE}} get machineconfig
    requires:
      vars:
        - K8S_CLUSTER
        - NODE
    vars:
      FILE:
        sh: ls {{.K8S_CLUSTER_DIR}}/bootstrap/talos/clusterconfig/{{.K8S_CLUSTER}}-{{.NODE}}*.yaml
      TALOS_IMAGE:
        sh: yq '.machine.install.image' < "{{.FILE}}"
    cmds:
      - echo "Upgrading Talos on node {{.NODE}}"
      - talosctl --nodes {{.NODE}} upgrade --image="{{.TALOS_IMAGE}}" --timeout=10m
      - talosctl --nodes {{.NODE}} health --wait-timeout=10m --server=false

  _apply-machineconfig:
    internal: true
    desc: Apply a single Talos machineConfig to a Talos node
    vars:
      MODE: '{{.MODE | default "auto"}}'
    preconditions:
      - which talosctl
      - test -f "{{.FILENAME}}"
    requires:
      vars:
        - K8S_CLUSTER
        - HOSTNAME
        - FILENAME
    cmds:
      - talosctl apply-config
        --nodes "{{.HOSTNAME}}"
        --file "{{.FILENAME}}"
        --mode="{{.MODE}}"
        {{ if eq "true" .INSECURE }}--insecure{{ end }}
        {{ if eq "true" .DRY_RUN }}--dry-run{{ end }}