【问题标题】:Python Fabric decoratorPython 织物装饰器
【发布时间】:2013-12-18 18:22:11
【问题描述】:

我的 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 没有被 fabric 读取...

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 没有设置的解决方案?

【问题讨论】:

  • 看起来您在init_env 中遇到了缩进错误。这两个 return 语句看起来应该缩进一级。
  • 这是一个糟糕的复制粘贴,我原来的缩进很好。我已经修改了我的帖子。
  • 您提到您正在从另一个 python 脚本调用任务。您是使用fab 命令还是其他方式调用其他脚本?
  • 在我的帖子中:我调用 fabfile 的脚本:from fabfile import init_env, restart_apache2 restart_apache2('eu-west-1', 'apache2')

标签: python decorator fabric


【解决方案1】:

我在这里猜测了一下,但我假设你遇到了麻烦,因为你试图同时解决两个问题。

第一个问题与多主机问题有关。 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'])

【讨论】:

  • 不错!非常感谢您的解决方案和解释:)
猜你喜欢
  • 2010-11-28
  • 1970-01-01
  • 2013-08-07
  • 2014-01-23
  • 1970-01-01
  • 2021-05-20
  • 2020-02-10
相关资源
最近更新 更多