出力を使用して情報を公開する

デプロイを作成するときに、他のテンプレートまたはユーザーが使用できるように、構成またはテンプレートの主要なプロパティの公開が必要になる場合があります。たとえば、テンプレート内に作成されたデータベースの IP アドレスを公開することで、各ユーザーが自身のテンプレートを構成するときに、その IP を簡単に参照できるようになります。

ユーザーが呼び出すことができる Key-Value ペアのリストを定義するには、テンプレートまたは構成の outputs セクションを使用します。outputs セクションで、任意のキーを定義し、キーの値を参照テンプレート プロパティ環境変数に設定します。ユーザーは出力を使用して、テンプレートで作成されたリソースの主要な情報にアクセスできます。たとえば、データベースをホストするインスタンスの IP アドレスを参照する databaseIP という出力を宣言すると、ユーザーは同じデプロイメントの他のテンプレートでこの出力を参照できます。

始める前に

出力を指定したサンプル テンプレートを以下に示します。

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 セクションは、databaseIpdatabasePort という 2 つのプロパティを宣言しています。databaseIp は、マスター リソースのネットワーク 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)

出力の宣言

outputs: セクションを resources: セクションと同じレベルで定義すれば、テンプレートまたは構成で出力の宣言を行うことができます。出力キーは、テンプレートまたは構成内で一意である必要があります。

outputs: セクションのサンプルを以下に示します。

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

完全なテンプレートでは、outputs は次のようになります。

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


次の値が出力可能です。

テンプレートからの出力を使用する

テンプレートで定義されている出力を使用するには、その出力がタイプとして含まれているテンプレートをインポートして使用します。たとえば、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 は、テンプレートで宣言されている出力です。上記の例では、databaseIp および databasePort となります。これは、参照を宣言する場合と同じ構文です。たとえば $ref.template.property[0] のようにして、リストアイテムを参照することもできます。

構成をデプロイすると、Deployment Manager によって構成が展開されて、出力への参照が出力値で置き換えられます。

スキーマで出力を記述する

付属スキーマのあるテンプレートの場合は、出力プロパティを詳細に記述できます。Deployment Manager は、outputs セクションの情報に関して適用や検証を行いません。しかし、このセクションを使用して出力に関する詳細情報を提供することは、テンプレートを使用するユーザーのメリットになるため意味があります。

スキーマ ファイルで、テンプレートの出力と合致する outputs セクションを指定します。次に例を示します。

...
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 つの仮想マシン インスタンスを作成する。
  2. backend.jinja は vm-3 と vm-4 を作成する。
  3. vm-1 がその外部 IP を出力として公開し、vm-4 がその出力を使用する。
  4. vm-3 が外部 IP を出力として公開し、vm-2 がその出力を使用する。

次のステップ