iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
☕️

ecspresso Advent Calendar 2020 Day 5 - Template Syntax

に公開

This is Day 5 of the ecspresso Advent calendar, where we cover how to use ecspresso, a deployment tool for Amazon ECS.

Templating Configuration Files

The ecspresso configuration files (YAML format) and the service/task definition files (JSON format) act as templates processed by kayac/go-config at runtime.

A typical use case for deployment is injecting an image tag into the template. In the example below, the {{ must_env TAG }} part is replaced with the value of the environment variable TAG when ecspresso is executed.

{
    "containerDefinitions" : [
        {
            "name": "nginx",
            "image": "nginx:{{ must_env `TAG` }}",
            // ....
        }
    ],
    // ...
}

By following a workflow like the one below, you can register a task definition with a unique tag and deploy it to the service for each deployment without manually editing the definition files:

  1. Build the container image, push it to ECR, and assign a unique tag for each deployment.
    (Using repository tags or commit hashes is common.)
  2. Set that value to the environment variable TAG and execute ecspresso.

Available Template Syntax

ecspresso (go-config) actually uses Go's standard package text/template to render template files, which are then parsed as YAML/JSON. ecspresso provides the following template functions:

env

"{{ env `NAME` `default value` }}"

If the environment variable NAME is set, it replaces the placeholder with that value; otherwise, it uses default value.

must_env

"{{ must_env `NAME` }}"

Replaces the placeholder with the value of the environment variable NAME. If the environment variable is not set at runtime, ecspresso will panic and stop forcibly.

By using must_env for values that would cause problems if left undefined, you can prevent deployments in an unintended state.

json_escape

"{{ must_env `JSON_VALUE` | json_escape }}"

Escapes the value as a JSON string. This is used when you need to escape characters (such as ") that require escaping when embedded within a string.

Template Tips

Write so as not to break YAML or JSON as much as possible

For example, consider a case where you want to parameterize region and cluster in config.yaml.

If you simply apply the template syntax and write it as follows, the raw { will be recognized as the start of an object, making it impossible to evaluate the template itself as valid YAML.

region: {{ must_env `AWS_REGION` }}
cluster: {{ must_env `CLUSTER` }}

When used with ecspresso, there is no problem because it is processed in the order of "rendering the template" → "parsing as YAML/JSON". However, when editing the file with an editor, it may interfere with formatting.

By quoting it as follows, you can maintain a valid YAML state.

region: '{{ must_env `AWS_REGION` }}'
cluster: '{{ must_env `CLUSTER` }}'

If you want to write values that conflict with the template syntax

From Issue #32.

If you want to write the literal string {{.ID}}, you cannot write it directly because {{ }} will be processed as a template.

Although it looks a bit complex, you can work around this by writing an expression that outputs the string {{.ID}} itself.

"{{`{{.ID}}`}}"

Since text/template has a way to customize the start and end strings of the syntax, it should be possible to switch the characters used for the syntax via ecspresso's command-line arguments. (If you have a request, please let us know in an issue.)

If you want to perform processing that cannot be handled by simple value expansion alone

Task definitions actually used in production often become JSON files with hundreds of lines. For tasks with many sidecars, the same descriptions are repeatedly used in multiple container definitions, which tends to worsen maintainability during changes.

If you want to perform processing that is beyond the capabilities of ecspresso's templates, such as wanting to share multiple task or container definitions, please refer to Day 20: Generating Definition Files with Jsonnet.

If you want to check the state where the template has actually been evaluated

Please refer to the explanation of the render command on Day 12.

Things not covered here

There is a feature to refer to values defined in a Terraform State file (tfstate) and expand them within the template. Please refer to Day 19: Terraform tfstate integration.


Day 6 will explain how to roll back if a problem occurs during deployment.

https://zenn.dev/fujiwara/articles/ecspresso-20201206.md

Discussion