ansible playbook of playbooks with variables - variables

I'm not even sure if this is possible..
I know you can have a playbook that calls other playbooks..
IE:
---
# MasterPlaybook.yml
- include: playbook1.yml
when: some_var == "true"
- include: playbook2.yml
when: someother_var == "true"
and this will work if I call MasterPlaybook.yml and pass in the Vars..
BUT I want to include the vars from some other yml
for example here is myvars.yml
some_var: "true"
someother_var: "false"
Other_var: "Foo"
So if I want this included in a playbook1.yml I simply add..
---
- name: Script Play use variables to get and push out the code
hosts: somegroup
remote_user: "some user"
vars:
url: 'The url of the build'
buildNumber: 'the build number'
jobName: 'passed in job name'
vars_files:
- ~/myvars.yml
serial: 1
and it will pull in the vars..
My question is how do I do this in the masterplaybook.yml so that I don't have to pass in the vars?
and while we are at it.. are there any good examples of a master playbook? (or a playbook of playbooks)

You can specify vars as part of the include statements. This is what I do for some of my projects.
---
- include: playbook1.yml
vars:
some_var: "true"
someother_var: "false"
Other_var: "Foo"
when: some_var == "true"
- include: playbook2.yml
when: someother_var == "true"

Have a look at roles in ansible. They are a more structured way for the "playbook of playbooks" concept. There you can define global variables in the "master" playbook and variables within the sub-playbooks http://docs.ansible.com/playbooks_roles.html.
You can also have a look at the example playbooks to see how roles are used and structured.

Related

How to reference a variable within a variable YAML GitLab pipeline

I am using env as a (lowercase) input variable for my pipeline and
I want to be able to have this stage use the correct AWS account based on the environment I input. Right now I have it set just as AWS_ACCOUNT_DEV so I need to have separate stages.
I just want this one stage to be able to be used for all environments based on my input - how can I achieve this?
variables:
AWS_ACCOUNT_DEV: 000000000
AWS_ACCOUNT_NONPROD: 000000000
Import Alertmanager Endpoint:
stage: import
dependencies:
- "Validate Credentials"
tags:
- ${runner}
rules:
- if: $CI_PROJECT_ID != $MONITORING_PROJECT_ID
variables:
AWS_IAM_DEPLOYER_ROLE: "arn:aws:iam::${AWS_ACCOUNT_DEV}:role/${runner_role}"
...
figured it out by adding:
rules:
- if: $CI_PROJECT_ID != $MONITORING_PROJECT_ID
- if: $ecs_env == "dev"
variables:
AWS_IAM_DEPLOYER_ROLE: "arn:aws:iam::${AWS_ACCOUNT_DEV}:role/${runner_role}"
- if: $ecs_env == "nonprod"
variables:
AWS_IAM_DEPLOYER_ROLE: "arn:aws:iam::${AWS_ACCOUNT_NONPROD}:role/${runner_role}"

Gitlab CI variable override in workflow

I want TEST_VAR to be overridden by the workflow but when I run a $NIGHTLY pipeline, it still prints "normal". What am I doing wrong here? According the the precedence, I believe it should work...
image: alpine
variables:
TEST_VAR: "normal"
workflow:
rules:
- if: $CI_COMMIT_BRANCH
- if: $NIGHTLY
variables:
TEST_VAR: "nightly"
test:
script:
- echo $TEST_VAR
One more option is hack with child pipelines.
nightly-run:
variables:
TEST_VAR: "nightly"
rules:
- if: $NIGHTLY
trigger:
include: .gitlab-ci.yml
strategy: depend
It will override global TEST_VAR if "nightly-run" triggers.
Pay attention all jobs that triggered by "parent pipeline" will with CI_PIPELINE_SOURCE == 'parent_pipeline'.
A solution can be resolve your issus is to update the $TEST_VAR in script part.
script:
- |
- if $NIGHTLY
then
$TEST_VAR = "nightly"
else
$TEST_VAR = "others values"
fi

Use dotted YAML variables file in Ansible

I'm trying to achieve the following using Ansible:
Define a YAML file with some variables in the dotted format inside it (variables.yml)
database.hosts[0]: "db0"
database.hosts[1]: "db1"
database.hosts[2]: "db2"
foo.bar: 1
foo.baz: 2
Load the variables in variables.yml by using the include_vars module in my playbook (playbook.yml) and print them in a tree structure
- hosts: all
gather_facts: not
tasks:
- name: "Loading vars"
run_once: true
include_vars:
file: 'variables.yml'
- name: "Testing"
debug:
msg: "{{ foo }}"
- name: "Testing"
debug:
msg: "{{ database }}"
Running this results in the following error:
fatal: [host0]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'foo' is undefined\n\nThe error appears to be in '.../playbook.yml': line 9, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: \"Testing\"\n ^ here\n"}
Which makes it clear that each property in the YAML file has been loaded as a separate property and not as properties within two trees rooted in database and foo.
Of course, the playbook works as expected if I specify the properties as follows:
database:
hosts:
- "db0"
- "db1"
- "db2"
foo:
bar: 1
baz: 2
However, I need the YAML variables file to be in the dotted format instead of in the classic indented format. Is there any way to achieve this? E.g.: a module different from include_vars or some configuration that I can add to the ansible.cfg file? I have already tried to use hash_behaviour=merge, but that didn't help.
Q: "I need the YAML variables file to be in the dotted format instead of in the classic indented format. Is there any way to achieve this?"
A: No. It's' not possible. See Creating valid variable names.

Ansible registered variable has attribute not found error due to multiple when conditions

How do we check for a registered variable if only one of the two conditions turns out to be true having the same registered variable?
Below is my playbook that executes only one of the two shell modules.
- name: Check file
shell: cat /tmp/front.txt
register: myresult
when: Layer == 'front'
- fail:
msg: data was read from front.txt and print whatever
when: myresult.rc != 0
- name: Check file
shell: cat /tmp/back.txt
register: myresult
when: Layer == 'back'
- fail:
msg: data was read from back.txt and print whatever
when: myresult.rc != 0
Run the above playbook as
ansible-playbook test.yml -e Layer="front"
I do get error that says myresult does not have an attribute rc. What is the best way to print debug one statements based on the condition met?
Note: I wish the fail to terminate the execution of the play as soon as the condition is met hence I beleive ignore_errors with fail will not help.
Note: The shell modules can be any Unix command.
I tried myresult is changed but that too does not help. Can you please suggest.
You may want to look at this logical grouping of tasks: blocks
- name: Check file
block:
- name: check file
shell: cat /tmp/front.txt
register: myresult
ignore_errors: true
- fail:
msg: data was read from front.txt and print whatever
when: myresult.rc != 0
when: Layer == 'front'
- name: Check file
block:
- name: check file
shell: cat /tmp/back.txt
register: myresult
ignore_erros: true
- fail:
msg: data was read from back.txt and print whatever
when: myresult.rc != 0
when: Layer == 'back'
when the variable Layer is set to the front it will execute the shell command for front. but in case when the file doesn't exists it will give the error no such file exists and stop the play. so i have put the ignore_errors in the shell task.it will ignore it and jump to the fail module.

Ansible: simulating a "passed when" module

Ansible provides a failed_when module, allowing users to specify certain fail conditions on their tasks, e.g. a certain string being found in stdout or stderr.
I am trying to do the opposite: I'd like my tasks not to fail if any of a set of strings is found in stdout or stderr. In other words, I'd like something approaching the functionality of a passed_when module.
I still want it to pass normally when the return code is 0.
But if it would fail (rc != 0) then it should first check for the occurrence of some string.
I.e. if some string is found it passes no matter what.
My reasoning goes like this:
There are many reasons why the task could
fail - but some of these, depending on the output, I do not consider
as a failure in the current context.
Does anybody have a good idea how this can be achieved?
Have a look here:
Is there some Ansible equivalent to "failed_when" for success
- name: ping pong redis
command: redis-cli ping
register: command_result
failed_when:
- "'PONG' not in command_result.stderr"
- "command_result.rc != 0"
will not fail if return code is 0 and there is no 'PONG' in stderr.
will not fail if there is "PONG" in stderr.
So it passes if any of the list is False
Your original question was phrased like this (using boolean logic to make it easier):
Succeed a command if a set of strings is found in stdout or stderr
Rephrasing your logic:
fail if a set of strings is NOT found in stdout or stderr. Using this logic it's easy to do with failed_when. Here's a snippet:
---
- name: Test failed_when as succeed_if
hosts: localhost
connection: local
gather_facts: no
tasks:
- name: "'succeed_if' set of strings in stdout"
command: /bin/echo succeed1
register: command_result
failed_when: "command_result.stdout not in ['succeed1',]"
- name: "'succeed_if' set of strings in stdout (multiple values)"
command: /bin/echo succeed2
register: command_result
failed_when: "command_result.stdout not in ['succeed1', 'succeed2']"
- name: "'succeed_if' set of strings in stderr (multiple values)"
shell: ">&2 /bin/echo succeed2 "
register: command_result
failed_when: "command_result.stderr not in ['succeed1', 'succeed2']"
- name: "'succeed_if' set of strings in stderr (multiple values) or rc != 0"
shell: ">&2 /bin/echo succeed2; /bin/false"
register: command_result
failed_when: "command_result.stderr not in ['succeed1', 'succeed2'] and command_result.rc != 0"
# vim: set ts=2 sts=2 fenc=utf-8 expandtab list:
Also the documenation you are probably looking for are Jinja2 Expressions