0

Ansible allows deeply nested dicts, but then doesn't actually allow you to get much use out of them! Here is my story.

I'm trying to configure a number of ini files with Ansible. To this end, I am using the ini_file module. This module requires at a minimum, four pieces of information:

  1. File path
  2. Section
  3. Option
  4. Value of that option

So, I've defined a dict:

  vars:
    conf:
      "/etc/conf1.ini":
        - section: main
          option: foo
          val: bar
        - section: main
          option: baz
          val: qux
      "/etc/otherconf.ini":
        - section: options
          option: flower
          val: bird

And so on. So, I can use:

  - name: Write ini files
    ini_file:
      path: "{{ item.0.key }}"
      section: "{{ item.1.section }}"
      option: "{{ item.1.option }}"
      value: "{{ item.1.val }}"
    loop: "{{ conf | dict2items | subelements('value') }}"

This... works. I can continue to use this. Example output of /etc/conf1.ini:

[main]
foo = bar
baz = qux

Question: Is there a better way? How can I organize my data to work better with (the new style of) Ansible loops? (i.e. nothing that starts with with_)

Note: I also really don't like having to use a fully qualified path as a dict key; I'd rather it be e.g. path: "/etc/conf1.ini" somehow.

Note 2: I don't have to have this all in one single variable, conf, but if I have one variable per ini file, how do I loop that?

courtlandj
  • 435
  • 9
  • 19
  • 1
    I'm no ansible expert, but two things jump out at me. Is `subelements('value')` what you are really using or is that a typo for `subelements('val')`? Secondly, you can clearly use `path` as another entry in your dictionary and make the key be some label just for humans. (Then you could check for a `path` subelement...) – Cupcake Protocol Nov 14 '18 at 00:46
  • If the syntax and looping become too complex, I would suggest just using the template module instead. – M_dk Nov 14 '18 at 11:11
  • Also remember that while you can do something thats complex, it might be a better idea to keep it simpler even though it means adding more tasks. At least, thats how I read the best practice guidelines: https://www.ansible.com/blog/ansible-best-practices-essentials – M_dk Nov 14 '18 at 11:26
  • 1
    @CupcakeProtocol - Yes, it's super intentional. Subelements is looking at the list of tuples that dict2items provides. Each tuple is key, value. That's why I can't name any keys in my variable as "value". Learned this trick from: https://stackoverflow.com/a/50711744/3201683 – courtlandj Nov 14 '18 at 15:47
  • @M_dk I don't see how templating is going to help me edit values in existing ini files. And, I don't really think what I am doing is all that "complex", either. I'm just sequentially setting values in some ini files, but I can't use a nice hierarchical data structure to do all the work for me -- I have to duplicate the "section" value unnecessarily all over the place. To me, that is more complex, not less. I cannot imagine writing it this way in any other language. – courtlandj Nov 14 '18 at 15:48
  • If value needs to be duplicated all over the place, it should probably just be a default value for your role? – M_dk Nov 14 '18 at 19:46
  • I just feel that you are needlesly complicating your datastructure. You do not need nest the config definition like that and you could write much simpler code Remember that one of the best practice guidelines is "dont program" in ansible and I feel you are edging into that territory. Anyway, this just advice from someone who is presently spending entire workdays porting and simplifying a needlessly complex Ansible codebase because the technical debt is getting out of hand and the guy who wrote most of the "tricks" quit just before I joined. – M_dk Nov 14 '18 at 19:57
  • I don't mean to be critical, but a default value for a role doesn't help me either: I need to modify an existing ini file, with more than one section. The section value has to be added to each option/value pair for that section. So, you see a default wouldn't really apply, as that value changes even within each ini file. What I (think that I) need is a task that constructs the 'ugly' values that the module actually consumes out of 'pretty' values that I write in human-readable form. Or better understanding of how to chain filters together. – courtlandj Nov 14 '18 at 20:56

0 Answers0