heat_template_version: rocky description: Configure hieradata overrides for specific nodes parameters: server: description: ID of the controller node to apply this config to type: string # Config specific parameters, to be provided via parameter_defaults # This would be a lookup of the node UUID as provided by dmidecode # to the json required for the node-specific hieradata # Note this needs to be a json blob e.g: # parameter_defaults: # NodeDataLookup: # {"AB4114B1-9C9D-409A-BEFB-D88C151BF2C3": {"foo": "bar"}, # "8CF1A7EA-7B4B-4433-AC83-17675514B1B8": {"foo2": "bar2"}} NodeDataLookup: type: json default: {} description: json containing per-node configuration map resources: NodeSpecificConfig: type: OS::Heat::SoftwareConfig properties: group: script inputs: - name: node_lookup config: | #!/bin/sh node_id=$(dmidecode --s system-uuid | awk 'match($0, \ /[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}/) \ { print substr($0, RSTART, RLENGTH) }' | tr '[:upper:]' '[:lower:]') # thanks to dmidecode 3.1, we have to handle both the upper case # and lower case versions of the UUID from dmidecode. LP#1816652 # upper for dmidecode < 3.1 and lower for dmidecode >= 3.1 node_id_upper=$(echo $node_id | tr '[:lower:]' '[:upper:]') # needed to handle where python lives function get_python() { command -v python3 || command -v python2 || command -v python || exit 1 } # Create a /etc/puppet/hieradata/UUID.json file to provide # the data of the NodeDataLookup parameter that matches the # system UUID echo $node_lookup | $(get_python) -c " import json import sys input = sys.stdin.readline() or '{}' cnt = json.loads(input) print(json.dumps(cnt.get('${node_id}', {}))) " > /etc/puppet/hieradata/${node_id}.json # handle upper case node id LP#1816652 echo $node_lookup | $(get_python) -c " import json import sys input = sys.stdin.readline() or '{}' cnt = json.loads(input) print(json.dumps(cnt.get('${node_id_upper}', {}))) " > /etc/puppet/hieradata/${node_id_upper}.json NodeSpecificDeployment: type: OS::Heat::SoftwareDeployment properties: name: NodeSpecificDeployment config: {get_resource: NodeSpecificConfig} server: {get_param: server} input_values: node_lookup: {get_param: NodeDataLookup} outputs: deploy_stdout: description: Deployment reference, used to trigger puppet apply on changes value: {get_attr: [NodeSpecificDeployment, deploy_stdout]}