Running an ansbile handler as an one time thing - ansible

Very frequently when I'm making changes to an ansible playbook (or role) I am working with some something like this
tasks:
...
- name: task x
notify: handler a
...
- name: task y
...
handlers:
...
- name: handler a
...
Now during the development, task x succeeds and performs a change but task y fails because there's an error in it. handler a is not notified.
Later on I manage to fix task y and it performs its change but since task x was already changed in the previous run, it reports no change and handler a remains not notified.
I guess I should have run it with --force-handlers but now that the deal is done, what is the correct way to force handler a to run now.

Yes you can force the handler to run by adding the following after task x:
- meta: flush_handlers
Of course now you are in a predicament where you are relying on a changed status for the handler to run so this isn't much good to you.
You could add changed_when: True to task x to get the handler to run and then revert it. There is no correct way to get it to run because it is relying on the changed status of the notifying task

Related

why is the ansible sros_command module responding with an error from a role, but works independently

I am attempting to send a command to an SROS device using an ansible role. The task itself is:
- name: invoke the sros cli
sros_command:
commands: ["{{item.input}}"]
register: sros_command_result
This command is being run inside a loop of several commands. I know that the module will allow you to send multiple commands at once, but I need to do additional processing on each command so its simpler to handle them individually. I've verified that item.input is correct, and the notation is sending the command as a list which is what the module wants for input.
In the case I am testing the command itself is show chassis.
I have verified that I am connected to the device, and an independent debug run of the module only generates the correct response from the device.
When I run this via my role though, it response with: "Unable to decode JSON from response to exec_command('{\"command\": \"show chassis\", \"prompt\": null, \"answer\": null}'). Received 'None'."
Im very lost. I do not know why this error is appearing (other than the device not sending a response), nor can I figure out any way to debug this.

Global variable that count number of errors

Im new in Ansible. Im using playbooks/roles in Openstack and im searching for a Global variable or similar that count the number of errors in the playbook or at least that an error ocurred in some moment.
This is why (let say that this variable is called GLOB):
In Task:
---
# tasks file
- name: testing block
block:
# List of tests to run in this test suite:
- include: ../tests/DoThings.yml #API calls, http 50x possible errors: YES
always: #Final task always executed
- include: ../tests/Clear.yml #API calls, http 50x possible errors: YES
- include: ../tests/Report.yml #NOT API calls, http 50x possible errors: NO, just log checker.
So if some error ocurred in DoThings.yml i want to clear all the thing with Clear.yml and AFTER execute Report.yml, inside this i will check if GLOBAL var has 1 failed (one or more failed). This is because a failed can be
A "50x HTTP", that is impossible to predict, you have to try again (this is important to detect for me and differentiate from other errors)
A normal error for code mistake or similar, easy to fix (not important in this case)

Can you change the interim message of Ansible's until retries loop?

In one of my playbooks I start a service and poll for its status before moving onto the next task like the following:
- name: Poll for service status
uri:
url: http://some-service/status
register: response
until: response.status == 200
retries: 12
delay: 10
This logs a message each time it queries the URL which looks like
FAILED - RETRYING: TASK: Poll for service status
Is there a way to customise this message? Specifically remove the word FAILED.
After grepping around, I found the "FAILED - RETRYING" message in the default output callback (read about callbacks here). That means you can change the callback in ansible.cfg to something that suits your needs- or make your own. You can even search the code for v2_runner_retry to see the various outputs.
For instance, here's what stdout_callback=oneline returns. There are no "retrying" messages even at -vv. It still says "FAILED" but that's because it actually failed.
ansible-playbook -vvi localhost, p.yml
ansible-playbook 2.4.1.0
config file = /opt/app/ansible.cfg
configured module search path = ['/opt/app/library']
ansible python module location = /usr/local/lib/python3.5/dist-packages/ansible
executable location = /usr/local/bin/ansible-playbook
python version = 3.5.2 (default, Sep 14 2017, 22:51:06) [GCC 5.4.0 20160609]
Using /opt/app/ansible.cfg as config file
1 plays in p.yml
META: ran handlers
localhost | FAILED! => {"attempts": 3,"changed": false,"content": "","failed": true,"msg": "Status code was not [200]: Request failed: <urlopen error [Errno -2] Name or service not known>","redirected": false,"status": -1,"url": "http://some-service/status"}
Aside from setting it in ansible.cfg the documentation implies it can be done in a role. I have no idea how.
As #techraf said, the Ansible folks are pretty good at reviewing pull requests.

drone.io 0.5 slack no longer working

We had slack notification working in drone.io 0.4 just fine, but since we updated to 0.5 I can't get it working despite trying out the documentation.
Before, it was like this
build:
build and deploy stuff...
notify:
slack:
webhook_url: $$SLACK_WEBHOOK_URL
channel: continuous_integratio
username: drone
You can see here that I used the $$ to reference the special drone config file of old.
Now my latest attempt looks like this
pipeline:
build and deploy stuff...
slack:
image: plugins/slack
webhook: https://hooks.slack.com/services/...
channel: continuous_integratio
username: drone
According to the documentation slack is now indented within the pipeline (previously build) level.
I tried changing slack out for notify like it was before, used the SLACK_WEBHOOK secret only via the drone cli and there where other things I attempted as well.
Does anyone know what I might be doing wrong?
This is an (almost exact) yaml I am using with slack notification enabled with the exception that I've masked the credentials
pipeline:
build:
image: golang
commands:
- go build
- go test
slack:
image: plugins/slack
webhook: https://hooks.slack.com/services/XXXXXXXXX/YYYYYYYYY/ZZZZZZZZZZZZZZZZZZZZZZZZ
when:
status: [ success, failure ]
There is unfortunately nothing in your example that jumps out, perhaps with the exception of the channel name having a typo (although I'm not sure if that represents your real yaml configuration or not)
If you are attempting to use secrets (via the cli) you need to make sure you sign your yaml file and commit the signature file to your repository. You can then reference your secret in the yaml similar to 0.4 but with a slightly different syntax:
pipeline:
build:
image: golang
commands:
- go build
- go test
slack:
image: plugins/slack
webhook: ${SLACK_WEBHOOK}
when:
status: [ success, failure ]
You can read more about secrets at http://readme.drone.io/usage/secret-guide/
You can also invoke the plugin directly from the command line to help test different input values. This can help with debugging. See https://github.com/drone-plugins/drone-slack#usage
The issue was that in 0.4 the notify plugin was located outside the scope of the pipeline (then build) and now since 0.5 its located inside the pipeline. This combined with the fact that when a pipeline fails it quits the scope immediately, which means the slack (then notify) step never get's reached at all anymore.
The solution to this is to just explicitly tell it to execute the step on failure with the when command:
when:
status: [ success, failure ]
This is actually mentioned in the getting-started guide, though, but I didn't go through till the end as I was aiming to quickly get it up and running and didn't worry about what I considered to be edge cases.

Set environment in Ansible doesn't seem to work

The Consul lookup plugin has the following code. I would like to override by setting the environment variable for ANSIBLE_CONSUL_URL. I can't seem to get my task to use the environment variable. The task runs fine if I set the environment variable manually prior to running the task.
self.agent_url = 'http://localhost:8500'
if os.getenv('ANSIBLE_CONSUL_URL') is not None:
self.agent_url = os.environ['ANSIBLE_CONSUL_URL']
My task:
- name: Build list of modules and its associated tag
environment:
ANSIBLE_CONSUL_URL: "http://indeploy001.local.domain:8500"
set_fact: deploy_list="{{ item | replace("deploys/" + environment_id + "/",'') }}-{{ lookup('consul_kv','deploys/' + environment_id + '/' + item) }}"
with_items: "{{ modules }}"
register: deploy_list_result
Error
TASK: [Build list of modules and its associated tag] **************************
fatal: [127.0.0.1] => Failed to template deploy_list="{{ item | replace("deploys/" + environment_id + "/",'') }}-{{ lookup('consul_kv','deploys/' + environment_id + '/' + item) }}": Error locating 'deploys/sf/ariaserver' in kv store. Error was HTTPConnectionPool(host='localhost', port=8500): Max retries exceeded with url: /v1/kv/deploys/sf/ariaserver (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x1eac410>: Failed to establish a new connection: [Errno 111] Connection refused',))
FATAL: all hosts have already failed -- aborting
Lookups are a templating feature. The keys of a task are rendered to resolve any Jinja expressions before the task is executed. That means your lookup is executed before the task is executed. The environment key simply is a task property, which has an effect when the task is executed. But you're not getting that far.
Also, I'm not 100% sure what would happen with your environment in this special case used in a set_fact task. set_fact is an action plugin, running on the control machine. So do lookups. But the task itself is not delegated to localhost. So it's possible the env var would be set for the control machine or on the remote machine. My guess though is, it is not set at all, neither on localhost nor remotely. The reason for my guess is, many action plugins do later in the process call a module with the same name, which then is executed on the target host. The logical behavior, and what a user would expect, would be that the env var then is set on the remote host by the module. Just a guess and neglectable given the first paragraph.
Conclusion:
If a lookup plugin is depending on environment variables, you can not set them in the same task. They need to be set previously - what you already found working.

Resources