Impostazione delle opzioni avanzate dell'API

Questa pagina descrive come configurare le opzioni di configurazione avanzate, come le mappature di input e le proprietà virtuali, per i provider di tipi. Per saperne di più sui tipi, leggi la panoramica dei tipi. Per saperne di più sui provider di tipi, leggi la guida di una pagina all'integrazione con Deployment Manager.

Se stai tentando di integrare un'API che non soddisfa i requisiti API definiti da Deployment Manager, puoi utilizzare le mappature di input e le proprietà virtuali per risolvere queste incoerenze. Le mappature di input ti consentono di fornire mappature esplicite dei parametri API in caso di ambiguità, mentre le proprietà virtuali ti consentono di esporre proprietà arbitrarie che non esistono nelle API sottostanti, in modo da semplificare l'input e nascondere le complessità dell'API agli utenti.

L'implementazione delle opzioni di configurazione avanzate richiede una conoscenza approfondita dell'API per cui stai creando il provider di tipi. Poiché ogni API può variare notevolmente rispetto alle altre, questa pagina fornisce indicazioni ed esempi generali, ma non indicazioni specifiche per le API.

Prima di iniziare

  • Se vuoi utilizzare gli esempi di riga di comando in questa guida, installa lo strumento a riga di comando `gcloud`.
  • Se vuoi utilizzare gli esempi di API in questa guida, configura l'accesso API.
  • Configura l'accesso all'API v2beta se vuoi utilizzare gli esempi di API in questa guida.
  • Scopri come creare una configurazione.

Scenari comuni che richiedono opzioni di configurazione avanzate

Il nome della proprietà viene riutilizzato con valori diversi

In alcune API, lo stesso nome di proprietà o parametro potrebbe essere riutilizzato in metodi diversi, ma con valori diversi. Ad esempio, un'API potrebbe specificare che il parametro name per la creazione di una risorsa (una richiesta POST), potrebbe avere il valore foo/bar, mentre lo stesso campo name per le richieste di aggiornamento (PATCH o PUT) potrebbe richiedere il valore foo/bar/baz.

I valori delle proprietà possono essere dedotti dalla risposta API

Alcuni metodi API richiedono un valore generato dal server che viene restituito quando effettui una richiesta GET alla risorsa. Ad esempio, un'API potrebbe richiedere un parametro etag per effettuare richieste di aggiornamento durante la mutazione di una risorsa. Il valore etag cambia dopo ogni richiesta di mutazione, quindi ottieni il parametro etag corrente eseguendo una richiesta GET alla risorsa, prima di effettuare la richiesta di aggiornamento della risorsa.

Utilizzando le mappature di input, puoi indicare a Deployment Manager che il campo etag può essere recuperato dalla risorsa API. Deployment Manager esegue automaticamente una richiesta GET per ottenere questo valore quando un utente chiama il metodo specificato nelle mappature di input.

Semplificare l'input dell'utente

Deployment Manager supporta le proprietà virtuali, ovvero proprietà arbitrarie che puoi esporre agli utenti tramite Deployment Manager per usi diversi. Considera le proprietà virtuali come proprietà che non esistono nell'API sottostante, ma sono variabili arbitrarie il cui valore puoi inserire in base alle esigenze nelle mappature di input. Ad esempio, supponiamo che esista una proprietà API che deve essere codificata in base64 prima che il valore venga inviato all'API sottostante. Anziché chiedere agli utenti di fornire il valore in codifica base64, potresti creare una proprietà virtuale che richieda agli utenti il valore di testo normale, quindi codificare il valore in base64 con le mappature di input e, infine, fornire il risultato all'API sottostante.

Specificare le opzioni avanzate

Per specificare le opzioni avanzate, fornisci la proprietà collectionOverrides quando crei la risorsa del provider di tipi e definisci le mappature di input o le proprietà virtuali per ogni raccolta API in base alle tue esigenze.

Ad esempio, utilizzando gcloud CLI, puoi fornire opzioni avanzate utilizzando un file YAML e fornirlo con la richiesta type-providers create. Un file YAML di esempio potrebbe essere simile al seguente:

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]

Questa configurazione indica a Deployment Manager:

  • Per il metodo create, cerca il campo denominato emailAddress.displayName nel corpo della risorsa e imposta il valore del campo sull'input dell'utente per la proprietà displayName nella configurazione di Deployment Manager. Quindi, se un utente imposta la configurazione come segue:

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

    Deployment Manager imposterà il valore di emailAddress.displayName su John Doe.

  • Per il metodo update, il campo si trova nel percorso della risorsa anziché nel corpo della risorsa, ma viene applicata la stessa mappatura di input.

Specificare le mappature di input

Una mappatura di input ti consente di mappare o inserire informazioni per determinati campi API in modo che Deployment Manager possa interagire più facilmente con l'API sottostante, alleviando l'onere per gli utenti di comprendere il comportamento API sottile.

Utilizza le mappature di input per semplificare l'interazione degli utenti con l'API. Ad esempio, puoi utilizzare le mappature di input per ottenere automaticamente i valori generati dal server, come fingerprint, ID o etag. In questo modo, gli utenti non devono eseguire una richiesta get separata sulla risorsa ogni volta che vogliono apportare un aggiornamento.

Allo stesso modo, puoi utilizzare le mappature di input anche per gestire situazioni ambigue o confuse in cui lo stesso campo API ha valori diversi per metodi diversi. Ad esempio, una richiesta di creazione di una risorsa potrebbe richiedere una proprietà name che l'utente può specificare, ma la stessa API potrebbe richiedere una proprietà name in un formato diverso per i metodi update. Puoi utilizzare le mappature di input per indicare a Deployment Manager quale valore è appropriato per ogni metodo API.

Per specificare le mappature di input per un provider di tipi, fornisci la proprietà options.inputMappings. Puoi definire mappature di input che si applicano all'intera API oppure puoi fornire esplicitamente mappature di input per ogni raccolta:

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

Di seguito sono descritte le parti importanti di questa sintassi.

Raccolta

[SPECIFIC_COLLECTION] è la raccolta API a cui si applica questa mappatura di input. Ad esempio, se stai fornendo mappature di input per un documento di rilevamento di Google, come l'API Service Account IAM, le raccolte pertinenti sono projects.serviceAccounts e projects.serviceAccountKeys.

Per un'API che utilizza la specifica OpenAPI, il percorso della raccolta potrebbe essere /example-collection/{name}. Puoi esplorare un esempio OpenAPI funzionale nel repository GitHub OpenAPI.

Nome campo

"fieldName" è l'attributo o la proprietà API per cui vuoi specificare la mappatura di input. Ad esempio, "fieldName": "fingerprint", "fieldName": "etag" e così via.

Località

Le proprietà API possono essere visualizzate come parametri nel percorso dell'URL o come parte del corpo della richiesta o della risposta. Specifica dove si applica questa mappatura di input, ad esempio l'URL PATH o il BODY della richiesta come località. I valori supportati includono:

  • PATH
  • BODY
  • QUERY
  • HEADER

Corrispondenza del metodo

Specifica a quali metodi si applica questa mappatura di input. Utilizza le espressioni regolari per specificare più metodi. Ad esempio:

"methodMatch":"^create$"

Per le specifiche OpenAPI, puoi eseguire le seguenti operazioni:

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

Valore

Specifica il valore che Deployment Manager deve inserire per questo campo. Questo campo utilizza la notazione JSONPath. Ad esempio, questa mappatura di input indica che per il campo name, Deployment Manager deve prendere il valore fornito dall'utente e inserirlo nel formato projects/$.project/topics/$resource.properties.topic:

"inputMappings":[
{
  "fieldName":"name",
  "location":"PATH",
  "methodMatch":"^post$",
  "value":"concat(\"projects/\", $.project, \"/topics/\", $.resource.properties.topic)"
}...
  • Quando utilizzi $.resource.properties.[VARIABLE], imposti il valore di una proprietà che un utente imposterà nella sua configurazione. Ad esempio, per $.resource.properties.topic, il valore sarà il valore fornito dall'utente per la proprietà topic nella sua configurazione:

    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
    
  • Per fare riferimento alla risorsa stessa dopo una richiesta get, utilizza $.resource.self.[VARIABLE]. Ad esempio, per le richieste di aggiornamento, se vuoi ottenere l'ultima fingerprint, puoi utilizzare questa sintassi per indicare a Deployment Manager di eseguire un'operazione get e recuperare il valore:

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

Utilizzare le proprietà virtuali

Le proprietà virtuali sono proprietà arbitrarie che puoi esporre agli utenti tramite Deployment Manager. Queste proprietà non fanno parte dell'API sottostante, ma sono variabili arbitrarie che possono essere utilizzate per trasmettere informazioni o nascondere le incoerenze dell'API agli utenti. Puoi fare riferimento alle proprietà virtuali anche nelle mappature di input.

Le proprietà virtuali seguono lo schema JSON 4. Fornisci le proprietà virtuali come parte delle options per una raccolta specifica:

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

In un file di definizione YAML, questo aspetto è il seguente:

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

Ad esempio, considera un'API fittizia che genera indirizzi email. Supponiamo che l'API abbia un metodo per creare un'email che accetta una proprietà emailAddress.displayName. Quando un utente effettua una richiesta di creazione di un indirizzo email, fornisce una richiesta simile alla seguente:

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

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

Ora, supponiamo che l'API esponga un modo per aggiornare l'indirizzo email, ma il metodo per aggiornare un'email richieda solo la proprietà displayName, anziché la email.displayName proprietà:

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

{
  "displayName": "josh"
}

Come ti aspetti che gli utenti forniscano questo valore quando utilizzano questo provider di tipi? Potresti chiedere loro di specificare la proprietà in modo diverso a seconda dell'operazione:

# 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

In alternativa, puoi creare una proprietà virtuale che accetta lo stesso valore, indipendentemente dall'operazione, e poi utilizzare le mappature di input per mappare la proprietà virtuale al parametro API appropriato. Per questo esempio, supponiamo di aver definito una proprietà virtuale denominata displayName. Le mappature di input potrebbero essere simili alle seguenti:

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

In particolare, la proprietà virtuale è definita qui:

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

In formato leggibile:

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

Ora, gli utenti possono specificare displayName come proprietà di primo livello sia per le richieste di aggiornamento sia per quelle di creazione e Deployment Manager saprà come mappare correttamente il valore.

# 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

Passaggi successivi