According to Best Practices I keep my script files in roles/X/files structure. So I have:
roles/X/files/
script.sh
library.sh
library2.sh
In roles/X/tasks/main.yml I invoke the script:
- name: Do something
script: script.sh --options
But there is sourcing of a library in the script. I wondered that only script.sh file was copied to remote_tmp/ansible-tmp-xxx/script.sh.
For each task, a file is copied to another directory (another temp directory).
Is it normal behavior? I want avoid copying files manually.
$ ansible --version
ansible 2.4.0.0
...
python version = 2.7.5 (default, Aug 4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
My solution:
roles/X/files/test_lib.sh
#!/usr/bin/env bash
LIB="$HOME/.ansible/tmp/lib"
if [[ -f "$LIB/library.sh" ]]; then
source "$LIB/library.sh"
do_it
else
echo "ERROR library.sh not found"
fi
roles/x/files/lib/library.sh
do_it() {
echo "I'm the library"
}
roles/X/tasks/main.yml
---
- name: Creates directory
file:
path: $HOME/.ansible/tmp
state: directory
recurse: yes
- name: Check if required files exist
stat:
path: $HOME/.ansible/tmp/lib/library.sh
register: stat_lib_directory
- name: Copy library
# this copies lib from $HOME!!!
#command: cp -r lib/. $HOME/.ansible/tmp/
copy:
src: lib
dest: $HOME/.ansible/tmp
directory_mode: 0755
mode: 0644
when: stat_lib_directory.stat.exists == False
- name: Run the script on remote host
script: test_lib.sh
register: out
- debug: var=out.stdout_lines
- name: Cleaning
file:
path: $HOME/.ansible/tmp/lib
state: absent
And it finally works:
$ ansible-playbook copy-dir.yml
PLAY [host] ****************************************************************************
TASK [copy-dir : Creates directory] ****************************************************
ok: [host]
TASK [copy-dir : Check if required files exist] ****************************************
ok: [host]
TASK [copy-dir : Copy library] *********************************************************
changed: [host]
TASK [copy-dir : Run the script on remote host] ****************************************
changed: [host]
TASK [copy-dir : debug] ****************************************************************
ok: [host] => {
"out.stdout_lines": [
"\u001b[?1034hI'm the library"
]
}
TASK [copy-dir : Cleaning] *************************************************************
changed: [host]
PLAY RECAP *****************************************************************************
host : ok=6 changed=3 unreachable=0 failed=0
Just use ansible.builtin.copy and let ansible handles it for you?
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/copy_module.html
Although if I have a shell script long enough that requires libraries I'd probably rewrite that in Python and even turn that into a Ansible module!
https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_general.html
Have fun!
Related
So I created this Ansible playbook to:
copy a zip file and unzip it
copy a zip file and unzip it
make script inside the file executable
run the script
enable 2 services
- name: fideliplaybook
hosts: k8scluster
tasks:
- name: copying file with playbook
become: true
copy:
src: /home/lc/lc.zip
dest: /home/lc/
mode: 755
- name: Update apt cache and install unzip
become: true
command: apt install unzip
- name: unzip file
become: true
unarchive:
src: /home/lc/lc.zip
dest: /home/lc/
- name: make script executable
become: true
file: dest=/home/lc/lc/install.sh mode=755
- name: Execute the script
become: true
command: sh /home/lc/lc/install.sh
- name: Enable service 1
become: true
command: systemctl enable service1.service
- name: Enable service 2
become: true
command: systemctl enable service1.service
the issue that I am facing here that when ansible is trying to execut the script "install.sh"
it somehow fails becuse script cant find 2 other scripts although the other scripts are in the same file.
so 3 scripts are in lc.zip but when running install.sh with ansible it cant find the 2 other scripts.
I fixed the issue by typing the full path of the 2 scripts inside the first script.
but anyone have an idea why this issue occuers.
one more quistion when i used ansible hosts file to define hosts and variables it didnt worked with INI like this:
[webservers]
www[01:50].example.com
It only woks In YAML:
...
webservers:
hosts:
www[01:50].example.com:
Anyone know why?
About the script not finding the other two scripts, you should update the full path to the other two scripts if the path is always fixed OR if you want to use the relative path, you can try the following,
- name: Execute the script
become: true
command: sh install.sh
args:
chdir: /home/lc/lc/
And the inventory looks fine. Here is a test to confirm.
# cat test.ini
[webservers]
tstsrv[7:8]
# ansible-playbook -i test.ini test.yaml -u admin -k
SSH password:
PLAY [webservers] ***********************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************
ok: [tstsrv8]
ok: [tstsrv7]
TASK [print hostname] ***********************************************************************************************************************************************
changed: [tstsrv8]
changed: [tstsrv7]
PLAY RECAP **********************************************************************************************************************************************************
tstsrv7 : ok=2 changed=1 unreachable=0 failed=0
tstsrv8 : ok=2 changed=1 unreachable=0 failed=0
#
Consider script module dedicated for running scripts on targets, if possible.
I'm running a script remotely on an ansible client which creates a filename HOSTNAME.html.
I plan to run this on numerous clients in one go, so I need to be able to copy all the files *.html from all the clients.
I'm new to this so have a little playbook.
---
- hosts: tariq-test
tasks:
- name: run script
script: /usr/bin/cfg2html-linux
- name: fetch file
fetch:
src: /root/*.html
dest: /tmp/
flat: yes
And get this:
[root#ansible playbooks]# ansible-playbook scp.yml
PLAY [tariq-test] *******************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************
ok: [tariq-test]
TASK [run script] *******************************************************************************************************************************************
changed: [tariq-test]
TASK [fetch file] *******************************************************************************************************************************************
fatal: [tariq-test]: FAILED! => {"changed": false, "msg": "file not found: /root/*.html"}
to retry, use: --limit #/etc/ansible/playbooks/scp.retry
PLAY RECAP **************************************************************************************************************************************************
tariq-test : ok=2 changed=1 unreachable=0 failed=1
(Not tested)
Option 1:
If the filename is hostname.html and there is only one file
fetch:
src: "/root/{{ansible_hostname}}.html"
dest: /tmp/
flat: yes
Option 2:
Find the files with *.html pattern and then use fetch within loop.
- name: Find files
find:
path: "{{folder}}"
pattern: "*.html"
register: html_files
- name: Fetch files
fetch:
src: "{{item.path}}"
dest: /tmp/
flat: yes
with_items: "{{html_files.files}}"
I want to create a zip to package my function by using ansible, this is my playbook:
---
- name: build lambda functions
hosts: localhost
- name: Buid Zip Package
command: zip -r functions/build/build-function.zip .
args:
chdir: functions/function-package/
the function I want to package has its code inside functions/function-package/
I get this error:
> TASK [Buid Zip Package]
> ******************************************************** fatal: [localhost]: FAILED! => {"changed": false, "cmd": "zip -r
> functions/build/build-function.zip", "failed": true, "msg": "[Errno 2]
> No such file or directory", "rc": 2}
The paths are very correct, I don't know what else to check!
the playbook is in a file in the same level as the directory /functions
this is the strtucture of the files:
-- playbook.yml
-- /functions
-- /build
-- /function-package
-- script.py
-- lib
the zip is to be put inside /build
If you're using chdir: functions/function-package on your task, then you're running the zip command inside the functions/function-package directory. That means that the path functions/build/build-function.zip is probably no longer valid, since you're inside a child of the functions/ directory.
Based on the information in your question, the appropriate path is probably ../build/, like this:
- name: build lambda functions
hosts: localhost
- name: Buid Zip Package
command: zip -r ../build/build-function.zip .
args:
chdir: functions/function-package/
Update
If I replicate your directory layout:
$ find *
functions
functions/function-package
functions/function-package/script.py
functions/build
playbook.yml
And run this playbook:
---
- hosts: localhost
gather_facts: false
tasks:
- name: Build Zip Package
command: zip -r ../build/build-function.zip .
args:
chdir: functions/function-package
It works just fine:
$ ansible-playbook playbook.yml
PLAY [localhost] ******************************************************************************
TASK [Build Zip Package] **********************************************************************
changed: [localhost]
PLAY RECAP ************************************************************************************
localhost : ok=1 changed=1 unreachable=0 failed=0
And the .zip file exists as expected:
$ ls -l ./functions/build/build-function.zip
-rw-rw-r--. 1 lars lars 209 Jan 3 08:19 ./functions/build/build-function.zip
I'm writing an Ansible script to setup a zookeeper cluster. After extract zookeeper tar ball:
unarchive: src={{tmp_dir}}/zookeeper.tar.gz dest=/opt/zookeeper copy=no
I get a zookeeper directory that contains version number:
[root#sc-rdops-vm09-dhcp-2-154 conf]# ls /opt/zookeeper
zookeeper-3.4.8
To proceed, I have to know name of the extracted sub-directory. For example, I need to copy a configure to /opt/zookeeper/zookeeper-3.4.8/conf.
How to get zookeeper-3.4.8 with Ansible statement?
Try with this:
➜ ~ cat become.yml
---
- hosts: localhost
user: vagrant
tasks:
- shell: ls /opt/zookeeper
register: path
- debug: var=path.stdout
➜ ~ ansible-playbook -i hosts-slaves become.yml
[WARNING]: provided hosts list is empty, only localhost is available
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [localhost]
TASK [command] *****************************************************************
changed: [localhost]
TASK [debug] *******************************************************************
ok: [localhost] => {
"path.stdout": "zookeeper-3.4.8"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0
Then you could use {{ path.stdout }} to set the name of the path, in the next tasks.
Alternatively, before you proceed with the next steps you could rename this directory
- name: Rename directory
shell: mv `ls -d -1 zookeeper*` zookeeper
The above shell command substitution (inside backticks) should work.
When using Ansible through Ansible Pull, the template directive's validate step fails to find the file specified by %s.
"No such file" error reported by ansible-pull:
TASK [ssh : place ssh config file] *********************************************
fatal: [localhost]: FAILED! => {
"changed": true,
"cmd": "sshd -t -f /home/nhooey/.ansible/tmp/ansible-tmp-1453485441.94-279324955743/source",
"failed": true,
"msg": "[Errno 2] No such file or directory",
"rc": 2
}
Problematic template directive:
- name: place ssh config file
template:
src: etc/ssh/sshd_config
dest: /etc/ssh/sshd_config
owner: root
group: root
mode: 0644
validate: 'sshd -t -f %s'
This happens with either Ansible 1.9.4 or 2.0.0.2 from (Python 2.7's Pip) and only when using Ansible Pull. Running ansible-playbook locally after manually checking out the repository works fine.
Unfortunately I'm not able to reproduce this error in the trivial case with a sample repository that I created.
Failure to reproduce error with simple test case:
$ virtualenv .venv && source .venv/bin/activate && pip install ansible
$ ansible-pull --directory /tmp/ansible-test \
--url https://github.com/nhooey/ansible-pull-template-validate-bug.git playbook.yaml
Starting Ansible Pull at 2016-01-22 13:14:51
/Users/nhooey/git/github/nhooey/ansible-pull-template-validate-bug/.venv/bin/ansible-pull \
--directory /tmp/ansible-test \
--url https://github.com/nhooey/ansible-pull-template-validate-bug.git \
playbook.yaml
localhost | SUCCESS => {
"after": "07bb13992910e0efe30d071d5f5a2a2e88251045",
"before": "07bb13992910e0efe30d071d5f5a2a2e88251045",
"changed": false
}
[WARNING]: provided hosts list is empty, only localhost is available
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [localhost]
TASK [Delete template file] ****************************************************
changed: [localhost]
TASK [Test template validation] ************************************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=3 changed=2 unreachable=0 failed=0
Playbook that won't fail in the simple test case above:
---
- hosts: localhost
tasks:
- name: Delete template file
file:
path: /tmp/file
state: absent
- name: Test template validation
template:
src: file
dest: /tmp/file
validate: 'ls %s'
It seems like there could be a problem with the timing around when ansible-pull creates and deletes temporary files in Ansible.
What's happening?
It's saying that it can't find sshd because it's not in the path. Silly me...