Ansible - Replace the host part of an ipv4 address - ipv4

- hosts: localhost
gather_facts: False
vars_prompt:
- name: ServerIP
prompt: Enter the ServerIP to replace
private: False
default: "11.11.4.10"
vars:
Y: '126'
pre_tasks:
- name: Set some facts
set_fact:
ServerIP1: "{{ServerIP}}"
- name: Save ServerIP in a register
shell: echo {{ServerIP1}}
register: resultip
Note: I know I can split the host portion of the Ip using the following code:
- name: show the last octet of the ServerIP
debug: msg={{resultip.stdout.split('.')[3]}}
What I want:
- name: Replace the last octet of the ServerIP with a variable var
# How can I do this ?
I want to store/display:
x.x.x.{{ Y }}

If you want to replace the last octet of ServerIP with the value
of Y the following should work for you:
set_fact:
NewIP: "{{ ServerIP.split('.')[0] }}.{{ ServerIP.split('.')[1] }}.{{ ServerIP.split('.')[2] }}.{{ Y }}"

Related

ansible based wordpress installation not working

Hope y'all are enjoying the holidays. I am attempting an automated installation of wordpress on my Linux VM using ansible. To that end, I have written this ansible piece of code that tries to mimic the official ubuntu guide.
Here is the code:
- name: "Installing wordpress dependencies"
hosts: all
become: True
gather_facts: True
vars:
get_installer: 'curl -sS https://getcomposer.org/installer -o /tmp/composer-setup.php || /bin/true'
get_signature: 'curl -sS https://composer.github.io/installer.sig'
tasks:
- name: "Update repository"
apt:
update_cache: "yes"
- name: "Installing requirements"
apt:
name:
- "curl"
- "php"
- "php-cli"
- "gnupg"
- "unzip"
- "mysql-server"
- "php-fpm"
- "php-mysql"
- "apache2"
- "ghostscript"
- "libapache2-mod-php"
- "php-bcmath"
- "php-curl"
- "php-imagick"
- "php-intl"
- "php-json"
- "php-mbstring"
- "php-xml"
- "php-zip"
state: present
- name: Populate service facts
ansible.builtin.service_facts:
- name: Print service facts
ansible.builtin.debug:
var: ansible_facts.services
- name: "stopping nginx if running"
service:
name: nginx
state: stopped
when: "'nginx' in ansible_facts.services"
- name: "remove nginx if installed"
apt:
name:
- "nginx"
state: absent
- name: stop Mysql
service:
name: mysql
state: stopped
when: "'mysql' in ansible_facts.services"
- name: stop apache2
service:
name: apache2
state: stopped
when: "'apache2' in ansible_facts.services"
- name: Installing wordpress through source
hosts: all
become: True
gather_facts: False
vars:
wprootdir: "/srv/www/wordpress"
tasks:
- name: checking if wp src dir exists
stat:
path: "{{ wprootdir }}"
register: dir_details
- name: delete existing wordpress source files
become_user: www-data
no_log: True
file:
#path: "{{ item.path }}"
#recurse: True
path: "{{ wprootdir }}"
state: absent
#with_items: "{{ path_list.files }}"
- name: creating /var/www for wordpress source
file:
#path: "'{{ wp-root-dir }}' + 'wordpress'"
path: "/srv/www/wordpress"
recurse: yes
state: directory
owner: www-data
mode: '0755'
- name: downloading and extracting wordpress source
shell:
cmd: "curl https://wordpress.org/latest.tar.gz | sudo -u www-data tar zx -C /srv/www"
register: status
- fail:
msg: "Unable to download or extract wordpress source"
when: (status.rc != 0)
- name: Configuring apache for wordpress
hosts: all
become: True
gather_facts: False
vars:
wprootdir: "/srv/www/wordpress"
wpconffile: "/etc/apache2/sites-available/wordpress.conf"
tasks:
- name: deleting the file if it exists
file:
path: "{{ wpconffile }}"
state: absent
- name: creating wordpress conf file
file:
path: "{{ wpconffile }}"
state: touch
owner: www-data
- name: populating wordpress conf file
template:
src: apache2.j2
dest: "{{ wpconffile }}"
- name: enabling the site
shell:
cmd: "a2ensite wordpress"
- name: enable URL rewriting
shell:
cmd: "a2enmod rewrite"
- name: disable default "it works" site
shell:
cmd: "a2dissite 000-default"
- name: restart apache2
service:
name: apache2
state: reloaded
- name: Configuring database
hosts: all
become: True
gather_facts: True
#gather_facts: yes
vars:
mysql_port: 3306
mysql_socket: /var/run/mysqld/mysqld.sock
mysql_superuser: root
mysql_superuser_home: "{% if mysql_superuser == 'root' %}/root{% else %}/home/{{ mysql_superuser }}{% endif %}"
mysql_superuser_password: SuperUserPwd
mysql_wordpress_password: WordpressPwd
http_port: 80
tasks:
- name: Installing PyMySql through pip
pip:
name: PyMySql
state: present
- name: ensure mysql is running and starts on boot
service:
name: mysql
state: started
enabled: True
- name: Removes anonymous user account for localhost
community.mysql.mysql_user:
name: ''
state: absent
login_user: root
login_password: ""
login_unix_socket: "{{ mysql_socket }}"
when: ansible_local.mysqlinfo is undefined
- name: adding a password for root user
mysql_user:
# Update the superuser to have all grants and a password
name: "{{ mysql_superuser }}"
host: localhost
password: "{{ mysql_superuser_password }}"
priv: "*.*:ALL,GRANT"
# Login *as root* to perform this change, even though you might
# be altering the root user itself
login_user: root
login_password: ""
login_port: "{{ mysql_port }}"
login_host: localhost
login_unix_socket: "{{ mysql_socket }}"
# As a good measure,have ansible check whether an implicit login
# is possible first
check_implicit_admin: yes
when: ansible_local.mysqlinfo is undefined
- name: "Create custom fact directory"
file:
path: "/etc/ansible/facts.d"
state: "directory"
recurse: yes
when: ansible_local.mysqlinfo is undefined
- name: "record mysql info in custom fact"
template:
src: mysqlinfo.j2
dest: /etc/ansible/facts.d/mysqlinfo.fact
mode: 0644
when: ansible_local.mysqlinfo is undefined
- name: "re-run setup to use custom facts"
setup:
filter: ansible_local
when: ansible_local.mysqlinfo is undefined
- debug:
msg:
- "mysqlinfo is {{ ansible_local.mysqlinfo }}"
when: ansible_local.mysqlinfo is defined
#- name: Create system-wide mysql configuration file
#template:
#src: mysql_sys.cnf.j2
#dest: /etc/my.cnf
#- name: Create mysql configuration file for `{{ mysql_superuser }}`
#template:
#src: mysql_superuser.cnf.j2
#dest: "{{ mysql_superuser_home }}/.my.cnf"
- name: create database wordpress
mysql_db:
db: wordpress
state: present
login_user: "{{ ansible_local.mysqlinfo.mysql_superuser }}"
login_password: "{{ ansible_local.mysqlinfo.mysql_superuser_password }}"
login_unix_socket: "{{ mysql_socket }}"
when: ansible_local.mysqlinfo is defined
- name: Create database user 'wordpress' with all database privileges
community.mysql.mysql_user:
name: wordpress
password: "{{ mysql_wordpress_password }}"
login_user: "{{ ansible_local.mysqlinfo.mysql_superuser }}"
login_password: "{{ ansible_local.mysqlinfo.mysql_superuser_password }}"
priv: '*.*:ALL'
state: present
when: ansible_local.mysqlinfo is defined
- name: Flush privileges
mysql_query:
login_db: wordpress
login_user: "{{ ansible_local.mysqlinfo.mysql_superuser }}"
login_password: "{{ ansible_local.mysqlinfo.mysql_superuser_password }}"
login_unix_socket: "{{ mysql_socket }}"
query: FLUSH PRIVILEGES
# UFW Configuration
- name: "UFW - Allow HTTP on port {{ http_port }}"
ufw:
rule: allow
port: "{{ http_port }}"
proto: tcp
notify:
- Restart Mysql
tags: [ system ]
handlers:
- name: Restart Mysql
service:
name: mysql
state: restarted
- name: Restart Apache2
service:
name: apache2
state: restarted
- name: Configuring wordpress to connect to the database
hosts: all
gather_facts: False
become: true
vars:
wpconfigfile: "/srv/www/wordpress/wp-config.php"
tasks:
- name: copy sample config to wp-config.php
#become_user: www-data
copy:
remote_src: yes
src: /srv/www/wordpress/wp-config-sample.php
dest: "{{ wpconfigfile }}"
owner: www-data
- name: "re-run setup to use custom facts"
setup:
filter: ansible_local
- name: set database credentials in the config file
become: false
#become_user: www-data
#become_method: "su"
# multiple commands are run like this whereas with
# single command one can use a cmd paramater
# since this is technically *not* a list passed to /bin/sh
# we do not need a list here. Instead it is a series of
# commands being passed to /bin/sh
#shell: |
# apparently, passing this list directly doesn't seem to work
# what works is this loop
command: "{{ item }}"
with_items:
- "sudo -u www-data sed -i s/database_name_here/wordpress/ {{ wpconfigfile }}"
- "sudo -u www-data sed -i s/username_here/wordpress/ {{ wpconfigfile }}"
- "sudo -u www-data sed -i s/password_here/{{ ansible_local.mysqlinfo.mysql_wordpress_password }}/ {{ wpconfigfile }}"
- name: get random secret keys
uri:
url: https://api.wordpress.org/secret-key/1.1/salt/
return_content: yes
body_format: json
register: wordpress_keys
- debug:
var: wordpress_keys.content
- name: delete existing bak file
file:
path: "{{ wpconfigfile }}.bak"
state: absent
- name: run script to remove key placeholders
become_user: www-data
script:
chdir: /srv/www/wordpress/
cmd: replacelines.py
executable: /usr/bin/python3
environment: /srv/www/wordpress/
- name: update config file
become_user: www-data
copy:
remote_src: yes
src: "{{ wpconfigfile }}.bak"
dest: "{{ wpconfigfile }}"
- blockinfile:
path: "{{ wpconfigfile }}"
marker: // {mark} ANSIBLE MANAGED BLOCK
# having this separator here was giving me issues
#block: |
block:
"{{ wordpress_keys.content }}"
handlers:
- name: Restart Mysql
service:
name: mysql
state: restarted
- name: Restart Apache2
service:
name: apache2
state: restarted
Associated jinja2 template files are here:
Apache2 template:
<VirtualHost *:80>
Servername {{ ansible_hostname }}
DocumentRoot "{{ wprootdir }}"
<Directory "{{ wprootdir }}">
Options FollowSymLinks
AllowOverride Limit Options FileInfo
DirectoryIndex index.php
Require all granted
</Directory>
<Directory "{{ wprootdir }}/wp-content">
Options FollowSymLinks
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
mysqlinfo template
{
"mysql_port": "{{ mysql_port }}",
"mysql_socket": "{{ mysql_socket }}",
"mysql_superuser": "{{ mysql_superuser }}",
"mysql_superuser_password": "{{ mysql_superuser_password }}",
"mysql_wordpress_password": "{{ mysql_wordpress_password }}"
}
replacelines.py script:
import re
with open("wp-config.php", "r") as wpconfig, open("wp-config.php.bak", "w") as wpconfigbak:
for line in wpconfig:
found = re.search(r'AUTH_KEY|SECURE_AUTH_KEY|LOGGED_IN_KEY|NONCE_KEY|AUTH_SALT|SECURE_AUTH_SALT|LOGGED_IN_SALT|NONCE_SALT', line.strip());
if (not found):
wpconfigbak.write(line)
else:
continue
inventory file:
[local]
localhost ansible_connection=local
With this playbook I am able to see the wordpress landing page when I open 'localhost:80/' on my Linux machine. However I am unable to get to the wordpress dashboard. I run the playbook like so: ansible-playbook -i inventory SetupWordpress.yaml
To save time, you may use my github repo:
git clone -b WIP git#github.com:redbilledpanda/DevOpsScripts.git
cd DevOpsScripts && ansible-playbook -i inventory SetupWordpress.yaml
After the playbook completes, I go to http://localhost:80 and I am presented with the installer:
I fill in the details:
Apparently, it succeeds:
When I try logging in, I don't see the dashboard. Instead, I never go past the login screen (it doesn't say incorrect credentials or anything though):
I am at a loss as to what am I doing wrong. Keen to hear from you folks.
UPDATE1: If I skip the part where I generate the wordpress 'salts'/keys it works. I can see the dashboard etc. With these salts however, it just won't get to the wordpress admin dashboard.
Using a minimal sample config file wpconfig.file
<?php
/**
* The base configuration for WordPress
* ...
* Authentication unique keys and salts.
*
* Change these to different unique phrases! You can generate these using
* the {#link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}.
*
* You can change these at any point in time to invalidate all existing cookies.
* This will force all users to have to log in again.
* ...
*/
and a minimal example playbook
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Get random secret keys
uri:
url: https://api.wordpress.org/secret-key/1.1/salt/
return_content: yes
body_format: json
register: wordpress_keys
- name: Show keys
debug:
var: wordpress_keys.content
- name: Write keys to config
blockinfile:
path: wpconfig.file
marker: // {mark} ANSIBLE MANAGED BLOCK
block:
"{{ wordpress_keys.content }}"
it results into the expected and probably correct output.
TASK [Show keys] ************************************************************************************************
ok: [localhost] =>
wordpress_keys.content: |-
define('AUTH_KEY', '...');
define('SECURE_AUTH_KEY', '...');
define('LOGGED_IN_KEY', '...');
define('NONCE_KEY', '...');
define('AUTH_SALT', '...');
define('SECURE_AUTH_SALT', '...');
define('LOGGED_IN_SALT', '...');
define('NONCE_SALT', '...');
<?php
/**
* The base configuration for WordPress
* ...
* Authentication unique keys and salts.
*
* Change these to different unique phrases! You can generate these using
* the {#link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}.
*
* You can change these at any point in time to invalidate all existing cookies.
* This will force all users to have to log in again.
* ...
*/
// BEGIN ANSIBLE MANAGED BLOCK
define('AUTH_KEY', '...');
define('SECURE_AUTH_KEY', '...');
define('LOGGED_IN_KEY', '...');
define('NONCE_KEY', '...');
define('AUTH_SALT', '...');
define('SECURE_AUTH_SALT', '...');
define('LOGGED_IN_SALT', '...');
define('NONCE_SALT', '...');
// END ANSIBLE MANAGED BLOCK
Summary
Your current question and description seems not to be focused on the necessary part but on everything not so related around
On Ansible tasks I am not able to (re-)produce an issue
The part deals with configuration for a 3rd party web service or PHP only
According this it seems not to be related to Ansible at all
The problem domain seems to be Wordpress and PHP setup and configuration only, namely the config file
For further troubleshooting you may try to template module – Template a file out to a target host, the config file including keys generated define('AUTH_KEY', '{{ lookup('password', '/dev/null chars=ascii_letters length=64') }}');
Check with Browser in Incognito Mode because of invalidated cookies
Therefore it is also not about programming at all
An other site on Stack like serverfault.com, superuser.com, devops.staexchange.com or wordpress.stackexchange.com might fit better for your question
-regenerate the security keys
-Make sure the keys are entered correctly in the wp-config file of your WordPress installation.

ansible insert rows into mysql db

I am novice to ansible and trying out few use cases to grab more knowledge. I am trying out one use case where I plan to connect to MYSQL db and run one select query. What I am trying is shown in the playbook below. This code works fine. Now I want to run one insert query to insert some rows from .csv file. How can I achieve this?
ansible playbook:
---
- hosts: localhost
gather_facts: false
#become: true
tasks:
- name: Excute query to db with positional arguments
community.mysql.mysql_query:
login_host: sqltest-lb-fm-in.dbaas.domain.com
login_user: devops_baseline_db
login_password: *********
login_port: 3307
login_db: mydb
ca_cert : mydomain-SHA256-Root-CA.crt
query: SELECT * FROM Inventory
register: output
- debug:
msg: "{{ output }}"
example of /tmp/report.csv content
Date,Hostname/IP,OS-Version,Package-Name,Pre-installed-Package-Status,Current-Installed-Version,Post-installed-Package-Status,log-loc
2022-12-15,10.109.20.12,12.5,curl,up-to-date,7.60.0-11.49.1,up-to-date,http://hostname/log_dir/
2022-12-15,10.109.20.12,12.5,libcurl4-32bit,up-to-date,7.60.0-11.49.1,up-to-date,http://hostname/log_dir/
2022-12-15,10.109.20.12,12.5,libcurl4,up-to-date,7.60.0-11.49.1,up-to-date,http://hostname/log_dir/
2022-12-15,10.109.20.12,12.5,libtiff5,up-to-date,4.0.9-44.56.1,up-to-date,http://hostname/log_dir/
You have Three ways
1. using ansible mysqldb module (Not working but expected to work) :
- name: Copy database dump file
ansible.builtin.copy:
src: /tmp/report.csv
dest: /tmp
- name: Restore database
community.mysql.mysql_db:
name: my_db
state: import
target: /tmp/report.csv
2. Using Commands:
- name: Copy database dump file
ansible.builtin.copy:
src: /tmp/report.csv
dest: /tmp
- name: Excute query to db with positional arguments
community.mysql.mysql_query:
login_host: sqltest-lb-fm-in.dbaas.domain.com
login_user: devops_baseline_db
login_password: *********
login_port: 3307
login_db: mydb
ca_cert : mydomain-SHA256-Root-CA.crt
query: |
LOAD DATA LOCAL INFILE '/tmp/report.csv'
INTO TABLE Inventory
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;
3. Looping over lines:
- name: Read CSV File
community.general.read_csv:
path: /tmp/report.csv
register: report
delegate_to: localhost
- name: Excute query to db with positional arguments
community.mysql.mysql_query:
login_host: sqltest-lb-fm-in.dbaas.domain.com
login_user: devops_baseline_db
login_password: *********
login_port: 3307
login_db: mydb
ca_cert : mydomain-SHA256-Root-CA.crt
query: |
INSERT INTO Inventory (Date,Hostname,OS-Version,Package-Name,Pre-installed-Package-Status,Current-Installed-Version,Post-installed-Package-Status,log-loc)
VALUES ({{ item.Date }},{{ item.Hostname }},{{ item.OS_Version }}, {{ item.Package_Name }},{{ item.Pre_installed_Package_Status }},{{ item.Current_Installed_Version }},{{ item.Post_installed_Package_Status }},{{ item.log_loc }});
loop: "{{ report }}"
I know it's a bit dirty but you can try it. ;)
Note that I have removed/changed some special characters or you can find some workaround for that

Ansible set_facts by localhost json file and copy to remote hosts

I'm trying to copy a json file from my localhost to remote hosts, and use the json "version" key value as a parameter in the destination file name.
JSON:
{"name": "test", "version": 3}
YML:
---
- name: Get json file version
hosts: locahost
become: true
tasks:
- name: Register licenses file
command: "cat conf/licenses.json"
register: result
- name: Save the json data
set_fact:
jsondata: "{{ result.stdout | from_json }}"
- name: Save licenses file version
set_fact:
file_version: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: 'version'
- name: Deploy Licenses File
hosts: hosts
become: true
tasks:
- name: Copy licenses file
copy:
src: "conf/licenses.json"
dest: "/tmp/licenses_{{ file_version }}.json"
When I run the playbook above, the Deploy Licenses File key doesn't find the file_version fact, even though I can see it is successfully saved in the Get json file version key.
Set file_version fact:
ok: [localhost] => {
"ansible_facts": {
"file_version": "1"
},
"changed": false
}
Error:
The task includes an option with an undefined variable. The error was: 'file_version' is undefined
I think the facts are saved on the given host granularity and are not global facts per playbook initiation.
My current workaround is to combine the keys to a single task and then it works correctly, but I prefer to get the version once instead of repeating it for each remote host.
To access facts of another host, you can always use the hostvars special variable.
So, in your case:
dest: "/tmp/licenses_{{ hostvars.localhost.file_version }}.json"
Now, you actually do not need that level of complication with two plays and could well do:
- name: Deploy Licenses File
hosts: hosts
become: true
tasks:
- name: Copy licenses file
copy:
src: "{{ _licence_file }}"
dest: "/tmp/licenses_{{ file_version }}.json"
vars:
_licence_file: conf/licenses.json
file_version: >-
{{ (lookup('file', _licence_file) | from_json).version }}
The first play runs at localhost only. Therefore the variables declared in the first play are available to localhost only. This is the reason that the variables are not available to host in the second play
The error was: 'file_version' is undefined
Run once the tasks in a block of the first play at all hosts. This way the variables will be available to all hosts in the second play. For example, the simplified playbook below does the job
- hosts: all
tasks:
- block:
- include_vars:
file: licenses.json
name: jsondata
- set_fact:
file_version: "{{ jsondata.version }}"
run_once: true
- hosts: hosts
tasks:
- copy:
src: licenses.json
dest: "/tmp/licenses_{{ file_version }}.json"
Created file at the remote host
shell> ssh admin#test_11 cat /tmp/licenses_3.json
{"name": "test", "version": 3}
The code can be further simplified. The single play below does the job as well
- hosts: hosts
tasks:
- include_vars:
file: licenses.json
name: jsondata
run_once: true
- copy:
src: licenses.json
dest: "/tmp/licenses_{{ jsondata.version }}.json"

Passing Values from a CSV file into an Ansible playbook

The files below are my playbook, inventory, and a CSV file ( my dictionary)
network_objects.yml
---
- hosts: all
connection: httpapi
gather_facts: False
vars_files:
- 'my_var.yml'
tasks:
- name: add-host
check_point.mgmt.cp_mgmt_host:
name: New Host 1
ip_address: 192.0.2.1
state: present
auto_publish_session: yes
- name: add-group
check_point.mgmt.cp_mgmt_group:
name: New Group 1
members:
- New Host 1
state: present
auto_publish_session: yes
my_var.yml
ansible_httpapi_validate_certs: False
ansible_httpapi_use_ssl: True
ansible_network_os: check_point.mgmt.checkpoint
ansible_python_interpreter: "python3"
ansible_user: admin
ansible_password: password
hosts
[check_point]
checkpoint ansible_host=#IP address of checkpoint
users.csv
Name,IP Address,Comments
PCUSER1,10.11.92.44, Created by User Feb 19 2021
PCUSER2,10.11.12.13, Created by User 02/19/2012
readCSV.yml           ---> This  reads a csv file called users.csv
- name: "Check for CSV File"
hosts: localhost
gather_facts: no
tasks:
- name: Read CSV File and Return a dictionary
read_csv:
path: users.csv
key: name
register: user
- ansible.builtin.debug:
msg: '{{ user }}
What I want to achieve,
I want to be able to read my CSV and pass those variables in the order the CSV data are listed. Then I can publish the New Host ( with all the Names, IP Addresses, Comments ) to Checkpoint
- name: add-host
check_point.mgmt.cp_mgmt_host:
name: {{ Get all Names from CSV File }}
ip_address: {{ Get all IP Addresses from CSV File }}
comments: {{ Get all Comments from CSV File }}
- name: add-host
check_point.mgmt.cp_mgmt_host:
name: {{ item.key }}
ip_address: {{ item.value[0]}}
comments: {{ item.value[1] }}
loop: "{{ user |dict2items}}"
I'm not sure for value.
i think the ouput of user is { user:[ip_address,comments],...}
Look your's structure dictonnaries, i think my purpose is good but adapt it.
source https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#iterating-over-a-dictionary

Can't access register variable in a loop

I've been following this example playbook to create rackspace servers using Ansible
http://nicholaskuechler.com/2015/01/09/build-rackspace-cloud-servers-ansible-virtualenv/
Which works great, but only works on one server at a time, so I am trying to make it more dynamic, using with_items to loop through the number of servers I want to build
tasks:
- name: Rackspace cloud server build request
local_action:
module: rax
credentials: "{{ credentials }}"
name: "{{ item }}"
flavor: "{{ flavor }}"
image: "{{ image }}"
region: "{{ region }}"
files: "{{ files }}"
wait: yes
state: present
networks:
- private
- public
with_items:
- server-app-01
- server-app-02
register: rax
This creates the servers fine, but when I try and add this to the deploy group using the method in the link, I get an error, as expected as now there is a 'results' key I"ve tried all kinds of ways to try and target this in the way that I perceive the documentation to allude to:
- name: Add new cloud server to host group
local_action:
module: add_host
hostname: "{{ item.success.name }}"
ansible_ssh_host: "{{ item.success.rax_accessipv4 }}"
ansible_ssh_user: root
groupname: deploy
with_items: rax.results
(I’ve also tried many other kinds of ways to target this)
But I get ‘One or more undefined variables: ‘list object’ has no attribute ‘rax_accessipv4”
This is a stripped down version of the object I get back from rax, through debug. These servers don't exist anymore.
http://pastebin.com/NRvM7anS
Can anyone tell me where I'm going wrong I'm starting to go a bit mad
If you notice the type of rax.results.success is list.
So this: hostname: "{{ item.success.name }}"
should be
hostname: "{{ item.success[0].name }}" or
hostname: "{{ item['success'][0]['name'] }}"
.
{
"changed": true,
"msg": "All items completed",
"results": [
{
"instances": [
{
"name": "server-app-01",
"rax_accessipv4": "134.213.51.171",
"rax_accessipv6": "2a00:1a48:7808:101:be76:4eff:fe08:5251",
}
],
"item": "server-app-01",
"success": [
{
"name": "server-app-01",
"rax_accessipv4": "134.213.51.171",
"rax_accessipv6": "2a00:1a48:7808:101:be76:4eff:fe08:5251",
}
],
"timeout": []
},
......
}
I was just wrestling with this Friday. Here is my solution:
---
- name: Provision rackspace webheads
hosts: localhost
gather_facts: false
max_fail_percentage: 10
tasks:
- name: Provision a set of instances
local_action:
group: servers
count: 5
exact_count: yes
credentials: cred.ini
flavor: <FLAVOR ID>
group: raxhosts
image: <IMAGE ID>
key_name: <SSH KEYNAME>
module: rax
name: webheads
state: present
wait: yes
register: rax
- name: Add new instances to the group 'raxhosts'
local_action:
module: add_host
hostname: "{{ item.name }}"
ansible_ssh_host: "{{ item.rax_accessipv4 }}"
ansible_ssh_pass: "{{ item.rax_adminpass }}"
groupname: raxhosts
with_items: rax.success
when: rax.action == 'create'
- name: Wait for hosts
local_action: wait_for host={{ item.rax_accessipv4 }} port=22 delay=60 timeout=600 state=started
with_items: rax.success
Here is what my cred.ini looks like:
[rackspace_cloud]
username =
api_key =
Run it like so:
RAX_CREDS_FILE=cred.ini RAX_REGION=DFW ansible-playbook <playbook>.yml