環境定義用のタスク
fabricでサーバ構成を役割別に定義する方法はenv.roledefsにホスト一覧を指定するタスクを定義する方法があります。
environments.py
@task
def env_test():
u'''テスト用設定'''
env.roledefs = {
"web": ["www.test"],
"db" : ["db.test"]
}
@task
def env_production():
u'''本番用設定'''
env.roledefs = {
"web": ["www01","www02"],
"db" : ["db01"]
}
しかし、ちょっと冗長なのでYAMLから自動生成してみた。
YAML版
env.yaml
test:
roledefs:
web: [www.test]
db: [db.test]
production:
roledefs:
web: [www01, www02]
db: [db01]
こんな感じでデータを読み込んでタスクを作るヘルパーを定義。
(参考: http://www.backlog.jp/blog/2013/09/fabric-advanced.html)
helper/yaml_loader.py
# -*- coding: utf-8 -*-
import os, time
import yaml
from fabric.api import env,task
def load_env_from_yaml(yaml_file, namespace):
u'''yamlファイルから実行環境タスクを作成'''
if os.path.exists(yaml_file):
env_data = yaml.safe_load(open(yaml_file).read())
for env_name, env_dict in env_data.items():
__create_env_task(env_name, env_dict, namespace)
else:
print('No {0} found. skipped.'.format(yaml_file))
def __create_env_task(env_name, env_dict, namespace):
u'''実行環境タスクの定義'''
f = lambda: env.update(env_dict)
f.__doc__ = u'''Set environment for {0}'''.format(env_name)
task_name = 'env_{0}'.format(env_name)
wrapper = task(name=task_name)
rand = '%d' % (time.time() * 100000)
namespace['task_%s_%s' % (task_name, rand)] = wrapper(f)
fabfile.py で読み込んで使う。
fabfile.py
import os
from helper.yaml_loader import load_env_from_yaml
# Execute fabric at fabfile.py directory.
__fabric_dir = os.path.abspath(os.path.dirname(__file__))
os.chdir(__fabric_dir)
# Load Environments
load_env_from_yaml('env.yaml', globals())
globals()はfabfileから渡してあげないとタスクが使えないのに注意。
TODO
- 例外処理
- 見やすさのために task_name, task_descriptionを定義できるようにする。
-
envで使っちゃいけないキーってあるのかな。(とはいえ前述の方法では書けちゃうんだけど)