I have a ansible role that requires other roles, but is not loading correctly from my playbook. My role is here, Jenkins Role, it has dependencies on two other geerlingguy roles, which are listed here
meta/main.yml
galaxy_info:
author: Jd Daniel
description: Jenkins installer
company: GE Health
min_ansible_version: 2.2
role_name: jenkins
license: GPLv3
platforms:
- name: EL
versions:
- 7
galaxy_tags:
- jenkins
- deployment
- continuous-deployment
- cd
dependencies:
- { role: geerlingguy.repo-epel }
- { role: geerlingguy.jenkins, jenkins_plugins: [] }
My roles ansible.cfg in this role also points to the roles/ directory
[defaults]
# without this, the connection to a new instance is interactive
host_key_checking = False
roles_path = roles/
and the roles are downloaded into the roles/ folder
┌─[10:25:24]─[ehime#GC02WW38KHTD6E]─[~/Repositories/Infra/Ansible/ansible-role-jenkins]
└──> tree -L 2
.
├── [ehime 34K] LICENSE
├── [ehime 1.3K] README.md
├── [ehime 128] ansible.cfg
├── [ehime 96] defaults
│ └── [ehime 32] main.yml
├── [ehime 96] files
│ └── [ehime 633] job.xml
├── [ehime 96] handlers
│ └── [ehime 33] main.yml
├── [ehime 96] meta
│ └── [ehime 417] main.yml
├── [ehime 160] roles
│ ├── [ehime 384] geerlingguy.java
│ ├── [ehime 416] geerlingguy.jenkins
│ └── [ehime 320] geerlingguy.repo-epel
├── [ehime 96] tasks
│ └── [ehime 737] main.yml
├── [ehime 352] tests
│ ├── [ehime 669] README.md
│ ├── [ehime 276] Vagrantfile
│ ├── [ehime 121] ansible.cfg
│ ├── [ehime 203] inventory
│ ├── [ehime 221] requirements.yml
│ ├── [ehime 96] roles
│ ├── [ehime 10] test_7_default.retry
│ └── [ehime 182] test_7_default.yml
└── [ehime 96] vars
└── [ehime 91] main.yml
My tasks should be pulling these in then? right?
tasks/main.yml
---
- name: Install required roles
include_role:
name: "{{ roles }}"
vars:
roles:
- geerlingguy.epel-repo
- geerlingguy.jenkins
.... other tasks ....
When running my playbook though...
jenkins.yml
#
# Ansible to provision Jenkins on remote host
#
- name: Install Jenkins and its plugins
hosts: all
become: yes
become_method: sudo
gather_facts: yes
vars:
jenkins_hostname: localhost
jenkins_http_port: 8080
roles:
- ehime.jenkins
pre_tasks:
- name: CA-Certificates update command line execution
command: /bin/update-ca-trust
tasks:
- name: Set up pipeline
jenkins_job:
config: "{{ lookup('file', 'files/job.xml') }}"
name: test-auto
user: "{{ jenkins_admin_username }}"
password: "{{ jenkins_admin_password }}"
When trying to run the following playbook though
#
# Ansible to provision Jenkins on remote host
#
- name: Install Jenkins and its plugins
hosts: all
become: yes
become_method: sudo
gather_facts: yes
vars:
jenkins_hostname: localhost
jenkins_http_port: 8080
roles:
- ehime.jenkins
pre_tasks:
- name: CA-Certificates update command line execution
command: /bin/update-ca-trust
tasks:
- name: Set up pipeline
jenkins_job:
config: "{{ lookup('file', 'files/job.xml') }}"
name: test-auto
user: "{{ jenkins_admin_username }}"
password: "{{ jenkins_admin_password }}"
With my playbooks config...
ansible.cfg
[defaults]
# without this, the connection to a new instance is interactive
host_key_checking = False
roles_path = roles/
remote_user = ec2-user
private_key_file = ../_keys/test-jenkins
I get the following error....
error
TASK [include_role : {{ roles }}] ************************************************************************************************************************************************************************************************************
ERROR! Invalid role definition: [u'geerlingguy.epel-repo', u'geerlingguy.jenkins']
It's evidently NOT seeing the roles in roles/ehime.jenkins/roles but I'm not sure how to get those working. It also seem like it ignores my meta/main.yml for a galaxy install? Should these be in the requirements.yml?
Like an idiot, I had my dependencies tabbed in too far...
galaxy_info:
author: Jd Daniel
description: Jenkins installer
company: GE Health
min_ansible_version: 2.2
role_name: jenkins
license: GPLv3
platforms:
- name: EL
versions:
- 7
galaxy_tags:
- jenkins
- deployment
- continuous-deployment
- cd
# Issue is here....
dependencies:
- { role: geerlingguy.repo-epel }
- { role: geerlingguy.jenkins, jenkins_plugins: [] }
should have been
galaxy_info:
author: Jd Daniel
description: Jenkins installer
company: GE Health
min_ansible_version: 2.2
role_name: jenkins
license: GPLv3
platforms:
- name: EL
versions:
- 7
galaxy_tags:
- jenkins
- deployment
- continuous-deployment
- cd
# Issue is here....
dependencies:
- { role: geerlingguy.repo-epel }
- { role: geerlingguy.jenkins, jenkins_plugins: [] }
Related
my playbook directory structure.
/ansible_repo/
└── playbooks/
├──playbooks1.yml
├──playbooks2.yml
├── somerole.yml --> main playbook with roles
└── roles/
└── somerole
├── default
│ └── main.yml
├── handler
│ └── main.yml
├── tasks
│ └── main.yml
└── vars
└── main.yml
playbooks1.yml :
---
- hosts: all
tasks:
- pause:
minutes: 3
- name: ping host
win_ping:
somerole.yml :
---
- hosts: ci_host
roles:
- somerole
somerole\tasks\main.yml :
---
- include: playbooks/playbooks1.yml
when I run the role on some host:
ansible-playbook role-test.yml -vv --limit somehost
I get this error:
fatal: [somehost]: FAILED! =>
reason: |-
conflicting action statements: hosts, tasks
if I change the like that it passed:
- pause:
minutes: 3
- name: ping host
win_ping:
I tried understand how to set hosts and tasks in both, role-tasks-main and playbook.yml
and include the playbook into the role task.
if I get conflict I can config hierarchy host?
The error indicates that you are including a playbook inside a role, and for a role hosts and tasks are not allowed.
As somerole.yml is your main playbook, you can invoke other playbooks and roles as necessary.
Example:
- name: run playbook playbook1
import_playbook: playbooks/playbooks1.yml
- hosts: ci_host
roles:
- somerole
- name: run playbook playbook2
import_playbook: playbooks/playbooks2.yml
GOAL
I want to create a portable role folder that utilizes textfsm templates in role directory.
Directory structure
$ tree
.
├── ansible.cfg
├── hosts.ini
├── out_pb1
├── pb1.yml
├── roles
│ ├── command_facts
│ │ ├── tasks
│ │ │ └── main.yml
│ │ ├── templates
│ │ │ └── textfsm // I want this
│ │ └── vars
└── templates
└── textfsm // created for testing
PROBLEM
parse_cli_textfsm is referencing to templates/textfsm instead of roles/command_facts/templates/textfsm
The goal is portability so specifying full path is not considered.
ATTEMPTS TO FIX (FAIL)
Executes pb1.yml
Error shown as below if I deleted templates/textfsm in the pb1.yml directory.
$ ansible-playbook pb1.yml -u username -k
(omitted)
TASK [command_facts : set_fact]
fatal: [target]: FAILED! => {"msg": "unable to locate parse_cli_textfsm template: /templates/textfsm"}
I tried to utilize system variable role_path that is {{ raw_output.stdout | parse_cli_textfsm('{{ role_path }}/templates/textfsm') }} but it is not working. {{ role_path }} turns into a normal string.
$ ansible-playbook pb1.yml -u username -k
(omitted)
TASK [ixrs_facts : set_fact]
fatal: [target]: FAILED! => {"msg": "unable to locate parse_cli_textfsm template: {{ role_path }}/templates/textfsm"}
FILES
roles/command_facts/task/main.yml
---
- name: show protocols all
raw: "show protocols all"
register: raw_output
- set_fact:
output: {{ raw_output.stdout | parse_cli_textfsm("/templates/textfsm") }}
- debug: var=output[::]
pb1.yml
---
- name: testing
hosts: target
gather_facts: false
roles:
- { role: command_facts }
REFERENCE
https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#network-cli-filters
{{ output.stdout[0] | parse_cli_textfsm('path/to/fsm') }}
parse_cli_textfsm('{{ role_path +“/templates/textfsm“) }}
Works for me...
Hth
I am trying to implement a custom network command module as an Ansible role. This module will run commands on remote devices.
Ansible connection type is network_cli
Created the role by using below command
ansible-galaxy init --type=network test-command-mod
which gave me below default directory structure
roles
└── test-command-mod
├── cliconf_plugins
│ ├── myos.py (my file)
├── defaults
│ └── main.yml
├── files
├── library
│ ├── __init__.py
│ └── myos_command.py (my file - the command module)
├── meta
│ └── main.yml
├── module_utils
│ └── myos.py (my file)
├── README.md
├── tasks
│ ├── execute-commands.yml ( a test task to run commands )
│ └── main.yml
├── templates
├── terminal_plugins
│ ├── myos.py (my file - emulating the myos terminal)
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
Below it is how used in an Ansible playbook
- hosts: my_os_cli
gather_facts: False
roles:
- role: test-command-mod
tasks:
- name: run some commands on the device
myos_command:
commands:
- command: 'show version'
- command: 'show ntp status'
vars:
ansible_connection: network_cli
ansible_network_os: myos
When using from a role, it fails with below message
The full traceback is:
Traceback (most recent call last):
File "/ansible/bin/ansible-connection", line 102, in start
self.connection._connect()
File "/ansible/lib/ansible/plugins/connection/network_cli.py", line 338, in _connect
raise AnsibleConnectionFailure('network os %s is not supported' % self._network_os)
AnsibleConnectionFailure: network os myos is not supported
When running Ansible in debug mode, saw below in the log
unable to load cliconf for network_os myos
Moreover, it is trying to look for plugins/cliconf/myos.py under default Ansible location instead of the my Ansible role (test-command-mod).
I expect it to look in roles/test-command-mod/cliconf_plugins/myos.py
Is this a bug or by design?
Also, role works if
ansible.cfg is updated with
cliconf_plugins = ./roles/test-command-mod/cliconf_plugins
terminal_plugins = ./roles/test-command-mod/terminal_plugins
OR set the below environment variables
export ANSIBLE_TERMINAL_PLUGINS=./roles/test-command-mod/terminal_plugins
export ANSIBLE_CLICONF_PLUGINS=./roles/test-command-mod/cliconf_plugins
OR if copy files (my file); to their respective directories in ansible installation.
Thoughts please?
EDIT: ansible.cfg as follows
[defaults]
# after suggestion
#cliconf_plugins = cliconf_plugins:./roles/test-command-mod/cliconf_plugins
#terminal_plugins = terminal_plugins:../roles/test-command-mod/terminal_plugins
# before suggestion
cliconf_plugins = ./roles/test-command-mod/cliconf_plugins
terminal_plugins = ./roles/test-command-mod/terminal_plugins
[paramiko_connection]
look_for_keys = False
We have the exact same issue and we have been investigating for a week.
We tried the same things as you did with the same results.
The solution we came up with is to use the install.yml in the tasks directory in order to add the terminal and cliconf into their respectives system install directories.
---
- block:
- name: Create terminal target directory
file:
path: /usr/share/ansible/plugins/terminal/
state: directory
mode: 0755
connection: local
- name: install terminal plugin
copy:
src: terminal_plugins/myos.py
dest: /usr/share/ansible/plugins/terminal/myos.py
connection: local
- name: Create cliconf target directory
file:
path: /usr/share/ansible/plugins/cliconf/
state: directory
mode: 0755
connection: local
- name: install cliconf plugin
copy:
src: cliconf_plugins/myos.py
dest: /usr/share/ansible/plugins/cliconf/myos.py
connection: local
run_once: true
You may then add a call to install.yml in main.yml so that it executes the copy when you use the role:
---
- name: install/update driver
include: install.yml
Regards,
Stopostit
So I have my directory structure roughly like this
$ tree
.
├── ansible.cfg
├── play.yml
├── roles
│ ├── create_new_user
│ │ ├── defaults
│ │ │ └── main.yml
│ │ └── tasks
│ │ └── main.yml
│ ├── update
│ │ └── tasks
│ │ └── main.yml
└── tests
├── inventory
└── test.yml
Inside my .travis.yml file
---
sudo: required
dist: trusty
language: python
python: "2.7"
# Doc: https://docs.travis-ci.com/user/customizing-the-build#Build-Matrix
env:
- ANSIBLE_VERSION=2.0.0.0
- ANSIBLE_VERSION=1.9.6
- USER=tasdik
install:
- if [ "$ANSIBLE_VERSION" = "latest" ]; then pip install ansible; else pip install ansible==$ANSIBLE_VERSION; fi
- if [ "$ANSIBLE_VERSION" = "latest" ]; then pip install ansible-lint; fi
script:
- ansible-playbook -i tests/inventory tests/test.yml --syntax-check
- ansible-playbook -i tests/inventory tests/test.yml -vvvv --skip-tags "update, copy_host_ssh_id"
# check is the user is created or not
- id -u $USER | grep -q "no" && (echo "user not found" && exit 1) || (echo "user found" && exit 0)
I am trying to skip a task inside the role which is inside roles/create_new_user/tasks/main.yml
But the task is not getting skipped. The role in question
---
- name: Copy .ssh/id_rsa from host box to the remote box for user {{ username }}
become: true
copy:
src: ~/.ssh/id_rsa.pub
dest: /home/{{ username }}/.ssh/authorized_keys
mode: 0600
owner: "{{ username }}"
group: "{{ username }}"
tags:
- copy_host_ssh_id
Contents of tests/test.yml
---
- hosts: localhost
connection: local
become: true
roles:
- {role: ../roles/update}
- {role: ../roles/create_new_user}
Travis build
https://travis-ci.org/prodicus/ansible-bootstrap-server/
DOCS:
http://docs.ansible.com/ansible/playbooks_tags.html#tags
Remove space in tags enumeration string (quotes also unnecessary because you have no spaces) :
--skip-tags update,copy_host_ssh_id
I have my directory structure as this
└── digitalocean
├── README.md
├── play.yml
└── roles
├── bootstrap_server
│ └── tasks
│ └── main.yml
├── create_new_user
│ └── tasks
│ └── main.yml
├── update
│ └── tasks
│ └── main.yml
└── vimserver
├── files
│ └── vimrc_server
└── tasks
└── main.yml
When I am creating a user under the role create_new_user, I was hard coding the user name as
---
- name: Creating a user named username on the specified web server.
user:
name: username
state: present
shell: /bin/bash
groups: admin
generate_ssh_key: yes
ssh_key_bits: 2048
ssh_key_file: .ssh/id_rsa
- name: Copy .ssh/id_rsa from host box to the remote box for user username
become: true
copy:
src: ~/.ssh/id_rsa.pub
dest: /home/usernmame/.ssh/authorized_keys
mode: 0600
owner: username
group: username
One way of solving this may be to create a var/main.yml and put the username there. But I wanted something through which I can specify the username at play.yml level. As I am also using the username in the role vimrcserver.
I am calling the roles using play.yml
---
- hosts: testdroplets
roles:
- update
- bootstrap_server
- create_new_user
- vimserver
Would a template work here in this case? Couldn't find much from these SO questions
I got it working by doing a
---
- hosts: testdroplets
roles:
- update
- bootstrap_server
- role: create_new_user
username: username
- role: vimserver
username: username
on play.yml
Although would love to see a different approach then this
Docs: http://docs.ansible.com/ansible/playbooks_roles.html#roles
EDIT
I finally settled with a directory structure like
$ tree
.
├── README.md
├── ansible.cfg
├── play.yml
└── roles
├── bootstrap_server
│ └── tasks
│ └── main.yml
├── create_new_user
│ ├── defaults
│ │ └── main.yml
│ └── tasks
│ └── main.yml
├── update
│ └── tasks
│ └── main.yml
└── vimserver
├── defaults
│ └── main.yml
├── files
│ └── vimrc_server
└── tasks
└── main.yml
Where I am creating a defaults/main.yml file inside the roles where I need the usage of {{username}}
If someone is interested in the code,
https://github.com/tasdikrahman/ansible-bootstrap-server
You should be able to put username in a vars entry in play.yml.
Variables can also be split out into separate files.
Here is an example which shows both options:
- hosts: all
vars:
favcolor: blue
vars_files:
- /vars/external_vars.yml
tasks:
- name: this is just a placeholder
command: /bin/echo foo
https://docs.ansible.com/ansible/playbooks_variables.html#variable-file-separation
Ansible seems to delight in having different ways to do the same thing, without having either a nice comprehensive reference, or a rationale discussing the full implications of each different approach :). If you didn't remember the above was possible (I'd completely forgotten vars_files), the easiest option to find from the documentation might have been a third way, which is the most sophisticated one.
There's a prominent recommendation for ansible-examples. You can see a group_vars directory, with files which automatically provide values for hosts according to their groups, including the magic all group. The group_vars directory can be placed in the same directory as the playbook.
https://github.com/ansible/ansible-examples/tree/master/lamp_simple
Maybe this is what you want?
---
- hosts: testdroplets
roles:
- update
- bootstrap_server
- { role: create_new_user, username: 'foobar' }
- vimserver
https://docs.ansible.com/ansible/2.5/user_guide/playbooks_reuse_roles.html#using-roles
If you use include_role, variables can be passed like below.
- hosts: all_hosts
tasks:
- include_role:
name: "path/to/role"
vars:
var1: "var2_value"
var2: "var2_value"
Can't you just pass the variable from the command line with the -e parameter? So you can specifiy the variable even before execution. This also results in the strongest variable declaration which always takes precendence (see Variable precendence).
If you want to place it inside your playbook I suggest defining the username with the set_fact directive in the playbook. This variable is then available in all roles and included playbooks as well. Something like:
---
- hosts: testdroplets
pre_tasks:
- set_fact:
username: my_username
roles:
- update
- bootstrap_server
- create_new_user
- vimserver
It is all here: http://docs.ansible.com/ansible/playbooks_variables.html
while there are already some good answers, but I wanted to add mine because I've done this exact thing.
Here is the role I wrote: https://github.com/jmalacho/ansible-examples/tree/master/roles/users
And, I use hash_merge=true, and ansible's group_vars to make a dictionary of users: keys,groups so that adding a new user by host or by environment, and re-running is easy.
I also wrote up how my team uses group variables for environments once like this: "https://www.coveros.com/ansible-environment-design/"