どんな運用チームにも、まだ自動化するところまで手が回っていない手作業があるものです。 トイル (toil) が完全に無くなることは決してありません。
成長企業のチームに非常にありがちなのが、インフラの変更手続きやユーザーアカウントのプロビジョニングが、最大のトイル源となっているケースです。 後者の例について手順の一部を書き出してみると、たとえば以下のようになるでしょう:
- ユーザーのSSHキーペアを作成する
- 公開鍵をGitにコミットしてmasterにプッシュする
- ビルドジョブの完了を待つ
- 従業員のディレクトリからユーザーのメールアドレスを見つける
- 1Password経由でユーザーに秘密鍵を送信する
これは比較的短い例ですが、一連のプロセスが20ステップに達することもあります。 またあるときは作業が分岐するケース、作業を進めるとともに経過を追っていかなければならないような特殊ケースが発生することもあるでしょう。 時が経つにつれ、このような手順は手のつけようのないほど大きく複雑になってしまう可能性があります。
こういった手続きは、考える必要のあることはほとんどないにも関わらずじっと注視していなければならないので、フラストレーションが溜まるものです。 全力で注意を向けていなければらならないのに、私たちは面白い問題や充実した解決策によって報われることはありません。単に、終わったらチェックボックスに作業完了のチェックが入るだけです。 このような手続きのことを、私は スログ (slog, 長くつらい仕事) と呼んでいます。
この手の手続きこそ、まさに自動化の対象といえるでしょう。 個々のどのステップも、どうやって自動化したらいいかは容易にわかります。 そしてコンピュータは私たちよりもずっと速く、正確に、かつ実務上のブレ (practical drift)に至りにくく、忠実に指示を実行してくれることも知っています。
しかしながら、ときにスログの自動化は1か0かの命題のように感じられます。 ええ、ステップ2やステップ5を実行するスクリプトは書けるでしょう。 しかし、それだけでは手続きの煩わしさを本当に減らすことはできません。 単一の目的を持ったスクリプトを別の規約や期待に応えるよう拡張することにつながり、今度はスクリプトを使う上で複数ステップからなる手続きに従う羽目になるかもしれません。
このような無駄の認知こそ、手作業のスログから脱出するために本当に解決しなければならない問題です。 私は、そのようなときにかなりの確度で役立つアプローチを見つけました: 「なんにもしない」スクリプトを書くことです。
「なんにもしない」スクリプトを書く
ほぼどのようなスログであっても、なんにもしないスクリプト へ落とし込むことができます。 なんにもしないスクリプトとは、スログの手続きをコード化したスクリプトで、各ステップを関数の中にカプセル化したものです。たとえば上記の手順なら以下のように、なんにもしないスクリプトを書けるでしょう:
import sys
def wait_for_enter():
raw_input("Press Enter to continue: ")
class CreateSSHKeypairStep(object):
def run(self, context):
print("Run:")
print(" ssh-keygen -t rsa -f ~/{0}".format(context["username"]))
wait_for_enter()
class GitCommitStep(object):
def run(self, context):
print("Copy ~/new_key.pub into the `user_keys` Git repository, then run:")
print(" git commit {0}".format(context["username"]))
print(" git push")
wait_for_enter()
class WaitForBuildStep(object):
build_url = "http://example.com/builds/user_keys"
def run(self, context):
print("Wait for the build job at {0} to finish".format(self.build_url))
wait_for_enter()
class RetrieveUserEmailStep(object):
dir_url = "http://example.com/directory"
def run(self, context):
print("Go to {0}".format(self.dir_url))
print("Find the email address for user `{0}`".format(context["username"]))
context["email"] = raw_input("Paste the email address and press enter: ")
class SendPrivateKeyStep(object):
def run(self, context):
print("Go to 1Password")
print("Paste the contents of ~/new_key into a new document")
print("Share the document with {0}".format(context["email"]))
wait_for_enter()
if __name__ == "__main__":
context = {"username": sys.argv[1]}
procedure = [
CreateSSHKeypairStep(),
GitCommitStep(),
WaitForBuildStep(),
RetrieveUserEmailStep(),
SendPrivateKeyStep(),
]
for step in procedure:
step.run(context)
print("Done.")
実際のところ、このスクリプトは手順にあるステップに関して何もしません。 それゆえに、なんにもしないスクリプトと呼んでいます。 1つのタイミングにつき1つのステップをユーザーに見せて、手作業が完了するのを待つだけです。
初めは一見、このようなスクリプトに意味があるとは考えにくいかもしれません。 おそらくは、単に手順を読みづらくしただけなのではないかと。 ですが、なんにもしないスクリプトの効果はてきめんです:
- 今やっていることを見失い、ステップを飛ばしてしまうような失敗を減らせます。その結果、スログに集中して注力することが楽になります。
- 手続きの各プロセスが関数の中にカプセル化されているので、ステップ内のテキストを、自動化されたアクションをとるコードに置き換えていくことが可能です。
- しだいに、あなたは便利なステップのライブラリを開発するようになり、将来的に自動化のタスクの効率が向上するでしょう。
なんにもしないスクリプトは、あなたのチームの手作業を減らすことはありません。 しかしタスクを自動化するに至るまでのハードルを下げ、チームが徐々にトイルを削減するのに役立つことでしょう。