herokuへのメンテナンスを行うための中継サーバの構成をansibleで作っている最中です。
やりたいことはほぼできたのですが、1つだけ課題が残っていました。それは、ansibleでherokuに自動ログインできないことです。今回、それをなんとか自動ログインさせることに成功したので、メモとして残しておきます。
expectモジュールだとNG
herokuへのログインはheroku cliを使えばCUIでできるので、ansibleのexpectモジュールを使ってログインしようとしたのですが、なぜかうまくいきませんでした。 どうも、herokuのパスワードを入力後の改行コードが何故かパスワードの一部として解釈されてしまい、タイムアウトしてしまいました。
NGだったやつを残しておきます。
--- - name: heroku-cliのインストール command: sudo sh -c "export PATH=/usr/local/bin:$PATH && curl https://cli-assets.heroku.com/install.sh | sh" args: creates: /usr/local/bin/heroku - name: pexpectのインストール pip: name: pexpect executable: pip3.8 - name: Heroku Loginする become_user: "{{ user }}" expect: command: heroku auth:login --interactive responses: "Email: ": "{{ heroku_email }}" "Password: ": "{{ heroku_token }}" echo: yes environment: PATH: "/usr/local/bin:{{ ansible_env.PATH }}" no_log: yes
scriptモジュール経由でexpectを使えばOK
入力の自動化はexpectでできるはずなので、もっと具体的に書き込めばいいかなと思い、expectコマンドをインストールして直接使うようにしてみました。
roleのファイルはこれ。
変数でheroku_email
とheroku_token
を渡しています。(2要素認証にしているためパスワードの代わりにトークンを使用)
ローカルにscriptがあればいいので、scriptモジュールで指定。argsのexecutableで実行される命令としてexpectを指定しています(デフォルトだとshになる)
--- - name: heroku-cliのインストール command: sudo sh -c "export PATH=/usr/local/bin:$PATH && curl https://cli-assets.heroku.com/install.sh | sh" args: creates: /usr/local/bin/heroku - name: yumでexpectのインストール yum: name: expect state: present - name: ローカルから、expectスクリプトを実行してheroku loginする become_user: "{{ user }}" script: heroku_login.exp args: executable: /usr/bin/expect environment: PATH: "/usr/local/bin:{{ ansible_env.PATH }}" HEROKU_EMAIL: "{{ heroku_email }}" HEROKU_TOKEN: "{{ heroku_token }}" changed_when: false
expectスクリプトである、heroku_login.expは、これ。肝は、sendでパスワード文字列を送った後に入れているsleep 1
です。
spawn heroku auth:login --interactive sleep 1 expect "Email: " send "$env(HEROKU_EMAIL)" send "\r" sleep 1 expect "Password: " send "$env(HEROKU_TOKEN)" sleep 1 send "\r" sleep 2 interact
heroku cliは、入力されたパスワード文字列を****
という感じに隠してくれるのですが、表示が****
になる前に改行コード\r
を送ってしまうと、パスワードの1部と解釈されるみたいでした。
そのため、パスワード入力後に1秒のsleepを差し込んで、****
に変換されるのを確認した後、改行コードを送るようにしたところ、ログインできました👍