Orr Matityahu
Orr Matityahu

Reputation: 41

Parse a puppet manifest with Python

I have a puppet manifest file - init.pp for my puppet module In this file there are parameters for the class and in most cases they're written in the same way:

Example Input:

class test_module(
    $first_param = 'test',
    $second_param = 'new' )

What is the best way that I can parse this file with Python and get a dict object like this, which includes all the class parameters?

Example output:

param_dict = {'first_param':'test', 'second_param':'new'}

Thanks in Advance :)

Upvotes: 1

Views: 2238

Answers (3)

napuzba
napuzba

Reputation: 6288

You can use regular expression (straightforward but fragile)

import re
def parse(data):
    mm = re.search('\((.*?)\)', data,re.MULTILINE)
    dd = {}
    if not mm:
        return dd
    matches = re.finditer("\s*\$(.*?)\s*=\s*'(.*?)'", mm.group(1), re.MULTILINE)
    for mm in matches:
        dd[mm.group(1)] = mm.group(2)
    return dd

You can use it as follows:

import codecs
with codecs.open(filename,'r') as ff:
     dd = parse(ff.read())

Upvotes: 2

Dominic Cleal
Dominic Cleal

Reputation: 3205

Puppet Strings is a rubygem that can be installed on top of Puppet and can output a JSON document containing lists of the class parameters, documentation etc.

After installing it (see above link), run this command either in a shell or from your Python program to generate JSON:

puppet strings generate --emit-json-stdout init.pp

This will generate:

{
  "puppet_classes": [
    {
      "name": "test_module",
      "file": "init.pp",
      "line": 1,
      "docstring": {
        "text": "",
        "tags": [
          {
            "tag_name": "param",
            "text": "",
            "types": [
              "Any"
            ],
            "name": "first_param"
          },
          {
            "tag_name": "param",
            "text": "",
            "types": [
              "Any"
            ],
            "name": "second_param"
          }
        ]
      },
      "defaults": {
        "first_param": "'test'",
        "second_param": "'new'"
      },
      "source": "class test_module(\n    $first_param = 'test',\n    $second_param = 'new' ) {\n}"
    }
  ]
}

(JSON trimmed slightly for brevity)

You can load the JSON in Python with json.loads, and extract the parameter names from root["puppet_classes"]["docstring"]["tags"] (where tag_name is param) and any default values from root["puppet_classes"]["defaults"].

Upvotes: 4

Alex Harvey
Alex Harvey

Reputation: 15472

I don't know about the "best" way, but one way would be:

1) Set up Rspec-puppet (see google or my blog post for how to do that). 2) Compile your code and generate a Puppet catalog. See my other blog post for that.

Now, the Puppet catalog you compiled is a JSON document.

3) Visually inspect the JSON document to find the data you are looking for. Its precise location in the JSON document depends on the version of Puppet you are using.

4) You can now use Python to extract the data as a dictionary from the JSON document.

Upvotes: 0

Related Questions