Compare commits
10 commits
eb70c87759
...
fc1ab1f2cb
Author | SHA1 | Date | |
---|---|---|---|
fc1ab1f2cb | |||
085d1377de | |||
![]() |
8cf3bc1903 | ||
![]() |
e0d6c4b526 | ||
![]() |
623651e49b | ||
![]() |
9b6dd4cc61 | ||
![]() |
144646a2c1 | ||
![]() |
2cf2657501 | ||
![]() |
0969aabbe3 | ||
![]() |
f067936f25 |
6 changed files with 135 additions and 88 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,3 +1,7 @@
|
|||
.terraform.lock.hcl
|
||||
.terraform/
|
||||
*.tfstate
|
||||
receita-provider
|
||||
backend
|
||||
*.tfstate.backup
|
||||
bin/
|
||||
|
|
42
Makefile
Normal file
42
Makefile
Normal file
|
@ -0,0 +1,42 @@
|
|||
|
||||
arch?=darwin_amd64
|
||||
provider_directory=~/.terraform.d/plugins/terraform.local/balhau/receita/1.0.0/$(arch)/
|
||||
|
||||
.PHONY: help
|
||||
help: ## Show this help.
|
||||
@sed -ne 's/^\([^[:space:]]*\):.*##/\1:\t/p' $(MAKEFILE_LIST) | column -t -s $$
|
||||
|
||||
.PHONY: clean-bin
|
||||
clean-bin: ## Clean all the generated binaries
|
||||
rm -rf bin
|
||||
|
||||
.PHONY: clean-terraform-state
|
||||
clean-terraform-state: ## Clean all the terraform state generated by terraform-init/terraform-apply
|
||||
rm -rf example/.terraform example/terraform.tfstate.backup example/.terraform.lock.hcl example/terraform.tfstate
|
||||
|
||||
.PHONY: clean
|
||||
clean: clean-bin clean-terraform-state ## Clean all the generated resources
|
||||
|
||||
.PHONY: terraform-init
|
||||
terraform-init: clean-terraform-state ## Execute terraform-init on example terraform directory
|
||||
cd example; terraform init
|
||||
|
||||
.PHONY: terraform-apply
|
||||
terraform-apply: ## Execute terraform-apply on example directory
|
||||
cd example; terraform apply -auto-approve
|
||||
|
||||
.PHONY: build
|
||||
build: ## Build binaries, both the backed dummy server as the terraform provider binary
|
||||
mkdir -p bin
|
||||
go build -o bin/terraform-provider-receita
|
||||
go build -o bin/backend api/backend.go
|
||||
|
||||
.PHONY: install-provider
|
||||
install-provider: ## Install provider in the terraform plugin directory
|
||||
mkdir -p $(provider_directory)
|
||||
cp bin/terraform-provider-receita $(provider_directory)
|
||||
|
||||
.PHONY: run-backend
|
||||
run-backend: build ## Start the backend web server
|
||||
bin/backend
|
||||
|
90
README.md
90
README.md
|
@ -49,87 +49,31 @@ provider "receita" {
|
|||
}
|
||||
```
|
||||
|
||||
### Running this
|
||||
|
||||
For that we can use http module from python3 and run
|
||||
Managing terraform providers involves a bit of typing in the command line. To avoid typing to much we have here a `Makefile` with most of the command line instructions we need.
|
||||
|
||||
To figure out how to use this makefile just type
|
||||
|
||||
```sh
|
||||
python3 -m http.server 9999
|
||||
make help
|
||||
|
||||
help: Show this help.
|
||||
clean-bin: Clean all the generated binaries
|
||||
clean-terraform-state: Clean all the terraform state generated by terraform-init/terraform-apply
|
||||
clean: Clean all the generated resources
|
||||
terraform-init: Execute terraform-init on example terraform directory
|
||||
terraform-apply: Execute terraform-apply on example directory
|
||||
build: Build binaries, both the backed dummy server as the terraform provider binary
|
||||
install-provider: Install provider in the terraform plugin directory
|
||||
run-backend: Start the backend web server
|
||||
```
|
||||
|
||||
This will open a http server in the port `9999`. This will not implement the endpoints defined in the code but will be enough to log the calls and this will be enough for us to validate the provider lifecycle.
|
||||
|
||||
### Running the provider
|
||||
|
||||
To run this provider we should jump into `example` directory and initialize `terraform` in the folder. For this it is enough to run
|
||||
#### Note
|
||||
|
||||
By default the step `make install-provider` will install the provider assuming a darwin (macos). If you want this to be installed in a different environment you would need to override the parameter `arch`. As an example for linux amd64 would be something like
|
||||
|
||||
```sh
|
||||
terraform init
|
||||
```
|
||||
|
||||
If all steps run properly unti this moment we should end up with a success command. Next step is the `plan`
|
||||
|
||||
For this we just
|
||||
|
||||
```sh
|
||||
terraform plan -out tf_plan.state
|
||||
```
|
||||
|
||||
The end result should be a `binary` file containing the terraform state to be executed.
|
||||
To finally apply the terraform changes we need to run
|
||||
|
||||
```sh
|
||||
terraform apply tf_plan.state
|
||||
```
|
||||
|
||||
If all went good you should have something like this
|
||||
|
||||
```
|
||||
receita_receita.receita_one: Creating...
|
||||
receita_receita.receita_one: Creation complete after 0s [id=500c3203-7210-45e0-8599-6a4048b78179]
|
||||
|
||||
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
|
||||
```
|
||||
|
||||
as output.
|
||||
|
||||
At the same time the mock server that we just started should log a call to an endpoint
|
||||
|
||||
```
|
||||
code 404, message File not found
|
||||
"GET /create HTTP/1.1" 404 -
|
||||
```
|
||||
|
||||
You should have also a `terraform.tfstate` file. Which is a human readable `json` representation of the current terraform state.
|
||||
Should look something like
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 4,
|
||||
"terraform_version": "1.4.6",
|
||||
"serial": 1,
|
||||
"lineage": "bef05e13-6bcf-44f0-a62e-131ade285463",
|
||||
"outputs": {},
|
||||
"resources": [
|
||||
{
|
||||
"mode": "managed",
|
||||
"type": "receita_receita",
|
||||
"name": "receita_one",
|
||||
"provider": "provider[\"terraform.local/balhau/receita\"]",
|
||||
"instances": [
|
||||
{
|
||||
"schema_version": 0,
|
||||
"attributes": {
|
||||
"author": "Maria Bacalhau",
|
||||
"id": "500c3203-7210-45e0-8599-6a4048b78179",
|
||||
"name": "Bola de carne"
|
||||
},
|
||||
"sensitive_attributes": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"check_results": null
|
||||
}
|
||||
make arch=linux_amd64 install-provider
|
||||
```
|
||||
|
|
41
api/backend.go
Normal file
41
api/backend.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
func handleCreate(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Printf("got /create request\n")
|
||||
io.WriteString(w, "Resource created!\n")
|
||||
}
|
||||
|
||||
func handleUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Printf("got /update request\n")
|
||||
io.WriteString(w, "Resource updated!\n")
|
||||
}
|
||||
|
||||
func handleDelete(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Printf("got /delete request\n")
|
||||
io.WriteString(w, "Resource deleted\n")
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/create", handleCreate)
|
||||
mux.HandleFunc("/update", handleUpdate)
|
||||
mux.HandleFunc("/delete", handleDelete)
|
||||
|
||||
err := http.ListenAndServe(":9999", mux)
|
||||
|
||||
if errors.Is(err, http.ErrServerClosed) {
|
||||
fmt.Printf("server closed\n")
|
||||
} else if err != nil {
|
||||
fmt.Printf("error starting server: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
|
@ -10,7 +10,18 @@ provider "receita" {
|
|||
endpoint = "http://localhost:9999"
|
||||
}
|
||||
|
||||
resource "receita_receita" "receita_one" {
|
||||
name = "Bola de carne"
|
||||
resource "receita_receita" "bola_carne" {
|
||||
name = "Bola de carne"
|
||||
#name = "Batata frita"
|
||||
author = "Maria Bacalhau"
|
||||
}
|
||||
|
||||
resource "receita_receita" "bacalhau_todos" {
|
||||
name = "Bacalhau com todos"
|
||||
author = "Antonio Mariscada"
|
||||
}
|
||||
|
||||
resource "receita_receita" "pato_bravo" {
|
||||
name = "Pato bravo"
|
||||
author = "Jose Pato"
|
||||
}
|
||||
|
|
|
@ -107,20 +107,11 @@ func (r *ReceitaResource) Create(ctx context.Context, req resource.CreateRequest
|
|||
|
||||
// Do specific stuff
|
||||
endpoint := r.providerData.Model.Endpoint
|
||||
hResp, _ := http.Get(endpoint.ValueString() + "/create")
|
||||
|
||||
fmt.Println("Before the call")
|
||||
fmt.Println(hResp.Body)
|
||||
|
||||
hResp, err := http.Get(endpoint.ValueString() + "/create")
|
||||
|
||||
fmt.Println("After the call")
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if hResp.Close == false {
|
||||
fmt.Println("http closed")
|
||||
}
|
||||
//End specific stuff
|
||||
|
||||
//log the creation of the resource in the terraform logging system
|
||||
tflog.Trace(ctx, "created a receita resource")
|
||||
|
@ -157,7 +148,13 @@ func (r *ReceitaResource) Update(ctx context.Context, req resource.UpdateRequest
|
|||
return
|
||||
}
|
||||
|
||||
//Do specific update stuff
|
||||
// Do specific stuff
|
||||
endpoint := r.providerData.Model.Endpoint
|
||||
hResp, _ := http.Get(endpoint.ValueString() + "/update")
|
||||
|
||||
fmt.Println(hResp.Body)
|
||||
|
||||
//End specific stuff
|
||||
|
||||
//Finally update the terraform state
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
|
@ -169,6 +166,14 @@ func (r *ReceitaResource) Delete(ctx context.Context, req resource.DeleteRequest
|
|||
// Load tf state into the model
|
||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
||||
|
||||
// Do specific stuff
|
||||
endpoint := r.providerData.Model.Endpoint
|
||||
hResp, _ := http.Get(endpoint.ValueString() + "/delete")
|
||||
|
||||
fmt.Println(hResp.Body)
|
||||
|
||||
//End specific stuff
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue