Como configurar opções avançadas de API

Nesta página, descrevemos como configurar as opções de configuração avançadas de provedores de tipos, como mapeamentos de entrada e propriedades virtuais. Para saber mais sobre tipos, leia Visão geral de tipos. Para saber mais sobre provedores de tipos, leia o Guia de uma página sobre como integrar o Deployment Manager.

Para integrar uma API que não cumpre os requisitos de API definidos pelo Deployment Manager, use os mapeamentos de entrada e as propriedades virtuais como auxílio para solucionar as inconsistências. Com os mapeamentos de entrada, você pode fornecer mapeamentos explícitos dos parâmetros da API com ambiguidades. As propriedades virtuais, por sua vez, permitem expor propriedades arbitrárias que não existem nas APIs subjacentes. Assim, você pode simplificar a entrada e ocultar as complexidades da API dos usuários.

Implementar as opções de configuração avançadas exige uma grande familiaridade com a API para a qual você está criando o provedor de tipos. Como as APIs podem ser muito diferentes umas das outras, esta página fornece orientações e exemplos gerais, e não para uma API específica.

Antes de começar

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

O nome da propriedade é reutilizado com valores diferentes

No caso de determinadas APIs, o mesmo nome de propriedade ou parâmetro é reutilizado em diferentes métodos, mas com valores diferentes. Por exemplo, uma API pode especificar que o parâmetro name usado na criação um recurso (uma solicitação POST) tenha o valor foo/bar, enquanto o mesmo campo name, nas solicitações de atualização (PATCH ou PUT), requer o valor foo/bar/baz.

Os valores de propriedade podem ser inferidos a partir da resposta da API

Alguns métodos de API exigem o valor gerado pelo servidor que é retornado quando é feita uma solicitação GET para o recurso. Por exemplo, uma API pode exigir um parâmetro etag para fazer solicitações de atualização ao modificar um recurso. O valor etag muda após cada solicitação de modificação. Portanto, para saber qual é o parâmetro etag atual, execute uma solicitação GET para o recurso, antes de fazer a solicitação para atualizar o recurso.

Ao usar mapeamentos de entrada, você pode informar ao Deployment Manager que o campo etag pode ser recuperado por meio do recurso da API. O Deployment Manager executa automaticamente uma solicitação GET para conseguir esse valor quando um usuário chama o método que especificado.

Simplificação da entrada de usuários

O Deployment Manager oferece suporte para propriedades virtuais. Essas são propriedades arbitrárias que podem ser expostas aos usuários para diferentes usos por meio do Deployment Manager. Trate as propriedades virtuais como se não existissem propriedades na API subjacente, mas sim variáveis arbitrárias cujo valor você pode inserir conforme necessário nos mapeamentos de entrada. Por exemplo, imagine que há uma propriedade de API que precisa ser codificada em base64 antes de enviar o valor para a API subjacente. Em vez de pedir aos usuários que forneçam o valor na codificação base64, você pode criar uma propriedade virtual que solicite aos usuários o valor do texto simples. Depois, codifique o valor em base64 com mapeamentos de entrada. Por fim, forneça o resultado para a API subjacente.

Como especificar as opções avançadas

Para especificar opções avançadas, forneça a propriedade collectionOverrides ao criar o recurso de Provedor de tipos. Depois, defina os mapeamentos de entrada ou as propriedades virtuais de cada coleção de APIs, conforme a necessidade.

Por exemplo, ao usar a ferramenta gcloud, você pode fornecer opções avançadas usando um arquivo YAML e fornecendo-o com a solicitação type-providers create. Veja abaixo um exemplo de como o arquivo YAML pode ser:

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]

Essas configurações passam as seguintes instruções ao Deployment Manager:

  • Para o método create, procure o campo chamado emailAddress.displayName no corpo do recurso e defina o valor desse campo como a entrada do usuário para a propriedade displayName na configuração do Deployment Manager. Então, se um usuário definir a configuração desta maneira:

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

    O Deployment Manager definirá o valor e emailAddress.displayName como "John Doe".

  • Para o método update, o campo está no caminho do recurso, em vez de no corpo, mas o mesmo mapeamento de entrada se aplica.

Como especificar mapeamentos de entrada

O mapeamento de entrada permite mapear ou inserir informações em determinados campos da API. Desse modo, o Deployment Manager consegue interagir de maneira mais harmoniosa com a API subjacente. Isso alivia a responsabilidade dos usuários de ter que entender o comportamento sutil da API.

Use mapeamentos de entrada para simplificar a interação entre os usuários e a API. Por exemplo, você pode usar mapeamentos de entrada para conseguir automaticamente valores gerados pelo servidor, como impressões digitais, códigos ou marcas de entidade. Isso poupa aos usuários o trabalho de executar uma solicitação get em separado no recurso sempre que desejarem fazer uma atualização.

Da mesma forma, você também pode usar os mapeamentos de entrada para lidar com situações ambíguas ou confusas, em que o mesmo campo da API tem valores distintos para métodos diferentes. Por exemplo, uma solicitação para criar um recurso pode exigir uma propriedade name especificada pelo usuário. No entanto, a mesma API também pode exigir uma propriedade name em formato diferente para os métodos update. Assim, você pode usar mapeamentos de entrada para informar ao Deployment Manager qual valor é apropriado para cada método de API.

Para especificar os mapeamentos de entrada de um provedor de tipos, forneça a propriedade options.inputMappings. Você pode definir os mapeamentos de entrada que se aplicam à API por inteiro ou fornecer explicitamente aqueles aplicáveis a cada coleção:

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

Todas as partes importantes dessa sintaxe estão descritas abaixo.

Coleção

[SPECIFIC_COLLECTION] é a coleção da API à qual o mapeamento de entrada se aplica. Por exemplo, se você estiver fornecendo mapeamentos de entrada para um documento do Google Discovery, como a IAM Service Accounts API, as coleções relevantes serão projects.serviceAccounts e projects.serviceAccountKeys.

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

Nome do campo

"fieldName" é o atributo ou propriedade da API para que você pretende especificar o mapeamento de entrada. Por exemplo, "fieldName": "fingerprint", "fieldName": "etag" e assim por diante.

Local

As propriedades da API podem aparecer como parâmetros no caminho do URL ou como parte do corpo da solicitação ou da resposta. Especifique como local onde o mapeamento de entrada se aplica, como o PATH do URL ou o BODY da solicitação. Os valores aceitos são:

  • PATH
  • BODY
  • QUERY
  • HEADER

Correspondência de métodos

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

"methodMatch":"^create$"

Para as especificações da OpenAPI, você pode fazer:

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

Valor

Especifique o valor que o Deployment Manager deve inserir nesse campo. O campo usa a notação JSONPath. Por exemplo, esse mapeamento de entrada instrui que, para o campo name, o Deployment Manager deve pegar o valor fornecido pelo usuário e inseri-lo no formato projects/$.project/topics/$resource.properties.topic:

"inputMappings":[
{
  "fieldName":"name",
  "location":"PATH",
  "methodMatch":"^post$",
  "value":"concat(\"projects/\", $.project, \"/topics/\", $.resource.properties.topic)"
}...
  • Ao usar $.resource.properties.[VARIABLE], você define o valor de uma propriedade que o usuário também definirá na própria configuração. Por exemplo, para $.resource.properties.topic, o valor será aquele fornecido pelo usuário para a propriedade topic na configuração do usuário:

    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 uma solicitação get, use $.resource.self.[VARIABLE]. Por exemplo, para solicitações de atualização, se você quer conseguir a impressão digital mais recente, pode usar essa sintaxe para instruir ao Deployment Manager que execute uma operação get e extraia 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'
    }
    

Como usar propriedades virtuais

Propriedades virtuais são propriedades arbitrárias que podem ser expostas aos usuários por meio do Deployment Manager. Essas propriedades não fazem parte da API subjacente. Elas são variáveis arbitrárias que podem ser usadas para transmitir informações ou ocultar dos usuários as inconsistências na API. Você também pode fazer referência a propriedades virtuais nos mapeamentos de entrada.

As propriedades virtuais seguem o esquema JSON 4. Forneça as propriedades virtuais como parte das options de 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": [
    ...
   ]
  }

Em um arquivo de definição de YAML, a aparência seria:

- 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, imagine uma API falsa que gera endereços de e-mail. Vamos supor que essa API tenha um método para criar e-mails que usa a propriedade emailAddress.displayName. Quando um usuário quer criar um endereço de e-mail, ele envia a seguinte solicitação:

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

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

Agora, digamos que a API exponha uma maneira de atualizar os endereços de e-mail, mas o método para essa atualização requer apenas a propriedade displayName, em vez da propriedade email.displayName:

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

{
  "displayName": "josh"
}

Como os usuários podem fornecer o valor ao usar esse provedor de tipos? Você pode pedir a eles que especifiquem a propriedade de uma maneira diferente, dependendo da 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

Como alternativa, você pode criar uma propriedade virtual que usa o mesmo valor, independentemente da operação. Depois, use os mapeamentos de entrada para mapear a propriedade virtual para o parâmetro da API apropriado. Neste exemplo, suponha que você definiu uma propriedade virtual chamada displayName. Os mapeamentos de entrada podem ter a seguinte aparência:

{
    "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 está definida aqui:

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

Em formato legível:

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

Agora, os usuários podem especificar displayName como a propriedade de nível superior para as solicitações de atualização e criação. 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

Próximas etapas

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Documentação do Cloud Deployment Manager