No such file or directory when using zip command - ansible

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

Related

Ansible playbook failed when running a shell script

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.

Ansible best practices - how to use role/files from files directory?

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!

Ansible fails to locate templates in role's /templates directory [duplicate]

Does ansible pass Role Default variables to the Handlers within the same Role?
Here's a minimal excerpt of the playbook that has the issue:
Role hierarchy
- playbook.yml
- roles/
- gunicorn/
- defaults/
- main.yml
- handlers/
- main.yml
- code-checkout/
- tasks/
- main.yml
Here's the file contents
gunicorn/defaults/main.yml
---
gu_log: "/tmp/gunicorn.log"
gunicorn/handlers/main.yml
---
- name: Clear Gunicorn Log
shell: rm {{ gu_log }}
finalize/tasks/main.yml
---
- name: Test Handlers
shell: ls
notify:
- Restart Gunicorn
playbook.yml
---
- name: Deploy
hosts: webservers
tasks:
- include: roles/finalize/tasks/main.yml
handlers:
- include: roles/gunicorn/handlers/main.yml
AFAIK everything looks good. However, I get this error during the playbook execution
FAILED! => {"failed": true, "msg": "the field 'args' has an invalid
value, which appears to include a variable that is undefined. The
error was: 'gu_log' is undefined\n\nThe error appears to have been in
'/roles/gunicorn/handlers/main.yml':
line 3, column 3, but may\nbe elsewhere in the file depending on the
exact syntax problem.\n\nThe offending line appears to be:\n\n\n-
name: Restart Gunicorn\n ^ here\n"}
Using Ansible 2.2 on Ubuntu 12.04 LTS
Here's a modified version of techraf's script that creates all the directories and demonstrates my issue
#!/bin/bash
mkdir -p ./rtindru-test/roles/gunicorn
mkdir -p ./rtindru-test/roles/gunicorn/defaults
mkdir -p ./rtindru-test/roles/gunicorn/handlers
mkdir -p ./rtindru-test/roles/finalize/tasks
cat >./rtindru-test/roles/finalize/tasks/main.yml <<HANDLERS_END
---
- name: Test Handlers
shell: rm {{ gu_log }}
HANDLERS_END
cat >./rtindru-test/roles/gunicorn/handlers/main.yml <<HANDLERS_END
---
- name: Clear Gunicorn Log
shell: rm {{ gu_log }}
HANDLERS_END
cat >./rtindru-test/roles/gunicorn/defaults/main.yml <<DEFAULTS_END
---
gu_log: "/tmp/gunicorn.log"
DEFAULTS_END
cat >./rtindru-test/playbook.yml <<PLAYBOOK_END
---
- name: Deploy
hosts: localhost
tasks:
- include: roles/finalize/tasks/main.yml
handlers:
- include: roles/gunicorn/handlers/main.yml
PLAYBOOK_END
touch /tmp/gunicorn.log
ls -l /tmp/gunicorn.log
ansible-playbook ./rtindru-test/playbook.yml
ls -l /tmp/gunicorn.log
Output
PLAY [Deploy]
TASK [setup]
******************************************************************* ok: [localhost]
TASK [Test Handlers]
*********************************************************** fatal: [localhost]: FAILED! => {"failed": true, "msg": "the field 'args' has
an invalid value, which appears to include a variable that is
undefined. The error was: 'gu_log' is undefined\n\nThe error appears
to have been in '/rtindru-test/roles/finalize/tasks/main.yml': line 2,
column 3, but may\nbe elsewhere in the file depending on the exact
syntax problem.\n\nThe offending line appears to be:\n\n---\n- name:
Test Handlers\n ^ here\n"} to retry, use: --limit
#/rtindru-test/playbook.retry
PLAY RECAP
********************************************************************* localhost : ok=1 changed=0 unreachable=0
failed=1
You are neither defining nor using any roles. With the following task:
- include: roles/finalize/tasks/main.yml
you are only including a tasks file into your playbook. It has nothing to do with roles.
To assign a role you should specify a list of roles for a play (one or more):
role:
- my_role1
- my_role2
Please have a look at the documentation on roles and feel free to use the playbook and structure as created by the below script.
Does ansible pass Role Default variables to the Handlers within the same Role?
Yes it does.
For a proof run the following bash script which creates and runs a minimal example. It takes the contents of gunicorn/defaults/main.yml and gunicorn/handlers/main.yml from the question intact and adds missing components: the tasks and the playbook. It creates a file to be removed and runs the playbook.
#!/bin/bash
mkdir -p ./so41285033/roles/gunicorn
mkdir -p ./so41285033/roles/gunicorn/defaults
mkdir -p ./so41285033/roles/gunicorn/handlers
mkdir -p ./so41285033/roles/gunicorn/tasks
cat >./so41285033/roles/gunicorn/tasks/main.yml <<TASKS_END
---
- debug:
changed_when: true
notify: Clear Gunicorn Log
TASKS_END
cat >./so41285033/roles/gunicorn/handlers/main.yml <<HANDLERS_END
---
- name: Clear Gunicorn Log
shell: rm {{ gu_log }}
when: "'apiservers' not in group_names"
HANDLERS_END
cat >./so41285033/roles/gunicorn/defaults/main.yml <<DEFAULTS_END
---
gu_log: "/tmp/gunicorn.log"
DEFAULTS_END
cat >./so41285033/playbook.yml <<PLAYBOOK_END
---
- hosts: localhost
gather_facts: no
connection: local
roles:
- gunicorn
PLAYBOOK_END
touch /tmp/gunicorn.log
ls -l /tmp/gunicorn.log
ansible-playbook ./so41285033/playbook.yml
ls -l /tmp/gunicorn.log
The result:
-rw-r--r-- 1 techraf wheel 0 Dec 23 07:57 /tmp/gunicorn.log
[WARNING]: Host file not found: /etc/ansible/hosts
[WARNING]: provided hosts list is empty, only localhost is available
PLAY [localhost] ***************************************************************
TASK [gunicorn : debug] ********************************************************
ok: [localhost] => {
"msg": "Hello world!"
}
RUNNING HANDLER [gunicorn : Clear Gunicorn Log] ********************************
changed: [localhost]
[WARNING]: Consider using file module with state=absent rather than running rm
PLAY RECAP *********************************************************************
localhost : ok=2 changed=2 unreachable=0 failed=0
ls: /tmp/gunicorn.log: No such file or directory
Interpretation:
Before running the playbook the file /tmp/gunicorn.log was created and its existence verified:
-rw-r--r-- 1 techraf wheel 0 Dec 23 07:57 /tmp/gunicorn.log
After running the playbook the file /tmp/gunicorn.log does not exist:
ls: /tmp/gunicorn.log: No such file or directory
Ansible correctly passed the variable gu_log value to the Clear Gunicorn Log handler which removed the file.
Final remark:
The problem described in question is impossible to reproduce, because the question does not contain complete nor verifiable example in the meaning of MCVE.

Ansible not detecting Role default variables in its handler

Does ansible pass Role Default variables to the Handlers within the same Role?
Here's a minimal excerpt of the playbook that has the issue:
Role hierarchy
- playbook.yml
- roles/
- gunicorn/
- defaults/
- main.yml
- handlers/
- main.yml
- code-checkout/
- tasks/
- main.yml
Here's the file contents
gunicorn/defaults/main.yml
---
gu_log: "/tmp/gunicorn.log"
gunicorn/handlers/main.yml
---
- name: Clear Gunicorn Log
shell: rm {{ gu_log }}
finalize/tasks/main.yml
---
- name: Test Handlers
shell: ls
notify:
- Restart Gunicorn
playbook.yml
---
- name: Deploy
hosts: webservers
tasks:
- include: roles/finalize/tasks/main.yml
handlers:
- include: roles/gunicorn/handlers/main.yml
AFAIK everything looks good. However, I get this error during the playbook execution
FAILED! => {"failed": true, "msg": "the field 'args' has an invalid
value, which appears to include a variable that is undefined. The
error was: 'gu_log' is undefined\n\nThe error appears to have been in
'/roles/gunicorn/handlers/main.yml':
line 3, column 3, but may\nbe elsewhere in the file depending on the
exact syntax problem.\n\nThe offending line appears to be:\n\n\n-
name: Restart Gunicorn\n ^ here\n"}
Using Ansible 2.2 on Ubuntu 12.04 LTS
Here's a modified version of techraf's script that creates all the directories and demonstrates my issue
#!/bin/bash
mkdir -p ./rtindru-test/roles/gunicorn
mkdir -p ./rtindru-test/roles/gunicorn/defaults
mkdir -p ./rtindru-test/roles/gunicorn/handlers
mkdir -p ./rtindru-test/roles/finalize/tasks
cat >./rtindru-test/roles/finalize/tasks/main.yml <<HANDLERS_END
---
- name: Test Handlers
shell: rm {{ gu_log }}
HANDLERS_END
cat >./rtindru-test/roles/gunicorn/handlers/main.yml <<HANDLERS_END
---
- name: Clear Gunicorn Log
shell: rm {{ gu_log }}
HANDLERS_END
cat >./rtindru-test/roles/gunicorn/defaults/main.yml <<DEFAULTS_END
---
gu_log: "/tmp/gunicorn.log"
DEFAULTS_END
cat >./rtindru-test/playbook.yml <<PLAYBOOK_END
---
- name: Deploy
hosts: localhost
tasks:
- include: roles/finalize/tasks/main.yml
handlers:
- include: roles/gunicorn/handlers/main.yml
PLAYBOOK_END
touch /tmp/gunicorn.log
ls -l /tmp/gunicorn.log
ansible-playbook ./rtindru-test/playbook.yml
ls -l /tmp/gunicorn.log
Output
PLAY [Deploy]
TASK [setup]
******************************************************************* ok: [localhost]
TASK [Test Handlers]
*********************************************************** fatal: [localhost]: FAILED! => {"failed": true, "msg": "the field 'args' has
an invalid value, which appears to include a variable that is
undefined. The error was: 'gu_log' is undefined\n\nThe error appears
to have been in '/rtindru-test/roles/finalize/tasks/main.yml': line 2,
column 3, but may\nbe elsewhere in the file depending on the exact
syntax problem.\n\nThe offending line appears to be:\n\n---\n- name:
Test Handlers\n ^ here\n"} to retry, use: --limit
#/rtindru-test/playbook.retry
PLAY RECAP
********************************************************************* localhost : ok=1 changed=0 unreachable=0
failed=1
You are neither defining nor using any roles. With the following task:
- include: roles/finalize/tasks/main.yml
you are only including a tasks file into your playbook. It has nothing to do with roles.
To assign a role you should specify a list of roles for a play (one or more):
role:
- my_role1
- my_role2
Please have a look at the documentation on roles and feel free to use the playbook and structure as created by the below script.
Does ansible pass Role Default variables to the Handlers within the same Role?
Yes it does.
For a proof run the following bash script which creates and runs a minimal example. It takes the contents of gunicorn/defaults/main.yml and gunicorn/handlers/main.yml from the question intact and adds missing components: the tasks and the playbook. It creates a file to be removed and runs the playbook.
#!/bin/bash
mkdir -p ./so41285033/roles/gunicorn
mkdir -p ./so41285033/roles/gunicorn/defaults
mkdir -p ./so41285033/roles/gunicorn/handlers
mkdir -p ./so41285033/roles/gunicorn/tasks
cat >./so41285033/roles/gunicorn/tasks/main.yml <<TASKS_END
---
- debug:
changed_when: true
notify: Clear Gunicorn Log
TASKS_END
cat >./so41285033/roles/gunicorn/handlers/main.yml <<HANDLERS_END
---
- name: Clear Gunicorn Log
shell: rm {{ gu_log }}
when: "'apiservers' not in group_names"
HANDLERS_END
cat >./so41285033/roles/gunicorn/defaults/main.yml <<DEFAULTS_END
---
gu_log: "/tmp/gunicorn.log"
DEFAULTS_END
cat >./so41285033/playbook.yml <<PLAYBOOK_END
---
- hosts: localhost
gather_facts: no
connection: local
roles:
- gunicorn
PLAYBOOK_END
touch /tmp/gunicorn.log
ls -l /tmp/gunicorn.log
ansible-playbook ./so41285033/playbook.yml
ls -l /tmp/gunicorn.log
The result:
-rw-r--r-- 1 techraf wheel 0 Dec 23 07:57 /tmp/gunicorn.log
[WARNING]: Host file not found: /etc/ansible/hosts
[WARNING]: provided hosts list is empty, only localhost is available
PLAY [localhost] ***************************************************************
TASK [gunicorn : debug] ********************************************************
ok: [localhost] => {
"msg": "Hello world!"
}
RUNNING HANDLER [gunicorn : Clear Gunicorn Log] ********************************
changed: [localhost]
[WARNING]: Consider using file module with state=absent rather than running rm
PLAY RECAP *********************************************************************
localhost : ok=2 changed=2 unreachable=0 failed=0
ls: /tmp/gunicorn.log: No such file or directory
Interpretation:
Before running the playbook the file /tmp/gunicorn.log was created and its existence verified:
-rw-r--r-- 1 techraf wheel 0 Dec 23 07:57 /tmp/gunicorn.log
After running the playbook the file /tmp/gunicorn.log does not exist:
ls: /tmp/gunicorn.log: No such file or directory
Ansible correctly passed the variable gu_log value to the Clear Gunicorn Log handler which removed the file.
Final remark:
The problem described in question is impossible to reproduce, because the question does not contain complete nor verifiable example in the meaning of MCVE.

Ansible via Ansible Pull can't find file in `template: validate="stat %s"`

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...

Resources