How to know in which task an ansible play failed when launched using AWX API? - error-handling

I intend to launch ansible jobs on AWX using AWX api and get a call back from the ansible playbook to be informed about the result of the play.
To do so I'm using the /api/v2/job_templates/<job-template-id>/launch/ with some extra_vars in the body to pass parameters to my play.
{
"extra_vars": {
"target": "w.x.y.z", (put here a real IP)
"directory_name_1": "dir1",
"directory_name_2": "dir2",
"file_name": "file1" (or "subdir/file1" to make it fails)
}
}
I've also configured a webhook notification in the job-template with the default customization: {{ job_metadata }}
I've put here the play I'm using which is super simple, it creates 2 directories and one file in the first directory.
- hosts: "{{ target }}"
name: fbplay
tasks:
- name: Create dummy directory 1
file:
path: "{{directory_name_1}}"
state: directory
- name: Create dummy directory 2
file:
path: "{{directory_name_2}}"
state: directory
- name: Create dummy file in directory
file:
path: "{{directory_name_1}}/{{file_name}}"
state: touch
mode: u=rw,g=r,o=r
All of this work great and in case of error 4 tasks will be executed on the target machine:
TASK [Gathering Facts] *********************************************************
TASK [Create dummy directory 1] ************************************************
TASK [Create dummy directory 2] ************************************************
TASK [Create dummy file in directory] ******************************************
...but here is my question with regard to error handling: How can I indicate in the call back which task failed in case of error ?
In fact I can know if the play failed or not getting, in case of success:
"hosts": {
"w.x.y.z": {
"failed": false,
"changed": 1,
"dark": 0,
"failures": 0,
"ok": 4,
"processed": 1,
"skipped": 0,
"rescued": 0,
"ignored": 0
}
}
and in case of failure:
"hosts": {
"w.x.y.z": {
"failed": true,
"changed": 0,
"dark": 0,
"failures": 1,
"ok": 3,
"processed": 1,
"skipped": 0,
"rescued": 0,
"ignored": 0
}
}
But I cannot get the exact task that failed (in this case the last one by passing a filename containing a sub-directory that does not exist for example).
I'm a newbie on AWX & ansible and I'm fighting with what I thought would be a relatively simple point... so any hints or ideas is welcome.
Thx beforehand.

in case it helps someone, I actually confirm that ARA does what I was looking for above which is to display if using its web client (or provide through an API) exactly which task failed in each playbook you ran.

ARA does an excellent job for analyzing awx-runs, but it has to be set up on the AWX-server (the host running the AWX instance), if I understand correctly.
A workaroud would be to use the awx commandline interface ( see https://docs.ansible.com/ansible-tower/latest/html/towercli/index.html and * ):
watch --color 'awx --conf.host https://awx.site --conf.username my.user --conf.password "my_super_secret" -k -f human job_events list --job 3232445 --event "runner_on_failed" --filter "stdout"'
One could also sroll the API for different "?event=runner_on_failed", like:
https://your.awx.site/api/v2/jobs/3232445/job_events/?event=runner_on_failed
Or other "filters" like:
awx --conf.host https://awx.site --conf.username my.user --conf.password "my_supersecret" -k -f human job_events list --job 3232445 --event "runner_on_unreachable" --filter "*" >/tmp/tmp
https://docs.ansible.com/ansible-tower/latest/html/towercli/output.html#human-readable-tabular-formatting
https://docs.ansible.com/ansible-tower/latest/html/towercli/reference.html#awx-job-events-list
* (not to confuse with awx-cli/tower-cli - I think they are different)

Related

Unable to run relay-compiler

I installed the relay for my react-native project following the steps on relay.dev. Running the compiler works fine when I have an empty schema file. Putting schema to the file starts throwing me this error:
thread 'main' panicked at 'Expect GraphQLAsts to exist.', /home/runner/work/relay/relay/compiler/crates/relay-compiler/src/compiler.rs:335:14
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace
My schema file is
// relay_schema.graphql
type Query {
tasks: [TaskNode]
}
type TaskNode {
id: ID!
}
and my relay config is:
module.exports = {
// ...
// Configuration options accepted by the `relay-compiler` command-line tool and `babel-plugin-relay`.
src: './src/',
language: 'flow',
schema: './relay_schema.graphql',
exclude: ['**/node_modules/**', '**/__mocks__/**', '**/__generated__/**'],
};
I'm completely lost on what to do here
Started working after updating src to src: './'. It's better to verify the paths such as src and schema. Error messages shown by the compiler are not much help when stuck here.

Ansible dynamic inventory refresh

I have created a simple dynamic inventory python which prints JSON to standard output mentioned below, but Ansible inventory does not refresh.
Command: ansible-playbook playbooks/deploy.yaml -i playbook/inventory_test.py
Inventory JSON:
{
'python_hosts': {
'hosts': ['10.220.21.122', '10.220.21.278'],
'vars': {
'ansible_ssh_user': 'projectuser',
}
},
'_meta': {
'hostvars': {
'10.220.21.122': {
'host_specific_var': 'testhost'
},
'10.220.21.278': {
'host_specific_var': 'towerhost'
}
}
}
}
I also tried this:
- hosts: localhost
tasks:
- name: test
script: ./inventory_test.py
- name: Refresh inventory
meta: refresh_inventory
- name: print new inventory
debug:
var: groups
But inventory still does not refresh automatically.
Ansible version is 2.6.4
Any help on this is really appreciated.
This is because of the cache...
Go to ~/.ansible/tmp and delete inventory_test.cache file.
Also, this is helpful answer if you able edit playbook...

Custom Module is not installed on the kurento media server but appears on the kurento-media-server --list

I am trying to develop a custom module for the Kurento-media-server but i have find two roadblocks,following the instructions on the documentation i have been able to:
create the custom module folder with the command:
kurento-module-scaffold.sh <module_name> <output_directory>
and them generate the files with:
cmake .. -DCMAKE_INSTALL_PREFIX=/usr && make && sudo make install
i have added two lines to the bgRemoverFilterOpenCVImpl on the /src/server/objects/bgRemoverFilterOpenCVImpl.cpp file so the filter adds a hello world text to the image.
void bgRemoverFilterOpenCVImpl::process (cv::Mat &mat)
{
cv::Point textOrg(50, 50);
putText( mat, "Hello World", textOrg, 1, 2, cv::Scalar(0, 0, 0) );
}
i them build the .deb file with debuild -us -uc and install it successfully so that when i run the kurento-media-server --list command i see my new custom module on the list:
....
bgRemoverFilter
bgremoverfilter.bgRemoverFilter
....
i them generated the js client code with the command cmake .. -DGENERATE_JS_CLIENT_PROJECT=TRUE and added the js generated folder to my node.js project using npm link for test purposes i am using the Kurento-Chroma project from the Kurento-node-repository so i have modified it to register my module and to create my custom filter instead of the chroma one. for this made changes to the server.js file on lines 28 and 249:
...
//kurento.register('kurento-module-chroma');
kurento.register('kurento-module-bgremoverfilter');
...
pipeline.create('bgremoverfilter.bgRemoverFilter', options, function(error, filter) {
if (error) {
return callback(error);
}
return callback(null, webRtcEndpoint, filter);
});
the node application runs correctly but when i start the loopback to get my videofeed with the filter applied it sends this error message:
Error message from server: Exiting with error SyntaxError: Module 'bgRemoverFilter' is not installed in the Kurento Media Server
despite the module being loaded on kurento-media-server --list the app cant create the filter object, i thought this was a naming issue so when i create a one word name custom module like "harel" to avoid camel case naming problems and install it i get on the list:
...
harel
harel.harel
...
and when trying to create and use this filter on the same kurento-chroma example i get a different error:
SyntaxError: sink param should be a MediaElement, not harel
at ChecktypeError (/home/ubuntu/www/kurento-chroma/node_modules/kurento-client/lib/checkType.js:32:10)
at checkMediaElement (/home/ubuntu/www/kurento-chroma/node_modules/kurento-client-core/lib/abstracts/MediaElement.js:1082:11)
at checkType (/home/ubuntu/www/kurento-chroma/node_modules/kurento-client/lib/checkType.js:84:25)
at WebRtcEndpoint.MediaElement.connect (/home/ubuntu/www/kurento-chroma/node_modules/kurento-client-core/lib/abstracts/MediaElement.js:489:3)
at connectMediaElements (/home/ubuntu/www/kurento-chroma/server.js:260:20)
at /home/ubuntu/www/kurento-chroma/server.js:197:17
at /home/ubuntu/www/kurento-chroma/server.js:254:20
at callback2 (/home/ubuntu/www/kurento-chroma/node_modules/kurento-client/lib/KurentoClient.js:527:7)
at /home/ubuntu/www/kurento-chroma/node_modules/kurento-client/lib/KurentoClient.js:385:7
at Object.dispatchCallback [as callback] (/home/ubuntu/www/kurento-chroma/node_modules/kurento-jsonrpc/lib/index.js:613:9)
so, am i missing something on the installation process? i suspect there is something wrong with the JS generated code in the first case.
on the second case when using a single word name, why does this work? the app is able to create the filter but then fails when trying to connect it to the webrtcEndPoint
i have look at all the questions and threads i could find but did'nt get any answers. here is a repository with my custom filter code including the generated js library
please help, if more clarifications or details are needed request them.
UPDATE
i wrote to one of the kurento developers that recommended i use kurento-media-server --version to get the actual list of loaded modules, this is a followup to that:
kurento-media-server --version returns:
Version: 6.7.0~1.g6ebaa27
Found modules:
Module: 'backgroundremoval' version '0.0.1~3.g045ef96'
Module: 'bgremoverfilter' version '0.0.1~0.g3a1e793'
Module: 'chroma' version '6.6.1~3.g6df8f1d'
Module: 'core' version '6.6.3'
Module: 'elements' version '6.6.3'
Module: 'filters' version '6.7.0~1.g0314843'
Module: 'harel' version '0.0.1~0.gaec7e6d'
so yes backgroundremoval, bgremoverfilter and harel are the custom modules i have created and they are on the list.
i still dont know why when i use a camelcase name as bacgroundRemoverFilter i cant get the module to load in javascript althoug the generated code is loaded on my node.js project when it tries to create the filter the app sends the "module not installed error"
so i started using all minus names, for my module "harel" this gets loaded with no problems and when i try to create the media element with
pipeline.create('harel.harel')...
the filter gets created but them fails when a try to connect it to a webrtcEnpoint with
filter.connect(webRtcEndpoint, function(error) {
if (error) {
return callback(error);
}
return callback(null);
});
it returns the error: SyntaxError: sink param should be a MediaElement, not harel
turns out that error is send by /node_modules/kurento-client-core/lib/abstracts/MediaElement.js:489:3 when calling a function Checktype
checkType('MediaElement', 'sink', sink, {required: true});
so i added a console.log() after the filter its created to see what was different between the chroma filter and my custom filter, this is the result:
harel {
domain: null,
_events:
{ removeListener: [Function],
newListener: [Function],
_describe: [Function: bound emit],
_rpc: [Function: encodeRpc],
release: { [Function: bound onceWrapper] listener: [Function] } },
_eventsCount: 5,
_maxListeners: undefined,
id: 'ad5e2447-3801-4d96-81b4-c40390b16248_kurento.MediaPipeline/18e8c6b9-df88-4d52-851c- 8c664a26ee3d_harel.harel' }
ChromaFilter {
domain: null,
_events:
{ removeListener: [Function],
newListener: [Function],
_describe: [Function: bound emit],
_rpc: [Function: encodeRpc],
release: { [Function: bound onceWrapper] listener: [Function] } },
_eventsCount: 5,
_maxListeners: undefined,
id: '97f370b5-81ae-45e1-a979- dab6c1c4cd28_kurento.MediaPipeline/06658282-67bf-47bc- b006-9f0dbae01767_chroma.ChromaFilter' }
both objects have the same properties excetp for the id. so how come the same function works with ChromaFilter bu not with harel if the object passed is almost the same. This is were i am now. will keep digging.
The problem with my process was that i used npm link to add the generated client-js code to my node.js app. For that to work i had to install the kurento-client package on the client-js folder and when my app ran it will generate the custom plugin with a different kurento-client than the one it was using.
so even thought the Chroma-filter and my harel module looked the same they were from two different kurento-client classes.
instead of using npm-link i just copied the generated js-client code inside my node-modules folder and that did the trick.
hope this is usefull to people that find this error.

How to add more than one value to a variable in ansible playbook?

I have defined a value to variable in my playbook as :
war_name: abc
and i m calling this war_name in the roles as :
- name: Download war file
get_url:
url=http://url/directory/packages/tomcat/{{ war_name }}.war
Now the problem is I have to assign 2 values to variable war_name in playbook
like
war_name: abc,xyz
How can i do this in my playbook?
If used with_items as :
- name: Download war file
get_url:
url=http://url/directory/packages/tomcat/{{ item }}.war
with_items:
- abc
- xyz
when: "'server' in app_name"
It results in an error as :
TASK [tomcat : Download war file]
********************************************** failed: [10.x.x.x] (item=abc) => {"failed": true, "item": "abc", "msg": "missing required
arguments: dest"} failed: [10.x.x.x] (item=xyz) => {"failed": true,
"item": "xyz", "msg": "missing required arguments: dest"}
You are missing the dest argument that is required for get_url
Here is the modified version of your task:
- name: Download war file
get_url:
url: "http://url/directory/packages/tomcat/{{ item }}.war"
dest: "/path-where-you-want-to-place/{{ item }}"
with_items:
- abc
- xyz
when: "'server' in app_name"
Hope that help you
what you can do is something like this
war_name:
war1: one
war2: two
This is basically a dictionary. Though i am not sure what actually you wanna do here? I guess you want to place 2 wars at a same location with different names, if that is the case you can actually use with_items

Create Ansible local facts from variables

I am trying to create local facts from variables.
My fact is:
datadog_http_checks:
- name : {{ env }} ResourceManager
url : http://{{ inventory_hostname }}:
threshold : 5
window : 5
timeout : 10
My task is:
- include_vars: clouderamanager.yml
- lineinfile: dest=/etc/ansible/facts.d/datadog_http_checks.fact line={{ datadog_http_checks }} create=yes
Which doesn't create the local facts, it fails with following error
TASK [hadoop : lineinfile] *****************************************************
fatal: [hmn001.dev.abc.cc]: FAILED! => {"changed": false, "failed": true, "module_stderr": "", "module_stdout": "Traceback (most recent call last):\r\n File \"/home/xyz/.ansible/tmp/ansible-tmp-1460581285.88-252089462921262/lineinfile\", line 2540, in <module>\r\n main()\r\n File \"/home/abc/.ansible/tmp/ansible-tmp-1460581285.88-252089462921262/lineinfile\", line 371, in main\r\n ins_aft, ins_bef, create, backup, backrefs)\r\n File \"/home/abc/.ansible/tmp/ansible-tmp-1460581285.88-252089462921262/lineinfile\", line 266, in present\r\n lines.append(line + os.linesep)\r\nTypeError: can only concatenate list (not \"str\") to list\r\n", "msg": "MODULE FAILURE", "parsed": false}
Lineinfile does exactly what it says it does: it changes a single line in a file.
If you want to create a local fact that looks like:
datadog_http_checks:
- name : {{ env }} ResourceManager
url : http://{{ inventory_hostname }}:
threshold : 5
window : 5
timeout : 10
Then you need to create a file that looks like this:
[datadog_http_checks]
name={{ env }} ResourceManager
url=http://{{ inventory_hostname }}:
threshold=5
window=5
timeout=10
You can do this with the template module if, like in your example, you have variables in it that you want to dynamically build.
In this exact scenario though I'm confused as to what the benefit of this is rather than having a variable set up as you have in your question and using that rather than templating out a local fact file and then re-reading it later.