【问题标题】:Ansible command from inside virtualenv?来自virtualenv内部的Ansible命令?
【发布时间】:2013-11-18 04:33:32
【问题描述】:

这看起来应该很简单:

tasks:
- name: install python packages
  pip: name=${item} virtualenv=~/buildbot-env
  with_items: [ buildbot ]
- name: create buildbot master
  command: buildbot create-master ~/buildbot creates=~/buildbot/buildbot.tac

但是,除非首先获取 virtualenv 的激活脚本,否则该命令将不会成功,并且在 Ansible command module 中似乎没有这样做的规定。

我已经尝试在各种 .profile、.bashrc、.bash_login 等中获取激活脚本,但没有成功。或者,还有 shell 命令,但它似乎有点尴尬:

- name: create buildbot master
  shell: source ~/buildbot-env/bin/activate && \
         buildbot create-master ~/buildbot \
         creates=~/buildbot/buildbot.tac executable=/bin/bash

有没有更好的办法?

【问题讨论】:

  • 我也在寻找一个更清晰的答案。我目前使用两行脚本来完成这个技巧并使用 Ansible 的脚本模块运行它。
  • JFYI,${item} 语法已弃用,将来将被删除。

标签: virtualenv ansible


【解决方案1】:

更好的方法是使用已安装脚本的完整路径 - 它会自动在其 virtualenv 中运行:

tasks:
- name: install python packages
  pip: name={{ item }} virtualenv={{ venv }}
  with_items: [ buildbot ]
- name: create buildbot master
  command: "{{ venv }}/bin/buildbot create-master ~/buildbot
            creates=~/buildbot/buildbot.tac"

【讨论】:

  • 值得注意的是,任何人在摸不着头脑的时候偶然发现了这一点,虽然以完整路径调用可执行文件通常有效,但并不完全相同:github.com/pypa/pipenv/issues/393#issue-233266934
  • 迄今为止最干净的答案,没有破解东西,来到这里试图运行安装在 virtualenv 中的 luigi 守护程序,刚刚意识到我所要做的就是给它提供 virtualenv 目录中 luigid 的路径。
  • 并非所有实用程序都会在虚拟 env bin 文件夹中安装二进制文件
【解决方案2】:

这是包装方法的通用版本。

venv_exec.j2:

#!/bin/bash
source {{ venv }}/bin/activate
$@

然后是剧本:

tasks:
  - pip: name={{ item }} virtualenv={{ venv }}
    with_items:
      - buildbot
  - template: src=venv_exec.j2 dest={{ venv }}/exec mode=755
  - command: "{{ venv }}/exec buildbot create-master {{ buildbot_master }}"

【讨论】:

  • 不错的主意。您甚至可以使用脚本模块一次性完成所有操作
【解决方案3】:

这是一种为整个游戏启用 virtualenv 的方法;此示例在一次播放中构建 virtualenv,然后在下一次开始使用它。

不确定它有多干净,但它可以工作。我只是在 mikepurvis 在这里提到的基础上建立一点。

---
# Build virtualenv
- hosts: all
vars:
  PROJECT_HOME: "/tmp/my_test_home"
  ansible_python_interpreter: "/usr/local/bin/python"
tasks:
  - name: "Create virtualenv"
    shell: virtualenv "{{ PROJECT_HOME }}/venv"
           creates="{{ PROJECT_HOME }}/venv/bin/activate"

  - name: "Copy virtualenv wrapper file"
    synchronize: src=pyvenv
                 dest="{{ PROJECT_HOME }}/venv/bin/pyvenv"

# Use virtualenv
- hosts: all
vars:
  PROJECT_HOME: "/tmp/my_test_home"
  ansible_python_interpreter: "/tmp/my_test_home/venv/bin/pyvenv"
tasks:
  - name: "Guard code, so we are more certain we are in a virtualenv"
    shell: echo $VIRTUAL_ENV
    register: command_result
    failed_when: command_result.stdout == ""

pyenv 包装文件:

#!/bin/bash
source "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/activate"
python $@

【讨论】:

  • 这看起来很棒;我需要尝试在角色内部执行此操作的含义,但应该很简单地将 ansible_python_interpreter 设置为默认变量。
【解决方案4】:

只需在 shell 中运行 virtualenvs pip:

shell: ~/buildbot-env/pip install ${item}

像魅力一样工作。我不知道 pip 模块对 virtualenvs 做了什么,但它似乎没什么用。

【讨论】:

    【解决方案5】:

    正如我上面评论的,我创建了一个脚本,说它叫做buildbot.sh

    source ~/buildbot-env/bin/activate
    buildbot create-master [and more stuff]
    

    然后用这样的任务在遥控器上运行它:

    - name: Create buildbot master
      script: buildbot.sh
    

    对我来说,这似乎仍然没有必要,但它可能比在 shell 命令中运行它更干净。您的剧本看起来更简洁,但代价是无法立即看到脚本的作用。

    至少有些模块确实使用了 virtualenv,因为 django_managerax_clb 已经有一个内置的 virtualenv 参数。对于 Ansible 来说,包含一个 command-in-virtenv 类型的模块可能不是那么大的一步。

    【讨论】:

    • 人力资源部。是的,我不确定这是前进还是后退。不过,它的更通用版本可能是票。例如,一个脚本从环境变量中获取 venv 位置,然后使用 $@ 传递命令。
    猜你喜欢
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    相关资源
    最近更新 更多