Looping through composer require with ansible task - ansible

I feel like this should be really straight-forward, but I've been pouring over the ansible docs and other answers here, and I'm stuck.
What I want to do is to set up an array or list of composer packages to be used in a composer require statement using the ansible composer object.
So, I've got a set fact like so to define the modules:
- name: Define modules to be required
set_fact:
modules:
- vendor1/package1
- vendor2/package2
- vendorN/packageN
I've put this in the top of my ansible project so it's easily accessible and editable (It'd be sweet to figure out how to simply define the packages in a yaml file as vars, and then use set_fact in the playbook, but I'll stick to scope here)
With this in mind, I then have a role in the project with a composer task where I want to require each of these:
- name: "Require packages"
composer:
command: require
arguments: {{ modules_to_be_required }}
working_dir: "{{ app['directory'] }}"
Originally, I did this using with_items like so:
- name: "Require packages"
composer:
command: require
arguments: "{{ item }}"
working_dir: "{{ app['directory'] }}"
with_items
- vendor1/package1
- vendor2/package2
- vendorN/packageN
This does work; however, it causes a composer update to run with each iteration of with_items which takes far too long. To me, it makes more sense to take the list of packages to be required, convert them to a string separated by spaces, and then pass that as an argument.
In my research I found that I could convert a list to a string with the join filter, so I tried this:
- name: "Require packages"
composer:
command: require
arguments: {{ modules | join(" " ) }}
working_dir: "{{ app['directory'] }}"
But, this gives me a YAML syntax error:
The offending line appears to be:
command: require
arguments: {{ modules | join(" ") }}
^ here
I've tried wrapping "{{ modules | join(" ") }}" but I get yelled at for the quotes in the parenthesis.
Am I approaching this idea in the right way, or what questions do I need to ask to get to the answer? Any guidance is appreciated.

Your join filter can use single quotes
arguments: "{{ modules | join(' ') }}"
or you can escape the double quotes
arguments: "{{ modules | join(\" \") }}"
or you can use single quotes for the variable and double for the join
arguments: '{{ modules | join(" ") }}'

Related

How to access an ansible block variable in a file from the same block

I define a yml variable files for ansible with the following structure:
appserver:
root_directory: C:\app
config_directory: '{{ root_directory }}\config'
it seems the second variable config_directory cannot be interpreted correctly, I get a VARIABLE NOT FOUND ERROR.
I tried with:
appserver:
root_directory: C:\app
config_directory: '{{ appserver.root_directory }}\config'
It does not work either, I have a very long trace of error, the most interesting part is :
recursive loop detected in template string:{{ appserver.root_directory }}\config
When I use double quotes instead of simple quotes,
appserver:
root_directory: C:\app
config_directory: "{{ appserver.root_directory }}\config"
I get the following error:
The offending line appears to be:
app_root: D:\WynsureEnvironments\Application
wynsure_root: "{{ appserver.root_directory }}\config"
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
When using variable blocks, how can I reuse variables to assign new variables?
Thanks!
You cannot use such a recursive jinja2 variable declaration in ansible.
Here are 2 (non exhaustive list) alternative solutions:
Don't use a hash. Prepend your vars names. You will typically find this type of naming conventions in e.g. reusable roles on ansible galaxy
appserver_root_directory: C:\app
appserver_config_directory: '{{ appserver_root_directory }}\config'
If you really need a hash of this kind, declare a "private" variable outside of your hash and reuse it inside.
_appserver_root: C:\app
appserver:
root_directory: "{{ _appserver_root }}"
config_directory: "{{ _appserver_root }}\config"

Ansible find replace is not working for 2 lines

- name: Cassandra cassandra.yaml
lineinfile:
dest: "{{ home}}/conf/cassandra.yaml"
state: present
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
# backup: yes
with_items:
- { regexp: "data_file_directories:", line: "data_file_directories: \n - {{ data_directory }}" }
in the first file first run it looks good but in the second run it keeps adding new line. what needs to be done in order to the second run also looks good.
data_file_directories:
- /mount1/data
second run
data_file_directories:
- /mount1/data
- /mount1/data
- /mount1/data
I want some thing like
data_file_directories:
- /mount1/data
lineinfile ― as its name suggest ― is a module to ensure a certain line is in the target file; not lines.
To deal with multiple lines either:
use regexp module with matchgroup and backreference ― the exact implementation is dependent on other constructs in the target file,
use blockinfile module ― the exact implementation is dependent on other constructs in the target file,
or (preferably) use template module.

Performing an Ansible lookup using first_found and skip

I'd like to perform a lookup in Ansible using first_found as well as its skip option. I've created the following play to do so:
- name: Include group playbooks
include: "{{lookup('first_found', dict=(files=[item + '.yml', 'empty.yml'], skip=true))}}"
with_items: "{{group_names}}"
I'm receiving this error, however:
ERROR! Unexpected Exception: '_raw_params'
How can I pass skip option?
First of all, I doubt your dict= parameters passing. See my other answer for correct call.
And about your error: first_found lookup with skip option returns empty list if nothing is found – but include statement expects filename as free-form parameter.
You can workaround it like this:
- name: Include group playbooks
include: "{{ filename }}"
when: filename is string
vars:
filename: "{{ lookup('first_found', dict(files=[item + '.yml', 'empty.yml'], skip=true)) }}"
with_items: "{{group_names}}"

Concat multiple variables and strings in ansible playbook

I'm trying multiple concatenation when preforming with_items for the destination section.
Right now it looks like this:
- name: create app except+lookup
copy: content="" dest="{{ dir.comp ~ '/config/con2dd/' ~ item.name ~ 'File.txt' }}" force=no group=devops owner=devops mode: 0755
with_items:
...
I get:
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
Tried couple of approaches but none resulted something that's working.
Is it possible to concat the variables with the strings?
Don't mix pure YAML and key=value syntaxes for parameters. And always use YAML syntax for complex arguments:
- name: create app except+lookup
copy:
content: ""
dest: "{{ dir.comp }}/config/con2dd/{{ item.name }}File.txt"
force: no
group: devops
owner: devops
mode: 0755
with_items:
...
You are not quoting the value associated with the key copy. For that to happen the first character has to be double (or single) quote. The example, given in the feedback, does this correctly, but is not explicit about it. Once a scalar start with a non-quote (yours start with the c from content quotes occurring in the scalar will no longer have a special meaning.
Because of a bug in the parser that Ansible uses, the : (colon space) in that scalar (mode: 0755) causes trouble, you should double quote the whole scalar and escape the double quotes that occur within it:
copy: "content=\"\" dest=\"{{ dir.comp ~ '/config/con2dd/' ~ item.name ~ 'File.txt' }}\" force=no group=devops owner=devops mode: 0755"
or alternatively use single quotes (which have different escape rules:
copy: 'content="" dest="{{ dir.comp ~ ''/config/con2dd/'' ~ item.name ~ ''File.txt'' }}" force=no group=devops owner=devops mode: 0755'
You can test scalars yourself on this online YAML parser, it has the same bug as what causes Ansible not to parse your YAML correctly.
This parser, handles the in scalar : correctly and will not produce an error with your input (but it has other problems).

How to pass variable in command module in ansible

i am using folloing task in YAMl file.
- name: Run deployment of RWI Artifact
command: "{{ deploy_script }} /home/scripts/lite /application/ a-CL '--Home=/opt/AppServer --appClassLoaderMode=abc'"
but typically , i am getting following error
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
i tried all combination but dont know how to put those quotes correctly.
please suggest
In YAML if you start string with quote, it is considered as quoted string, so you must end the string with the same quote.
Try:
- name: Run deployment of RWI Artifact
command: "{{ deploy_script }} /home/scripts/lite /application/ a-CL '--Home=/opt/AppServer --appClassLoaderMode=abc'"
I assume that deploy_script has no spaces.

Resources