Terraform Cloud Project Bootcamp with Andrew Brown — 2.3.0 Resource Skeleton

Gwen Leigh
4 min readOct 16, 2023

--

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

Issue #44 Goals

  • ✅ 1) Fix validateUUID()
  • ✅ 2) Define providerConfigure()
  • ✅ 3) Write skeletons for Resource() and CRUD functions.

Workflow

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 in append 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() takes p as an argument, which is a Provider object from the Terraform SDK’s schema 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 (for Config) 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 include user_uuid, token, and endpoint (the credentials and the website URL) that are required to access our TerraTowns website.

Resources

Bootcamp

About GoLang

--

--

Gwen Leigh

Cloud Engineer to be. Actively building my profile, network and experience in the cloud space. .