How can I pass a relative path so that Ansible can copy files from node/keys and copy them to a server?
The playbook is ansible/playbook.
My directory structure is:
├── ansible
│ ├── inventory
│ └── playbook
├── node
│ ├── keys
│ ├── index.js
│ ├── node_modules
│ ├── package-lock.json
│ └── utils
└── shell
├── data.json
├── create-data.sh
├── destory.sh
└── firewall-rules.sh
Below is the playbook:
- hosts: all
vars:
source: "{{ source }}"
destination: /home/ubuntu
tasks:
- name: Copy files
copy:
src: "{{ source }}"
dest: "{{ destination }}"
That's how I run:
ansible-playbook -i inventory/inventory.yaml playbook/crypto-generate.yaml
--extra-vars "source=../node/keys"
I am trying to pass a relative path.
I am using {{ playbook_dir }} to construct full path,see
special ansible variables
- name: Copy files
copy:
src: "{{ playbook_dir }}/../../node/keys"
dest: "{{ destination }}"
You can use absolute paths with src that avoids the problems of not knowing where is the root folder.
Local path to a file to copy to the remote server. This can be
absolute or relative. If path is a directory, it is copied
recursively. In this case, if path ends with "/", only inside contents
of that directory are copied to destination. Otherwise, if it does not
end with "/", the directory itself with all contents is copied. This
behavior is similar to the rsync command line tool.
https://docs.ansible.com/ansible/latest/modules/copy_module.html
Related
I have an Ansible role that will provision an ubuntu server in Azure. The VM provisioning is working fine for me but I need to copy few files from my localhost to this VM how can I do this?
├── defaults
│ └── main.yml
├── files
│ ├── cloud-init.yaml
│ └── files.txt
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── tasks
│ ├── copyfile.yaml
│ ├── main.yml
│ ├── apachenic.yaml
│ └── apachevm.yaml
└── vars
└── main.yml
Here I have kept the file files.txt (the file I want to copy) in file folder and created a new task file (copyfile.yaml) for copying. Adding content of copy tasks below.
- name: copy certs
become: true
become_user: admin
ansible_sudo_password: pass123
copy:
src: files.txt
dest: /home/admin/
owner: admin
group: admin
I have tried multiple times re-arranging and creating a new task file getting the below error message.
ERROR! conflicting action statements: copy, ansible_sudo_password
for me looks like your YAML is malformed.
try this: (top level play, lets say, its copyFilesTXT.yml )
- hosts: all
become: true
become_user: admin
become_method: sudo
tasks:
- name: copy files.txt file to remote machine
copy:
src: files.txt
dest: /home/admin/
owner: admin
group: admin
mode: 0644
this task can be started by this console invocation
/bin/ansible-playbook --ask-become-pass -i hosts.ini copyFilesTXT.yml -vv
it will ask for sudo password from STDIN, so you can provide it.
Also, you can omit --ask-become-pass and add this variable in vars/main.yml
ansible_become_pass: pass123
so, sudo password will be loaded from vars/main.yml
I try to copy files from roles/common/files with fileglob, but ansible-playbook searchs them in roles/common/tasks/files
Using Roles documentation says:
Any copy, script, template or include tasks (in the role) can
reference files in roles/x/{files,templates,tasks}/ (dir depends on
task) without having to path them relatively or absolutely.
Playbook:
# ./ansible/roles/common/tasks/main.yml
- hosts: localhost
connection: local
gather_facts: no
tasks:
- name: setup bashrc
import_tasks: bashrc.yml
Task:
# ./ansible/roles/common/tasks/bashrc.yml
- name: try to find bashrc libs in roles/common/files/bashrc
copy:
src: "{{ item }}"
dest: /tmp
with_fileglob:
- bashrc/*.lib.sh
# Causes the same error:
# loop: "{{ lookup('fileglob', 'bashrc/*', wantlist=True) }}"
Files tree:
.
├── ansible
│ └── roles
│ └── common
│ ├── files
│ │ └── bashrc
│ │ ├── shell-aliases.lib.sh
│ │ ├── shell-functions.lib.sh
│ │ └── shell-settings.lib.sh
│ └── tasks
│ ├── bashrc.yml
│ ├── main.retry
│ └── main.yml
Run playbook:
$ ansible-playbook -vvvvv ./ansible/roles/common/tasks/main.yml
...
TASK [try to find bashrc libs in roles/common/files/bashrc] *******...
task path: /home/<user>/git/homedirsync/ansible/roles/common/tasks/bashrc.yml:1
looking for "bashrc" at "/home/<user>/git/homedirsync/ansible/roles/common/tasks/files/bashrc"
looking for "bashrc" at "/home/<user>/git/homedirsync/ansible/roles/common/tasks/bashrc"
looking for "bashrc" at "/home/<user>/git/homedirsync/ansible/roles/common/tasks/files/bashrc"
looking for "bashrc" at "/home/<user>/git/homedirsync/ansible/roles/common/tasks/bashrc"
[WARNING]: Unable to find 'bashrc' in expected paths
...
Ansible version:
ansible 2.6.1
config file = /home/<user>/.ansible.cfg
configured module search path = [u'/var/ansible/library']
ansible python module location = /usr/local/lib/python2.7/dist-packages/ansible
executable location = /usr/local/bin/ansible
python version = 2.7.6 (default, Nov 13 2018, 12:45:42) [GCC 4.8.4]
I saw a lot of examples where it works and issues where it doesn't, but I can't localize the root of problem in my case. Community, please help.
Q: "Unable to find subdir in expected paths with fileglob"
A: Quoting from fileglob's NOTES
"Matching is against local system files on the Ansible controller. "
Role's feature "Any copy, script, template or include tasks can reference files in roles/x/{files,templates,tasks} ..." does not apply to fileglob.
Instead, it's possible to use special variables. For example
with_fileglob:
- '{{ role_path }}/files/bashrc/*.lib.sh'
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
I am using the Ansible Synchronize module like so:
- name: Synchronization of src on the control machine to dest on the remote hosts
synchronize:
src: http-checks/
dest: "{{ datadog_path }}/conf.d/http_check.d/"
delete: yes
recursive: yes
After the playbook executes, a directory called ~core/ is created with this directory structure:
├── ansible.cfg
├── hosts
├── site.yaml
└── ~core
└── .ansible
└── tmp
└── ansible-tmp-1528320500.98-124390628295059
└── synchronize.py
Question: How do I prevent the directory from being created?
I can't find any reference to this tmp directory in the ansible docs or the rsync docs.
After looking at https://github.com/ansible/ansible/issues/21562
It seems I need to add remote_tmp in ansible.cfg:
# ansible.cfg
...
remote_tmp = $HOME/.ansible/tmp
I'm trying to organize my playbooks according to the Directory Layout structure. The documentation doesn't seem to have a recommendation for host-specific files/templates.
I have 2 plays for a single site
example.com-provision.yml
example.com-deploy.yml
These files are located in the root of my structure. The provisioning playbook simply includes other roles
---
- hosts: example.com
roles:
- common
- application
- database
become: true
become_method: su
become_user: root
The deployment playbook doesn't include roles, but has it's own vars and tasks sections. I have a couple template and copy tasks, and am wondering what the 'best practice' is for where to put these host-specific templates/files within this directory structure.
Right now I have them at ./roles/example.com/templates/ and ./roles/example.com/files/, but need to reference the files with their full path from my deployment playbook, like
- name: deployment | copy httpd config
template:
src: ./roles/example.com/templates/{{ host }}.conf.j2
# ...
instead of
- name: deployment | copy httpd config
template:
src: {{ host }}.conf.j2
# ...
Facing the same problem the cleanest way seems for me the following structure:
In the top-level directory (same level as playbooks) I have a files folder (and if I needed also a templates folder). In the files folder there is a folder for every host with it's own files where the folder's name is the same as the host name in inventory.
(see the structure below: myhost1 myhost2)
.
├── files
│ ├── common
│ ├── myhost1
│ ├── myhost2
|
├── inventory
│ ├── group_vars
│ └── host_vars
├── roles
│ ├── first_role
│ └── second_role
└── my_playbook.yml
Now in any role you can access the files with files modules relatively:
# ./roles/first_role/main.yml
- name: Copy any host based file
copy:
src: "{{ inventory_hostname }}/file1"
dest: /tmp
Explanation:
The magic variable inventory_hostname is to get the host, see here
The any file module (as for example copy) looks up the files directory in the respective role directory and the files directory in the same level as the calling playbook. Of course same applies to templates (but if you have different templates for the same role you should reconsider your design)
Semantically a host specific file does not belong into a role, but somewhere outside (like host_vars).