running an ansible local task in a remote playbook - ansible

I'm trying to get this task to run locally (on the machine that is running the playbook) :
- name: get the local repo's branch name
local_action: git branch | awk '/^\*/{print $2}'
register: branchName
I tried plenty of variations with no success
all other tasks are meant to run on the target host, which is why running the whole playbook local is not an option
TASK: [get the local repo's branch name] **************************************
<127.0.0.1> REMOTE_MODULE git branch | awk '/^\*/{print $2}'
<127.0.0.1> EXEC ['/bin/sh', '-c', 'mkdir -p $HOME/.ansible/tmp/ansible-tmp-1407258765.57-75899426008172 && chmod a+rx $HOME/.ansible/tmp/ansible-tmp-1407258765.57-75899426008172 && echo $HOME/.ansible/tmp/ansible-tmp-1407258765.57-75899426008172']
<127.0.0.1> PUT /tmp/tmpQVocvw TO /home/max/.ansible/tmp/ansible-tmp-1407258765.57-75899426008172/git
<127.0.0.1> EXEC ['/bin/sh', '-c', '/usr/bin/python /home/max/.ansible/tmp/ansible-tmp-1407258765.57-75899426008172/git; rm -rf /home/max/.ansible/tmp/ansible-tmp-1407258765.57-75899426008172/ >/dev/null 2>&1']
failed: [portal-dev] => {"failed": true}
msg: this module requires key=value arguments (['branch', '|', 'awk', '/^\\*/{print $2}'])
FATAL: all hosts have already failed -- aborting
update:
I have followed bkan's suggestion (bellow), and got a bit further, but
- name: get the local repo's branch name
local_action: command git branch | (awk '/^\*/{print $2}')
sudo: no
register: branchName
now the git command gets launched but not correctly (see error below).
note that this command runs perfectly as a "shell" but unfortunately there is no local_shell equivalent of local_action ...
failed: [portal-dev] => {"changed": true, "cmd": ["git", "branch", "|", "(awk", "/^\\*/{print $2})"], "delta": "0:00:00.002980", "end": "2014-08-05 18:00:01.293632", "rc": 129, "start": "2014-08-05 18:00:01.290652"}
stderr: usage: git branch [options] [-r | -a] [--merged | --no-merged]
or: git branch [options] [-l] [-f] <branchname> [<start-point>]
or: git branch [options] [-r] (-d | -D) <branchname>...
or: git branch [options] (-m | -M) [<oldbranch>] <newbranch>
...

The format for local_action is:
local_action: <module_name> <arguments>
In your example, Ansible thinks you are trying to use the git module and throws an error because you don't have the correct arguments for the git module. Here is how it should look:
local_action: shell git branch | awk '/^\*/{print $2}'
Source: http://docs.ansible.com/playbooks_delegation.html#delegation

Related

Skip confirmation in Ansible during deleting node with Kubspray

I'm trying to run Ansible playbook remove-node.yml from Kubespray repository.
But when I run a job I get an error:
TASK [check confirmation] ******************************************************
fatal: [node61]: FAILED! => {"changed": false, "msg": "Delete nodes confirmation failed"}
I'm doing it through GitLabCI and here is my .gitlab-ci.yml:
stages:
- deploy
image: ***/releases/kubespray:v2.12.5
variables:
ANSIBLE_HOST_KEY_CHECKING: "False"
before_script:
- mkdir -p ~/.ssh
- echo "$id_rsa" | base64 -d > ~/.ssh/id_rsa
- chmod -R 700 ~/.ssh
delete_node:
stage: deploy
when: manual
script:
- ansible-playbook -v -u root --key-file=~/.ssh/id_rsa --extra-vars skip_confirmation=yes -i inventory/hosts.ini /kubespray/remove-node.yml -e "node=node61"
I've tried check_confirmation, skip_confirmation=true, True or 'true' and other variations, but none of them works
The required variable is delete_nodes_confirmation not skip_confirmation.
So the answer is delete_nodes_confirmation=yes.
Can you run your script like this?
ansible-playbook -v -u root --key-file=~/.ssh/id_rsa -i inventory/hosts.ini /kubespray/remove-node.yml --extra-var "node=node61 skip_confirmation=true"

starting jboss server using ansible and returning back control [duplicate]

This question already has answers here:
Ansible Command module says that '|' is illegal character
(2 answers)
Closed 5 years ago.
Below yaml playbook restarts the jboss server but doesnt get back control to execute next ansible command. I have also used wait for module to stop waiting for current command result and go for next command. But still ansbile hangs on current command indefinitely . Please let me know when I went wrong?
---
- hosts: test1
tasks:
- name: simple command
become: true
command: whoami
register: output
- debug:
msg: "I gave the command whoami and the out is '{{output.stdout}}'"
- name: change to jboss user
become: true
become_user: jboss
command: whoami
register: output
- debug:
msg: "I gave the command whoami and the out is '{{output.stdout}}'"
- name: start jboss server as jboss user
become: true
become_user: jboss
command: sh /usr/jboss/bin/run.sh -c XXXXXXXX -b x.x.x.x &
when: inventory_hostname in groups['test1']
register: restartscript
- debug:
msg: "output of server restart command is '{{restartscript.stdout}}'"
- name: waiting for server to come back
local_action:
module: wait_for
timeout=20
host=x.x.x.x
port=8080
delay=6
state=started
terminal output message
ESTABLISH SSH CONNECTION FOR USER: XXXXXXXXXXX
SSH: EXEC sshpass -d12 ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o User=XXXXXXXXX -o ConnectTimeout=10 -o ControlPath=/home/tcprod/XXXXXXXXXX/.ansible/cp/ansible-ssh-%h-%p-%r -tt X.X.X.X '/bin/sh -c '"'"'sudo -H -S -p "[sudo via ansible, key=hvgwnsbxpkxvbcmtcfvvsplfphdrevxg] password: " -u jboss /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-hvgwnsbxpkxvbcmtcfvvsplfphdrevxg; /usr/bin/python /tmp/ansible-tmp-XXXXXXXXX.XX-XXXXXXXXXXXXXX/command.py'"'"'"'"'"'"'"'"' && sleep 0'"'"''
The & is not allowed in Ansible "command".
command: sh /usr/jboss/bin/run.sh -c XXXXXXXX -b x.x.x.x &
Try removing it or use shell instead of command.
From Ansible documentation about command:
The given command [...] will not
be processed through the shell, so variables like $HOME and operations
like "<", ">", "|", ";" and "&" will not work (use the shell module if
you need these features).

Ansible: enforce pipefail

Earlier today, we experienced a nasty issue that was caused by the following shell pipe:
- name: get remote branches
shell: git ls-remote -h git#bitbucket.org:orga/repo.git | sed 's_.*refs/heads/__g'
register: branches_remote
The git command fails, but the return code of the entire pipe is 0. This is default bash/sh behavior.
To fix this, in sh/bash, you can set -o pipefail or set -e. Is it possible to do that in ansible, preferably globally for all my shell commands?
In general you should try to use the shell commands as a last resort as they tend to be a bit brittle. If you need to use the shell module with any shell options, simply submit it as part of your command pipeline as shown below. The executable parameter forces the use of bash shell.
[user#ansible ~]$ ansible myhost -m shell -a "executable=/bin/bash set -o pipefail && false | echo hello there"
myhost | FAILED | rc=1 >>
hello there
[user#ansible ~]$ ansible myhost -m shell -a "executable=/bin/bash set -o pipefail && true | echo hello there"
myhost | success | rc=0 >>
hello there
Bash accepts set -o pipefail, but the default executable is /bin/sh which, on platforms such as Debian, is not guaranteed to support this, probably for a good reason (dash is a pure-posix shell).
You can configure /bin/bash as the executable in ansible.cfg:
[defaults]
executable = /bin/bash
The same can be done in molecule.yml
provisioner:
name: ansible
config_options:
defaults:
executable: /bin/bash
There is no configuration executable_flags available, so you should adjust the actions yourself:
- name: pipes that fail should fail the action
shell: |
set -e -o pipefail
git ls-remote -h git#bitbucket.org:orga/repo.git | sed 's_.*refs/heads/__g'
register: branches_remote
You can set the executable for the shell module, for example:
- name: get remote branches
shell: |
set -e -o pipefail
git ls-remote -h git#bitbucket.org:orga/repo.git | sed 's_.*refs/heads/__g'
args:
executable: /usr/bin/bash
register: branches_remote

enabling extglob with ansible

is there any way to enable extglob from ansible?
- name: copy files
sudo: yes
shell: shopt -s extglob
but I got error:
failed: [host] => {"changed": true, "cmd": "shopt -s extglob", "delta": "0:00:00.001410", "end": "2015-10-20 09:10:36.438309", "rc": 127, "start": "2015-10-20 09:10:36.436899", "warnings": []}
stderr: /bin/sh: 1: shopt: not found
FATAL: all hosts have already failed -- aborting
I need extglob to be on to run this command. this command excluding directory vendor from being copied.
cp -pav --parents `git diff --name-only master feature/deploy_2186 !(vendor)` /tmp/current
The command is running properly from terminal, but not from ansible task. and after reading some article, it needs to enable extglob, so I can use !(vendor) pattern to exlcude vendor directory.
error when run copy from ansible task
failed: [host] => {"changed": true, "cmd": "cp -pav --parents `git diff --name-only master new_release !(vendor)` /tmp/current", "delta": "0:00:00.003255", "end": "2015-10-20 09:22:16.387262", "rc": 1, "start": "2015-10-20 09:22:16.384007", "warnings": []}
stderr: fatal: ambiguous argument '!': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
cp: missing destination file operand after '/tmp/current'
Try 'cp --help' for more information.
my ansible task to do copy, which if I remove !(vendor) it works perfectly but it has vendor inside:
- name: copy files
shell: cp -pav --parents `git diff --name-only master feature/deploy_2186 !(vendor)` /tmp/current
args:
chdir: /var/www
tags: release
There are 3 ways you can address this.
1) Put the command into a shell script copy.sh and set shell: copy.sh.
#!/bin/bash
shopt -s extglob
cp -pav --parents `git diff --name-only master feature/deploy_2186 !(vendor)` /tmp/current
2) Use grep -v instead of extglob:
shell: cp -pav --parents `git diff --name-only master feature/deploy_2186 * | grep -v /vendor/` /tmp/current
3) Use bash to set extglob and run the cp command. You need to pass two separate lines to the ansible task variable. Since the syntax is Yaml it boils down to embed a newline in the shell string. Test it yourself.
shell: |
bash -c 'shopt -s extglob
cp -pav --parents `git diff --name-only master feature/deploy_2186 !(vendor)` /tmp/current'
or
shell: "bash -c 'shopt -s extglob \n cp -pav --parents `git diff --name-only master feature/deploy_2186 !(vendor)` /tmp/current'"
You may need to do something like this so that the shopt and cp commands are actually run within the same shell instance:
- name: copy files
sudo: yes
shell: shopt -s extglob && cp -pav --parents `git diff --name-only master feature/deploy_2186 !(vendor)` /tmp/current

Unable to run top on a remote host via Ansible

I have the following playbook:
---
- hosts: ESNodes
remote_user: ihazan
tasks:
- name: Run Monitoring
action: command /tmp/monitoring/cpu_mon
The content of /tmp/monitoring/cpu_mon is as follows:
top -bn1800 -p $(ps -ef | grep elasticsearch | grep -v grep | grep -v sudo | awk '{print $2}') | grep root > /tmp/cpu_stats &
Pay attention that top is run the the background with &
When running that playbook Ansible get stuck forever on the top command:
-bash-4.1$ ansible-playbook es_playbook_run.yml -l PerfSetup -K -f 10
sudo password:
PLAY [ESNodes] ****************************************************************
GATHERING FACTS ***************************************************************
ok: [isk-vsrv643]
TASK: [Run Monitoring] ********************************************************
When running it via remote SSH(which is what ansible should do) it works fine:
-bash-4.1$ ssh ihazan#isk-vsrv643 'nohup /tmp/monitoring/cpu_mon'
-bash-4.1$
Following is the debug version of the output:
-bash-4.1$ ansible-playbook es_playbook_run.yml -l PerfSetup -K -f 10 -vvvv
sudo password:
PLAY [ESNodes] ****************************************************************
GATHERING FACTS ***************************************************************
<isk-vsrv643> ESTABLISH CONNECTION FOR USER: ihazan on PORT 22 TO isk-vsrv643
<isk-vsrv643> EXEC /bin/sh -c 'mkdir -p $HOME/.ansible/tmp/ansible-1393860499.75-256362698809430 && chmod a+rx $HOME/.ansible/tmp/ansible-1393860499.75-256362698809430 && echo $HOME/.ansible/tmp/ansible-1393860499.75-256362698809430'
<isk-vsrv643> REMOTE_MODULE setup
<isk-vsrv643> PUT /tmp/tmpZh9bYP TO /usr2/ihazan/.ansible/tmp/ansible-1393860499.75-256362698809430/setup
<isk-vsrv643> EXEC /bin/sh -c '/usr/bin/python /usr2/ihazan/.ansible/tmp/ansible-1393860499.75-256362698809430/setup; rm -rf /usr2/ihazan/.ansible/tmp/ansible-1393860499.75-256362698809430/ >/dev/null 2>&1'
ok: [isk-vsrv643]
TASK: [Run Monitoring] ********************************************************
<isk-vsrv643> ESTABLISH CONNECTION FOR USER: ihazan on PORT 22 TO isk-vsrv643
<isk-vsrv643> EXEC /bin/sh -c 'mkdir -p $HOME/.ansible/tmp/ansible-1393860500.32-92141081389545 && chmod a+rx $HOME/.ansible/tmp/ansible-1393860500.32-92141081389545 && echo $HOME/.ansible/tmp/ansible-1393860500.32-92141081389545'
<isk-vsrv643> REMOTE_MODULE command /tmp/monitoring/cpu_mon
<isk-vsrv643> PUT /tmp/tmp7dYRPY TO /usr2/ihazan/.ansible/tmp/ansible-1393860500.32-92141081389545/command
<isk-vsrv643> EXEC /bin/sh -c '/usr/bin/python /usr2/ihazan/.ansible/tmp/ansible-1393860500.32-92141081389545/command; rm -rf /usr2/ihazan/.ansible/tmp/ansible-1393860500.32-92141081389545/ >/dev/null 2>&1'
Thx in advance
Use fire and forget mode, i.e. async + poll 0 :
---
- hosts: ESNodes
remote_user: ihazan
tasks:
- name: Run Monitoring
action: command /tmp/monitoring/cpu_mon
async: 45
poll: 0
Whole scoop on async is here : http://docs.ansible.com/playbooks_async.html
Good luck.

Resources