-1

Summary:

I have nested dict like in example and i want to loop over it. For every "item" i want to have nested keys and value f.e.

Input

python:
  lint:
    where: 'here'

Output:

python.lint.where: 'here'

Why i need it:

I'm creating role for managing visual studio code via ansible. I want to install it, create settings.json (this questions is for this case), install/remove plugins. Configuration should be created from variables like: list of extensions, dictionary of settings, repo path etc. With this role i can create one file configuration for my developing environment which can i set via 'one-click'.

Have dict configuration.yml:

## vscode config
code_config:
  python:
    pythonPath: '/usr/bin/python'
    linting:
      enabled: "true"
      pep8Enabled: "true"
      ignorePath:
        - '.code'
        - '.vscode'

And sample playbook

- hosts: localhost
  vars_files: 'configuration.yml'
  tasks:
    - name: Hello
      template:
        src: file.j2
        dest: /etc/file.conf

file.j2

{
{% for key,value in code_config %}
{{ key }}: {{ value }},
{% endfor %}
}

Want to have output like:

{
python.pythonPath: '/usr/bin/python',
python.linting.enabled: 'true',
python.linting.pep8Enabled: 'true',
}
Farfax
  • 3
  • 1
  • Welcome to stack overflow. This community is for answering very specific questions. As such there is an expectation that you have something you have done and are struggling with a specific issue. Please try writing the script yourself, but if you get stuck, you can come back and ask a question about the specific problem you're having. Read [How to Ask](https://stackoverflow.com/questions/how-to-ask) for more details. – MichaelD Aug 18 '19 at 20:45
  • You may benefit from [this question](https://stackoverflow.com/questions/1773805/how-can-i-parse-a-yaml-file-in-python) – MichaelD Aug 18 '19 at 20:47

1 Answers1

0

This is a difficult one to achieve with the standard Ansible/Jinja2 filters, but you could create your own custom filter. For example...

  1. Create a directory in your playbook directory called filter_plugins
  2. Create the python script filter_plugins/dict2settings.py with contents:
#!/usr/bin/env python

class FilterModule(object):
    def filters(self):
        return {'dict2settings': dict2settings}

def dict2settings(var, config={}, parent_keys=[]):
    if isinstance(var, dict):
        for key,value in var.items():
            parent_keys.append(key)
            dict2settings(value, config, parent_keys)
    else:
        config['.'.join(parent_keys)] = var
        parent_keys.pop()
    return config
  1. Use the custom filter in your playbook:
- hosts: localhost
  gather_facts: no

  vars:
    code_config:
      python:
        pythonPath: '/usr/bin/python'
        linting:
          enabled: "true"
          pep8Enabled: "true"
          ignorePath:
            - '.code'
            - '.vscode'

  tasks:
    - copy:
        content: "{{ code_config | dict2settings | to_nice_json }}"
        dest: /etc/file.conf

The output file will have contents:

{
    "python.linting.enabled": "true",
    "python.linting.ignorePath": [
        ".code",
        ".vscode"
    ],
    "python.linting.pep8Enabled": "true",
    "python.pythonPath": "/usr/bin/python"
}

Given that your expected output in your question is not actually valid JSON, you may need to play around slightly with the formatting, using a template or otherwise. But the custom filter just provides a flat key/value dictionary, so it should be pretty easy to work with.

Matt P
  • 2,452
  • 1
  • 12
  • 15