Task je moderní varianta legendárního Make, což jej předurčuje k automatizaci a univerzálnímu použití. Jedním ze způsobů, kde Taskfile dokáže fantasticky pomoct, je správa vzdálených přístupů přes SSH. Zoxide jako cd na stereoidech tomu skvěle sekunduje. Ukážeme si jak.

Unixová předmluva

Unixová filozofie založená na adresářové struktuře a silných CLI utilitách je nepřekonatelná. Ačkoliv většina začátečníků dává přednost grafickým klikátkům, s postupem času se admini vždy dopracují k příkazové řádce. Nejen pro její efektivitu, ale také pro možnost skriptování a takřka neomezenou univerzálnost. Představte si adresář např. s názvem ~/infra a v něm podadresáře označující vzdálené SSH stroje, např. ~/infra/vps1.example.com a ~/infra/vps2.example.com. Pokud se přepneme z vps1 do takového adresáře, stačí jen spustit task ssh a jsme nalogovaní.

zoxide

Kdo nezná zoxide, ten se jistě zarazil nad z vps1. Jak už bylo řečeno, zoxide je takové cd na stereoidech. Pamatuje si adresářové cesty, na které často chodíme a pak nám umožní přes z <kousek_názvu> skočit rovnou do adresáře, jehož název obsahuje <kousek_názvu>. Zoxide se vyplatí používat každému. Bez ohledu na to, jestli jej kombinuje s Task nebo ne. Zoxide je administrátorský must-have.

Task

Nyní k Task. Abychom jej dokázali náležitě ocenit, připomeňme si základní rozdíly mezi Make (Makefile) a Task (Taskfile.yml):

VlastnostMakeTask (go-task)
Nástrojmaketask
Konfigurační souborMakefileTaskfile.yml
SyntaxeVlastní DSLYAML
Primární účelBuild systémObecný task runner
Typ závislostíSouborové (timestamp-based)Logické mezi tasky
Cross-platformPrimárně UnixLinux / macOS / Windows
ČitelnostHorší u větších projektůVelmi dobrá
InstalaceObvykle předinstalovánoNutná instalace nástroje
Paralelní běhAno (-j)Ano (native podpora)
Typické použitíKompilace, CI buildDev workflow, Docker, migrace, testy

Jaký je tedy princip? V terminálu přes z vps1 skočit do lokálního adresáře náležejícímu konkrétnímu stroji a přes task ssh se do něj nalogovat. Samozřejmě s podporou certifikátů a hardwarových klíčů. Ale to snad netřeba zdůrazňovat.

Struktura projektu

.
├── .git
├── .gitignore
├── targets
   ├── vps1.example.com
   ├── .env
   ├── Taskfile.yml -> ../../tasks/Taskfile.yml
   └── tasks -> ../../tasks
   └── vps2.example.com
       ├── .env
       ├── Taskfile.yml -> ../../tasks/Taskfile.yml
       └── tasks -> ../../tasks
└── tasks
    ├── ping.yml
    ├── ssh.yml
    ├── talos
    └── Taskfile.yml

Příklad pro konfigurační soubor .env:

targets/vps1.example.com/.env
INFRA_NAME=vps1.example.com
INFRA_HOST=vps1.example.com

INFRA_SSH=true
INFRA_SSH_PORT=2222
INFRA_SSH_USER=user

Obsah Taskfile.yml:

Taskfile.yml
version: '3'

dotenv: ['.env']

includes:
  fping:
    taskfile: ./tasks/fping.yml
    flatten: true

  ping:
    taskfile: ./tasks/ping.yml
    flatten: true

  ssh:
    taskfile: ./tasks/ssh.yml
    flatten: true

Všímavější jistě napadlo, že přes task fping a task ping si můžeme z konkrétního adresáře opingat konkrétní stroj. A mají pravdu. Protože jsme jednotlivé tasks rozhodili do vyhrazených souborů, pojďme si ukázat jejich obsah:

fping.yml
version: '3'

tasks:
  fping:
    desc: "Ping with fping"
    silent: true
    cmds:
      - |
        if [ -z "$INFRA_HOST" ]; then
          echo "INFRA_HOST is not set in .env file" >&2
          exit 1
        fi
        fping "$INFRA_HOST"
ping.yml
version: '3'

tasks:
  ping:
    desc: "Ping until CTRL+C is pressed"
    silent: true
    cmds:
      - |
        if [ -z "$INFRA_HOST" ]; then
          echo "INFRA_HOST is not set in .env file"
          exit 1
        fi
        ping "$INFRA_HOST"
ssh.yml
version: '3'

tasks:
  ssh:
    desc: "SSH connect"
    silent: true
    cmds:
      - |
        if [ "${INFRA_SSH}" != "true" ]; then
          echo "INFRA_SSH is not true. Skipping SSH connection."
          exit 0
        fi

        SSH_PORT=${INFRA_SSH_PORT:-22}
        SSH_USER=${INFRA_SSH_USER:-root}
        SSH_HOST=${INFRA_HOST:-${INFRA_NAME}}

        if [ -z "${SSH_HOST}" ]; then
          read -p "Enter target host: " SSH_HOST
        fi

        echo "Connecting to ${SSH_USER}@${SSH_HOST} on port ${SSH_PORT}..."
        ssh -p "${SSH_PORT}" -l "${SSH_USER}" "${SSH_HOST}"

Pingáním to nekončí

Nyní, když jsme si hezky rozchodili fping, ping a ssh, jistě vás napadá spousta dalších rozšíření. O tom třeba někdy jindy. Ale pro ochutnávku jak to může vypadat s podporou pro Helm, Kubernetes a Talos:

targets/talos.example.com/.env
INFRA_NAME=talos.example.com
INFRA_HOST=xxx.xxx.xxx.xxx

# SSH
INFRA_SSH=false

# Kubernetes
INFRA_KUBERNETES=true

# Talos
INFRA_TALOS=true
INFRA_TALOS_BOOTSTRAP_CLUSTERNAME=talos.example.com
INFRA_TALOS_BOOTSTRAP_ENDPOINT=https://xxx.xxx.xxx.xxx:6443
.
├── .git
├── .gitignore
├── targets
   ├── talos.example.com
   ├── .env
   ├── Taskfile.yml -> ../../tasks/Taskfile.yml
   └── tasks -> ../../tasks
   └── vps2.example.com
       ├── .env
       ├── Taskfile.yml -> ../../tasks/Taskfile.yml
       └── tasks -> ../../tasks
└── tasks
    ├── fping.yml
    ├── helm
   └── helm.yml
    ├── kubernetes
   ├── get-nodes.yml
   └── kubectl.yml
    ├── ping.yml
    ├── ssh.yml
    ├── talos
   ├── bootstrap.yml
   ├── create-single-cluster.yml
   ├── dashboard.yml
   ├── download-kubeconfig.yml
   ├── gen-config.yml
   ├── get-extensions.yml
   ├── health.yml
   ├── query-mstage.yml
   ├── talosctl.yml
   └── version.yml
    └── Taskfile.yml

Symlinky pro praktičnost

Aby všechno krásně fungovalo a my jsme nemuseli do každého podadresáře kopírovat konfigurační soubory, uděláme symlink nejen pro Taskfile.yml, ale také pro celý podadresář ./tasks. Jistě, nebylo nutné includes používat, když budeme mít jen tři tasky task fping | task ping | task ssh, ale jako základ pro budoucí rozšíření je fajn to rozdělit hned ze startu.

Task můžeme používat bez zoxide a naopak. Ale kombinace těchto dvou nástrojů je famózní. Tak co, kolik dalších využití pro task xy vás napadá?