Utiliser des modules de modèle

Les modules de modèle sont des fichiers d'aide qui exécutent des fonctions spécifiques afin d'augmenter l'efficacité de vos modèles. Un module peut par exemple générer des noms uniques pour vos ressources. Deployment Manager peut exécuter n'importe quel module rédigé en Python ou Jinja.

Avant de commencer

Créer un module de modèle

Un module de modèle est traité comme un fichier de modèle standard et peut être rédigé en Jinja ou en Python.

Par exemple, vous trouverez ci-dessous un modèle d'aide générant un nom avec un préfixe et un suffixe.

Jinja


En Jinja, ce modèle d'assistance (appelé helpers/common.jinja dans cet exemple) se présenterait comme suit:



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

Vous pouvez ensuite importer ce modèle et l'utiliser en tant que module. Dans votre modèle Jinja, cela donnerait l'exemple suivant :

# 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-11
    networkInterfaces:
    - network: https://www.googleapis.com/compute/v1/projects/{{ env['project'] }}/global/networks/default
      accessConfigs:
      - name: External NAT
        type: ONE_TO_ONE_NAT

La configuration doit ensuite importer les deux fichiers (dont le fichier 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

Le service Deployment Manager développe la configuration, qui ressemble au final à ceci :

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, le modèle d'aide (appelé helpers/common.py dans cet exemple) ressemblerait à ceci:

# 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

Pour l'utiliser dans votre modèle 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.

"""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-11'}
          }],
          'networkInterfaces': [{
              'network': COMPUTE_URL_BASE + 'projects/' + context.env['project']
                         + '/global/networks/default',
              'accessConfigs': [{
                  'name': 'External NAT',
                  'type': 'ONE_TO_ONE_NAT'
              }]
          }]
      }
  }]
  return {'resources': resources}

La configuration doit ensuite importer les deux fichiers (dont le fichier 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

Voici un module d'aide plus complexe :

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

Étapes suivantes