Creating a Template

You can create a deployment using a configuration at any time, but as you create more complex configurations, you should create and use templates for more flexible and robust configurations.

A template is a separate file from your configuration that defines a set of resources. You import a template into your configuration and Deployment Manager expands the template and inlines the contents during deployment, leaving a cleaner, simpler configuration file. After it has been imported, you can use a template in the same way you use a resource type.

A template can use other templates and Deployment Manager recursively expands templates when they are used in a configuration, so that the final result after templates have been expanded would be as if you had written the configuration without templates. For example, a configuration with templates could look like this:

imports:
- path: vm-template.jinja

resources:
- name: vm-instance
  type: vm-template.jinja

After Deployment Manager expands the templates, the full configuration looks like this, without additional work on your part:

resources:
- name: vm-instance
  type: compute.v1.instance
  properties:
    disks:
    - deviceName: boot
      type: PERSISTENT
      boot: true
      autoDelete: true
      initializeParams:
        sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/family/debian-9
    machineType: https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-f/machineTypes/f1-micro
    networkInterfaces:
    - network: $(ref.a-new-network.selfLink)
      accessConfigs:
      - name: External NAT
        type: ONE_TO_ONE_NAT
    zone: us-central1-f

Next, you will take the configuration you created in step two, Create a Configuration, and create a template from the contents. Then, import and use the template in your configuration to create a new deployment.

At the end, your new deployment contains the same resources as your first deployment but the configuration file will be much simpler.

Writing Jinja2 or Python templates

You can write templates in your choice of Python or Jinja2. Python templates are more powerful and give you the option to programmatically create or manage your templates. If you are familiar with Python, use Python for your templates.

Jinja2 is a simpler but less powerful templating language that uses the same syntax as YAML. If you aren't familiar with Python or just want to write simple templates without messing with Python, use Jinja2. The rest of this guide offers examples in both Jinja and Python.

Python Templates

If you choose to write templates in Python, there are only two requirements for Python templates:

  • The template must define a method called GenerateConfig() or generate_config(). If you use both method names in the same template, the generate_config() method will take precedence.

  • The method must return a Python dictionary.

Other than that, it is up to you to generate the contents of your template. For examples of the methods you can use to write a Python template, see Creating a Basic Template.

Create your first template

Make a copy of the resources definition you created in step four, Using References, into a new file called vm-template.[jinja|py]. Choose the appropriate file extension based on whether you want to use Jinja or Python templates. Remember to replace [MY_PROJECT] with your own project ID:

Jinja

{#
Copyright 2016 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
#}

resources:
- name: the-first-vm
  type: compute.v1.instance
  properties:
    zone: us-central1-f
    machineType: https://www.googleapis.com/compute/v1/projects/[MY_PROJECT]/zones/us-central1-f/machineTypes/f1-micro
    disks:
    - deviceName: boot
      type: PERSISTENT
      boot: true
      autoDelete: true
      initializeParams:
        sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/family/debian-9
    networkInterfaces:
    - network: $(ref.a-new-network.selfLink)
      accessConfigs:
      - name: External NAT
        type: ONE_TO_ONE_NAT

Python

# Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Creates the virtual machine."""

COMPUTE_URL_BASE = 'https://www.googleapis.com/compute/v1/'


def GenerateConfig(unused_context):
  """Creates the first virtual machine."""

  resources = [{
      'name': 'the-first-vm',
      'type': 'compute.v1.instance',
      'properties': {
          'zone': 'us-central1-f',
          'machineType': ''.join([COMPUTE_URL_BASE, 'projects/[MY_PROJECT]',
                                  '/zones/us-central1-f/',
                                  'machineTypes/f1-micro']),
          'disks': [{
              'deviceName': 'boot',
              'type': 'PERSISTENT',
              'boot': True,
              'autoDelete': True,
              'initializeParams': {
                  'sourceImage': ''.join([COMPUTE_URL_BASE, 'projects/',
                                          'debian-cloud/global/',
                                          'images/family/debian-9'])
              }
          }],
          'networkInterfaces': [{
              'network': '$(ref.a-new-network.selfLink)',
              'accessConfigs': [{
                  'name': 'External NAT',
                  'type': 'ONE_TO_ONE_NAT'
              }]
          }]
      }
  }]
  return {'resources': resources}

Create a second template

Create a file named vm-template-2.[jinja|py] and add the following contents. Remember to replace [MY_PROJECT] with your own project ID:

Jinja

{#
Copyright 2016 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
#}

resources:
- name: the-second-vm
  type: compute.v1.instance
  properties:
    zone: us-central1-f
    machineType: https://www.googleapis.com/compute/v1/projects/[MY_PROJECT]/zones/us-central1-f/machineTypes/g1-small
    disks:
    - deviceName: boot
      type: PERSISTENT
      boot: true
      autoDelete: true
      initializeParams:
        sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/family/debian-9
    networkInterfaces:
    - network: $(ref.a-new-network.selfLink)
      accessConfigs:
      - name: External NAT
        type: ONE_TO_ONE_NAT

Python

# Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Creates the virtual machine."""

COMPUTE_URL_BASE = 'https://www.googleapis.com/compute/v1/'


def GenerateConfig(unused_context):
  """Creates the second virtual machine."""

  resources = [{
      'name': 'the-second-vm',
      'type': 'compute.v1.instance',
      'properties': {
          'zone': 'us-central1-f',
          'machineType': ''.join([COMPUTE_URL_BASE, 'projects/[MY_PROJECT]',
                                  '/zones/us-central1-f/',
                                  'machineTypes/g1-small']),
          'disks': [{
              'deviceName': 'boot',
              'type': 'PERSISTENT',
              'boot': True,
              'autoDelete': True,
              'initializeParams': {
                  'sourceImage': ''.join([COMPUTE_URL_BASE, 'projects/',
                                          'debian-cloud/global',
                                          '/images/family/debian-9'])
              }
          }],
          'networkInterfaces': [{
              'network': '$(ref.a-new-network.selfLink)',
              'accessConfigs': [{
                  'name': 'External NAT',
                  'type': 'ONE_TO_ONE_NAT'
              }]
          }]
      }
  }]
  return {'resources': resources}

Import your templates

Go back to your configuration, two-vms.yaml. At the top of the file, import your template by adding the imports string, followed by the relative path to the template file. Then, replace the properties of your resources with the name of the templates.

Jinja

# Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

imports:
- path: vm-template.jinja
- path: vm-template-2.jinja

resources:
- name: vm-1
  type: vm-template.jinja
- name: vm-2
  type: vm-template-2.jinja
- name: a-new-network
  type: compute.v1.network
  properties:
    IPv4Range: 10.0.0.1/16

Python

# Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

imports:
- path: vm-template.py
- path: vm-template-2.py

resources:
- name: vm-1
  type: vm-template.py
- name: vm-2
  type: vm-template-2.py
- name: a-new-network
  type: compute.v1.network
  properties:
    IPv4Range: 10.0.0.1/16

Resource Names

When you use a template, your resource names are defined using the name field provided in the template, not the name in the configuration file.

For example, in this case, the virtual machine instances are created using the names in the templates you created, “the-first-vm” and “the-second-vm.” The values “vm-1” and "vm-2," defined in the configuration, are used to name an instantiation of the template, but are not resource names, unless you decide to use environment variables to set both names to be the same.

Save your configuration and deploy it!

gcloud deployment-manager deployments create deployment-with-templates --config two-vms.yaml

View your deployment

gcloud deployment-manager deployments describe deployment-with-templates

Also, you can use the deployment’s manifest to see the original configuration with the templates and the expanded configuration which includes the contents of the templates. Remember, to get a manifest, take the manifest-TIMESTAMP value from the output above, and provide it in the following command:

gcloud deployment-manager manifests describe manifest-TIMESTAMP --deployment deployment-with-templates

Great, you created a deployment using a template! Next, see how to create configurations with templates that call other templates.

Delete Your Deployment

Compute Engine resources incur charges, so you should delete this deployment, as it is no longer necessary for future steps. Deleting this deployment deletes all the resources in this deployment as well. If you leave the deployment around, you will run into conflicts with future examples.

To delete this deployment:

gcloud deployment-manager deployments delete deployment-with-templates

Next: Using Multiple Templates

Related topics

Was this page helpful? Let us know how we did:

Send feedback about...

Cloud Deployment Manager Documentation