我在fabfile中有一些结构任务,我需要在执行之前初始化env变量。我正在尝试使用一个装饰器,它可以工作,但面料总是说“没有找到主机请指定(单个)”然而如果我打印我的变量“env”的内容似乎都很好。 我也从另一个python脚本调用我的任务。
from fabric.api import *
from instances import find_instances
def init_env(func):
def wrapper(*args, **kwargs):
keysfolder = 'keys/'
env.user = 'admin'
env.key_filename = '%skey_%s_prod.pem'%(keysfolder, args[0])
env.hosts = find_instances(args[1])
return func(args[0], args[1])
return wrapper
@init_env
def restart_apache2(region, groupe):
print(env.hosts)
run('/etc/init.d/apache2 restart')
return True
我的脚本调用fabfile:
from fabfile import init_env, restart_apache2
restart_apache2('eu-west-1', 'apache2')
重启apache2中的打印输出:
[u'10.10.0.1',u'10.10.0.2']
知道我的任务restart_apache2为什么不使用env变量?
由于
编辑:
有趣的是,如果在我的脚本中调用fabfile,我使用fabric.api中的设置并设置主机ip,它可以工作。这表明我的装饰器已经初始化了env变量,因为密钥和用户被发送到结构。只有env.hosts才能被布料读取......
EDIT2:
我可以使用fabric.api中的设置来达到我的目标,就像那样:
@init_env
def restart_apache2(region, groupe):
for i in env.hosts:
with settings(host_string = '%s@%s' % (env.user, i)):
run('/etc/init.d/apache2 restart')
return True
奖金问题,有没有设置直接使用env.hosts的解决方案?
答案 0 :(得分:3)
我猜这里有点,但我假设你遇到了麻烦,因为你试图一次解决两个问题。
第一个问题涉及多个主机的问题。 Fabric包含roles的概念,它们只是一组机器,您可以一次发出命令。 find_instances
函数中的信息可用于填充此数据。
from fabric import *
from something import find_instances
env.roledefs = {
'eu-west-1' : find_instances('eu-west-1'),
'eu-west-2' : find_instances('eu-west-2'),
}
@task
def restart_apache2():
run('/etc/init.d/apache2 restart')
第二个问题是您为不同的服务器组设置了不同的密钥。解决此问题的一种方法是使用SSH配置文件,以防止您必须将密钥/用户帐户的详细信息与结构代码混合在一起。您可以在~/.ssh/config
中为每个实例添加一个条目,也可以使用local SSH config(env.use_ssh_config
和env.ssh_config_path
)
Host instance00
User admin
IdentityFile keys/key_instance00_prod.pem
Host instance01
User admin
IdentityFile keys/key_instance01_prod.pem
# ...
在命令行上,您应该能够发出如下命令:
fab restart_apache2 -R eu-west-1
或者,您仍然可以执行单个主机:
fab restart_apache2 -H apache2
在您的脚本中,这两个等同于execute函数:
from fabric.api import execute
from fabfile import restart_apache2
execute(restart_apache2, roles = ['eu-west-1'])
execute(restart_apache2, hosts = ['apache2'])