Exponer información mediante salidas

Cuando creas una implementación, puede que quieras exponer propiedades clave de tus configuraciones o plantillas para que otras plantillas u otros usuarios las utilicen. Por ejemplo, puede que quieras exponer la dirección IP de una base de datos creada en una plantilla para que los usuarios puedan hacer referencia a la IP fácilmente al configurar sus propias plantillas.

Puedes usar la sección outputs de tu plantilla o configuración para definir una lista de pares clave-valor a los que pueden llamar los usuarios. En la sección de salidas, puede definir claves arbitrarias y asignarles como valor una referencia, una propiedad de plantilla o una variable de entorno. Los usuarios pueden usar las salidas para acceder a información clave sobre los recursos creados por la plantilla. Por ejemplo, puedes declarar una salida llamada databaseIP que haga referencia a la dirección IP de una instancia que aloja una base de datos. Los usuarios pueden hacer referencia a esa salida en otras plantillas de la misma implementación.

Antes de empezar

Ejemplo

Aquí tienes una plantilla de ejemplo con resultados:

mongodb.jinja
{% set MASTER = env["name"] + "-" + env["deployment"] + "-mongodb" %}
resources:
- name: {{ MASTER }}
  type: instance
  ...
outputs:
- name: databaseIp
  value: $(ref.{{ MASTER }}.network[0].ip)  # Treated as a string during expansion
- name: databasePort
  value: 88

En la sección de salidas se declaran dos propiedades: databaseIp y databasePort. databaseIp usa una referencia que se resuelve en la dirección IP de red del recurso principal, mientras que databasePort es un valor estático. En otra plantilla, puedes importar mongodb.jinja, usar la plantilla como tipo y llamar a las salidas. Por ejemplo:

imports:
- path: example/path/to/mongodb.jinja
  name: mongodb.jinja

resources:
- name: my_mongo
  type: mongodb.jinja
  properties:
    size: 100

- name: my_instance
  type: compute.v1.instance
  properties:
    
    databaseIp: $(ref.my_mongo.databaseIp)
    databasePort: $(ref.my_mongo.databasePort)

Declarar una salida

Declara una salida en una plantilla o una configuración definiendo una sección outputs: al mismo nivel que la sección resources:. Las claves de salida deben ser únicas en la plantilla o en la configuración.

Por ejemplo, una sección outputs: de muestra podría tener el siguiente aspecto:

...
outputs:
- name: databaseIp
  value: $(ref.my-first-vm.networkInterfaces[0].accessConfigs[0].natIP)
- name: machineType
  value: {{ properties['machineType'] }}
- name: databasePort
  value: 88

Así es como podrían aparecer los resultados en una plantilla completa:

{#
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: my-first-vm
  type: compute.v1.instance
  properties:
    zone: us-central1-a
    machineType: zones/us-central1-a/machineTypes/{{ properties['machineType'] }}
    disks:
    - deviceName: boot
      type: PERSISTENT
      boot: true
      autoDelete: true
      initializeParams:
        sourceImage: projects/debian-cloud/global/images/family/debian-11
    networkInterfaces:
    - network: global/networks/default
      accessConfigs:
      - name: External NAT
        type: ONE_TO_ONE_NAT

# Declare outputs here
outputs:
- name: databaseIp
  value: $(ref.my-first-vm.networkInterfaces[0].accessConfigs[0].natIP)
- name: machineType
  value: {{ properties['machineType'] }}
- name: databasePort
  value: 88


Los valores de salida pueden ser:

Usar las salidas de las plantillas

Para usar un resultado que se haya definido en una plantilla, importa y usa la plantilla que contiene el resultado como tipo. Por ejemplo, para usar las salidas definidas en una plantilla llamada template_with_outputs.jinja, debe importarse y usarse para crear un recurso:

# 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: template_with_outputs.jinja
  name: template.jinja

resources:
- name: my-first-vm
  type: template.jinja
  properties:
    machineType: n1-standard-1

outputs:
- name: databaseIp
  value: $(ref.my-first-vm.databaseIp)
- name: machineType
  value: $(ref.my-first-vm.machineType)
- name: databasePort
  value: $(ref.my-first-vm.databasePort)


Para llamar a una salida, usa el siguiente formato:

$(ref.RESOURCE.OUTPUT)
  • RESOURCE es el nombre del recurso creado por la plantilla. En el ejemplo anterior, es my-first-vm.

  • OUTPUT es el resultado declarado en la plantilla. En el ejemplo anterior, serían databaseIp y databasePort. Esta es la misma sintaxis que usas para declarar referencias. También puedes hacer referencia a elementos de una lista. Por ejemplo: $ref.template.property[0].

Cuando despliega la configuración, Deployment Manager la expande y, a continuación, sustituye las referencias a las salidas por los valores de salida.

Describir las salidas en los esquemas

En las plantillas que tienen esquemas asociados, puedes describir las propiedades de salida con más detalle. Deployment Manager no aplica ni valida ninguna información en la sección de salidas, pero puede ser útil usar esta sección para proporcionar más información sobre las salidas relevantes, lo que beneficiará a los usuarios que utilicen sus plantillas.

En el archivo de esquema, proporcione una sección de salidas que coincida con la salida de su plantilla. Por ejemplo:

...
outputs:
  databaseIp:
    description: Reference to ip address of your new cluster
    type: string
  databasePort:
    description: Port to talk on
    type: integer

Los usuarios pueden consultar su archivo de esquema para conocer el uso y el tipo de sus resultados.

Buscar valores de salida finales

Después de implementar plantillas que usen salidas, consulta los valores de salida finales viendo el diseño de la configuración de la implementación. Los valores de salida finales se indican mediante la propiedad finalValue. Todos los valores de salida se incluyen en este campo, incluidos los valores de salida de las plantillas anidadas. Por ejemplo:

layout: |
  resources:
  - name: vm_template
    outputs:
    - finalValue: 104.197.69.69
      name: databaseIp
      value: $(ref.vm-test.networkInterfaces[0].accessConfigs[0].natIP)
    properties:
      zone: us-central1-a
    resources:
    - name: datadisk-example-instance
      type: compute.v1.disk
    - name: vm-test
      type: compute.v1.instance
    type: vm_template.jinja
name: manifest-1455057116997

Evita las dependencias circulares

Tenga cuidado al crear plantillas en las que dos o más recursos dependan de las salidas de los demás. Deployment Manager no impide esta estructura, pero si las salidas provocan una dependencia circular, la implementación no se realizará correctamente. Por ejemplo, Deployment Manager acepta el siguiente fragmento, pero si el contenido de las plantillas provoca una dependencia circular, la implementación fallará:

resources:
- name: frontend
  type: frontend.jinja
  properties:
    ip: $(ref.backend.ip)
- name: backend
  type: backend.jinja
  properties:
    ip: $(ref.frontend.ip)

Como ejemplo de una dependencia circular en la que falla la implementación, supongamos que tanto frontend.jinja como backend.jinja tienen este aspecto:

resources:
- name: {{ env['name'] }}
  type: compute.v1.instance
  properties:
    zone: us-central1-f
    ...
    networkInterfaces:
    - network: global/networks/default
      accessConfigs:
      - name: External NAT
        type: ONE_TO_ONE_NAT
    metadata:
      items:
      - key: startup-script
        value: |
          #!/bin/bash
          export IP={{ properties["ip"] }}
      ...

outputs:
- name: ip
  value: $(ref.{{ env['name'] }}.networkInterfaces[0].accessConfigs[0].natIP)

Recuerda que ambos recursos usaban la propiedad de salida IP del recurso opuesto:

resources:
- name: frontend
  type: frontend.jinja
  properties:
    ip: $(ref.backend.ip)
- name: backend
  type: backend.jinja
  properties:
    ip: $(ref.frontend.ip)

Sin embargo, no se puede rellenar ninguno de los valores de IP porque ambas propiedades dependen de la existencia del otro recurso, lo que crea una dependencia circular. Aquí tienes la misma plantilla, pero totalmente desplegada:

resources:
- name: frontend
  type: compute.v1.instance
  properties:
    zone: us-central1-f
    ...
    networkInterfaces:
    - network: global/networks/default
      accessConfigs:
      - name: External NAT
        type: ONE_TO_ONE_NAT
    metadata:
      items:
      - key: startup-script
        value: |
          #!/bin/bash
          export IP=$(ref.backend.networkInterfaces[0].accessConfigs[0].natIP)
- name: backend
  type: compute.v1.instance
  properties:
    zone: us-central1-f
    ...
    networkInterfaces:
    - network: global/networks/default
      accessConfigs:
      - name: External NAT
        type: ONE_TO_ONE_NAT
    metadata:
      items:
      - key: startup-script
        value: |
          #!/bin/bash
          export IP=$(ref.frontend.networkInterfaces[0].accessConfigs[0].natIP)

Deployment Manager devuelve un error si intentas ejecutar la configuración:

 code: u'CONDITION_NOT_MET'
 message: u'A dependency cycle was found amongst backend, frontend.'>]>

Sin embargo, esta plantilla funcionaría si:

  1. frontend.jinja ha creado dos instancias de máquina virtual, vm-1 y vm-2.
  2. backend.jinja ha creado vm-3 y vm-4.
  3. vm-1 expuso su IP externa como salida y vm-4 usó esa salida.
  4. vm-3 expuso una IP externa como salida y vm-2 usó esa salida.

Siguientes pasos