API 詳細オプションの設定

このページでは、タイプ プロバイダの入力マッピングや仮想プロパティなどの詳細構成オプションの設定方法について説明します。タイプの詳細については、タイプの概要をご覧ください。タイプ プロバイダの詳細については、Deployment Manager との統合手順のまとめをお読みください。

Deployment Manager によって定義される API の要件を満たしていない API の統合を試みる場合は、入力マッピングと仮想プロパティを使用して、それらの不整合の解決に役立てることができます。入力マッピングにより、曖昧さがある API パラメータの明示的なマッピングを行い、仮想プロパティにより、基盤の API に存在しない任意のプロパティを公開できるため、入力を簡略化し、API の複雑さをユーザーから隠すことができます。

詳細構成オプションを実装するには、タイプ プロバイダを作成する API に関する深い理解が必要です。API はそれぞれ大きく異なることがあるため、このページでは特定の API のガイダンスではなく、一般的なガイダンスと例をご紹介します。

始める前に

詳細構成オプションが必要な一般的なシナリオ

プロパティ名が異なる値で再利用される

特定の API では、異なるメソッドで同じプロパティ名またはパラメータ名が再利用されることがありますが、異なる値で再利用されることはありません。たとえば、API でリソースの作成(POST リクエスト)のための name パラメータは値 foo/bar を持ち、更新リクエスト(PATCH または PUT)の同じ name フィールドに値 foo/bar/baz を必要とする場合があります。

プロパティ値が API レスポンスから推定できる

特定の API メソッドでは、リソースに対して GET リクエストを行うと返されるサーバーによって生成された値が必要です。たとえば、API でリソースの変更時に更新リクエストを行うための etag パラメータが必要な場合があります。etag の値は各変更リクエストの後に変更されるため、リソースを更新するリクエストを行う前に、リソースに対して GET リクエストを行うことによって現在の etag パラメータを取得します。

入力マッピングを使用すると、API リソースから etag フィールドを取得できることを Deployment Manager に伝えることができます。入力マッピングで指定したメソッドをユーザーが呼び出すと、Deployment Manager によって GET リクエストが自動的に実行され、この値が取得されます。

ユーザー入力の簡略化

Deployment Manager では任意のプロパティである仮想プロパティがサポートされており、さまざまな用途で Deployment Manager を通じてユーザーに公開できます。仮想プロパティは、基盤の API に存在せず、入力マッピングで必要に応じて値を挿入できる任意の変数であるプロパティとして扱います。たとえば、値が基盤の API に送信される前に base64 でエンコードされている必要がある API プロパティがあるとします。ユーザーに base64 でエンコードされた値を指定するように指示する代わりに、ユーザーに書式なしテキスト値の入力を求める仮想プロパティを作成し、その後、入力マッピングで値を base64 でエンコードして、最後にその結果を基盤の API に渡すことができます。

詳細オプションの指定

詳細オプションを指定するには、タイプ プロバイダ リソースの作成時に collectionOverrides プロパティを指定し、必要に応じて各 API コレクションの入力マッピングまたは仮想プロパティを定義します。

たとえば、gcloud CLI を使用して、YAML ファイルを使用する詳細オプションを指定し、type-providers create リクエストで YAML ファイルを指定できます。サンプル YAML ファイルは次のようになります。

collectionOverrides:
- collection: /emailAddresses/v1beta/people
  options:
    inputMappings:
    - methodMatch: ^create$
      fieldName: emailAddress.displayName
      value: $.resource.properties.displayName
      location: BODY
    - methodMatch: ^update$
      fieldName: displayName
      value: $.resource.properties.displayName
      location: PATH
    virtualProperties: |
      schema: http://json-schema.org/draft-04/schema#
      type: object
        properties:
          displayName:
            type: string
credential:
  basicAuth:
    user: [USERNAME]
    password: [PASSWORD]

この構成では、Deployment Manager に次のように指示します。

  • create メソッドの場合、リソース本文で emailAddress.displayName という名前のフィールドを探し、このフィールドの値を、Deployment Manager の構成で displayName プロパティへのユーザーの入力に設定します。ユーザーが次のように config を設定するとします。

     resources:
     - name: example
       type: myproject/emailAddress:/emailAddresses/v1beta/people
       properties:
       - displayName: John Doe
         ...
    

    Deployment Manager によって emailAddress.displayName の値が John Doe に設定されます。

  • update メソッドの場合、フィールドはリソース本文ではなくリソースパス内にありますが、同じ入力マッピングが適用されます。

入力マッピングの指定

入力マッピングにより、特定の API フィールドの情報のマッピングまたは挿入が可能になるため、Deployment Manager が基盤の API とよりシームレスにやり取りでき、ユーザーが API の細かな動作を理解しなければならない負担を解放します。

入力マッピングを使用してユーザーが API を操作する方法を簡略化します。たとえば、入力マッピングを使用して、フィンガープリント、ID、ETag などのサーバーで生成される値を自動的に取得できます。これによって、ユーザーが更新を行うたびにリソースに対して個別の get リクエストを実行する手間が省かれます。

同様に、同じ API フィールドでメソッドごとに値が異なる場合、入力マッピングを使用すると、あいまいさや混乱を回避できます。たとえば、リソースの作成リクエストではユーザーが指定できる name プロパティが必要で、同じ API の update メソッドでは異なる形式の name プロパティが必要になる場合があります。入力マッピングを使用すると、それぞれの API メソッドの適切な値を Deployment Manager に通知できます。

タイプ プロバイダに入力マッピングを指定するには、options.inputMappings プロパティを指定します。API 全体に適用する入力マッピングを定義することも、各コレクションに対して入力マッピングを明示的に指定することもできます。

# Input mappings for the entire API
"options": {
  "inputMappings": [
      {
          "fieldName": "[NAME]",
          "location":  "[PATH | BODY | QUERY | HEADER]",
          "methodMatch": "[REGEX_MATCHING_CERTAIN_METHODS]",
          "value": "[VALUE_TO_INJECT]"
      },
      {
          "fieldName": "[NAME]",
          "location":  "[PATH | BODY | QUERY | HEADER]",
          "methodMatch": "[REGEX_MATCHING_CERTAIN_METHODS]",
          "value": "[VALUE_TO_INJECT]"
      }
   ]
},
# Input mappings for specific collections
"collectionOverrides": [
    {
        "collection": "[SPECIFIC_COLLECTION]",
        "options": {
            "inputMappings": [
                {
                    "fieldName": "[NAME]",
                    "location": "[PATH | BODY | QUERY | HEADER]",
                    "methodMatch": "[REGEX_MATCHING_CERTAIN_METHODS]",
                    "value": "[VALUE_TO_INJECT]"
                },
                {
                    "fieldName": "[NAME]",
                    "location": "[PATH | BODY]",
                    "methodMatch": "[REGEX_MATCHING_CERTAIN_METHODS]",
                    "value": "[VALUE_TO_INJECT]"
                },
                ...[additional fields if necessary]...
            ]
        }
    }
]

この構文の重要な各部分について以下で説明します。

コレクション

[SPECIFIC_COLLECTION] はこの入力マッピングが適用される API コレクションです。たとえば、Google Discovery ドキュメントのための入力マッピングを用意する場合は、IAM Service Accounts API のように、関連するコレクションは projects.serviceAccountsprojects.serviceAccountKeys です。

OpenAPI 仕様を使用する API の場合、コレクションのパスは /example-collection/{name} などになります。OpenAPI GitHub リポジトリで、機能する OpenAPI の例を検索できます。

フィールド名

"fieldName" は、入力マッピングを指定する API 属性またはプロパティです("fieldName": "fingerprint", "fieldName": "etag" など)。

ロケーション

API プロパティは URL パス内のパラメータとして、またはリクエストやレスポンスの本文の一部として指定できます。URL PATH やリクエスト BODY など、この入力マッピングを適用する場所を指定します。次の値がサポートされています。

  • PATH
  • BODY
  • QUERY
  • HEADER

メソッド match

この入力マッピングを適用するメソッドを指定します。複数のメソッドを指定するには、正規表現を使用します。次に例を示します。

"methodMatch":"^create$"

OpenAPI 仕様の場合、次のように実行できます。

"methodMatch: ^(put|get|delete|post)$"

Deployment Manager でこのフィールドに挿入する必要がある値を指定します。このフィールドでは、JSONPath 表記を使用します。たとえば、この入力マッピングが伝えているのは、name フィールドに対して、Deployment Manager はユーザーが指定した値を取得して、projects/$.project/topics/$resource.properties.topic 形式でそれを挿入する必要があるということです。

"inputMappings":[
{
  "fieldName":"name",
  "location":"PATH",
  "methodMatch":"^post$",
  "value":"concat(\"projects/\", $.project, \"/topics/\", $.resource.properties.topic)"
}...
  • $.resource.properties.[VARIABLE] を使用する場合は、ユーザーが自分の構成で設定するプロパティの値を指定します。たとえば、$.resource.properties.topic の場合、値はユーザーが自分の構成の topic プロパティに指定する値になります。

    resources:
    - name: example
      type: example-type-provider:collectionA
      properties:
        topic: history # The value of "history" would be used for the `name` parameter because of the input mapping above
    
  • get リクエストの後にリソース自体を参照するには、$.resource.self.[VARIABLE] を使用しますたとえば、更新リクエストの場合、最新のフィンガープリントを取得するには、この構文を使用して、Deployment Manager に get を実行し、値を取得するように指示できます。

    {
      'fieldName': 'fingerprint',
      'location': 'BODY',
      'methodMatch': '^(put)$',
      # self represents the resource by doing a GET on it.
      # This mappings gets latest fingerprint on the request.
      # Final PUT Body will be
      # {
      #   "name": "my-resource-name",
      #   "fingerprint": "<server generated fingerprint>"
      # }
      'value': '$.resource.self.fingerprint'
    }
    

仮想プロパティの使用

仮想プロパティは、Deployment Manager によってユーザーに公開できる任意のプロパティです。これらのプロパティは基盤の API に含まれていませんが、情報を渡したり、API の不整合をユーザーから隠したりするために使用できる任意の変数です。入力マッピングの仮想プロパティを参照することもできます。

仮想プロパティは JSON 4 スキーマに準拠しています。仮想プロパティは、特定のコレクションの options の一部として指定します:

"collection": "[SPECIFIC_COLLECTION]",
  "options": {
   "virtualProperties": "schema: http://json-schema.org/draft-04/schema#\ntype: object\nproperties:\n  [PROPERTY]:\n    type: [DATA_TYPE]\n  [ANOTHER_PROPERTY]:\n    type: [ANOTHER_DATA_TYPE]n"
   "inputMappings": [
    ...
   ]
  }

YAML 定義ファイルでは、次のようになります。

- collection: projects.serviceAccounts
  options:
    virtualProperties: |
      schema: http://json-schema.org/draft-04/schema#
      type: object
      properties:
        a-property:
          type : string
        b-property:
          type : string
      required:
      - a-property
      - b-property
    inputMappings:
    ...

たとえば、メールアドレスを生成する架空の API を考えてみましょう。API に emailAddress.displayName プロパティを取得するメールを作成するためのメソッドがあるとします。ユーザーがメールアドレスを作成するリクエストを行う場合、次のようなリクエストを指定します。

POST https://example.com/emailAddresses/v1beta/people/

{
  "emailAddress": {
    "displayName": "john"
  }
}

ここで、たとえば API はメールアドレスを更新する方法を公開しているとしても、メールを更新するメソッドでは email.displayName プロパティではなく、displayName プロパティだけを必要とします。

POST https://example.com/emailAddresses/v1beta/people/john

{
  "displayName": "josh"
}

ユーザーがこのタイプのプロバイダを使用する場合、この値を指定するようにユーザーに指示するにはどうしたらよいのでしょうか。オペレーションに応じて異なるプロパティを指定するようにユーザーに依頼します。

# Creating an email
resources:
- name: example-config
  type: projects/test-project:emailAddresses
  properties:
    emailAddress:
      displayName: john

# Updating an email
resources:
- name: example-config
  type: projects/test-project:emailAddresses
  properties:
    displayName: john

あるいは、オペレーションに関係なく同じ値を取得する仮想プロパティを作成し、入力マッピングを使用して、仮想プロパティを適切な API パラメータにマッピングできます。この例では、displayName という名前の仮想プロパティを定義したとします。入力マッピングは次のようになります。

{
    "collectionOverrides":[
      {
        "collection":"emailAddresses",
        "options":{
          "inputMappings":[
            {
              "fieldName":"emailAddress.displayName",
              "location":"BODY",
              "methodMatch":"^create$",
              "value":"$.resource.properties.displayName"
            },
            {
              "fieldName":"displayName",
              "location":"BODY",
              "methodMatch":"^update$",
              "value":"$.resource.properties.displayName"
            }
          ],
          "virtualProperties":"schema: http://json-schema.org/draft-04/schema#\ntype: object\nproperties:\n  displayName:\n    type: string\nrequired:\n- displayName\n"
        }
      }
    ],
    "descriptorUrl":"https://example.com/emailAddresses/v1beta/",
    "options":{
      "nameProperty":""
    }
}

特に、仮想プロパティはここに定義されています。

"virtualProperties":"schema: http://json-schema.org/draft-04/schema#\ntype: object\nproperties:\n  displayName:\n    type: string\nrequired:\n- displayName\n"

人が読める形式では、次のようになります。

"virtualProperties":
  "schema: http://json-schema.org/draft-04/schema#\n
   type: object\n
   properties:\n
     displayName:\n
     - type: string\n
   required:\n
   - displayName\n"

これで、ユーザーが更新リクエストと作成リクエストの両方でトップレベルのプロパティとして displayNameを指定すると、Deployment Manager に値を正しくマッピングする方法が伝わります。

# Creating an email
resources:
- name: example-config
  type: projects/test-project:emailAddresses
  properties:
    displayName: john

# Updating an email
resources:
- name: example-config
  type: projects/test-project:emailAddresses
  properties:
    displayName: john

次のステップ