@cloudbusting/handlebars

Read cloudbusting inframodels and use as input for Handlebars templates

Usage no npm install needed!

<script type="module">
  import cloudbustingHandlebars from 'https://cdn.skypack.dev/@cloudbusting/handlebars';
</script>

README

@cloudbusting/handlebars

What is this package for?

This package helps you transform a Cloudbusting infraplan model to a set of files (e.g. Terraform or Cloudformation templates) using Handlebar templates.

How do I use it?

Use this package as the base for your cloudbuster.

First, create a new node.js project for your cloudbuster, and add this package to it:

npm install @cloudbusting/handlebars

Next, create a generator:

const generator = new Generator({
    templateDir: './templates',
    defaultDir: './.default',
    partialsDir: './partials',
    outputDir: './output',
    outputFileExt: '.txt',
    preprocess: resources => { }
});

generator.run('infraplans/test-infra.json');

You can pass the following options:

templateDir the directory that contains the template files. Defaults to ./templates.
defaultDir the directory that contains the template files. Defaults to ./.default.
partialsDir the directory that contains the template files. Defaults to ./partials.
outputDir the directory where to store the files in. Defaults to ./output.
outputFileExt the extension of the generated files. Defaults to .txt.
preprocess function that can be used to preprocess all resources before they are used.

Note: preprocessing can be used to normalize the resource names. Terraform for example does not support certain characters in resource names.

How does it work?

Basically, the generator will process each item through a handlebars template file with the same name.

So, the structure of the templates directory is important. It can contain the following:

.root directory

All files in defaultDir will be copied to the root of outputDir. This is useful for files that are always the same. For example, when using Terraform you can put files here that contain the provider, fixed variables, roles or resources that are not part of the infraplan's blueprint.

partials

The files under partialsDir will be registered as Handlebars partials under their full filename. Registration is recursive. So the file ./partials/tags/default.tf can be referenced in a Handlebars template file using {{> tags/default.tf}}.

templates files

Finally, templateDir should contain Handlebar template files for each resource type in your infraplan. It will look for a file that starts with the resourceType. E.g. when processing resource of type alb it will use alb.tf as template.

Data structure

The infraplan will be normalized using the @cloudbuster/modelbuilder package, so you can easily reference the item's parent, children and connections.

For example, if you have a blueprint with the following definition:

{
  "resourceType": "alb",
  "title": "Application Load Balancer",
  "icon": "/images/Elastic-Load-Balancing.svg",
  "rules": {
    "allowedConnections": [
      {
        "to": "ecs-fargate-container",
        "defaultName": "/path",
        "settings": [
          {
            "name": "healthcheckendpoint",
            "label": "Healthcheck endpoint",
            "type": "text",
            "required": true
          }
        ]
      }
    ]
  }
},
{
  "resourceType": "ecs-cluster",
  "title": "ECS Cluster",
  "icon": "/images/AWS-Fargate_light-bg.svg",
  "dimension": {
    "width": 200,
    "height": 150
  },
  "rules": {
    "allowedChildren": [
      "ecs-fargate-container"
    ]
  }
},
{
  "resourceType": "ecs-fargate-container",
  "title": "Fargate container",
  "icon": "/images/Amazon-Elastic-Container-Service_Service_light-bg.svg",
  "rules": {
    "allowedParents": ["ecs-cluster"],
    "settings": [
      {
        "name": "cpu",
        "type": "select",
        "label": "CPU units",
        "required": true,
        "options": "0.25 vCPU=256, 0.5 vCPU=512, 1 vCPU=1024, 2 vCPU=2048, 4 vCPU=4096"
      },
      {
        "name": "memoryLimitMiB",
        "type": "text",
        "label": "Memory (MiB)",
        "required": true,
        "hint": "Valid values vary per CPU. Check AWS docs",
        "pattern": "^[0-9]{3,5}quot;
      }
    ]
  }
}

Then the input object that is passed to the handlebars template for a ecs-fargate-container resource looks like this:

{
  "resourceId": "656adffd-1d4f-4e61-807b-d62f9444cdad",
  "resourceType": "ecs-fargate-container",
  "name": "winestore-api",
  "cpu": "256",
  "memoryLimitMiB": "512",
  "parent": {
    "resourceId": "19999a64-9b7f-45c1-810c-a458560ecdbc",
    "resourceType": "ecs-cluster",
    "name": "winestore"
  },
  "children": [],
  "incoming": [
    {
      "name": "/",
      "resourceId": "14910bcf-2717-48a8-a24d-d0a93fa7fec5",
      "resourceType": "connection",
      "healthcheckendpoint": "/api/health",
      "from": {
        "resourceId": "fbb60a11-a35a-411d-a1cb-893a2a652b54",
        "resourceType": "alb",
        "name": "www.wining.it"
      }
    }
  ],
  "outgoing": []
}

Running the package

When running the infraplan generator, the package will first clear the outputDir by removing all files with the outputFileExt extension.

Next, it will load the specified infraplan file and preprocess it.

Finally, for each item in the infraplan it will look for a file that starts with the item's resourceType and use that as a template for Handlebars.

So for example, when processing a resource with resourceType ecs-fargate-service, it will look for any filename that starts with this, and use that as the template file.

The result is written to the outputDir under the name ${resourceType}.${name}.${extension}.

Extra's

Handlebar helpers

This package includes and initializes the handlebar-helpers package.

See the Handlebars website for information on using Handlebars templates.