2018年6月30日土曜日

fabric2 入門

概要

fabric は Python 製のデプロイツールです
簡単に言うとパラレルでシェルを実行することができるツールです
Ruby でいうところの Capistrano です
今回はインストールから簡単なサンプルを実行するところまでやってみました

環境

  • macOS 10.13.5
  • Python 3.6.5
  • fabric 2.1.3

インストール

  • pip3 install fabric

サンプル集

いろいろと実行してみます
サーバへのアクセスは ID/PW 認証を想定しています

とりあえず SSH してコマンド実行

  • vim first.py
from fabric import Connection

conn = Connection("root@172.28.128.3", connect_kwargs = { "password": "xxxxxxxx" })
result = conn.run('uname -s')
print(result)

いきなりポイントですが認証情報を fabric のコード上に記載する場合は connect_kwargs オプションを使います
fabric1 では env を使うらしいのですが、fabric2 では使えません
代わりに Connection のインスタンスを生成する際に引数で指定します
ここで渡した connect_kwargs の dict はそのまま paramiko.client.SSHClient.connect のオプションとして扱われます

また、ホスト情報とユーザ情報だけは connect_kwargs には含めず、Connection の第一引数で指定します
connect_kwargs 側で指定すると

ValueError: Refusing to be ambiguous: connect() kwarg 'hostname' was given both via regular arg and via connect_kwargs!

というエラーになります

ファイルをアップロードする

  • vim upload.py
from fabric import Connection

conn = Connection("root@172.28.128.3", connect_kwargs = { "password": "xxxxxxxx" })
result = conn.put("./first.py", remote="/tmp/first.py")
print(result)

これまたポイントですが remote 側はディレクトリを指定するだけではアウトです
IOError が発生します
ちゃんと remote 側で配置するファイル名まで指定しましょう

シェルスクリプトを実行する

  • vim shell.py
  • chmod 755 test.sh
from fabric import Connection

conn = Connection("root@172.28.128.3", connect_kwargs = { "password": "xxxxxxxx" })
result = conn.put("./test.sh", remote="/tmp/test.sh", preserve_mode = True)
result = conn.run("/tmp/test.sh")
print(result)

事前に権限を変更しておきます
そして preserve_mode = True を指定することでローカルの権限情報を引き継いでリモートにコピーします
False にすると実行権限がなくなり実行できません
また、fabric2 では内部的に SFTP を使っているようです
preserve_mode = True でアップロード後に False にして再度実行しても権限はなくならないので、ターゲットサーバ上のファイルを一度削除してから再度アップロードしてください

テンプレートファイルアップロード

どうやら upload_template は fabric2 では使えないようです

エラーハンドリング 

  • vim error.py
from fabric import Connection
from invoke import UnexpectedExit

conn = Connection("root@172.28.128.3", connect_kwargs = { "password": "xxxxxxxx" })
try: 
    ret = conn.run("hoge")
    print(ret)
except UnexpectedExit as e:
    print(e)

UnexpectedExit を except する必要があります
fabric2 はステータスが 0 以外の場合エラーを発生させます
それを回避するためには上記のような対応をする必要があるようです
単純にコマンドでエラーになった場合は特に不要な処理だと思います

最後に

fabric2 に入門してみました
Web 上にはまだまだ fabric 1 系の情報が多いようです
機能的にも fabric1 のほうが豊富な印象です

API が全く互換していないので 1 系のドキュメントは役に立ちません
Python3 で動かしたい場合は fabric2 を使うしかないですが、そうでない場合にはまだ移行は微妙かもしれないです

2 系へのアップグレードに関してはこちらが参考になると思います

参考サイト

0 件のコメント:

コメントを投稿