Fabric: Мета-билет обратной связи альфа/бета-версии Fabric 2!

Созданный на 21 апр. 2017  ·  28Комментарии  ·  Источник: fabric/fabric

Пожалуйста, сначала убедитесь, что вы прочитали этот пост в блоге и все его ссылки!: http://bitprophet.org/blog/2017/04/17/fabric-2-alpha-beta


Здесь можно оставить отзыв о проблемах, не охваченных ни одним из существующих тикетов; Пожалуйста, найдите ниже места в первую очередь!!


Не нашли ничего подходящего? Оставьте комментарий ниже! Я ищу отзывы _похожие, но не ограничиваясь этим_:

  • «Я отказываюсь использовать 2.0, пока вы не вернете волшебный, глобальный, не объектно-ориентированный режим!» (хотя я просто свяжу вас с pyinvoke/invoke # 186 и попрошу вас указать там обоснование;))
  • «Мне очень нравится то, что вы сделали с $feature, но отсутствует $sub-feature, которая мне очень нужна! Это планируется?» (Я либо скажу «да», либо «нет», либо «нет», но теперь вы можете тривиально реализовать это самостоятельно! Это не обязательно должно быть в ядре!')
  • «Мне очень нравится то, что вы сделали с $feature, но то, как оно настроено прямо сейчас, сложно/невозможно сделать $sub-use-case!» (Я, вероятно, попрошу вас рассказать подробности и, возможно, попросить пример PR API, который вы хотели бы видеть.)

Самый полезный комментарий

@haydenflinner Это произойдет в течение следующей недели или двух!! (Цель — выпустить до того, как я сяду в самолет на PyCon, то есть 10 мая.)

Например, см. недавно обновленную документацию по обновлению, над которой я работал на этой неделе: http://docs.fabfile.org/en/v2/upgrading.html .

На самом деле, я могу закрыть этот билет сейчас, так как скоро я буду принимать настоящие настоящие для 2.0.0 и выше 👍

Все 28 Комментарий

Небольшая ошибка в URL-адресе, он должен быть http://bitprophet.org/blog/2017/04/17/fabric-2-alpha-beta/

Это показывает, насколько хорошо я помню свой собственный веб-сайт, а? Спасибо! Я даже запустил проверку ссылок в своем посте, но... не против этого тикета ;)

У меня есть предложение о том, как можно реализовать систему roledefs Fabric 1 таким образом, который, как я считаю, соответствует философии Fabric 2. Каждая задача Collection также может иметь оформленные функции @group в том же пространстве имен, которые возвращают заполненные объекты Group , для которых могут выполняться задачи. Пространства имен будут иметь значение, поэтому, если fabfile.py содержит Collection с именем deploy , у которого есть @group с именами web и db , можно использовать deploy.web.execute(mytask) или fab -G deploy.web mytask для выполнения mytask на каждом хосте в группе web . Эти оформленные функции будут вызываться лениво и запоминаться, чтобы предотвратить ненужные вызовы API, если поиск по списку хостов будет медленной операцией, реализованной пользователем.

Соответствует ли это философии дизайна ткани 2? Я бы хотел попробовать реализовать, если это так.

Это отличная идея, @RedKrieg! Я откладывал собственный мозговой штурм о том, как «лучше» генерировать объекты Group и/или как ссылаться на них в CLI, но навскидку это звучит как разумный путь. Я просто выкинул слишком много слов в #1594 и включил туда вашу идею (+ ссылка). Давайте продолжим дискуссию там, но я бы хотел увидеть 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).

У меня было искушение попробовать миграцию на ткань 2, но я сразу же попал в точку. Я широко использую функции fabric.contrib , но документ по миграции говорит, что их больше не существует.

Конечно, я не хочу раздувать код, возвращаясь к их эквиваленту оболочки, и, судя по количеству проблем на contrib.* ткани 1.x, похоже, что он используется много, я думаю, что это отсутствие может быть серьезным препятствием для миграции для многих других.
Я нашел лоскутный проект, который, по-видимому, содержит эквивалент fabric.contrib , но его код не обновлялся годами.
Планируете ли вы портировать fabric.contrib на Fabric 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)

Но нет таких "?". Так что предлагаю зависнуть в бегах().

На самом деле моя программа огромна и там многопроцессное программирование. Чтобы поймать зависание, я выполняю удаленные команды со следующим кодом:

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, некоторые команды, запущенные из дочерних процессов, время от времени зависают.
Обновление На самом деле, это была моя ошибка в коде. Итак, ткань2 не содержит висящих

Всем привет,
Я провел несколько экспериментов с запуском и могу поделиться своим опытом.

Во-первых, я запустил команду из своей консоли

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'"

и это закончилось отлично и быстро с выходом = 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'"

Это было сделано так быстро с выходом = 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 на разветвленном процессе и напишу.
Обновление На самом деле, это была моя ошибка в коде. Таким образом, ткань2 не содержит подвески.

Было бы неплохо получить поддержку use_sudo для Transfer.put .

Я предполагаю, что самый простой обходной путь на данный момент - просто сделать put где-то, у меня есть разрешения, а затем sudo mv ?

@ned2 это все, что use_sudo действительно может сделать в get / put любом случае, например, так это делает v1. Насколько я знаю, на самом деле невозможно загрузить файл «с помощью sudo»! (Не без подключения с правами root, что является плохой идеей и в идеале даже не разрешено.)

Учитывая попытку иметь несколько более чистый API в v2, я почти с большей вероятностью реализую оболочку вместо того, чтобы связывать это поведение внутри самих get / put . Может быть, что-то вроде Transfer.sudo_put (что вызовет self.put ). Таким образом, "чистые" put остаются минимальными.

@bitprophet Я хотел бы начать с благодарности за довольно стабильное и полезное программное обеспечение для Fabric1 и за ваш подход к выпуску Fabric2.

Я начал играть с v2, но столкнулся с проблемой Connection. Я использую свою конфигурацию SSH из Fabric 1, 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 Это, вероятно, не вы, материал аутентификации все еще нуждается в доработке (в значительной степени из-за необходимости некоторой незавершенной работы Paramiko, поэтому исключения аутентификации не так уж сложно правильно интерпретировать). Я думаю, что в этом случае это может быть просто Fab 2 не интерпретирует IdentityFile — мы берем хост, пользователя, порт и кучу других настроек, но IdentityFile по-прежнему является TODO.

Отчасти это связано с тем, что мы также не имеем дело с парольными фразами прямо сейчас (см. выше — мы хотим избежать большой кладжи Fabric 1, когда нам приходится делать дикие догадки, если данный сбой аутентификации означает, что пароль или парольная фраза необходимы). Таким образом, вы, вероятно, просто перейдете к ошибке «Я не могу разблокировать этот файл» после этого. И то, и другое связано с тем, что я использую ssh-агент большую часть времени, что было бы моим первым предложением для немедленного обходного пути.

Тем не менее, я думаю, что мне, вероятно, стоит взломать как IdentityFile, так и явную поддержку конфигурации парольной фразы, потому что неагентские ключи, вероятно, являются наиболее распространенной настройкой аутентификации номер 1, поэтому его отсутствие, вероятно, означает, что большинство альфа/бета-пользователей остаются в беде. . Посмотрим, смогу ли я выбить это сегодня.

Покатался на 2.0а.

1) Я также немного не понимаю, как на самом деле определять и использовать хосты. Я могу бегать:

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

Но если я не хочу каждый раз передавать сведения о хосте (пользователь, хост, порт), я не знаю, как настроить хосты в fabfile.py ( Connection 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 сделал это до 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. Но да, странно получать ошибку PasswordRequiredException: Private key file is encrypted , когда у ssh-агента уже есть расшифрованный ключ. Если я правильно понял, после недопустимого входа в систему 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) Просто сбросьте поддержку ру 2.6 и 3.2-3.3 для ткани 2.0. Разве люди не должны просто двигаться дальше?

@tuukkamustonen - спасибо за отзыв! Ответы:

  1. Роли действительно подпадают под #1594 — и я думаю, что есть еще одна проблема, связанная с проблемой наличия данных конфигурации для каждого хоста, помимо того, как поддержка ssh_config делает это на своем собственном уровне.

    Решить, как именно согласовать конфигурацию на уровне структуры с ssh_config , а затем также с чем-либо из данных группы или времени выполнения... нетривиально. Хотя это определенно должно произойти в ближайшее время; Я просто хочу иметь наполовину продуманное решение вместо первого наброска.

  2. Опять же, да, это билет Paramiko, о котором вы упомянули, и ваше предположение верно, ситуация с неправильным именем пользователя всегда в конечном итоге терпит неудачу, и, поскольку Paramiko отслеживает только последнюю обнаруженную ошибку, получается, что последняя попытка, которую она пробовала, была зашифрованная копия ключа на диске. (Если вы, например, переместите этот ключ в другое место, последней ошибкой будет что-то другое.)

  3. Я только что прокомментировал этот тикет, он может (или не может) дублировать существующие тикеты для одной и той же общей функции. Я прокомментировал эти старые, и IIRC сказал: «Да, я думаю, это было бы неплохо, если бы это не портило Python 2». Однако это не такой высокий приоритет, как большинство более крупных недостающих функций, поэтому он попадает в категорию «требуется отличный, все отмеченные флажки PR, которые я могу просто объединить» :)

  4. Да, см. # 461, который очень старый, но все еще в моих мыслях. В наши дни большой вопрос заключается в том, как такая библиотека будет написана, чтобы охватить как Invoke, так и Fabric; во многих/большинстве случаев можно просто написать общие задачи Invoke, которые не «знают» о каком-либо разделенном локальном/удаленном контекстах, которым можно передать контекст соединения Fabric, когда кто-то хочет запустить их в удаленной системе.

    Такие «контекстно-независимые» задачи хотели бы жить в библиотеке «вызовов» (или какой-либо другой библиотеке, все еще зависящей от Invoke); но некоторые (например, все, что связано с передачей файлов, а не только с командами оболочки) должны быть «осведомлены о структуре». Выяснение того, как преодолеть этот разрыв, является проблемой.

    Можно пойти по пути «эта библиотека требует только вызова, не требует жесткой ткани, _но_ подмножество задач будет жаловаться, если вы не установите ткань и не передадите им контекст подключения». Можно разделить на две библиотеки (с ориентированной на Fabric, требующей более общей Invoke). И т. д.

  5. В последнее время это определенно в картах, см. paramiko/paramiko#1070 и/или pyinvoke/invoke#364. Invoke 1.0, Fabric 2.0 и Paramiko 3.0 (или, возможно, 2.4/2.5/что угодно) будут Python 2.7/3.4 и выше.

О (1):

Я уверен, что вы это уже знаете, но вы можете почерпнуть некоторые идеи из инвентаря Ansible . А может и нет :).

О (4):

Я думаю, что https://github.com/pyinvoke/invocations слишком самоуверен для этого. Invocations предоставляет _условия_ и может основываться на пакете в стиле пэчворк/кухни, но я бы не стал смешивать соглашения (как выпустить или проверить документ) с утилитами (как скопировать файл или изменить разрешения).

Я не вижу проблемы в том, чтобы поместить утилиты для локальных, удаленных и локальных + удаленных операций в одну и ту же библиотеку (пэтчворк). Какая операция поддерживает какой режим можно рассматривать как документацию (как строку документации, автоматически сгенерированную из аннотаций и т. д.).

Это лучше, чем разбивать логику на 2+ пакета. Потому что что, если вы сначала добавите операцию в свой пакет «только для вызова» (и могут быть даже операции «только для удаленного доступа»), а затем добавите поддержку для ее работы также на удаленных серверах? Вы бы переместили, скопировали или расширили код? В любом случае это больше работы, и пользователю нужен другой импорт и т. Д., Так что это звучит немного громоздко.

Что я могу сделать, чтобы довести это до совершенства, чтобы перейти на PyPi?

@haydenflinner Это произойдет в течение следующей недели или двух!! (Цель — выпустить до того, как я сяду в самолет на PyCon, то есть 10 мая.)

Например, см. недавно обновленную документацию по обновлению, над которой я работал на этой неделе: http://docs.fabfile.org/en/v2/upgrading.html .

На самом деле, я могу закрыть этот билет сейчас, так как скоро я буду принимать настоящие настоящие для 2.0.0 и выше 👍

Обратите внимание, вы все еще можете комментировать здесь, если хотите. Обратите внимание, что я надеюсь выполнить по крайней мере несколько кусков функциональной работы до релиза, наряду со всей подготовкой к управлению проектом.

Я посмотрел на ткань 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, который объединен с мастером и скоро выйдет; он добавляет возможность использовать @task(hosts=xxx) .

(re: 3: Что касается предоставления --hosts и друзей, как если бы они были аргументами для каждой задачи, это то, что я мог бы добавить когда-нибудь, но оно было разорвано, стоит ли оно того. Аналогично --help для каждой задачи.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги