hashicorp / terraform-plugin-codegen-openapi

OpenAPI to Terraform Provider Code Generation Specification
Mozilla Public License 2.0
53 stars 12 forks source link

Allow aliasing parameters to nested attributes #117

Open randomswdev opened 9 months ago

randomswdev commented 9 months ago

Use Cases or Problem Statement

In an OAS, it's possible for path or query parameters to have slightly different names then it's associated attribute in a create request body/response body schema.

The generator allow to specify aliases to map parameters to body's attributes. But the functionality supports only top level attributes, not attributes nested inside complex structures.

Consider, as an example, a kubernetes pod:

{
  "info": {
    "title": "Kubernetes",
    "version": "unversioned"
  },
  "openapi": "3.0.0",
  "paths": {
    "/apis/apps/v1/namespaces/{namespace}/daemonsets/{name}": {
      "get": {
...
      }
      "parameters": [
        {
          "description": "name of the DaemonSet",
          "in": "path",
          "name": "name",
          "required": true,
          "schema": {
            "type": "string",
            "uniqueItems": true
          }
        },
...
      ]
    }
...
  },
  "components": {
    "schemas": {
      "io.k8s.api.apps.v1.DaemonSet": {
        "description": "DaemonSet represents the configuration of a daemon set.",
        "properties": {
...
          "metadata": {
            "allOf": [
              {
                "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"
              }
            ],
            "default": {},
            "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata"
          },
...
      },
      "io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta": {
        "description": "ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create.",
        "properties": {
...
          "name": {
            "description": "Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names",
            "type": "string"
          },
...
    }
  }
}

The DaemonSet name in the path corresponds to the name attribute of the metadata attribute. So name is an attribute nested inside of the top-level metadata attribute. And this is currently not supported.

Proposal

Allow defining aliases using dot notation, to indicate a nesteda ttribute. For example, the daemon set specification would be:

# Ref: https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/daemonset_v1
provider:
  name: kubernetes

resources:
  daemonset_v1:
    create:
      path: /apis/apps/v1/namespaces/{namespace}/daemonsets
      method: POST
    read:
      path: /apis/apps/v1/namespaces/{namespace}/daemonsets/{name}
      method: GET
    update:
      path: /apis/apps/v1/namespaces/{namespace}/daemonsets/{name}
      method: PUT
    delete:
      path: /apis/apps/v1/namespaces/{namespace}/daemonsets/{name}
      method: DELETE
    schema:
      attributes:
        aliases:
          # Match 'namespace' parameter to 'namespace' in 'metadata'
          namespace: metadata.namespace
          name: metadata.name

Additional Information

Allowing to alias nested attributes means that the nested attribute has to change its computed_required_optional attributes, but also the elements on thwe path.

In the example above the 'metadata' attribute has to change to required (because it includes required path parameters and thus is required) and both 'namespace' and 'name' has to be changed to required.

Code of Conduct