How to write an Ansible task using with_dict in a loop (with_items)?

4,008 views
Skip to first unread message

Jean-Louis FEREY

unread,
Nov 25, 2014, 11:10:32 AM11/25/14
to ansible...@googlegroups.com
I want to update INI configuration files.

Today, I store my informations in a var file (in group_vars) this way :

# Identity configuration information identity_servers_conf: DEFAULT: admin_token: "{{identity_admin_token}}" verbose: True database: connection: "mysql://{{ identity_db_user }:{{ identity_db_password }}@{{ db_lb_name }}/{{ identity_db }}" token: provider: keystone.token.providers.uuid.Provider driver: keystone.token.persistence.backends.sql.Token

In my Ansible task, I use these informations this way:

- name: configuration / modify keystone.conf ini file DEFAULT section
  ini_file:
    section: DEFAULT
    dest: /etc/keystone/keystone.conf
    option: "{{item.key}}"
    value: "{{item.value}}"
  with_dict: identity_servers_conf['DEFAULT']

And I duplicate this task for every sections.

Is there a way to iterate through my dict file with each "section" parameters, i.e DEFAULT, database, token.
In fact, I try to find a way to do a with_dict nested in a with_items loop.


adéaime cetout

unread,
Jan 5, 2015, 7:37:05 AM1/5/15
to ansible...@googlegroups.com
hello,
I find very interesting this way of organizing variables for .ini files.

I wanted to use it myself, so I worked on a plugin that allows to generate all the keys of an .ini file in one pass with the inifile module.
It works fine and I use to manage my OpenStack configuration files.

I am not a specialist in development, but I think this plugin can be useful for everyone, so if someone wants to take over to maintain and integrate it into ansible, he is welcome.

The plugin transforms the hierarchy data in a list (section, key, value) for use directly with the inifile module with_inidata as below:

vars file :
...
glanceapi_conf
:
  DEFAULT
:
    verbose
: "{{ image_log_verbose }}"
    rabbit_host
: "{{ amqp_host }}"
    rabbit_port
: "{{ amqp_port }}"
    rabbit_userid
: "{{ amqp_userid }}"
    rabbit_password
: "{{ amqp_password }}"
    rabbit_ha_queues
: "{{ amqp_ha_queues }}"
  database
:
    connection
: "mysql://{{ image_db_user }}:{{ image_db_password }}@{{ db_host }}/{{ image_db }}"
  keystone_authtoken
:
    auth_uri
: "http://{{ identity_admin_host }}:{{ identity_api_port }}/v2.0"
    identity_uri
: "http://{{ identity_admin_host }}:{{ identity_admin_port }}"
    admin_tenant_name
: "{{ image_ks_tenant }}"
    admin_user
: "{{ image_ks_user }}"
    admin_password
: "{{ image_ks_password }}"
  paste_deploy
:
    flavor
: keystone
  glance_store
:
    default_store
: file
    filesystem_store_datadir
: /var/lib/glance/images/
...


   
plugin code :

# (c) 2014, Pierre-Yves KERVIEL <pierreyve...@orange.com>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.

# inidata is used to manage ini

import ansible.utils as utils
import ansible.errors as errors

class LookupModule(object):

   
def __init__(self, basedir=None, **kwargs):
       
self.basedir = basedir


   
def run(self, terms, inject=None, **kwargs):
        terms
= utils.listify_lookup_plugin_terms(terms, self.basedir, inject)

       
if not isinstance(terms, dict):
           
raise errors.AnsibleError("inidata lookup expects a dictionnary , got '%s'" %terms)

        ret
= []
       
for item0 in terms:
           
if not isinstance(terms[item0], dict):
               
raise errors.AnsibleError("inidata lookup expects a dictionary, got '%s'" %terms[item0])
           
for item1 in terms[item0]:
                ret
.append((item0, item1, terms[item0][item1]))

       
return ret





Task code :

- name: configuration.modify_glance-api_conf_file / modify glance-api.conf ini file
  ini_file
:
    section
: "{{ item.0 }}"
    dest
: /etc/glance/glance-api.conf
    option
: "{{ item.1 }}"
    value
: "{{ item.2 }}"
    backup
: yes
  with_inidata
: glanceapi_conf



 
To use it, simply copy the plugin code with the name "dataini" in the directory defined in /etc/ansible.cfg. This should be /usr/share/ansible_plugins/lookup_plugins
for the Ubuntu distribution and write your tasks as in my example. That's all.

I hope that this plugin will allow you to simplify your ini files management.

Best Regards

Michael DeHaan

unread,
Jan 5, 2015, 9:11:17 AM1/5/15
to ansible...@googlegroups.com
I would be tempted to keep it as a dictionary, but just to render the INI file using the template module.

That way additional lookup plugins can be avoided.

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/608eaab9-eba1-4d99-b8ee-ab3a21f98c16%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Message has been deleted

adéaime cetout

unread,
Jan 5, 2015, 10:40:52 AM1/5/15
to ansible...@googlegroups.com
Hello and thank you for your quick response.

In my opinion, to use a template, you must retrieve or generate it and keep it alive (track changes).
You must
also manage the template and variable files.
With this solution, we
only manage the specific keys in a single variables file.
This is very visual and updating it can be done very easily.

Best Regards

Reply all
Reply to author
Forward
0 new messages