LogoLogo
Bonsai (0.13) DocsGitHubDiscord CommunityGarden Enterprise
Bonsai (0.13)
Bonsai (0.13)
  • Welcome to Garden!
  • 🌸Overview
    • How Garden Works
    • Core Concepts
    • Adopting Garden
    • Garden vs Other Tools
  • 🌳Use Cases
    • Isolated On-Demand Preview Environments
    • Fast, Portable CI Pipelines that Run Anywhere
    • Shift Testing Left
    • Local Development With Remote Clusters
    • Jumpstart your Internal Developer Platform
  • 🌻Getting Started
    • Quickstart Guide
    • Installing Garden
    • Next Steps
  • 💐Tutorials
    • Your First Project
      • 1. Create a Garden Project
      • 2. Pick a Kubernetes Plugin
      • 3. Add Actions
      • 4. Add Tests
      • 5. Code Syncing (Hot Reload)
      • 6. Next Steps
  • 🌿Using Garden
    • About
    • Configuration Overview
    • Projects
    • Dashboard
    • Actions
    • Tests
    • Runs
    • Workflows
    • Variables and templating
    • Config Templates
    • Using the CLI
    • Modules
  • Kubernetes Plugins
    • About
    • Remote K8s Plugin Configuration
      • 1. Create a Cluster
        • AWS
        • GCP
        • Azure
      • 2. Configure Container Registry
        • AWS
        • GCP
        • Azure
        • Docker Hub
      • 3. Set Up Ingress, TLS and DNS
      • 4. Configure the Provider
    • Local K8s Plugin Configuration
      • 1. Install Local Kubernetes
      • 2. Configure the Provider
    • Ephemeral K8s Plugin Configuration
      • 1. Configure the Provider
      • 2. Login to the Garden dashboard
      • 3. Configure Ingress (optional)
      • 4. Retrieve Kubeconfig (optional)
    • Actions
      • Build
        • Container
      • Deploy
        • Kubernetes
        • Helm
        • Container
        • PersistentVolumeClaim
        • ConfigMap
      • Run and Test
        • Kubernetes Pod
        • Helm Pod
        • Kubernetes Exec
        • Container
    • Guides
      • In-Cluster Building
      • Minimal RBAC Configuration for Development Clusters
      • Deploying to Production
      • Using a Registry Mirror
  • ☘️Terraform Plugin
    • About
    • Plugin Configuration
    • Actions
  • 🌹Pulumi Plugin
    • About
    • Plugin Configuration
    • Actions
  • 🌼Other Plugins
    • Container
    • Exec (local scripts)
  • 🌷Guides
    • Migrating to Bonsai
    • Migrating from Docker Compose to Garden
    • Deprecations and updating to Cedar
    • Code Synchronization
    • Connecting a local application to a Kubernetes cluster (Local Mode)
    • Environments and namespaces
    • Using Garden in CircleCI
  • 🪷Advanced
    • Using Remote Sources
    • Custom Commands
  • 🎋Reference
    • Providers
      • conftest-container
      • conftest-kubernetes
      • conftest
      • container
      • ephemeral-kubernetes
      • exec
      • hadolint
      • jib
      • kubernetes
      • local-kubernetes
      • octant
      • otel-collector
      • pulumi
      • terraform
    • Action Types
      • Build
        • container Build
        • exec Build
        • jib-container Build
      • Deploy
        • configmap Deploy
        • container Deploy
        • exec Deploy
        • helm Deploy
        • kubernetes Deploy
        • persistentvolumeclaim Deploy
        • pulumi Deploy
        • terraform Deploy
      • Run
        • container Run
        • exec Run
        • helm-pod Run
        • kubernetes-exec Run
        • kubernetes-pod Run
      • Test
        • conftest-helm Test
        • conftest Test
        • container Test
        • exec Test
        • hadolint Test
        • helm-pod Test
        • kubernetes-exec Test
        • kubernetes-pod Test
    • Template Strings
      • Project template context
      • Environment template context
      • Provider template context
      • Action (all fields) template context
      • Action spec template context
      • Module template context
      • Remote Source template context
      • Project Output template context
      • Custom Command template context
      • Workflow template context
      • Template Helper Functions
    • Commands
    • Project Configuration
    • ConfigTemplate Reference
    • RenderTemplate Reference
    • Workflow Configuration
    • Garden Containers on Docker Hub
    • Module Template Configuration
    • Module Types
      • configmap
      • conftest
      • container
      • exec
      • hadolint
      • helm
      • jib-container
      • kubernetes
      • persistentvolumeclaim
      • pulumi
      • templated
      • terraform
  • 🌸Misc
    • FAQ
    • Troubleshooting
    • Telemetry
    • New Garden Cloud Version
  • Contributing to Garden
    • Contributor Covenant Code of Conduct
    • Contributing to the Docs
    • Setting up your developer environment
    • Developing Garden
    • Config resolution
    • Graph execution
Powered by GitBook
On this page
  • How it works
  • Defining actions and workflows
  • Defining and referencing inputs
  • Action references within a templated action
  • Sharing templates
  • Defining modules
  • Further reading
  • Next steps

Was this helpful?

  1. Using Garden

Config Templates

PreviousVariables and templatingNextUsing the CLI

Last updated 2 months ago

Was this helpful?

Config templates are a way to define reusable abstractions for actions or workflows. This provides a powerful yet easy-to-use mechanism to tailor Garden's functionality to your needs, improve governance, reduce boilerplate, and provide higher-level abstractions to application developers.

How do they work? You can create customized templates for actions and workflows, and render them using kind: RenderTemplate resources. These templates allow you to define your own schemas and abstractions, which are then translated at runtime to one or more resources.

Config templates can be defined within a project, or in a separate repository that can be shared across multiple projects (using remote sources).

This feature has been updated in 0.13 to support actions and workflows, in addition to modules. The ModuleTemplate resource kind has been renamed to ConfigTemplate, and instead of templated Modules, there is now a specific RenderTemplate kind to render the templates. The older declarations will still work until version 0.14, and are converted at runtime.

How it works

We'll use the to illustrate how templates work. This example has a k8s-container template, that generates one Build action of type container for building an image, and one Deploy action of type kubernetes for deploying that image. A template like this is useful to customize the Kubernetes manifests for your services, but of course it's just one simple example of what you could do.

The template is defined like this:

kind: ConfigTemplate
name: k8s-container
inputsSchemaPath: schema.json

configs:
  - kind: Build
    type: container
    name: ${parent.name}
    description: ${parent.name} image

  - kind: Deploy
    type: kubernetes
    name: ${parent.name}
    description: ${parent.name} manifests

    dependencies:
      - build.${parent.name}

    manifests:
      ...

And it's used like this:

kind: RenderTemplate
template: k8s-container
name: my-service
inputs:
  containerPort: 8080
  servicePort: 80

First off, notice that we have a kind: ConfigTemplate, which defines the template, and then a kind: RenderTemplate which references and uses the ConfigTemplate via the template field. You can have any number of instances referencing the same template.

The sections below describe the example in more detail.

Defining actions and workflows

Each template can include one or more actions (Build, Deploy, Test or Run) or workflows (kind: Workflow) under the configs key. The schema for each action or workflow is exactly the same as for normal actions or workflows with just a couple of differences:

  • In addition to any other template strings available when defining modules, you additionally have ${parent.name}, ${template.name} and ${inputs.*} (more on inputs in the next section). It's important that you use one of these for the names of the actions, so that every generated action has a unique name..

  • You can set a path field on each config to any subdirectory relative to the directory where the RenderTemplate config is placed.

Defining and referencing inputs

It's possible to define a schema to validate inputs given to a ConfigTemplate. If no schema is defined any inputs are allowed.

{
  "type": "object",
  "properties": {
    "containerPort": {
      "type": "integer"
    },
    "servicePort": {
      "type": "integer"
    },
    "replicas": {
      "type": "integer",
      "default": 3
    }
  },
  "required": [
    "containerPort",
    "servicePort"
  ]
}

This schema says that the containerPort and servicePort inputs are required, and that you can optionally set a replicas value as well. Any JSON Schema with "type": "object" is supported, and users can add any parameters that templated actions and modules should specify. These could be ingress hostnames, paths, or really any flags that need to be customizable per action or module.

These values can then be referenced using ${inputs.*} template strings, anywhere under the configs and modules fields.

Note that special care needs to be taken when using template strings in the inputs field in a RenderTemplate config. Fields in the resulting configs from the template may need to be resolvable at different times, and using e.g. action references in input values may not work in all cases.

Escaping template strings

Sometimes you may want to pass template strings through when generating files, instead of having Garden resolve them. This could for example be handy when templating a Terraform configuration file which uses a similar templating syntax.

To do this, simply add an additional $ in front of the template string, e.g. $${var.dont-resolve-me}.

Action references within a templated action

In many cases, it's important for the different actions in a single template to depend on one another, and to reference outputs from one another. You do this basically the same way as in normal actions, but because action names in a template are generally templated themselves, it's helpful to look at how to use templates in action references.

Here's a section from the manifests in our example:

...
      containers:
        - name: main
          image: ${actions.build["${parent.name}"].outputs.deployment-image-id}
          imagePullPolicy: "Always"
          ports:
            - name: http
              containerPort: ${inputs.containerPort}

Notice the image field above. We use bracket notation to template the action name, whose outputs we want to reference: ${actions.build["${parent.name}"].outputs.deployment-image-id}. Here we're using that to get the built image ID of the ${parent.name} Build in the same template.

Note that for a reference like this to work, that action also needs to be specified as a dependency.

Sharing templates

If you have multiple projects it can be useful to have a central repository containing action and module templates, that can then be used in all your projects.

To do that, simply place your ConfigTemplate configs in a repository (called something like garden-templates) and reference it as a remote source in your projects:

apiVersion: garden.io/v1
kind: Project
...
sources:
  - name: templates
    repositoryUrl: https://github.com/my-org/garden-templates:stable

Garden will then scan that repo when starting up, and you can reference the templates from it across your project.

Defining modules

Modules are deprecated and this feature will be removed in version 0.14.

  • In addition to any other template strings available when defining modules, you additionally have ${parent.name}, ${template.name} and ${inputs.*} (more on inputs in the next section). It's important that you use one of these for the names of the modules, so that every generated module has a unique name..

  • You can set a path field on the module to any subdirectory relative to the templated module directory. The module directory will be created if necessary.

Generating files

Note: It's usually advisable to add the generated files to your .gitignore, since they'll be dynamically generated.

In our example, we render a set of Kubernetes manifests. Here's the relevant section in the template:

...
    generateFiles:
      - sourcePath: manifests.yml
        targetPath: .manifests.yml

This reads a source file from template/manifests.yml (the sourcePath is relative to the location of the template), and writes it to module/.manifests.yml (targetPath is relative to the templated module).

Instead of specifying sourcePath, you can also specify value to provide the file contents directly as a string.

Module references within a templated module

In many cases, it's important for the different modules in a single template to depend on one another, and to reference outputs from one another. You do this basically the same way as in normal modules, but because module names in a template are generally templated themselves, it's helpful to look at how to use templates in module references.

Here's a section from the manifests file in our example:

...
      containers:
        - name: main
          image: ${modules["${parent.name}-image"].outputs.deployment-image-id}
          imagePullPolicy: "Always"
          ports:
            - name: http
              containerPort: ${inputs.containerPort}

Notice the image field above. We use bracket notation to template the module name, whose outputs we want to reference: ${modules["${parent.name}-image"].outputs.deployment-image-id}. Here we're using that to get the built image ID of the ${parent.name}-image module in the same template.

Note that for a reference like this to work, that module also needs to be specified as a build dependency.

Further reading

Next steps

On the ConfigTemplate, the inputsSchemaPath field points to a standard file, which describes the schema for the inputs field on every action and module that references the template. In our example, it looks like this:

Each template can include one or more modules under the modules key. The schema for each module is exactly the same as for normal with just a couple of differences:

You can specify files that should be generated as modules are resolved, using the modules[].generateFiles field. These files can include any of the same template strings as when .

.

.

.

Take a look at our for more of an in-depth discussion on Garden concepts and capabilities.

🌿
templated-k8s-container example
JSON Schema
Modules
ConfigTemplate reference docs
RenderTemplate reference docs
templated-k8s-container example
Guides section
defining modules