使用输出公开信息

创建部署时,您可能需要公开自己配置或模板的关键属性,以供其他模板或用户使用。例如,您可能希望公开在模板中创建的数据库的 IP 地址,以便用户在配置自己的模板时可以轻松引用 IP。

您可以使用模板或配置中的输出部分来定义用户可以调用的键/值对列表。在 outputs 部分中,您可以定义任意键并将键的值设置为引用模板属性环境变量。用户可以使用输出来访问模板所创建资源的关键信息。例如,您可以声明一个名为 databaseIP 的输出,该输出引用托管数据库的实例的 IP 地址,用户可以在同一部署的其他模板中引用该输出。

准备工作

示例

这是一个含 outputs 的示例模板:

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

outputs 部分声明了两个属性:databaseIpdatabasePortdatabaseIp 使用解析为主资源的网络 IP 地址的引用,而 databasePort 为静态值。在另一个模板中,您可以导入 mongodb.jinja,将模板用作类型,然后调用输出。例如:

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)

声明输出

通过在与 resources: 部分相同的级别定义 outputs: 部分,在模板或配置中声明输出。输出键在模板或配置中必须是唯一的。

例如,示例 outputs: 部分可能如下所示:

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

以下是输出在完整模板中的形式:



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

输出值可以是:

使用模板的输出

要使用模板中定义的输出,请导入并使用将输出作为类型的模板。例如,要使用名为 template_with_outputs.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: 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)

要调用输出,请使用以下格式:

$(ref.RESOURCE.OUTPUT)
  • RESOURCE 是模板创建的资源的名称。在上面的示例中,这是 my-first-vm

  • OUTPUT 是模板中声明的输出。在上面的示例中,这是 databaseIpdatabasePort。这与您用于声明引用的语法相同。您也可以引用列表项,例如:$ref.template.property[0]

部署配置时,Deployment Manager 将扩展配置,然后用输出值替换对输出的引用。

描述架构中的输出

对于采用附带架构的模板,您可以更详细地描述输出属性。Deployment Manager 不会强制执行或验证输出部分中的任何信息,使用此部分提供关于相关输出的更多信息可能利于使用模板的用户。

在架构文件中,提供输出部分,与模板中的输出匹配。例如:

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

用户可以引用您的架构文件,以了解输出的用法和类型。

查找最终输出值

部署使用输出的模板后,通过查看部署的配置布局来查看最终输出值。最终输出值由 finalValue 属性指明。此字段包含所有输出值,包括嵌套模板的输出值。例如:

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

避免循环依赖

创建模板时,若两个或多个资源的输出彼此依赖,则要注意。Deployment Manager 不会阻止该结构,但如果输出导致循环依赖,则部署无法成功部署。例如,Deployment Manager 可接受以下代码段,但如果模板的内容导致循环依赖,则部署将失败:

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

作为部署失败的循环依赖的示例,假设 frontend.jinja 和 backend.jinja 如下所示:

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)

请记住,两个资源都使用了相对资源的 IP 输出属性:

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

但是,任一 IP 值都不能填充,因为两个属性都依赖于其他资源的存在,从而创建循环依赖。这是完全展开的相同模板:

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 会返回错误:

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

但是,此模板在以下条件下有效:

  1. frontend.jinja 创建了 vm-1 和 vm-2 两个虚拟机实例。
  2. backend.jinja 创建了 vm-3 和 vm-4。
  3. vm-1 将其外部 IP 公开为输出且供 vm-4 使用。
  4. vm-3 将外部 IP 公开为输出供 vm-2 使用。

后续步骤