132

Suppose I have a role called "apache"

Now I want to execute that role on host 192.168.0.10 from the command line from Ansible host

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

Is there a way to do that?

Paolo
  • 20,112
  • 21
  • 72
  • 113
Karl
  • 2,903
  • 5
  • 27
  • 43

9 Answers9

112

With ansible 2.7 you can do this:

$ ansible localhost --module-name include_role --args name=<role_name>
localhost | SUCCESS => {
    "changed": false,
    "include_variables": {
        "name": "<role_name>"
    }
}
localhost | SUCCESS => {
    "msg": "<role_name>"
}

This will run role from /path/to/ansible/roles or configured role path.

Read more here: https://github.com/ansible/ansible/pull/43131

Oliver Salzburg
  • 21,652
  • 20
  • 93
  • 138
Julius Žaromskis
  • 2,026
  • 2
  • 14
  • 20
  • 2
    This does not really answer the question because there's no reference to the external role YAML file @kari implemented and wants to include. I have the same question. Yet after reading this answer, I only understand that it is feasible. I just don't know how. – Kola Feb 18 '19 at 12:04
  • Hopefully I have clarified the answer @Kola – Julius Žaromskis Feb 18 '19 at 14:23
  • 1
    This is broken in Ansible 2.8. It just logs cryptic error messages like `'ERROR! 'async_val' is not a valid attribute for a IncludeRole'.` – Christian Ciach May 27 '19 at 13:46
  • 1
    This solution seems to work for me with ansible 2.8.2. It does seem to have a problem with exposing variables to other roles included within the original role (which is not a problem in a playbook). I tried changing to `-a "name= public=yes"`, but that didn't help. – user2066480 Aug 22 '19 at 11:23
  • 1
    To understand what -m and -a does see https://docs.ansible.com/ansible/latest/user_guide/modules_intro.html Basically, this is how modules can be started from command line (`-m `) with key=value pairs as arguments (`-a key=value`) – andymel Sep 26 '20 at 18:27
  • 4
    one caveat is that ad-hoc cli commands don't have access to the `ansible_facts` which the role might need. To work around it, you can use caching: `ANSIBLE_CACHE_PLUGIN=jsonfile ANSIBLE_CACHE_PLUGIN_CONNECTION=/tmp/ansible-cache ansible -m setup yourHostname` and then `ANSIBLE_CACHE_PLUGIN=jsonfile ANSIBLE_CACHE_PLUGIN_CONNECTION=/tmp/ansible-cache ansible -m include_role .....` – petrtvaruzek Mar 07 '21 at 05:08
105

I am not aware of this feature, but you can use tags to just run one role from your playbook.

roles:
    - {role: 'mysql', tags: 'mysql'}
    - {role: 'apache', tags: 'apache'}

ansible-playbook webserver.yml --tags "apache"
abuzze
  • 1,483
  • 1
  • 10
  • 21
26

There is no such thing in Ansible, but if this is an often use case for you, try this script.
Put it somewhere within your searchable PATH under name 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
Konstantin Suvorov
  • 65,183
  • 9
  • 162
  • 193
  • 3
    I have created a "create an ansible-role" tool proposal, we will see: https://github.com/ansible/proposals/issues/131 – jhutar Jul 20 '18 at 05:53
  • 4
    Looks like it's been implemented in Ansible 2.7: https://github.com/ansible/ansible/pull/43131 – EM0 Aug 10 '18 at 08:00
  • 1
    Yes, please try `ansible localhost -m include_role -a name=myrole` - works for me! – jhutar May 06 '19 at 20:54
  • `ansible localhost -m include_role -a name=myrole` is broken since ansible 2.8. It just logs cryptic error messages like `'ERROR! 'async_val' is not a valid attribute for a IncludeRole'.` – Christian Ciach May 27 '19 at 13:41
  • This was re-fixed in [cd95843](https://github.com/ansible/ansible/commit/cd95843ea5f1bff40225b0430cfbb379cbe53661) – Brad Solomon Sep 10 '21 at 12:52
18

You could also check ansible-toolbox repository. It will allow you to use something like

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

I have written a small Ansible plugin, called auto_tags, that dynamically generates for each role in your playbook a tag of the same name. You can find it here.

After installing it (instructions are in the gist above) you could then execute a specific role with:

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

rkrzr
  • 1,842
  • 20
  • 31
5

Since in ansible 2.4 two options are available: import_role and include_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

Bram
  • 819
  • 1
  • 9
  • 24
berlinguyinca
  • 803
  • 1
  • 9
  • 16
5

Have you tried that? it's super cool. I'm using 'update-os' instead of 'apache' role to give a more meaningful example. I have a role called let's say ./roles/update-os/ in my ./ I add a file called ./role-update-os.yml which looks like:

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

Make this file executable (chmod +x role-update-os.yml). Now you can run and limit to whatever you have in your inventory ./update-os.yml -i inventory-dev --limit 192.168.0.10 the limit you can pass the group names as well.

  • --limit web,db > web and db is the group defined in your inventory
  • --limit 192.168.0.10,192.168.0.201
$ cat inventory-dev
[web]
192.168.0.10

[db]
192.168.0.201

Note that you can configure ssh-keys and sudoers policy to be able to execute without having to type password - ideal for automation, there are security implications with this. therefore you have to analyze your environment to see whether it's suitable.

slm
  • 15,396
  • 12
  • 109
  • 124
Y Melo
  • 413
  • 1
  • 6
  • 10
4

Yes, import_role is an ansible module and as such it may be invoked through ansible command. The following executes role pki on my_server

ansible my_server -m import_role \
                  -a "name=pki tasks_from=gencert" \
                  -e cn=etcdctl \
                  -e extended_key_usage=clientAuth
olopopo
  • 296
  • 1
  • 8
  • 2
    As a caveat, note that while this invocation works, it will *not* implicitly gather facts; so, if you have a role with a task that references something like `ansible_date_time`, this invocation will fail. I'm not sure if there's a workaround to that; it seems like you'd just need to use an 'entry-point' playbook instead. – Brad Solomon Sep 10 '21 at 12:53
1

You can create the playbook files from the command line:

  1. Install the role (if not already installed)
    ansible-galaxy install git+https://github.com/user/apache-role.git
    
  2. Create playbook and hosts files
    cat >> playbook.yml <<EOL
    ---
    - name: Run apache
      hosts: all
      roles:
        - apache-role
    EOL
    
    cat >> hosts <<EOL
    192.168.0.10
    EOL
    
  3. Run ansible
    ansible-playbook playbook.yml -i hosts
    
  4. Delete the files
    rm playbook.yml hosts
    
Noam Nol
  • 570
  • 4
  • 11