File and directory templating with Inventory as Variable

🟑 Intermediate

template composer

This example illustrates several key aspects of the templating system Templating Generation:

git checkout origin/osp-web-configuration .
git checkout origin/example-template-gen-playbook-file-by-file .

Prerequisites

Steps

1. Create Inventories

This scenario uses two CSV inventories. The first contains site details (e.g. name and color):

templates/inventory/sites.csv
source;destination;siteLocation;backgroundColor
templates/sources/site;root/fribourg;fribourg;A1A1A1
templates/sources/site;root/lausanne;lausanne;FFD835
templates/sources/site;root/berne;berne;1DAA54

The second maps individual lights to their corresponding sites:

templates/inventory/devices.csv
source;destination;deviceName;siteLocation
templates/sources;root/fribourg;light01;fribourg
templates/sources;root/lausanne;light02;lausanne
templates/sources;root/berne;light03;berne
templates/sources;root/lausanne;light04;lausanne

2. Define the Playbook

The playbook includes two tasks:

  • One task processes the light inventory to generate the base structure per site.

  • The other uses a SOURCE_DESTINATION_MIRRORING task to render dashboards based on a combination of sites and lights.

templates/playbooks/example.playbook
{
    "priority": 0,
    "environments": [
        {
            "names": ["Example file-by-file"],
            "tasks": [
                {
                    "type": "CSV_INVENTORY",
                    "sourceInventory": "templates/inventory/sites.csv",
                    "rules": [
                        {
                            "source": {
                                "type": "CELL_PICKER",
                                "column": 0
                            },
                            "destination": {
                                "type": "CELL_PICKER",
                                "column": 1
                            }
                        }
                    ]
                },
                {
                    "type": "SOURCE_DESTINATION_MIRRORING",
                    "paths": [
                        {
                            "source": {
                                "relativePath": "templates/sources/dashboard.view.nunjucks",
                                "type": "RELATIVE"
                            },
                            "destination": {
                                "relativePath": "root/devices/light/monitoring",
                                "type": "RELATIVE"
                            }
                        },
                        {
                            "source": {
                                "relativePath": "templates/sources/dashboard.web.nunjucks",
                                "type": "RELATIVE"
                            },
                            "destination": {
                                "relativePath": "root/devices/light/monitoring",
                                "type": "RELATIVE"
                            }
                        }
                    ],
                    "variables": {
                        "csvAsVariables": [
                            {
                                "variableName": "lights",
                                "relativePath": "templates/inventory/devices.csv"
                            },
                            {
                                "variableName": "sites",
                                "relativePath": "templates/inventory/sites.csv"
                            }
                        ]
                    }
                }
            ]
        }
    ]
}

3. Dashboard Template

The template creates a widget for each light, leveraging the inner_join mechanism.

A matching entry is looked up from the site inventory using siteLocation. If found, a site-specific color (backgroundColor) is applied to the widget.

templates/sources/dashboard.view.nunjucks
{% set comma = joiner(',') %}
{
    "configuration": [
      {% for light in lights -%}{{ comma() }}
      {
        "type": "BasicInputOutputValue",
        "id": "{{ light.deviceName }}",
        "title": "{{ light.deviceName }}",
        "valueSubscriptions": {
            "values": [
                {
                    "id": "{{ light.destination }}.light",
                    "type": "BOOLEAN",
                    "right": "READ_WRITE"
                }
            ]
        },
        "basicWidgetSettings": {
            "label": "{{ light.deviceName }}",
            "showTooltip": true,
            "onValue": false,
            "offValue": true,
            "onIcon": "logout",
            "offIcon": "warning_amber",
            "onBackgroundColor": "#{{ sites | innerJoin(light, "siteLocation", "backgroundColor") | first }}",
            "offBackgroundColor": "#{{ sites | innerJoin(light, "siteLocation", "backgroundColor") | first }}",
            "layout": ["label", "icon"]
        }
    }
    {%- endfor %}
    ],
    "layout": {
        "lg": []
    }
}
templates/inventory/sites.csv
source;destination;siteLocation;backgroundColor

4. Execute the Playbook

Template generation is triggered using one of these Composer commands:

5. Inspect the Output

The resulting file includes widgets for each light. Background color values are pulled from the corresponding site’s inventory entry:

root/devices/light/monitoring/dashboard.view
{
  "type": "BasicInputOutputValue",
  "id": "light01",
  "title": "light01",
  "valueSubscriptions": {
    "values": [
      {
        "id": "root.fribourg.light",
        "type": "BOOLEAN",
        "right": "READ_WRITE"
      }
    ]
  },
  "basicWidgetSettings": {
    "label": "light01",
    "showLabel": true,
    "showTooltip": true,
    "showIcon": true,
    "showValue": false,
    "onValue": false,
    "offValue": true,
    "onIcon": "logout",
    "offIcon": "warning_amber",
    "onBackgroundColor": "#A1A1A1",
    "offBackgroundColor": "#A1A1A1"
  }
}