自己文書化スクリプト

Lambda Smalltalkの構文は英語のように読める。スクリプトがそのままドキュメントになる。

従来のスクリプトの問題点

シェルスクリプト:

#!/bin/bash
for h in $(cat hosts.txt); do
  ssh $h "systemctl restart nginx" && \
  curl -s -o /dev/null -w "%{http_code}" http://$h/health | grep -q 200 && \
  echo "$h: OK" || echo "$h: FAILED"
done

これが何をしているか?構文を頭の中でパースする必要がある。

Python:

for host in open('hosts.txt'):
    subprocess.run(['ssh', host.strip(), 'systemctl restart nginx'])
    r = requests.get(f'http://{host.strip()}/health')
    print(f"{host.strip()}: {'OK' if r.status_code == 200 else 'FAILED'}")

まだマシだが、読むにはプログラミングの知識が必要。

Smalltalkの書き方

"全サーバーでnginxを再起動し、ヘルスチェックを実行"

hosts := (File read: 'hosts.txt') lines.

hosts do: [:host |
    host restart: 'nginx'.

    (host healthCheck)
        ifTrue:  [ (host, ': OK') printNl ]
        ifFalse: [ (host, ': FAILED') printNl ].
].

声に出して読んでみろ:

コード自体がドキュメントだ。


なぜこれが重要か

1. 監査可能な運用

監査人に「このスクリプトは何をしているか?」と聞かれたら、コードをそのまま見せられる:

"日次バックアップ手順"

Database dump: 'production' to: '/backup/daily/'.
S3 upload: '/backup/daily/' to: 'company-backups' prefix: (Date today asString).
Slack notify: '#ops' message: 'Daily backup completed'.

別途手順書を用意する必要がない。スクリプトがそのまま手順書だ。

2. 属人化の排除

新しいチームメンバーが運用スクリプトをすぐに理解できる:

"ステージングへデプロイ"

Git pull: 'origin/main'.
Docker build: '.' tag: 'app:staging'.
Kubernetes apply: 'k8s/staging.yaml'.

(App healthCheck: 'staging')
    ifTrue:  [ Slack notify: 'Staging deploy successful' ]
    ifFalse: [ Slack notify: 'Staging deploy FAILED' ].

暗黙知は不要。

3. ミスの削減

意図が明確なら、バグも明らか:

"古いログをアーカイブ(バグ - アーカイブではなく削除している!)"
Logs olderThan: 30 days delete.

"古いログをアーカイブ(正しい)"
Logs olderThan: 30 days moveTo: '/archive/'.

コードを読めば誰でもバグに気づく。


実践パターン

ヘルス監視

"全サービスを5分ごとにチェック"

services := #('web-01' 'web-02' 'db-primary' 'cache-01').

services do: [:svc |
    (svc isHealthy) ifFalse: [
        PagerDuty alert: svc , ' is DOWN'.
        svc restart.

        (svc isHealthy)
            ifTrue:  [ PagerDuty resolve: svc , ' recovered after restart' ]
            ifFalse: [ PagerDuty escalate: svc , ' still DOWN after restart' ].
    ].
].

データパイプライン

"ETL: ソースから抽出、変換、ウェアハウスにロード"

data := Postgres query: 'SELECT * FROM events WHERE date = today()'.

data := data
    select: [:row | row at: 'status' = 'completed']
    collect: [:row | row transform: TransformRules].

BigQuery insert: data into: 'analytics.daily_events'.

('Processed ', data size asString, ' records') printNl.

ロールバック付きデプロイ

"ブルーグリーンデプロイメント(自動ロールバック付き)"

| previousVersion |
previousVersion := App currentVersion.

App deploy: newVersion to: 'green'.

(App healthCheck: 'green')
    ifTrue: [
        LoadBalancer switchTo: 'green'.
        Slack notify: 'Deployed ', newVersion, ' successfully'.
    ]
    ifFalse: [
        App rollbackTo: previousVersion.
        Slack notify: 'Deploy failed, rolled back to ', previousVersion.
        PagerDuty alert: 'Deployment failure'.
    ].

はじめよう

Lambda Smalltalkは基本的な構成要素を提供する。以下と組み合わせて使え:

詳しいパターンは Examples を参照。