Template variables for configurable proxies

You're viewing Apigee X documentation.
View Apigee Edge documentation.

Apigee supports the use of property sets to specify template variables for ConfigurablePREVIEW API proxies in archive deployments. This feature enables customers to use string templates in their proxy configuration YAML files. When the archive is deployed to an Apigee environment, value substitutions are made for the template variables.

To learn more about configurable proxies, see ConfigurablePREVIEW API proxies.

Why use template variables in configurable proxies?

Template variables can be used to substitute for Apigee environment data that should not be hard-coded into your configurable proxy logic. For example, there are some fields in the proxy configuration, such as target.uri and jwt.issuer that may be environment-specific. Using template variables ensures that the correct substitutions are made when deployed to the specified environment, without the need to handle environment-switching logic in the configuration YAML file itself.

Template variables can also be used when the same values are used in fields across different proxies within the same archive. Using template variables to propagate the substituted values across numerous proxies is time-efficient and reduces the likelihood of manual error.

How to use template variables

Template variables use the string template ({{propertyset.params.var}}) to refer to variables in the configurable proxy. The variables are defined in a property set file (or files) that is scoped to a given Apigee environment. The property set file is then referenced in the configurable proxy config.yaml file. When the proxy archive is deployed to the Apigee environment, the values assigned in the property set for that environment are substituted and validated. For more information on environment scopes in property sets, see Using property sets.

Supported fields

The following configuration fields in the config.yaml support the use of template variables:

  • target.uri
  • jwt.remote_jwks.uri
  • jwt.audiences
  • jwt.forward_payload_header
  • jwt.issuer
  • locations[i].query
  • locations[i].header
  • locations[i].jwt_claim.name
  • http_match.path_template
  • http_request_transforms.* (all string fields)
  • target.service_account_authentication.access_token.scopes
  • target.service_account_authentication.id_token.audience

Sample implementation of template variables

The following example illustrates the steps required to use template variables in your configurable proxy's config.yaml, and highlights the benefits of using this feature in proxy development. Here we have an archive deployment defined as follows:

$SCM_ROOT/
  src/main/apigee/
    apiproxies/
      petstore/ // This folder name determines the proxy name
        config.yaml // A single file defining the configurable proxy
    environments/ //
      prod/ // environment name
        deployments.json
        resources/
          properties/
            params.properties // Property set file for the prod environment
      dev/
        ...

In this archive, the config.yamlcontains the following:

# config.yaml
basepath: "/v1"
consumer_authorization:  # API Key enforcement
  locations:
  - header: x-api-key
target:
  uri: https://www.petstore-dev.com
operations:
- id: getPets
  http_match:
  - path_template: "/pets"
    method: GET

In this example, the target.uri value listed is only applicable to the dev environment. In the prod environment, the target.uri value should be https://www.petstore.com. When promoting the proxy from dev to prod, proxy developers would need to manually change this field or include some logic for selecting the correct target per environment.

Variable templating eliminates the need to make manual changes or add evaluation logic to the proxy to accommodate changes between environments. If variables are used, the config.yaml can be written as follows:

# config.yaml
basepath: "/v1"
consumer_authorization:  # API Key enforcement
  locations:
  - header: x-api-key
target:
  uri: https://{{propertyset.params.target_host}}
operations:
- id: getPets
  http_match:
  - path_template: "/pets"
    method: GET

The target_host varriables are defined in two property sets files; one for dev and one for prod, as shown below:

# /dev/resources/properties/params.properties
target_host=www.petstore-dev.com
# /prod/resources/properties/params.properties
target_host=www.petstore.com

Because the property sets referenced in the config.yaml are environment-scoped, the correct value for target.uri will be substituted upon deployment of the archive to the chosen environment.

Limitations and best practices

Limitations and best practices for the use of template variables and property sets in ConfigurablePREVIEW API proxies are described in detail below.

Variable templating

The following limitations apply to the use of variable templating in ConfigurablePREVIEW API proxies:

  • The variable templating syntax supports simple value substitutions only. Syntax using conditionals, loops, etc., are not supported.
  • Variable templating can only be used for values corresponding to string-typed proto fields. Arbitrary text substitution is not supported, with string types validated upon deployment.
  • Each supported stringfield has a maximum of 3 variable references. For example, the following template would be rejected: {{propertyset.params.scheme}}://{{propertyset.params.host}}:{{ propertyset.params.port}}{{propertyset.params.path}}
  • Variable names cannot include dots (.) as these are not permitted characters in property set file or property names.

Property sets

The following limitations apply to the use of property set files in configurable config.yaml files:

  • For ConfigurablePREVIEW API proxies, only environment-scoped property set files are supported. The usage of property sets is subject to the same limits as in programmable API proxies.
  • Property sets that do not contain keys referred to in the proxy will result in errors, although unused key/value pairs in the property sets will be ignored in parsing.
  • Leading and trailing whitespaces in string templates are ignored. For example, {{  propertyset.params.target_host }} will be parsed into the key "propertyset.params.target_host", with whitespaces removed.
  • Variable keys in property sets for configurable proxy variables cannot contain { and/or }. For example, the following key type is not permitted: {{propertyset.params.target_{host}}}. This is a more restricted format than generally permitted for property sets used in programmable proxies.
  • Property sets are latin-1 encoded but unicode characters can be used with "escape" syntax. Developers must ensure correct encoding of any utf-8 characters used in property set variable keys.

Troubleshooting

The archive deployment service will send error message responses in the event that template variable validation fails, which should aid developers in identifying and correcting errors. Additionally, the Visual Studio Code extension provides syntax support for variable templating and should help developers identify common errors prior to deployment. [link to other docs?]

To check for configuration errors, use the following command to check the operation status:

$ gcloud alpha apigee operations describe b64c2665-b5ac-43cc-9e2d-232e8895c2ed

The command should return output similar to the following, with any errors identified and described in the error.message field:


Using Apigee organization 'myorg'
done: true
metadata:
  '@type': type.googleapis.com/google.cloud.apigee.v1.OperationMetadata
  operationType: INSERT
  state: FINISHED
  targetResourceName: /organizations/{org}/environments/{env}/archiveDeployments/{archive}
name: organizations/myorg/operations/b64c2665-b5ac-43cc-9e2d-232e8895c2ed
organization: myorg
response:

error:
  code: 3
  message: …
  
uuid: b64c2665-b5ac-43cc-9e2d-232e8895c2ed

The following sections describe several common misconfigurations and the corresponding error messages returned.

Property set format errors

Property set files that contain formatting errors will return an archive deployment error. See Create property sets for additional details about formatting property sets in Apigee X.

Variables defined incorrectly in property set

In the following example, deployment will result in variable not found errors. You can see that the target_host variable in the proxy config YAML file is not defined in the params.properties of the property set.

# config.yaml
...
target:
  uri: https://{{propertyset.params.target_host}}
...
# /prod/resources/properties/params.properties
host=www.petstore.com

The following error response is returned:

...
error:
  code: 3
  message: generic::invalid_argument: failed to validate proxy: file:config.yaml line:8 column:8
  unresolvable target URI "https://{{propertyset.params.target_host}}":
  invalid template "https://{{propertyset.params.target_host}}":
  property "target_host" not found in property set "params"
...

Invalid templates

In the following examples, incorrect or unbalanced double brackets generate an error response:

# config.yaml
...
target:
  uri: https://{{propertyset.params.target_host}
...
# config.yaml
...
target:
  uri: https://{{propertyset.params_{target_host}}
...

The following error response is returned:

...
error:
  code: 3
  message: generic::invalid_argument: failed to validate proxy: file:config.yaml line:8 column:8
  unresolvable target URI "https://{{propertyset.params.target_host}":
  invalid template "https://{{propertyset.params.target_host}": 1:41: invalid input text "}"
...

Invalid field values after template variable injection

The variable templating process will validate the template but not the field value itself. However, after template variable substitutions are made, the proxy config YAML file will be validated. An error response is returned if the final field values are invalid. For example, the following proxy config would result in a header with invalid characters, resulting in a validation error:

basepath: "/v1"
consumer_authorization:  # API Key enforcement
  locations:
  - header: "{{propertyset.params.apikey_header}}"
target:
  uri: https://www.petstore.com
operations:
- id: getPets
  http_match:
  - path_template: "/pets"
    method: GET
# /prod/resources/properties/params.properties
apikey_header=invalid{}characters:s

The following error response is returned:

...
error:
  code: 3
  message: generic::invalid_argument: failed to validate proxy: file:config.yaml line:4 column:13
  value resolved using properties [propertyset.params.apikey_header="invalid{}characters:s"] is invalid:
  file:config.yaml line:4 column:13 invalid header name:
  file:config.yaml line:4 column:13 "invalid{}characters:s" does not match the required format "^[-a-zA-Z0-9!#$%&'*+.^_`|~]+$"
...