How to set target hosts in Fabric file
我想使用Fabric将我的Web应用程序代码部署到开发、分段和生产服务器上。我的FabFix:
1 2 3 4 5 6 7 8 9 10 11 12 13 | def deploy_2_dev(): deploy('dev') def deploy_2_staging(): deploy('staging') def deploy_2_prod(): deploy('prod') def deploy(server): print 'env.hosts:', env.hosts env.hosts = [server] print 'env.hosts:', env.hosts |
样品输出:
1 2 3 4 | host:folder user$ fab deploy_2_dev env.hosts: [] env.hosts: ['dev'] No hosts found. Please specify (single) host string for connection: |
当我创建一个
它在结构文档中说"env.hosts只是一个python列表对象"。从我的观察来看,这根本不是真的。
有人能解释一下这是怎么回事吗?如何设置要部署的主机?
我做这个用declaring安实际函数为每个环境。例如: </P >
1 2 3 4 5 6 7 8 9 10 | def test(): env.user = 'testuser' env.hosts = ['test.server.com'] def prod(): env.user = 'produser' env.hosts = ['prod.server.com'] def deploy(): ... |
使用以上的I型函数,将下面的deploy到我的测试环境: </P >
1 | fab test deploy |
...and下面的deploy的生产: </P >
1 | fab prod deploy |
在好的事关于做IT这通这是《
使用roledefs </P >
1 2 3 4 5 6 7 8 9 10 11 | from fabric.api import env, run env.roledefs = { 'test': ['localhost'], 'dev': ['[email protected]'], 'staging': ['[email protected]'], 'production': ['[email protected]'] } def deploy(): run('echo test') |
选择角色,与R: </P >
1 2 3 | $ fab -R test deploy [localhost] Executing task 'deploy' ... |
这是一个simpler版serverhorrors回答: </P >
1 2 3 4 5 | from fabric.api import settings def mystuff(): with settings(host_string='12.34.56.78'): run("hostname -f") |
这是卡是自己,但finally压延出来。你不能简单的配置集的env.hosts从A内的任务。每个任务是executed的时代,一次为每个主机specified,SO的设置是fundamentally外出任务范围。 </P >
寻找在你的上面的代码,你可以简单的做这个: </P >
1 2 3 4 5 6 7 8 9 10 | @hosts('dev') def deploy_dev(): deploy() @hosts('staging') def deploy_staging(): deploy() def deploy(): # do stuff... |
这样看来,它会做什么,你是intending。。。。。。。 </P >
或你可以写一些自定义代码在全球范围,这将对arguments人力,和集env.hosts之前,你的任务是定义的函数。一个确实的原因,认为"S知道如何我已经集矿上。 </P >
由于fab 1.5,这是一种记录在案的动态设置主机的方法。
http://docs.fabfile.org/en/1.7/usage/execution.html动态主机
引用以下文档。
Using execute with dynamically-set host lists
A common intermediate-to-advanced use case for Fabric is to
parameterize lookup of one’s target host list at runtime (when use of
Roles does not suffice). execute can make this extremely simple, like
so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from fabric.api import run, execute, task # For example, code talking to an HTTP API, or a database, or ... from mylib import external_datastore # This is the actual algorithm involved. It does not care about host # lists at all. def do_work(): run("something interesting on a host") # This is the user-facing task invoked on the command line. @task def deploy(lookup_param): # This is the magic you don't get with @hosts or @roles. # Even lazy-loading roles require you to declare available roles # beforehand. Here, the sky is the limit. host_list = external_datastore.query(lookup_param) # Put this dynamically generated host list together with the work to be # done. execute(do_work, hosts=host_list) |
相反的一些其他的回答,它是可能的修改的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | from fabric.api import task, roles, run, env from fabric.tasks import execute # Not a task, plain old Python to dynamically retrieve list of hosts def get_stressors(): hosts = [] # logic ... return hosts @task def stress_test(): # 1) Dynamically generate hosts/roles stressors = get_stressors() env.roledefs['stressors'] = map(lambda x: x.public_ip, stressors) # 2) Wrap sub-tasks you want to execute on new env in execute(...) execute(stress) # 3) Note that sub-tasks not nested in execute(...) will use original env clean_up() @roles('stressors') def stress(): # this function will see any changes to env, as it was wrapped in execute(..) run('echo"Running stress test..."') # ... @task def clean_up(): # this task will NOT see any dynamic changes to env |
没有包装的子任务在
到explain为什么它的平安夜的事件。在命令行的Fab片段是崩溃的织物的图书馆运行的任务的主机列表。如果你尝试和改变的主机列表内的任务,你是esentially attempting变革的一个列表,而迭代过它。或在案例在你已经定义好的主持人,过环空的列表在你的代码在集的列表来回路过executed是永远的。 </P >
使用env.host _字符串是一个全面的工作方法的这一行为,只有在它的中的直接的函数是什么主机的连接物。这个原因的一些问题,你会被执行的remaking环,如果你想有一个数的主机的执行。 </P >
在扩通的人"麦克的能力集的主机在运行时,是保持对环境populatiing作为一种distinct任务,是集上的所有主机的字符串,用户等。然后,他们deploy运行的任务。它看起来像这样: </P >
1 | fab production deploy |
或 </P >
1 | fab staging deploy |
在分期和生产是一类的任务你已经给定的,但他们做不呼叫下一任务本身。的原则,它有什么样的工作,这是你的任务来整理,和打破的回路(的主持人,在《环境案例NONE,但它是一个循环.这一点),然后有环过的主机(现在的定义由preceding任务anew)。 </P >
你需要
1 2 3 4 5 6 7 8 9 10 | from fabric.context_managers import settings as _settings def _get_hardware_node(virtualized): return"localhost" def mystuff(virtualized): real_host = _get_hardware_node(virtualized) with _settings( host_string=real_host): run("echo I run on the host %s :: `hostname -f`" % (real_host, )) |
我对Fabric完全陌生,但是要让Fabric在多台主机上运行相同的命令(例如,在一个命令中部署到多个服务器),您可以运行:
1 | fab -H staging-server,production-server deploy |
其中,临时服务器和生产服务器是要对其运行部署操作的两个服务器。下面是一个简单的fabfile.py,它将显示操作系统名称。注意fabfile.py应该与运行fab命令的目录相同。
1 2 3 4 | from fabric.api import * def deploy(): run('uname -s') |
这至少适用于织物1.8.1。
这是非常简单的。是的env.host _初始化的字符串变量和所有的下面将executed commands是这个主机。 </P >
1 2 3 4 5 6 |
你需要修改env.hosts在模块级的,而不是在一个函数的任务。我制造了同样的错误。 </P >
1 2 3 4 5 6 7 8 9 10 11 | from fabric.api import * def _get_hosts(): hosts = [] ... populate 'hosts' list ... return hosts env.hosts = _get_hosts() def your_task(): ... your task ... |
这是另一个"SummerSault"模式,它支持
使用这种模式,我们只需要使用字典定义一次环境。
缺点是,如文中所述,添加
注:由于后期绑定,我们在工厂使用
机密.config.py
1 2 3 4 5 6 7 8 9 10 11 12 13 | ENVS = { 'my_env_1': { 'HOSTS': [ 'host_1', 'host_2', ], 'MY_OTHER_SETTING': 'value_1', }, 'my_env_2': { 'HOSTS': ['host_3'], 'MY_OTHER_SETTING': 'value_2' } } |
FabFiel.Py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import sys from fabric.api import env from secrets import config def _set_env(env_name): # can easily customize for various use cases selected_config = config.ENVS[env_name] for k, v in selected_config.items(): setattr(env, k, v) def _env_factory(env_dict): for k in env_dict: def func(k=k): _set_env(k) setattr(sys.modules[__name__], k, func) _env_factory(config.ENVS) def my_command(): # do work |
因此,为了设置主机并让命令在所有主机上运行,必须从以下内容开始:
1 2 3 4 5 | def PROD(): env.hosts = ['10.0.0.1', '10.0.0.2'] def deploy(version='0.0'): sudo('deploy %s' % version) |
一旦定义了这些内容,就在命令行上运行命令:
1 | fab PROD deploy:1.5 |
什么将在prod函数中列出的所有服务器上运行deploy任务,因为它在运行该任务之前设置env.hosts。
你可以assign到
不幸的是为你和我,织物设计的方法,这是不使用的情况。结帐的
使用的角色是目前被视是"适当的"和"正确"的方式做了研究,这是什么,你的"应该"做的。 </P >
这是说,如果你知道你是什么,你最喜欢的"很喜欢"或"欲望"是to perform a"能力的"系统"或交换系统的目标是在飞。 </P >
用于娱乐用途的SO(只读)。下面的实例illustrates什么多考虑可能的危险,但不知什么原因,thoroughly satisfying manoeuvre,那就是这样的: </P >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | env.remote_hosts = env.hosts = ['10.0.1.6'] env.remote_user = env.user = 'bob' env.remote_password = env.password = 'password1' env.remote_host_string = env.host_string env.local_hosts = ['127.0.0.1'] env.local_user = 'mark' env.local_password = 'password2' def perform_sumersault(): env_local_host_string = env.host_string = env.local_user + '@' + env.local_hosts[0] env.password = env.local_password run("hostname -f") env.host_string = env.remote_host_string env.remote_password = env.password run("hostname -f") |
然后运行: </P >
1 | fab perform_sumersault |