Python Fabric装饰器

时间:2013-12-08 20:50:34

标签: python decorator fabric

我在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的解决方案?

1 个答案:

答案 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 configenv.use_ssh_configenv.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'])