Definir opções avançadas da API

Esta página descreve como configurar opções de configuração avançadas, como mapeamentos de entrada e propriedades virtuais, para fornecedores de tipos. Para saber mais sobre os tipos, leia a Vista geral dos tipos. Para saber mais sobre os fornecedores de tipos, leia o guia de uma página para a integração com o Deployment Manager.

Se estiver a tentar integrar uma API que não satisfaz os requisitos da API definidos pelo Deployment Manager, pode usar mapeamentos de entrada e propriedades virtuais para ajudar a resolver estas inconsistências. Os mapeamentos de entrada permitem-lhe fornecer mapeamentos explícitos de parâmetros da API onde existe ambiguidade, e as propriedades virtuais permitem-lhe expor propriedades arbitrárias que não existem nas APIs subjacentes para que possa simplificar a entrada e ocultar as complexidades da API dos seus utilizadores.

A implementação de opções de configuração avançadas requer um conhecimento profundo da API para a qual está a criar o fornecedor de tipos. Uma vez que cada API pode variar muito em relação às outras, esta página fornece orientações e exemplos gerais, mas não orientações específicas da API.

Antes de começar

Cenários comuns que requerem opções de configuração avançadas

O nome da propriedade é reutilizado com valores diferentes

Em determinadas APIs, o mesmo nome de propriedade ou parâmetro pode ser reutilizado em diferentes métodos, mas com valores diferentes. Por exemplo, uma API pode especificar que o parâmetro name para criar um recurso (um pedido POST) pode ter o valor foo/bar, enquanto o mesmo campo name para pedidos de atualização (PATCH ou PUT) pode exigir o valor foo/bar/baz.

Os valores das propriedades podem ser inferidos a partir da resposta da API

Determinados métodos da API requerem um valor gerado pelo servidor que é devolvido quando faz um pedido GET ao recurso. Por exemplo, uma API pode exigir um parâmetro etag para fazer pedidos de atualização quando altera um recurso. O etag valor muda após cada pedido de mutação, pelo que obtém o parâmetro etag atual fazendo um pedido GET ao recurso antes de fazer o pedido para atualizar o recurso.

Com os mapeamentos de entrada, pode indicar ao Deployment Manager que o campo etag pode ser obtido a partir do recurso da API. O Deployment Manager executa automaticamente um pedido GET para obter este valor quando um utilizador chama o método especificado nos mapeamentos de entrada.

Simplifique a introdução do utilizador

O Deployment Manager suporta propriedades virtuais, que são propriedades arbitrárias que pode expor aos seus utilizadores através do Deployment Manager para diferentes utilizações. Trate as propriedades virtuais como propriedades que não existem na API subjacente, mas são variáveis arbitrárias cujo valor pode injetar conforme necessário nos mapeamentos de entrada. Por exemplo, imagine que existe uma propriedade da API que tem de ser codificada em base64 antes de o valor ser enviado para a API subjacente. Em vez de pedir aos seus utilizadores que forneçam o valor na codificação base64, pode criar uma propriedade virtual que peça aos utilizadores o valor de texto simples e, em seguida, codificar o valor em base64 com mapeamentos de entrada e, finalmente, fornecer o resultado à API subjacente.

Especificar opções avançadas

Para especificar opções avançadas, indique a propriedade collectionOverrides quando criar o recurso Type Provider e defina mapeamentos de entrada ou propriedades virtuais para cada coleção de API conforme necessário.

Por exemplo, através da CLI gcloud, pode fornecer opções avançadas com um ficheiro YAML e fornecer o ficheiro YAML com o seu pedido type-providers create. Um exemplo de um ficheiro YAML pode ter o seguinte aspeto:

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]

Estas configurações indicam ao Deployment Manager:

  • Para o método create, procure o campo denominado emailAddress.displayName no corpo do recurso e defina o valor desse campo como a entrada do utilizador para a propriedade displayName na configuração do Deployment Manager. Assim, se um utilizador definir a respetiva configuração da seguinte forma:

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

    O Deployment Manager define o valor de emailAddress.displayName como John Doe.

  • Para o método update, o campo encontra-se no caminho do recurso em vez do corpo do recurso, mas é aplicado o mesmo mapeamento de entrada.

Especificar mapeamentos de entrada

Um mapeamento de entrada permite-lhe mapear ou inserir informações para determinados campos da API, de modo que o Deployment Manager possa interagir mais facilmente com a API subjacente, aliviando os seus utilizadores do ónus de compreender o comportamento subtil da API.

Use mapeamentos de entrada para simplificar a forma como os utilizadores interagem com a API. Por exemplo, pode usar mapeamentos de entradas para obter automaticamente valores gerados pelo servidor, como impressões digitais, IDs ou etags. Isto evita que os utilizadores tenham de fazer um pedido get separado no recurso sempre que quiserem fazer uma atualização.

Da mesma forma, também pode usar mapeamentos de entrada para processar situações ambíguas ou confusas em que o mesmo campo da API tem valores diferentes para métodos diferentes. Por exemplo, um pedido para criar um recurso pode exigir uma propriedade name que o utilizador pode especificar, mas a mesma API pode exigir uma propriedade name num formato diferente para métodos update. Pode usar mapeamentos de entrada para indicar ao Deployment Manager qual o valor adequado para cada método da API.

Para especificar mapeamentos de entrada para um fornecedor de tipos, indique a propriedade options.inputMappings. Pode definir mapeamentos de entrada que se aplicam a toda a API ou pode fornecer explicitamente mapeamentos de entrada para cada recolha:

# 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]...
            ]
        }
    }
]

Cada uma das partes importantes desta sintaxe é descrita abaixo.

Coleção

[SPECIFIC_COLLECTION] é a coleção de APIs à qual este mapeamento de entrada se aplica. Por exemplo, se estivesse a fornecer mapeamentos de entrada para um documento de descoberta da Google, como a API IAM Service Accounts, as coleções relevantes são projects.serviceAccounts e projects.serviceAccountKeys.

Para uma API que usa a especificação OpenAPI, o caminho de recolha pode ser /example-collection/{name}. Pode explorar um exemplo de OpenAPI funcional no repositório do GitHub do OpenAPI.

Nome do campo

"fieldName" é o atributo ou a propriedade da API para o qual quer especificar o mapeamento de entrada. Por exemplo, "fieldName": "fingerprint", "fieldName": "etag" e assim sucessivamente.

Localização

As propriedades da API podem aparecer como parâmetros no caminho do URL ou como parte do corpo do pedido ou da resposta. Especifique onde este mapeamento de entrada se aplica, como o URL PATH ou o pedido BODY como a localização. Os valores suportados incluem:

  • PATH
  • BODY
  • QUERY
  • HEADER

Correspondência de métodos

Especifique a que métodos se aplica este mapeamento de entrada. Use regex para especificar vários métodos. Por exemplo:

"methodMatch":"^create$"

Para especificações da OpenAPI, pode fazer o seguinte:

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

Valor

Especifique o valor que o Deployment Manager deve injetar para este campo. Este campo usa a notação JSONPath. Por exemplo, este mapeamento de entrada indica que, para o campo name, o Deployment Manager deve usar o valor fornecido pelo utilizador e injetá-lo no formato projects/$.project/topics/$resource.properties.topic:

"inputMappings":[
{
  "fieldName":"name",
  "location":"PATH",
  "methodMatch":"^post$",
  "value":"concat(\"projects/\", $.project, \"/topics/\", $.resource.properties.topic)"
}...
  • Quando usa $.resource.properties.[VARIABLE], define o valor de uma propriedade que um utilizador vai definir na respetiva configuração. Por exemplo, para $.resource.properties.topic, o valor será o valor fornecido pelo utilizador para a propriedade topic na respetiva configuração:

    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
    
  • Para fazer referência ao próprio recurso após um pedido get, use $.resource.self.[VARIABLE]. Por exemplo, para pedidos de atualização, se quiser obter a impressão digital mais recente, pode usar esta sintaxe para indicar ao Deployment Manager que execute um get e obtenha o valor:

    {
      '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'
    }
    

Usar propriedades virtuais

As propriedades virtuais são propriedades arbitrárias que pode expor aos seus utilizadores através do Deployment Manager. Estas propriedades não fazem parte da API subjacente, mas são variáveis arbitrárias que podem ser usadas para transmitir informações ou ocultar inconsistências da API dos seus utilizadores. Também pode fazer referência a propriedades virtuais nos seus mapeamentos de entrada.

As propriedades virtuais seguem o esquema JSON 4. Indique propriedades virtuais como parte do elemento options para uma coleção específica:

"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": [
    ...
   ]
  }

Num ficheiro de definição YAML, isto teria o seguinte aspeto:

- 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:
    ...

Por exemplo, considere uma API falsa que gera endereços de email. Vamos supor que a API tem um método para criar um email que recebe uma emailAddress.displayNamepropriedade. Quando um utilizador faz um pedido para criar um endereço de email, fornece um pedido da seguinte forma:

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

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

Agora, suponhamos que a API expõe uma forma de atualizar o endereço de email, mas o método para atualizar um email requer apenas a propriedade displayName, em vez da propriedade email.displayName:

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

{
  "displayName": "josh"
}

Como espera que os seus utilizadores forneçam este valor quando usam este tipo de fornecedor? Pode pedir-lhe que especifique a propriedade de forma diferente consoante a operação:

# 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

Em alternativa, pode criar uma propriedade virtual que tenha o mesmo valor, independentemente da operação, e, em seguida, usar mapeamentos de entrada para mapear a propriedade virtual para o parâmetro da API adequado. Para este exemplo, suponha que definiu uma propriedade virtual denominada displayName. Os seus mapeamentos de entrada podem ter o seguinte aspeto:

{
    "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":""
    }
}

Especificamente, a propriedade virtual é definida aqui:

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

No formato legível:

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

Agora, os seus utilizadores podem especificar displayName como a propriedade de nível superior para pedidos de atualização e criação, e o Deployment Manager saberá como mapear o valor corretamente.

# 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

O que se segue?