Skip to content

Dynamic Templating

MartinDonnelly edited this page Jul 24, 2019 · 2 revisions

Dynamic Templating

The template file format document sets forth in detail the YAML-based model used to define OTC toolchain designs. It should be noted that all the properties declared in a toolchain YAML file can be assigned dynamically computed values at runtime - as opposed to static literal values defined at design time. This is a powerful capability that enables you to create highly adaptive templates - e.g. templates containing simple logic that can process and apply parameter values that are supplied at the time a toolchain is created. For example, you may want your toolchain to be sufficiently adaptable so as to handle any of the supported source code repository providers, without having to create separate templates for GitHub, GitLab, Bitbucket and so on.

How It Works

You can make your toolchain templates more dynamic through the use of new $keywords in toolchain YAML file. Chief amongst these is the $env keyword. In its simplest form this keyword can be used to resolve variables in the runtime environment like url parameters, variables defined within the YML file etc. However $env also has extended dot notation which can be used to carry out boolean and ternary logical operations.

The following snippet shows an historic fragment of YAML from the Simple Toolchain Hosted curated toolchain template which defined the source repository tool integration as follows:

services:
  sample-repo:
    service_id: hostedgit
    parameters:
      repo_name: '{{toolchain.name}}'
      repo_url: 'https://github.com/open-toolchain/node-hello-world'
      type: clone
      has_issues: true
      enable_traceability: true

This binds the toolchain to a hostedgit source repository, but unfortunately this means the toolchain would not work if application code happens to reside within some alternative source repository system.

To overcome this problem the required repository identifier can now be provided as a parameter (source_provider) to the DevOps page - see the documentation on services parameters. As a result, this tool integration definition can be made more flexible by using the $env object to configure its settings based on the updated runtime context information. The previous YML fragment can thus be updated as follows:

services:
  sample-repo:
    service_id: >
      $env.source_provider ? $env.source_provider : 'hostedgit'
    parameters:
      repo_name: $env.toolchain.name
      repo_url: >
        $env.type === 'link' ? 
          $env.app_repo : 'https://github.com/open-toolchain/node-hello-world'
      source_repo_url: >
        $env.type === 'fork' || $env.type === 'clone' ? 
          $env.app_repo : 'https://github.com/open-toolchain/node-hello-world'
      type: $env.type || 'clone'
      has_issues: true
      enable_traceability: true

Things To Note

  1. First up, observe that the service_id property is no longer hardwired to 'hostedgit' but instead a JavaScript-style ternary operation is applied: $env.source_provider ? $env.source_provider : 'hostedgit'. In other words if a url parameter named source_provider is passed in, then use it to assign the service_id property value. Otherwise fall back to the original 'hostedgit' default value.
  2. Secondly the repo_name property uses the $env keyword to resolve the toolchain name from the YAML variable. This is the equivalent of the previous mustache expression: '{{toolchain.name}}'.
  3. Thirdly note that both repo_url and source_repo_url use more complex logic to resolve their respective property value. Let's take repo_url as an example: $env.type === 'link' ? $env.app_repo : 'https://github.com/open-toolchain/node-hello-world'. Basically if the type parameter in the url request is set to 'link' (meaning that the application repository already exists), then use the app_repo parameter as the repo_url value. Otherwise, the application repository does not exist so just use a sample node-hello-world repository instead.
  4. Finally a simple boolean operation is used to dynamically assign the value of the type property: type: $env.type || 'clone'. If a type parameter is present in the URL request, assign its value to the type property. If not, assign a default 'clone' literal value.

In Summary

Many of the popular OTC templates take advantage of the new $env feature to add more dynamic behavior to their CI/CD toolchain, e.g. Secure Kube Toolchain, Simple Helm Toolchain. Explore these templates for the latest examples of dynamic features.