Expor informações através de resultados

Quando cria uma implementação, pode querer expor propriedades importantes das suas configurações ou modelos para que outros modelos ou utilizadores os consumam. Por exemplo, pode querer expor o endereço IP de uma base de dados criada num modelo para que os utilizadores possam referenciar facilmente o IP quando configurarem os seus próprios modelos.

Pode usar a secção outputs no seu modelo ou configuração para definir uma lista de pares de chave/valor que os utilizadores podem chamar. Na secção de saídas, define chaves arbitrárias e define o valor das chaves para uma referência, uma propriedade do modelo ou uma variável de ambiente. Os utilizadores podem consumir resultados para aceder a informações importantes sobre os recursos criados pelo modelo. Por exemplo, pode declarar uma saída denominada databaseIP que faça referência ao endereço IP de uma instância que aloja uma base de dados, e os utilizadores podem fazer referência a essa saída noutros modelos na mesma implementação.

Antes de começar

Exemplo

Segue-se um modelo de exemplo com 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

A secção de resultados declara duas propriedades: databaseIp e databasePort. databaseIp usa uma referência que é resolvida para o endereço IP de rede do recurso principal, enquanto databasePort é um valor estático. Noutro modelo, pode importar mongodb.jinja, usar o modelo como um tipo e chamar as saídas. Por exemplo:

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 uma saída

Declare uma saída num modelo ou numa configuração definindo uma secção outputs: no mesmo nível que a secção resources:. As chaves de saída têm de ser únicas no modelo ou na configuração.

Por exemplo, uma secção de outputs: de amostra pode ter este aspeto:

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

Veja como os resultados podem aparecer num modelo completo:

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


Os valores de saída podem ser:

Usar resultados de modelos

Para usar um resultado que foi definido num modelo, importe e use o modelo que contém o resultado como um tipo. Por exemplo, para usar resultados definidos num modelo denominado template_with_outputs.jinja, tem de ser importado e usado para criar um 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 chamar um resultado, use o seguinte formato:

$(ref.RESOURCE.OUTPUT)
  • RESOURCE é o nome do recurso criado pelo modelo. No exemplo acima, é my-first-vm.

  • OUTPUT é o resultado declarado no modelo. No exemplo acima, seria databaseIp e databasePort. Esta é a mesma sintaxe que usa para declarar referências. Também pode fazer referência a itens de listas, por exemplo: $ref.template.property[0].

Quando implementa a configuração, o Deployment Manager expande a configuração e, em seguida, substitui as referências às saídas pelos valores de saída.

Descrever resultados em esquemas

Para modelos com esquemas associados, pode descrever as propriedades de saída com mais detalhes. O Deployment Manager não aplica nem valida nenhuma informação na secção de resultados, mas pode ser útil usar esta secção para fornecer mais informações sobre os resultados relevantes, para benefício dos utilizadores que usam os seus modelos.

No ficheiro de esquema, indique uma secção de resultados que corresponda ao resultado no seu modelo. Por exemplo:

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

Os utilizadores podem consultar o seu ficheiro de esquema para compreender a utilização e o tipo de resultados.

Procurar valores de saída finais

Depois de implementar modelos que usam resultados, veja os valores de resultados finais vendo o esquema de configuração da implementação. Os valores de saída finais são indicados pela propriedade finalValue. Todos os valores de saída estão incluídos neste campo, incluindo os valores de saída de modelos aninhados. Por exemplo:

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

Evite dependências circulares

Tenha cuidado ao criar modelos em que dois ou mais recursos dependem dos resultados uns dos outros. O Deployment Manager não impede esta estrutura, mas se as saídas causarem uma dependência circular, a implementação não é feita com êxito. Por exemplo, o fragmento seguinte é aceite pelo Deployment Manager, mas, se o conteúdo dos modelos causar uma dependência circular, a implementação falha:

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

Como exemplo de uma dependência circular em que a implementação falha, suponha que frontend.jinja e backend.jinja tinham o seguinte aspeto:

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)

Recorde que ambos os recursos usaram a propriedade de saída IP do recurso oposto:

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

No entanto, não é possível preencher nenhum dos valores de IP porque ambas as propriedades dependem da existência do outro recurso, o que cria uma dependência circular. Aqui está o mesmo modelo, totalmente expandido:

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)

O Deployment Manager devolve um erro se tentar executar a configuração:

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

No entanto, este modelo funcionaria se:

  1. frontend.jinja criou duas instâncias de máquinas virtuais, vm-1 e vm-2.
  2. backend.jinja criou vm-3 e vm-4.
  3. A vm-1 expôs o respetivo IP externo como um resultado e a vm-4 usou esse resultado.
  4. A VM-3 expôs um IP externo como resultado e a VM-2 usou esse resultado.

O que se segue?