Configure OpenAPI → Terraform Mapping
This is part of a series of notes about code generating a Terraform Provider using OpenAPI
Now that we have found all the possible REST resources that can be used, it would make sense to allow the user to specify which should be used to generate a Terraform Provider.
The tool I'm developing will initialize a config given a specification. For petstore, it looks like this:
$ tfpgen init examples/openapi/petstore.yml
api:
scheme: bearer_token
default_endpoint: https://api.example.com/
provider:
name: example
specfile: examples/openapi3/petstore.yaml
output:
Pet:
tf_type_name_suffix: pet
tf_type: resource
media_type: application/json
binding:
create:
path: /pet
method: POST
read:
path: /pet/{petId}
method: GET
update:
path: /pet/{petId}
method: POST
delete:
path: /pet/{petId}
method: DELETE
PetFindByStatus:
tf_type_name_suffix: pet_find_by_status
tf_type: data_source
media_type: application/json
binding:
index:
path: /pet/findByStatus
method: GET
PetFindByTags:
tf_type_name_suffix: pet_find_by_tags
tf_type: data_source
media_type: application/json
binding:
index:
path: /pet/findByTags
method: GET
StoreInventory:
tf_type_name_suffix: store_inventory
tf_type: data_source
media_type: application/json
binding:
index:
path: /store/inventory
method: GET
StoreOrder:
tf_type_name_suffix: store_order
tf_type: data_source
media_type: application/json
binding:
read:
path: /store/order/{orderId}
method: GET
User:
tf_type_name_suffix: user
tf_type: data_source
media_type: application/json
binding:
index:
path: /user/{username}
method: GET
UserLogin:
tf_type_name_suffix: user_login
tf_type: data_source
media_type: application/json
binding:
index:
path: /user/login
method: GET
tfpgen will exhaustively include data sources without regard for any actual data being there. In this case, it's prudent to remove the entire UserLogin key.
The Capital Case keys are how tfpgen initially identifies resources, discussed in these notes.
Here the user will have the opportunity to customize the terraform provider name (used as the package name as well as prefixes for each resource/data source). In the example, the resource names should be generated as example_pet
in package example
, with a repository name of terraform-provider-example
.
The binding key gives the user some flexibility with dealing with unconventional (or un-rails-y) API paths & methods. For data source resources, it configures how the data source works: by identity or for an entire collection.
Alternatives:
You could use OpenAPI extensions to decorate a spec with Terraform provider information. I experimented with this approach but found that the location of extended attributes in the document felt unnatural. I think this is because the document is keyed by paths and multiple paths constitute a resource.
© Brandon Croft.