Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve internal variables with python yaml?

Tags:

python

yaml

I have a file test.yml :

---
Servers:
  Server1:
    location: "Earth"
    network: {ip: "0.0.0.0", mac: "00:00:00:00:00:00"}
    inbound: "{{ Configs.Earth.allowed_connections }}"

  Server2:
    location: "Earth"
    network: {ip: "0.0.0.1", mac: "00:00:00:00:00:02"}
    inbound: "{{ Configs.Earth.allowed_connections }}"

  Server3:
    location: "Moon"
    network: {ip: "0.0.0.2", mac: "00:00:00:00:00:02"}

  Server4:
    location: "Mars"
    network: {ip: "0.0.0.3", mac: "00:00:00:00:00:03"}
    inbound: "{{ Configs.Mars.allowed_connections }}"

Configs:
  Earth:
    allowed_connections:
      - 99.99.99.99
      - 99.99.99.98
      - 99.99.99.97

  Mars:
    allowed_connections:
      - 88.99.99.99
      - 88.99.99.98
      - 88.99.99.97

I'd like to resolve the inbound variables when I load the yml file with python. Is there a way to do this natively? Or will I need to write a function that searches for any variables containing "{{ }}" and then reset them.

The solution needs to allow for varying depths that the variables could be located at.

I have no issues loading the file with yaml.load it's the variable resolution I'm struggling with

like image 282
The Ref Avatar asked Nov 02 '25 03:11

The Ref


2 Answers

you can use Jinja template module here please see below example:

import yaml
from jinja2 import Environment

jsonobj = yaml.full_load(your_yaml_stream)
print jsonobj
print Environment().from_string(your_yaml_stream).render(jsonobj)

Output generated will be:

Servers:
  Server1:
    location: "Earth"
    network: {ip: "0.0.0.0", mac: "00:00:00:00:00:00"}
    inbound: "['99.99.99.99', '99.99.99.98', '99.99.99.97']"

  Server2:
    location: "Earth"
    network: {ip: "0.0.0.1", mac: "00:00:00:00:00:02"}
    inbound: "['99.99.99.99', '99.99.99.98', '99.99.99.97']"

  Server3:
    location: "Moon"
    network: {ip: "0.0.0.2", mac: "00:00:00:00:00:02"}

  Server4:
    location: "Mars"
    network: {ip: "0.0.0.3", mac: "00:00:00:00:00:03"}
    inbound: "['88.99.99.99', '88.99.99.98', '88.99.99.97']"

Configs:
  Earth:
    allowed_connections:
      - 99.99.99.99
      - 99.99.99.98
      - 99.99.99.97

  Mars:
    allowed_connections:
      - 88.99.99.99
      - 88.99.99.98
      - 88.99.99.97
like image 200
Amit Nanaware Avatar answered Nov 03 '25 20:11

Amit Nanaware


You can use anchors/aliases for this.

Eg for a reduced version of your example

>>> import yaml
>>> doc = """
Configs: 
  Mars: 
    allowed_connections: &mars # Mark this as an anchor
      - 88.99.99.99 
      - 88.99.99.98 
      - 88.99.99.97 
Servers: 
  Server: 
    location: "Mars" 
    network: {ip: "0.0.0.3", mac: "00:00:00:00:00:03"} 
    inbound: *mars  # references the anchor here
"""
>>> from pprint import pprint # just for formatting
>>> pprint(yaml.load(doc))
{'Configs': {'Mars': {'allowed_connections': ['88.99.99.99',
                                              '88.99.99.98',
                                              '88.99.99.97']}},
 'Servers': {'Server': {'inbound': ['88.99.99.99',
                                    '88.99.99.98',
                                    '88.99.99.97'],
                        'location': 'Mars',
                        'network': {'ip': '0.0.0.3',
                                    'mac': '00:00:00:00:00:03'}}}}

Note that the config section has to be before the server section so that it can be referenced.

More examples here.

like image 30
Holloway Avatar answered Nov 03 '25 19:11

Holloway



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!