Fabric: Fabric 2 alpha/beta 反馈元票!

创建于 2017-04-21  ·  28评论  ·  资料来源: fabric/fabric

请确保您首先阅读了这篇博文及其所有链接!: http: //bitprophet.org/blog/2017/04/17/fabric-2-alpha-beta


在这里可以就任何现有票证未涵盖的问题留下反馈; 请先搜索以下地方!!

  • Fabric 自己的任何与 SSH 相关的问题: https ://github.com/fabric/fabric/issues

    • 特别是“调用”标签: https ://github.com/fabric/fabric/labels/Invoke

    • 以及 2.0 里程碑: https ://github.com/fabric/fabric/milestone/24

  • 调用任务、子进程、CLI 解析等的问题: https ://github.com/pyinvoke/invoke/issues
  • 可以在以下位置找到较低级别的 SSH 内容: https ://github.com/paramiko/paramiko/issues

没有找到任何相关的东西? 在下面发表评论! 我正在寻找反馈_类似但不限于_:

  • “我拒绝使用 2.0,直到你回到神奇的、全局的、非面向对象的模式!” (尽管我只是将您链接到 pyinvoke/invoke#186 并要求您在那里提供理由;))
  • “我真的很喜欢你对 $feature 所做的事情,但它缺少了我真正需要的 $sub-feature!这是计划好的吗?” (我会说“是”、“不”或“不”,但您现在可以自己轻松实现它!它不需要在核心中!)
  • “我真的很喜欢你对 $feature 所做的事情,但它现在的设置方式,很难/不可能做 $sub-use-case!” (我可能会向您询问详细信息,并且可能会要求您提供您希望查看的 API 的示例 PR。)

最有用的评论

@haydenflinner这将在接下来的一两周内发生! (目标是在我乘飞机前往 PyCon 之前发布,也就是 5 月 10 日。)

例如,请参阅我这周刚刚更新的升级文档:http: //docs.fabfile.org/en/v2/upgrading.html

事实上,我现在也可以关闭这张票,因为我很快就会接受 2.0.0 及更高版本的真实票👍

所有28条评论

去展示我对自己网站的记忆有多好,嗯? 谢谢! 我什至在我的帖子上运行了一个链接检查器,但是……不反对这张票;)

我有一个关于如何以我认为符合结构 2 理念的方式实施结构 1 的角色定义系统的建议。 每个Collection任务还可以在同一命名空间中具有@group修饰函数,这些函数返回可以运行任务的填充Group对象。 命名空间很重要,所以如果fabfile.py包含一个名为deploy的 $#$ Collection $#$ ,他的@group名为webdb ,可以使用deploy.web.execute(mytask)fab -G deploy.web mytaskweb组中的每个主机上执行mytask 。 如果主机列表查找是用户实现的缓慢操作,这些修饰函数将被延迟调用并记忆以防止不必要的 API 调用。

这是否符合 Fabric 2 的设计理念? 如果是这样,我很想在实施中有所作为。

这是一个好主意,@RedKrieg! 我一直在推迟我自己的头脑风暴,以了解如何“最好”地生成 Group 对象和/或如何在 CLI 上引用它们,但这听起来像是一种合理的方法。 我刚刚在 #1594 中删减了太多单词,并在其中包含了您的想法(+ 链接)。 让我们在那里继续讨论,但是 tl;dr 是的,我很想看到 PoC PR。

尽管存在-H参数,但在本地运行命令的最佳方法是什么,例如,如果我想将本地构建和 rsync 与远程主机组合成一个任务?

@max-arnold Connection 对象有一个.local属性,在本地机器上的行为类似于.run :http: //docs.fabfile.org/en/v2/api/connection.html#fabric .connection.Connection.local

好吧,我想一个例子比文字更好:

<strong i="6">@task</strong>
def build(ctx):
    # should always run locally
    ctx.local('uname -a')


<strong i="7">@task</strong>
def deploy(ctx):
    build(ctx)
    # this one should run on remote host
    ctx.run('uname -a')

组合任务运行良好:

fab -H host deploy

仅本地任务因 AttributeError 而失败:没有为“本地”找到属性或配置键:

fab build

基本上我想要一个在本地做某事的任务,不管它是如何被调用的(有或没有-H )。

另一方面,某些命令仅用于远程运行。 如果没有主机, ctx.run将尝试在本地运行它们,这可能会导致意想不到的后果。

| 用户运行任务 | 命令/任务作者希望它运行 | 它应该如何表现? |
|---------------------|-------------------------- ---|----------------|
| 本地 | 本地 | run() 行为很好(但如果远程运行会违反作者的意图)|
| 本地 | 远程 | 它应该失败(或像旧结构那样要求主机字符串)|
|本地 | 本地或远程| run() 行为很好 |
| 远程 | 本地 | 它应该始终在本地运行,但 Context 没有 local() 方法来确保它 |
| 远程 | 远程 | run() 行为很好(但在本地调用期间会出现问题)|
| 远程 | 本地或远程| run() 行为很好 |

@max-arnold 正好是#98! 我实际上还没有完全解决。 将一些现代思想作为评论放在那里...编辑:这个

我注意到似乎与 sudo 不一致的地方。

其中connection是远程服务器,以 root 身份验证。

尝试将波浪号扩展为 root 以外的其他用户:

c.sudo("echo bar > ~/foo", user="builder")

这成功了,但不是写 /home/builder/foo,而是写 /root/foo。

另一方面,如果我只是尝试 ls:

c.sudo("ls", user="builder")

我得到Permission denied

感觉有些不对劲。

当达斯汀报告上述带外情况时,我的猜测是,这是sudo (命令,而不是方法)特定的皱纹,因为上次我看起来我们正在使用-H并且显然它的行为不像我们预期的那样 100%。

嗨杰夫,
因为我已经在 python 3 中工作了,所以现在我正在使用fabric3 (fabric 1.x 的移植)。

我很想尝试迁移到 Fabric 2,但我立即遇到了阻碍。 我广泛使用了fabric.contrib函数,但迁移文档说它不再存在。

当然,我不想让代码膨胀到它们的 shell 等价物,而且因为从 fabric 1.x 的contrib.*上的问题数量来看,它看起来被使用了很多,我认为它缺乏可能是许多其他人移居的严重障碍。
我发现拼凑项目显然包含相当于fabric.contrib ,但它的代码多年来没有更新。
你有计划将fabric.contrib移植到结构 2 吗?

谢谢,
加布里埃尔

@garu57是的,现在的计划是使用patchwork作为基本上“2.0 的贡献”。 目前它是基于 Fabric 1 的,但在 Fabric 2.0.0 发布后会发生变化。 我希望最常用的 contrib 位能够快速移植。

大家好,

有时我的程序运行一个远程命令,例如

source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./00-update-kernel.sh'

我看到脚本是这样执行的:

033[0;32m[DONE]\033[0m'
+ return 0
+ alt_test_done_msg 'Prepare evironment'
+ echo -e '* Prepare evironment    \033[0;32m[DONE]\033[0m'
+ exit 0

我还应该看到我的调试输出“?” 根据我的代码:

class GenericFabric(object):
    def __init__(self, host, user, key_filename=None, port=22):
        connection_string = "{u}@{h}:{p}".format(u=user, h=host, p=port)
        self.connection = Connection(connection_string)
        self.key_filename = key_filename

    #<strong i="13">@with_settings</strong>
    def generic_cmd(self, command_str, timeout, fabric_timeout, **kwargs):
        """
        Creating remote container from template

        <strong i="14">@type</strong> command_str:     str
        <strong i="15">@param</strong> command_str:    command for execute with VM
        <strong i="16">@type</strong> timeout          int or float
        <strong i="17">@param</strong> timeout         number of seconds for pause
        <strong i="18">@type</strong> fabric_timeout   int or float
        <strong i="19">@param</strong> fabric_timeout  number of seconds for timeout fabric run

        <strong i="20">@rtype</strong>:                FabricResponse
        <strong i="21">@return</strong>:               Return remote status of operation VM
        """
        if fabric_timeout > 0:
            command = self.connection.run(command_str.format(**kwargs),
                                          timeout=fabric_timeout,
                                          warn=True, echo=True)
        else:
            command = self.connection.run(command_str.format(**kwargs),
                                          warn=True, echo=True)
        print("?")
        if timeout > 0:
            sleep(timeout)
        return FabricResponse(command)

    def simple_generic_cmd(self, command_str, **kwargs):
        """
        <strong i="22">@type</strong> command_str:     str
        <strong i="23">@param</strong> command_str:    command for execute with VM

        <strong i="24">@rtype</strong>:                FabricResponse
        <strong i="25">@return</strong>:               Return remote status of operation VM
        """
        return self.generic_cmd(command_str, 0.1, 0, **kwargs)

但是没有“?”。 所以我建议有挂在run()。

实际上,我的程序很大,并且有多进程编程。 为了抓住挂起,我正在使用以下代码执行远程命令:

class TestingSystemVM(GenericFabric):
#######
    <strong i="7">@signal_alarm_down</strong>
    def run_rpm_test(self, command_test, package, type_of_test="base"):
        """

        """
        signal.signal(signal.SIGALRM, alarm_handler)
        signal.alarm(self.__timeout)
        returned_value = Queue()
        start_time = datetime.utcnow()
        directory, command_test = os.path.split(command_test)
        try:
            if command_test.endswith(".yml"):
                directory = directory.replace("/opt/QA", self.ansible.git_qa_repo)
                output = self.ansible.play_ansible(command_test,
                                                   package,
                                                   directory)
            else:
                vm_instance = (self.host,
                               self.user,
                               self.key_filename,
                               self.os_name,
                               self.platform,
                               self.arch)
                running_test = Process(target=separate_process_running_test,
                                       args=(vm_instance,
                                             returned_value,
                                             directory,
                                             command_test,
                                             package,
                                             type_of_test))
                running_test.start()
                running_test.join(self.__timeout)
                if running_test.is_alive():
                    running_test.terminate()
                    command_test_res = "FAIL: Timeout\n"
                    return command_test_res, work_time(start_time), 1
                elif returned_value.empty():
                    command_test_res = "FAIL: Problem while getting result\n"
                    return command_test_res, work_time(start_time), 1
                else:
                    output = returned_value.get()
        except TimeOut:
            command_test_res = "FAIL: Timeout\n"
            return command_test_res, work_time(start_time), 1
        if output.failed or (package.name in ("lve-utils", "lve-stats") and
                                     "FAIL" in output.stdout):
            res_output = "FAIL: " + output.stdout
        else:
            res_output = output.stdout
        return res_output, work_time(start_time), 0 if output.succeeded else 1

def separate_process_running_test(vm_instance, return_value_queue,
                                  directory, command_test, package,
                                  type_of_test="base"):
    """

    """
    sleep(0.5)

    signal.signal(signal.SIGTERM, kill_fabric_runner)
    signal.signal(signal.SIGINT, kill_fabric_runner)
    (host,
     user,
     key_filename,
     os_name,
     platform,
     arch) = vm_instance
    child_vm_instance = TestingSystemVM(host,
                                        user,
                                        key_filename,
                                        os_name,
                                        platform,
                                        arch,
                                        FakeAnsible())
    if command_test.endswith(".bats"):
        command_test = "/usr/bin/bats --tap " + command_test
    else:
        command_test = os.path.join("./", command_test)

    output = child_vm_instance.simple_generic_cmd(child_vm_instance._c_run_test,
                                                  envvars=child_vm_instance.env_vars,
                                                  exec_test=command_test,
                                                  dir=directory,
                                                  package=package.name,
                                                  pver=package.version,
                                                  prel=package.release,
                                                  type_test=type_of_test)
    print("!")
    return_value_queue.put(output)

当我使用fabric2时,从子进程启动的一些命令不时挂起。
更新。 实际上,这是我在代码中的错误。 所以,fabric2 不包含悬挂

大家好,
我做了一些启动实验,可以分享我的经验。

首先,我从控制台运行命令

ssh [email protected] -t "source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'"

并且以exit = 0完美而快速地结束:

###
+ echo -e '* Prepare evironment    \033[0;32m[DONE]\033[0m'
* Prepare evironment    [DONE]
+ exit 0
Connection to 192.168.0.34 closed.

好的。
然后我执行了另一个命令:

ssh [email protected] "source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'"

用 exit=0 也完成得如此之快:

###
+ echo -e '* Prepare evironment    \033[0;32m[DONE]\033[0m'
+ exit 0

但是没有“与 192.168.0.36 的连接已关闭”。 不知道重要不重要。

之后,我重新创建了虚拟机并通过 fabric2(来自 IPython)启动了命令:

In [1]: from fabric import Connection
In [2]: Connection('[email protected]').run("source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'", pty=True)
....
+ echo -e '* Prepare evironment    \033[0;32m[DONE]\033[0m'
* Prepare evironment    [DONE]
+ exit 0
Out[2]: <Result cmd="source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'" exited=0>

另外,我使用 pty=False 运行:

In [1]: from fabric import Connection

In [2]: Connection('[email protected]').run("source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'", pty=False)
+ echo -e '* Prepare evironment    \033[0;32m[DONE]\033[0m'
+ exit 0
Out[2]: <Result cmd="source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'" exited=0>

没有“连接到关闭。”在两个测试中。同样我不知道它是否重要。

其次,我认为这对我的立场来说不是一个好的环境,因为我需要从子进程启动。 因此,我再次重新创建了虚拟机并使用以下代码运行脚本:

In [1]: import subprocess

In [2]: t = subprocess.Popen(""" ssh [email protected] -t "source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'" """, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True); r = t.communicate()

在此运行的输出中有“与 192.168.0.34 的连接已关闭”。

另一方面

In [1]: import subprocess

In [2]: t = subprocess.Popen(""" ssh [email protected] "source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'" """, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True); r = t.communicate()

两人都没有上吊。

今晚我将在分叉的进程上使用fabric2 启动我的脚本,然后我会写。
更新。 实际上,这是我在代码中的错误。 因此,fabric2 不包含悬挂。

获得use_sudoTransfer.put $ 的支持会很好。

我想现在最简单的解决方法就是在我有权限的地方做一个put然后一个sudo mv

@ned2这就是use_sudo可以在get / put $ 中真正做到的一切,例如 v1 就是这样做的。 据我所知,实际上不可能“使用 sudo”上传文件! (如果没有以 root 身份连接,这是一个坏主意,理想情况下甚至是不允许的。)

鉴于尝试在 v2 中使用更简洁的 API,我几乎更有可能实现一个包装器,而不是将该行为捆绑在get / put本身中。 也许只是像Transfer.sudo_put (这将称为self.put )。 这样,“纯” put就保持在最低限度。

@bitprophet 首先,我要感谢您使用 Fabric1 提供的一些非常稳定且有用的软件以及您发布 Fabric2 的方法。

我已经开始使用 v2,但我遇到了 Connection 的问题。 我正在使用 Fabric 1 中的 SSH 配置,在尝试连接时,Fabric 1 会提示我输入密码。 Fabric 2 没有这样做,并且失败,表明身份验证失败。 我在 v2 文档中看不到任何提到 Connection 的身份验证机制的地方。 提到了 sudo 的密码,但据我所知,这是在连接成功之后..

我的问题是我是否遗漏了文档中的某些内容,或者这是否是缺少的功能或问题。

代码:

<strong i="10">@task</strong>
def testing(c):
    with Connection('MyHostname') as cxn:
        print("Connected")

        cxn.run('ls -l')

错误:

  File /lib/python3.4/site-packages/paramiko/auth_handler.py", line 223, in wait_for_response
    raise e 
paramiko.ssh_exception.AuthenticationException: Authentication failed.

我的 SSH 配置(替换值在此处发布):

Host MyHostname
  HostName replacedhostname.co.uk
  Port 22
  IdentityFile ~/.ssh/id_rsa
  User replaceduser

我使用的是最新的 v2 版本: https ://github.com/fabric/fabric/commit/fec3a22ee89900500ae731913fd33f9b56e89f46

希望解决这个问题可以帮助其他有同样问题的人。

感谢您的时间。

@Aiky30可能不是你,auth 的东西仍然需要工作(很大程度上是因为需要一些正在进行的 Paramiko 工作,所以正确解释 auth 异常并不难。)我认为在这种情况下它可能只是 Fab 2 没有解释IdentityFile - 我们获取主机、用户、端口和一堆其他设置,但 IdentityFile 仍然是一个 TODO。

这部分是因为我们现在也不处理密码短语(见上文 - 如果给定的身份验证失败意味着需要密码或密码短语,我们必须进行疯狂的猜测,以避免出现大的 Fabric 1 混乱)。 因此,在那之后您可能只是过渡到“我无法解锁此文件”错误。 这两者都是因为我大部分时间都使用 ssh-agent - 这将是我立即解决问题的第一个建议。

也就是说,我认为在 IdentityFile 和显式密码配置支持方面可能值得我破解,因为非代理密钥可能是最常见的 1 号身份验证设置,因此缺少它可能意味着大多数 alpha/beta 用户陷入困境. 看看我今天能不能把它弄出来。

花了 2.0a 转了一圈。

1)我对如何实际定义和使用主机也有点迷茫。 我可以跑:

   fab -H user<strong i="7">@host</strong>:22 some-task

但是如果我不想每次都传递主机详细信息(用户、主机、端口),我不确定如何在fabfile.pyConnection s 或Group ) 然后只是参考它们。 如果我正确理解了https://github.com/fabric/fabric/issues/1591#issuecomment -296343613,那么它目前不受支持(并在 https://github.com/fabric/fabric/issues/1594 中进行了跟踪)?

2)另外,我遇​​到了加密 SSH 密钥(在~/.ssh/id_rsa处)的问题,并且我有ssh-add 'd 到ssh-agent 。 如果我通过ssh-add -l列出密钥,它就会显示出来。 当我运行一些任务时,给出正确的用户名:

   fab -H musttu<strong i="20">@host</strong> sometask

一切正常。 但是,如果我使用不正确的用户,例如fab -H bad_user<strong i="23">@host</strong> sometask ,那么我会得到:

Traceback (most recent call last): ... File "/home/maximus/.virtualenvs/testenv/lib/python3.6/site-packages/paramiko/pkey.py", line 326, in _read_private_key raise PasswordRequiredException('Private key file is encrypted') paramiko.ssh_exception.PasswordRequiredException: Private key file is encrypted

但我认为这属于https://github.com/paramiko/paramiko/issues/387并且并非真正特定于 Fabric 2.0。 但是,是的,当 ssh-agent 已经拥有解密的密钥时,得到PasswordRequiredException: Private key file is encrypted错误确实感觉很奇怪。 如果我理解正确,在无效登录后, paramiko将回退到直接使用密钥,并且没有提供密码将引发此错误。

3) 允许类型注释任务函数会很好(以便在 IDE 中更好地自动完成)。 您有时间考虑https://github.com/pyinvoke/invoke/pull/458吗?

4)我喜欢拼凑库的想法。 对于fabric 1.x,有https://github.com/sebastien/cuisine (看起来很死),其中包含许多额外的功能(我自己没有使用过)。 拼凑的想法是构建类似的东西(所以 Chef/Ansible/SaltStack 风格的声明性函数,尽管范围缩小了)? 我一直讨厌其他工具遵循的多目录/多文件 YAML/DSL 方法,并且只想留在 python 中,以获得更大的灵活性、更少冗长的语法、IDE 自动完成、易于调试等。

5) 只需放弃对 fabric 2.0 的 py 2.6 和 3.2-3.3 支持。 人们不应该继续前进吗?

@tuukkamustonen - 感谢您的反馈! 回应:

  1. #1594 确实涵盖了角色 - 我认为除了ssh_config支持在其自身级别上如何做到这一点之外,还有另一张票可以解决仅拥有每个主机配置数据的相关问题。

    决定如何准确地协调结构级配置与ssh_config以及来自组或运行时数据的任何内容......并非易事。 虽然它肯定需要尽快发生; 我只想有一个半考虑的解决方案,而不是一个初稿。

  2. 再次,是的,这是您提到的 Paramiko 票证,您的猜测是准确的,错误用户名的情况最终会失败,并且由于 Paramiko 只跟踪它遇到的最后一个错误,它恰好是它尝试的最后一件事是密钥的磁盘上加密副本。 (例如,如果您将该键移到别处,最后一个错误将是其他错误。)

  3. 我刚刚评论了那张票,它可能(或可能不会)复制现有票证以获得相同的整体功能。 我评论过那些较旧的,IIRC 是“是的,我认为只要它不破坏 Python 2 就很好。” 但是,它的优先级不如大多数较大的缺失功能,因此它属于“需要一个很棒的,所有框都检查了我可以合并的 PR”桶:)

  4. 是的,请参阅#461,它非常古老但仍在我脑海中。 这些天来最大的问题是如何编写这样的库以跨越 Invoke 和 Fabric; 在许多/大多数情况下,可以简单地编写不“知道”任何拆分本地/远程上下文的通用调用任务,当人们想要针对远程系统运行它们时,可以将其交给 Fabric 连接上下文。

    这种“与上下文无关”的任务会希望存在于“调用”库(或其他一些仍然特定于 Invoke 的库)中; 但是有些(例如任何涉及文件传输而不仅仅是shell命令的东西)需要“结构感知”。 弄清楚如何弥合这一差距是问题所在。

    可以走“那个lib只需要调用,不需要fabric,_但是_如果你不安装fabric并给他们一个连接上下文,一部分任务会抱怨”的路线。 可以分成两个库(面向 Fabric 的库需要更通用的 Invoke 库)等等。

  5. 最近,这肯定是有可能的,请参阅 paramiko/paramiko#1070 和/或 pyinvoke/invoke#364。 Invoke 1.0、Fabric 2.0 和 Paramiko 3.0(或者,_maybe_,2.4/2.5/whatever)都将是 Python 2.7 / 3.4 及更高版本。

关于(1):

我确定您已经知道这一点,但您可能想从Ansible 的清单中获取一些想法。 或者可能不是 :)。

关于(4):

我认为https://github.com/pyinvoke/invocations是一种固执己见的方式。 Invocations 提供了 _conventions_ 并且可以构建在 patchwork/cuisine-style 包之上,但我不会将约定(如何发布或 doctest)与实用程序(如何复制文件或更改权限)混合。

我认为将仅用于本地、仅远程和本地+远程操作的实用程序放入同一个库(拼凑)中没有问题。 哪些操作支持哪种模式可以作为文档处理(作为文档字符串,从注释自动生成等)。

这比将逻辑拆分为 2 个以上的包感觉更好。 因为如果您首先将操作添加到“仅调用”程序包(甚至可能存在“仅远程”操作),然后添加对它的支持以使其在远程服务器上也能工作,该怎么办? 你会移动、复制或扩展代码吗? 无论哪种情况,它都需要更多的工作,并且用户需要不同的导入等,所以听起来有点麻烦。

我该怎么做才能让这个足够完善以继续使用 PyPi?

@haydenflinner这将在接下来的一两周内发生! (目标是在我乘飞机前往 PyCon 之前发布,也就是 5 月 10 日。)

例如,请参阅我这周刚刚更新的升级文档:http: //docs.fabfile.org/en/v2/upgrading.html

事实上,我现在也可以关闭这张票,因为我很快就会接受 2.0.0 及更高版本的真实票👍

请注意,如果您愿意,大家仍然可以在这里发表评论。 请注意,我希望在发布之前至少完成几块功能工作,以及所有项目管理准备工作。

我今天看了fabric v2,很抱歉,我不能让自己使用它。

  1. 角色定义去哪儿了? 为什么我不能再在命令行上传递角色名称了? 我应该自己实现吗?
  2. 为什么我不能再在命令行上向任务传递参数了? 我也应该自己实现吗?
  3. 为什么 -H 参数必须在任务参数之前? 应该反过来。 这太可怕了。

任务确实需要参数,但语法发生了变化。 请参阅http://docs.pyinvoke.org/en/1.1/concepts/invoking-tasks.html#task -command-line-arguments

@dgarstang你可能想考虑对那些给你免费劳动力的人采取更中立或同情的语气! 就说😉

  1. 请参阅#1594,在升级文档中链接了 IIRC
  2. @ploxiln 支持
  3. (部分)见#1772,它已合并到master,很快就会出来; 它增加了使用@task(hosts=xxx)的能力。

(re: 3: 在给予--hosts和朋友好像他们是每个任务的参数方面,这是我可能会在某个时候添加的东西,已经被撕裂是否值得。类似于每个任务--help ,我们添加的“魔法”排除越多,用户尝试为自己的任务参数使用相同名称并在它中断时感到困惑的可能性就越大。)

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

TimotheeJeannin picture TimotheeJeannin  ·  3评论

bitprophet picture bitprophet  ·  4评论

SamuelMarks picture SamuelMarks  ·  3评论

26huitailang picture 26huitailang  ·  3评论

acdha picture acdha  ·  4评论