This is a blog with random OpenShift, Kubernetes, OpenStack and Linux related notes so I don't forget things. If you find something inaccurate or that could be fixed, please file a bug report here.

View on GitHub

Back to home

27 August 2018

Dissecting TripleO service templates (part 1)

by Juan Antonio Osorio Robles

The purpose of this blog post is to dissect TripleO service templates and explain what each part does and why it’s there.

Please note that it’s important to know how to write Heat templates before continuing this guide; else you’re gonna be quite confused and won’t get the most benefit out of this.

As I mentioned in a previous blog post, all the service definitions for TripleO live in tripleo-heat-templates. At the time of writing this, we have three main directories where we can find these service definitions:

But, looking at the services in these directories can be quite confusing… Even knowing that the role_data output is the main thing, and that it has several options, it’s hard to discern what all these sections actually do; which are mandatory and which are optional; and even, in what cases are parameters mandatory and in which cases they aren’t. There’s a lot of legacy in these templates, and so, I thought trying to give some explanation for them would be a good idea.

What’s the bare-minimum?

Before, digging into details, it’s always good to know what the bare-minimum is. So lets look at a very minimal service template, rhsm.yaml

heat_template_version: rocky

description: Configure Red Hat Subscription Management.

    default: {}
    type: json
    default: {}
    description: Dictionary packing service data
    type: json
    default: {}
    description: Mapping of service_name -> network name. Typically set
                 via parameter_defaults in the resource registry.  This
                 mapping overrides those in ServiceNetMapDefaults.
    type: json
    default: {}
    type: json
    default: ''
    description: Role name on which the service is applied
    type: string
    default: {}
    description: Parameters specific to the role
    type: json
    default: {}
    description: Mapping of service endpoint -> protocol. Typically set
                 via parameter_defaults in the resource registry.
    type: json
    default: {}
    description: Hash of ansible-role-redhat-subscription variables
                 used to configure RHSM.
    # The parameters contains sensible data like activation key or password.
    hidden: true
      - role_specific
    type: json

  # Merging role-specific parameters (RoleParameters) with the default parameters.
  # RoleParameters will have the precedence over the default parameters.
    type: OS::Heat::Value
      type: json
          - map_replace:
            - vars: RhsmVars
            - values: {get_param: [RoleParameters]}
          - values:
              RhsmVars: {get_param: RhsmVars}

    description: Role data for the RHSM service.
      service_name: rhsm
        tripleo::rhsm::firewall_rules: {}
      upgrade_tasks: []
      step_config: ''
        - name: Red Hat Subscription Management configuration
          vars: {get_attr: [RoleParametersValue, value, vars]}
          - include_role:
              name: redhat-subscription

Lets go piece by piece and explain what’s going on.

Version and description

As with any other heat template, you do need to specify the heat_template_version, and preferably give a description of what the stack/template does.


You’ll notice that there are a bunch of heat parameters defined in this template that are not necessarily used. This is because service templates are created in the form of a heat resource chain object. This type of objects can create a “chain” or a set of objects with the same parameters, and gather the outputs of them. So, eventually we pass the same mandatory parameters to the chain. This happens in the common/services.yaml file. Lets take a look and see how this is called:

    type: OS::Heat::ResourceChain
      resources: {get_param: Services}
      concurrent: true
        ServiceData: {get_param: ServiceData}
        ServiceNetMap: {get_param: ServiceNetMap}
        EndpointMap: {get_param: EndpointMap}
        DefaultPasswords: {get_param: DefaultPasswords}
        RoleName: {get_param: RoleName}
        RoleParameters: {get_param: RoleParameters}

Here we can see that the mandatory parameters for the services are the following:

So, if you’re writing a service template yourself, these are the parameters you have to copy into your template.

Aside from these parameters, you can define any other parameter yourself for the service, and in order for your service to consume the parameter, you need to pass them via parameter_defaults.

The role_data output

This is the sole output that will be read and parsed in order to get the relevant information needed from your service. It’s value must be a map, and from the aforementioned example, it minimally contains the following:

These are the bare-minimum sections of role_data you need to set up. However, you might have noticed that the example I linked above has another section called host_prep_data. This section is not mandatory, but it is one of the several ways you can execute Ansible tasks on the host in order to configure your service. These options powered by Ansible will be covered in the next part of this series.

Also note if the service is executing its configuration on bare-metal, step_config will execute in steps. So it’s important that the puppet manifests take steps into account (which you will note in the manifests in puppet-tripleo). If you want to understand what steps does TripleO execute, check out my blog post about it

tags: tripleo - openstack

Back to home