Terraform Cloud Project Bootcamp with Andrew Brown — 2.3.0 Resource Skeleton
This article is part of my Terraform journey with Terraform Bootcamp by Andrew Brown and Andrew Bayko with Chris Williams and Shala.
My wild career adventure into Cloud Computing continues with Andrews, and I highly, highly recommend you to come join us. Check out Andrews’ free youtube learning contents. You can also buy some paid courses here to support their incredibly selfless cause.
Agenda
- Video here: 2 3 0 Resource Skeleton
- Feature branch here: 2.3.0
Issue #44 Goals
- ✅ 1) Fix
validateUUID()
- ✅ 2) Define
providerConfigure()
- ✅ 3) Write skeletons for
Resource()
and CRUD functions.
Workflow
- ✅ 1)
validateUUID()
- ✅ 2)
providerConfigure()
- ✅ 3)
Resource()
Conceptual Summary
Up until previous videos, we couldn’t do much with the Provider Plugin as it only has the skeleton with not much working detail. In this episode, we will flesh out the Resource()
skeleton to complete its definition.
1. validateUUID()
We will run into the uuid not defined
error. We have to install the uuid package
by google. Add “github.com/google/uuid
”. Then the terminal will require you to install it giving you the command.
go get github.com/ExamProCo/terraform-provider-terratowns
When we try to install it with the go-provided command, it errors out. Hang on, wasn’t it you who just gave me this command to run 👀!?
We have to run it inside the right module. So cd
into the directory terraform-providoer-terratowns
.
We also have to make some corrections to the main.go
file.
- Wrap the strings to print with double quotes.
errors
as the argument inappend
must be plural —errors
.return
statement is missing. Add one.
func validateUUID(v interface{}, k string) (ws []string, errors []error) {
+ log.Print("validateUUID:start") # double-quote
value := v.(string)
if _, err := uuid.Parse(value); err != nil {
+ errors = append(errors, fmt.Errorf("invalid UUID format")) # errors plural
}
+ log.Print("validateUUID:end") # double-quote
+ return # return statement
}
Now try running tf init
. It should initialise just fine.
2. providerConfigure()
We define the function providerConfigure()
.
providerConfigure()
takesp
as an argument, which is aProvider
object from the Terraform SDK’sschema
package.- The function returns a
schema.ConfigureContextFunc
which is a type representing a function used by the Terraform SDK to configure the provider. - Calling
providerConfigure()
will initialise a provider with the data filled with the values you provide (forConfig
) when making that call.
// main.go
func providerConfigure(p *schema.Provider) schema.ConfigureContextFunc {
return func(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) {
log.Print("providerConfigure:start")
config := Config{
Endpoint: d.Get("endpoint").(string),
Token: d.Get("token").(string),
UserUuid: d.Get("user_uuid").(string),
}
log.Print("providerConfigure:end")
return &config, nil
}
}
- Golang tips: Golang is VERY sensitive about special characters, letter cases, typos and so on. Make sure you are using double quotations not single, all functions or variables that need to be uppercase are correctly so, and so on. If you think you typed everything correctly and still running into errors, try copying and pasting Andrew’s source code from here.
Then Andrew adds the diag
package and thestruct
Config
.
// main.go
import {
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
}
At the top of the main.go
file, Andrew adds the Config
struct definition as it is used inside the providerConfigure()
function.
type Config struct {
Endpoint string
Token string
UserUuid string
}
Then build again with ./bin/build_provider
.
Now we define the CRUD actions. Every single resource in terraform provider
must have these CRUD actions defined.
func Resource() *schema.Resource {
log.Print("Resource:start")
resource := &schema.Resource{
CreateContext: resourceHouseCreate,
ReadContext: resourceHouseRead,
UpdateContext: resourceHouseUpdate,
DeleteContext: resourceHouseDelete,
}
log.Print("Resource:end")
return resource
}
Then we declare the skeletons of the CRUD functions. The detailed definitions will be completed in the next episode.
func resourceHouseCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
var diags diag.Diagnostics
return diags
}
func resourceHouseRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
var diags diag.Diagnostics
return diags
}
func resourceHouseUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
var diags diag.Diagnostics
return diags
}
func resourceHouseDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
var diags diag.Diagnostics
return diags
}
📑 Notes
- The purpose of the
providerConfigure()
function is to initialise our custom Provider with configuration details. These includeuser_uuid
,token
, andendpoint
(the credentials and the website URL) that are required to access our TerraTowns website.
Resources
Bootcamp
- Video: 2 3 0 Resource Skeleton
- My feature branch: 2.3.0
- My complete Learning Journal