hashicorp / terraform-plugin-codegen-openapi

OpenAPI to Terraform Provider Code Generation Specification
Mozilla Public License 2.0
49 stars 6 forks source link

Consider permitting remote/URL references in `$ref` #89

Open austinvalle opened 8 months ago

austinvalle commented 8 months ago

Putting this issue out to gauge interest, which we track via 👍🏻's on the issue itself. If this is a use-case that is relevant to you we'd also love to see examples/OpenAPI specs to ensure we end on a good solution.

Background

Using $ref is helpful for splitting OpenAPI spec's into more manageable pieces that can be reused. A good overview of this feature can be found in this document from Swagger: https://swagger.io/docs/specification/using-ref

Currently, tfplugingen-openapi supports local references, i.e, where all the references exist in the same OpenAPI spec file. If you attempt to use the generator on a OpenAPI spec that is split into multiple files and contains a remote/URL reference you'll receive an error:

OpenAPI spec example

// .. rest of openapi spec
"paths": {
  "/pet": {
    "post": {
      "description": "Add a new pet to the store",
      "requestBody": {
        "content": {
          "application/json": {
              "schema": {
                  // URL reference!
                  "$ref": "https://petstore3.swagger.io/api/v3/openapi.json#/components/schemas/Pet"
              }
          },

Error from tfplugingen-openapi

time=2023-11-03T08:35:19.696-04:00 level=ERROR msg="error executing command" err="error building OpenAPI 3.x model: remote lookups are not permitted, please set AllowRemoteLookup to true in the configuration\ncomponent 'https://petstore3.swagger.io/api/v3/openapi.json#/components/schemas/Pet' does not exist in the specification\nschema build failed: reference 'https://petstore3.swagger.io/api/v3/openapi.json#/components/schemas/Pet' cannot be found at line 124, col 41"

Consideration

The fantastic downstream library we use pb33f/libopenapi does support this, we'd just need to consider any potential footguns and accept a potential base URL for resolving remote references from the generator config. URL references should just work:tm:, but would benefit from some testing.

// Retrieve from generator config?
baseUrl, _ := url.Parse("https://petstore3.swagger.io/api/v3")
doc, err := libopenapi.NewDocumentWithConfiguration(oasBytes, &datamodel.DocumentConfiguration{
    BaseURL:               baseUrl,
    AllowFileReferences:   true,
    AllowRemoteReferences: true,
})
if err != nil {
    return fmt.Errorf("error parsing OpenAPI spec file: %w", err)
}