【问题标题】:Ansible: Can I execute role from command line?Ansible:我可以从命令行执行角色吗?
【发布时间】:2016-11-15 23:34:05
【问题描述】:

假设我有一个名为“apache”的角色

现在我想通过 Ansible 主机的命令行在主机 192.168.0.10 上执行该角色

ansible-playbook -i  "192.168.0.10" --role  "path to role"

有没有办法做到这一点?

【问题讨论】:

    标签: ansible ansible-role


    【解决方案1】:

    我不知道这个功能,但你可以使用标签来运行你的剧本中的一个角色。

    roles:
        - {role: 'mysql', tags: 'mysql'}
        - {role: 'apache', tags: 'apache'}
    
    ansible-playbook webserver.yml --tags "apache"
    

    【讨论】:

      【解决方案2】:

      在 Ansible 中没有这样的东西,但如果这对您来说是一个经常使用的案例,请试试这个脚本。
      将其放在名称为ansible-role 的可搜索路径中的某个位置:

      #!/bin/bash
      
      if [[ $# < 2 ]]; then
        cat <<HELP
      Wrapper script for ansible-playbook to apply single role.
      
      Usage: $0 <host-pattern> <role-name> [ansible-playbook options]
      
      Examples:
        $0 dest_host my_role
        $0 custom_host my_role -i 'custom_host,' -vv --check
      HELP
        exit
      fi
      
      HOST_PATTERN=$1
      shift
      ROLE=$1
      shift
      
      echo "Trying to apply role \"$ROLE\" to host/group \"$HOST_PATTERN\"..."
      
      export ANSIBLE_ROLES_PATH="$(pwd)/roles"
      export ANSIBLE_RETRY_FILES_ENABLED="False"
      ansible-playbook "$@" /dev/stdin <<END
      ---
      - hosts: $HOST_PATTERN
        roles:
          - $ROLE
      END
      

      【讨论】:

      • 我已经创建了一个“create an ansible-role”工具提案,我们将看到:github.com/ansible/proposals/issues/131
      • 看起来它已经在 Ansible 2.7 中实现了:github.com/ansible/ansible/pull/43131
      • 是的,请尝试ansible localhost -m include_role -a name=myrole - 适合我!
      • ansible localhost -m include_role -a name=myrole 自 ansible 2.8 以来已损坏。它只记录神秘的错误消息,例如 'ERROR! 'async_val' is not a valid attribute for a IncludeRole'.
      • 此问题已在 cd95843 中重新修复
      【解决方案3】:

      您也可以查看ansible-toolbox 存储库。它将允许您使用类似的东西

      ansible-role --host 192.168.0.10 --gather --user centos --become my-role
      

      【讨论】:

        【解决方案4】:

        我编写了一个名为auto_tags 的小型 Ansible 插件,它可以为你的剧本中的每个角色动态生成一个同名标签。你可以找到它here

        安装后(说明在上面的要点中),您可以执行特定角色:

        ansible-playbook -i "192.168.0.10" --tags "name_of_role"

        【讨论】:

          【解决方案5】:

          使用 ansible 2.7,您可以这样做:

          $ cd /path/to/ansible/
          $ ansible localhost -m include_role -a name=<role_name>
          localhost | SUCCESS => {
              "changed": false,
              "include_variables": {
                  "name": "<role_name>"
              }
          }
          localhost | SUCCESS => {
              "msg": "<role_name>"
          }
          

          这将从 /path/to/ansible/roles 或配置的角色路径运行角色。

          在这里阅读更多: https://github.com/ansible/ansible/pull/43131

          【讨论】:

          • 这并没有真正回答这个问题,因为没有引用外部角色 YAML 文件 @kari 实现并希望包括在内。我也有同样的问题。然而在阅读了这个答案之后,我才明白这是可行的。我只是不知道怎么做。
          • 希望我已经澄清了答案@Kola
          • 这在 Ansible 2.8 中被破坏了。它只记录神秘的错误消息,例如 'ERROR! 'async_val' is not a valid attribute for a IncludeRole'.
          • 这个解决方案似乎适用于我的 ansible 2.8.2。将变量暴露给原始角色中包含的其他角色似乎确实存在问题(这在剧本中不是问题)。我尝试更改为-a "name=&lt;role_name&gt; public=yes",但没有帮助。
          • 要了解 -m 和 -a 确实看到了什么 docs.ansible.com/ansible/latest/user_guide/modules_intro.html 基本上,这就是从命令行 (-m &lt;module-name&gt;) 以键=值对作为参数 (-a key=value) 启动模块的方式
          【解决方案6】:

          从 ansible 2.4 开始,有两个选项可用:import_roleinclude_role

          wohlgemuth@leela:~/workspace/rtmtb-ansible/kvm-cluster$ ansible localhost -m import_role -a name=rtmtb
           [WARNING]: No inventory was parsed, only implicit localhost is available
          
          localhost | CHANGED => {
              "changed": true, 
              "checksum": "d31b41e68997e1c7f182bb56286edf993146dba1", 
              "dest": "/root/.ssh/id_rsa.github", 
              "gid": 0, 
              "group": "root", 
              "md5sum": "b7831c4c72f3f62207b2b96d3d7ed9b3", 
              "mode": "0600", 
              "owner": "root", 
              "size": 3389, 
              "src": "/home/wohlgemuth/.ansible/tmp/ansible-tmp-1561491049.46-139127672211209/source", 
              "state": "file", 
              "uid": 0
          }
          localhost | CHANGED => {
              "changed": true, 
              "checksum": "1972ebcd25363f8e45adc91d38405dfc0386b5f0", 
              "dest": "/root/.ssh/config", 
              "gid": 0, 
              "group": "root", 
              "md5sum": "f82552a9494e40403da4a80e4c528781", 
              "mode": "0644", 
              "owner": "root", 
              "size": 147, 
              "src": "/home/wohlgemuth/.ansible/tmp/ansible-tmp-1561491049.99-214274671218454/source", 
              "state": "file", 
              "uid": 0
          }
          
          

          ansible.builtin.import_role – Import a role into a play

          ansible.builtin.include_role – Load and execute a role

          【讨论】:

          • 但是没有收集到任何事实,所以这并不等同于使用剧本。
          【解决方案7】:

          你试过吗?太酷了。我使用 'update-os' 而不是 'apache' 角色来举一个更有意义的例子。我在./ 中有一个名为./roles/update-os/ 的角色,我添加了一个名为./role-update-os.yml 的文件,它看起来像:

          #!/usr/bin/ansible-playbook
          ---
          - hosts: all
            gather_facts: yes
            become: yes
            roles:
            - update-os
          

          使该文件可执行 (chmod +x role-update-os.yml)。现在您可以运行并限制库存中的任何内容./update-os.yml -i inventory-dev --limit 192.168.0.10 您也可以传递组名。

          • --limit web,db > web 和 db 是您的库存中定义的组
          • --limit 192.168.0.10,192.168.0.201
          $ cat inventory-dev
          [web]
          192.168.0.10
          
          [db]
          192.168.0.201
          

          请注意,您可以将 ssh-keys 和 sudoers 策略配置为无需输入密码即可执行 - 非常适合自动化,这会带来安全隐患。因此,您必须分析您的环境,看看它是否合适。

          【讨论】:

            【解决方案8】:

            是的,import_role 是一个 ansible 模块,因此可以通过ansible 命令调用它。以下在my_server上执行角色pki

            ansible my_server -m import_role \
                              -a "name=pki tasks_from=gencert" \
                              -e cn=etcdctl \
                              -e extended_key_usage=clientAuth
            

            【讨论】:

            • 请注意,虽然此调用有效,但它不会隐式收集事实;因此,如果您的角色具有引用 ansible_date_time 之类的任务的角色,则此调用将失败。我不确定是否有解决方法;看来您只需要使用“入口点”剧本即可。