Skip to content

Commit

Permalink
Add a terraform provider (#13)
Browse files Browse the repository at this point in the history
Using https://github.com/dikhan/terraform-provider-openapi,
building a Terraform provider.

The built-in gRPC-gateway openapi support has some differences
from what the provider expects. Build our own for now.

List of known additions that have to be added:

- required Get method for Terraform resources.
- added Apply (PUT) method for updating resources (could probably be
  replaced with json merge-patch).
- Addition of an "id" field, since the provider generator does not have
  a first-class understanding of path fields.

Expected follow-up work includes:

- figuring out how to require the "id" parameter during resource create.
  - especially nested resources: probably have to use the resource model
    to extract parent information and pass that via reference,
constructing resource paths by reading the parents.
  • Loading branch information
toumorokoshi authored Jul 2, 2024
1 parent fd73f48 commit 125b45c
Show file tree
Hide file tree
Showing 27 changed files with 1,875 additions and 1,427 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
.idea
main
terraform-provider-bookstore
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ flowchart LR

## User Guide

Building the proto and openapi files:

```
go run main.go -i ./example/bookstore/bookstore.yaml -o ./example/bookstore/bookstore.yaml.output.proto
```

Building the Terraform provider:

```
go run example/terraform/main.go
```
15 changes: 11 additions & 4 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/aep-dev/aepc/parser"
"github.com/aep-dev/aepc/schema"
"github.com/aep-dev/aepc/validator"
"github.com/aep-dev/aepc/writer/openapi"
"github.com/aep-dev/aepc/writer/proto"
"github.com/spf13/cobra"
"google.golang.org/protobuf/encoding/protojson"
Expand Down Expand Up @@ -72,13 +73,19 @@ func ProcessInput(inputFile, outputFile string) error {
return fmt.Errorf("error parsing service: %w", err)
}
proto, _ := proto.WriteServiceToProto(ps)

err = WriteFile(outputFile, proto)
protoFile := fmt.Sprintf("%s.proto", outputFile)
err = WriteFile(protoFile, proto)
if err != nil {
return fmt.Errorf("error writing file: %w", err)
}
fmt.Printf("output proto file: %s\n", protoFile)
openapi, _ := openapi.WriteServiceToOpenAPI(ps)
openapiFile := fmt.Sprintf("%s.openapi.json", outputFile)
err = WriteFile(openapiFile, openapi)
if err != nil {
return fmt.Errorf("error writing file: %w", err)
}
fmt.Printf("output file: %s\n", outputFile)
fmt.Printf("output proto: %s\n", proto)
fmt.Printf("output openapi file: %s\n", openapiFile)
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion writer/proto/constants.go → constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package proto
package constants

const FIELD_NAME_PARENT = "parent"
const FIELD_NAME_PATH = "path"
Expand Down
44 changes: 42 additions & 2 deletions example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,48 @@ graph TD
OpenAPI("OpenAPI Definition")
client("Client")
resource -- aepc --> serviceProto
resource -- aepc --> OpenAPI
serviceProto -- protoc --> gService
serviceProto -- protoc --> httpService
httpService -- protoc --> OpenAPI
OpenAPI -- openapi-generator et al --> client
OpenAPI -- terraform-provider-openapi --> terraform provider
OpenAPI -- openapi-generator et al --> clients
```

## Terraform Provider

This example provides an example of generating a terraform provider using
[terraform-provider-openapi](https://github.com/dikhan/terraform-provider-openapi/blob/master/docs/publishing_provider.md).

### Building and installing the provider

To build the provider, run the following:

```sh
go build -o terraform-provider-bookstore github.com/aep-dev/aepc/example/terraform/
```

### Installing

See [scripts/terraform-provider-regenerate-and-install.sh]
for an example.


### Using

See example/terraform/example_usage/main.tf for an example.

You could do something like:

```sh
$ cd example/terraform/example_usage/
$ terraform init
# - uncomment resource "book" in main.tf
$ terraform apply -auto-approve
# - observe the resource has been created.
# - modify the resource isbn
$ terraform apply -auto-approve
# - observe the resource has been updated.
# - comment the resource out
$ terraform apply -auto-approve
# - observe the resource has been deleted.
```
36 changes: 20 additions & 16 deletions example/bookstore/bookstore.yaml
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
name: "bookstore.example.com"
resources:
- kind: "Book"
plural: "books"
properties:
isbn:
type: STRING
number: 1
parents:
- "bookstore.example.com/Publisher"
required: true
# parents:
# - "bookstore.example.com/Publisher"
methods:
create: {}
read: {}
update: {}
delete: {}
list: {}
global_list: {}
- kind: "Publisher"
methods:
read: {}
list: {}
- kind: "Author"
properties:
name:
type: STRING
number: 1
parents:
- "Publisher"
methods:
read: {}
apply: {}
# - kind: "Publisher"
# plural: "publishers"
# methods:
# read: {}
# list: {}
# - kind: "Author"
# plural: "authors"
# properties:
# name:
# type: STRING
# number: 1
# parents:
# - "Publisher"
# methods:
# read: {}
131 changes: 131 additions & 0 deletions example/bookstore/bookstore.yaml.output.openapi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
{
"swagger": "2.0",
"info": {
"title": "bookstore.example.com",
"version": "version not set"
},
"schemes": [
"http"
],
"paths": {
"/books": {
"get": {
"responses": {
"200": {
"schema": {
"items": {
"$ref": "#/definitions/Book"
}
}
}
},
"parameters": null
},
"post": {
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/Book"
}
}
},
"parameters": [
{
"in": "body",
"name": "body",
"schema": {
"$ref": "#/definitions/Book"
}
},
{
"in": "path",
"name": "id",
"schema": {},
"required": true,
"type": "string"
}
]
}
},
"/books/{id}": {
"delete": {
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/Book"
}
}
},
"parameters": null
},
"get": {
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/Book"
}
}
},
"parameters": null
},
"patch": {
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/Book"
}
}
},
"parameters": [
{
"in": "body",
"name": "body",
"schema": {
"$ref": "#/definitions/Book"
}
}
]
},
"put": {
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/Book"
}
}
},
"parameters": [
{
"in": "body",
"name": "body",
"schema": {
"$ref": "#/definitions/Book"
}
}
]
}
}
},
"definitions": {
"Book": {
"type": "object",
"required": [
"isbn"
],
"properties": {
"id": {
"type": "string",
"readOnly": true,
"x-terraform-id": true
},
"isbn": {
"type": "string"
},
"path": {
"type": "string",
"readOnly": true
}
}
}
}
}
Loading

0 comments on commit 125b45c

Please sign in to comment.