Usa módulos de plantilla

Los módulos de plantilla son archivos de ayuda que ejecutan funciones específicas para que tus plantillas sean más eficientes. Por ejemplo, puedes tener un módulo que genere nombres únicos para tus recursos. Deployment Manager puede ejecutar cualquier módulo escrito en Python o en Jinja.

Antes de comenzar

Crea un módulo de plantilla

Un módulo de plantilla se trata de igual manera que un archivo de plantilla normal y se puede escribir en Jinja o en Python.

Por ejemplo, la que sigue es una plantilla de ayuda que genera un nombre si se le da un prefijo o un sufijo.

Jinja


En Jinja, esta plantilla de ayuda (en el ejemplo, helpers/common.jinja) se vería de la siguiente manera:



    {%- macro GenerateMachineName(prefix='', suffix='') -%}        {{ prefix + "-" + suffix }}    {%- endmacro %}    

Luego, puedes importar esta plantilla y usarla como módulo. En tu plantilla en Jinja, podrías usar un módulo como el que sigue:

# 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.

    {% import 'helpers/common.jinja' as common %}
    resources:
    - name: {{ common.GenerateMachineName("myfrontend", "prod") }}      type: compute.v1.instance
      properties:
        zone: us-central1-f
        machineType: https://www.googleapis.com/compute/v1/projects/{{ env['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: https://www.googleapis.com/compute/v1/projects/{{ env['project'] }}/global/networks/default
          accessConfigs:
          - name: External NAT
            type: ONE_TO_ONE_NAT
    

Luego, la configuración debe importar ambos archivos (incluido el archivo helpers/common.jinja):

# Copyright 2015 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: helpers/common.jinja
    - path: vm-instance-example.jinja

    resources:
    - name: my-vm
      type: vm-instance-example.jinja
    

El servicio Deployment Manager expandirá la configuración y la configuración final presenta el siguiente aspecto:

resources:
    - name: myfrontend-prod
      type: compute.v1.instance
      properties:
        zone: us-central1-f
        machineType: https://www.googleapis.com/compute/v1/projects/myproject/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: https://www.googleapis.com/compute/v1/projects/myproject/global/networks/default
          accessConfigs:
          - name: External NAT
            type: ONE_TO_ONE_NAT
    

Python


En Python, la plantilla de ayuda (en el ejemplo, helpers/common.py) se vería de la siguiente manera:

# 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.

    """Generates name of a VM."""

    def GenerateMachineName(prefix, suffix):
      return prefix + "-" + suffix
    

Para usarlo en tu plantilla en Python, haz lo siguiente:

# 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.

    """Constructs a VM with imported module."""
    from helpers import common

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

    def GenerateConfig(context):
      """Generates configuration of a VM."""
      resources = [{
          'name': common.GenerateMachineName('myfrontend', 'prod'),
          'type': 'compute.v1.instance',
          'properties': {
              'zone': 'us-central1-f',
              'machineType': COMPUTE_URL_BASE + 'projects/' + context.env['project']
                             + '/zones/us-central1-f/machineTypes/f1-micro',
              'disks': [{
                  'deviceName': 'boot',
                  'type': 'PERSISTENT',
                  'boot': True,
                  'autoDelete': True,
                  'initializeParams': {
                      'sourceImage': COMPUTE_URL_BASE + 'projects/'
                                     'debian-cloud/global/images/family/debian-9'}
              }],
              'networkInterfaces': [{
                  'network': COMPUTE_URL_BASE + 'projects/' + context.env['project']
                             + '/global/networks/default',
                  'accessConfigs': [{
                      'name': 'External NAT',
                      'type': 'ONE_TO_ONE_NAT'
                  }]
              }]
          }
      }]
      return {'resources': resources}
    

Luego, la configuración debe importar ambos archivos (incluido el archivo helpers/common.py):

# Copyright 2015 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: helpers/common.py
    - path: vm-instance-example.py

    resources:
    - name: my-vm
      type: vm-instance-example.py
    

A continuación, verás un módulo de ayuda más complicado:

# Copyright 2015 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.
    """Helper methods for working with containers in config."""
    import common
    import default
    import yaml

    # Specific properties for this component, also see container_instance
    DCKRENV = default.DCKRENV
    DCKRIMAGE = default.DCKRIMAGE

    MANIFEST = """
    version: v1beta2
    containers:
      - name: %(name)s
        image: %(dockerImage)s
        ports:
          - name: %(name)s-port
            hostPort: %(port)i
            containerPort: %(port)i
        %(env)s
    """

    def GenerateManifest(context):
      """Generates a Container Manifest given a Template context.

      Args:
        context: Template context, which must contain dockerImage and port
            properties, and an optional dockerEnv property.

      Returns:
        A Container Manifest as a YAML string.
      """
      env = ""
      env_list = []
      if DCKRENV in context.properties:
        for key, value in context.properties[DCKRENV].iteritems():
          env_list.append({"name": key, "value": value})
      if env_list:
        env = "env: " + yaml.dump(env_list, default_flow_style=True)

      manifest_yaml_string = MANIFEST % {
          "name": context.env["name"],
          "dockerImage": context.properties[DCKRIMAGE],
          "port": context.properties[default.PORT],
          "env": env
      }
      return common.GenerateEmbeddableYaml(manifest_yaml_string)
    

Qué sigue