Collecting Terraform Resources

I just finished and got a LinkedIn Learning (AKA Lynda.com) course published last month on Learning Terraform (LinkedIn Learning Course & Lynda.com Course). Immediately after posting that I spoke with my editor at LinkedIn Learning and agreed on the next two courses I’ll record: Terraform Essentials and Go for Site Reliability Engineers. Consider me stoked to be putting this material together and recording more video courses, this is a solid win, as the internet dogge would say, “much excite, very wow”!

The following are some recent materials I’ve dug up in regards to Terraform, Go, and Site Reliability work. Some of which will very likely find it’s way into influencing my courses. Good material here if you’re looking for some solid, and arguably more advanced approaches, to your Terraform work.

Advanced Terraform Materials

The HashiCorp Documentation Material

Writing customer providers

Running Terraform in Automation

Go Library Data Generation Timings

Recently I put together some quick code to give some timings on the various data generation libraries available for Go. For each library there were a few key pieces of data generation I wanted to time:

  • First Name – basically a first name of some sort, like Adam, Nancy, or Frank.
  • Full Name – something like Jason McCormick or Sally Smith.
  • Address – A basic street address, or whatever the generator might provide.
  • User Agent – Such as that which is sent along with the browser response.
  • Color – Something like red, blue, green, or other color beyond the basics.
  • Email – A fully formed, albeit faked email address.
  • Phone – A phone number, ideally with area code and prefix too.
  • Credit Card Number – Ideally a properly formed one, which many of the generators seem to provide based on VISA, Mastercard, or related company specifications.
  • Sentence – A stand multi-word lorem ipsum based sentence would be perfect.

I went through and searched for libraries that I wanted to try out. Of all the libraries I found I narrowed it down to three specific libraries. When I add the imports for these libraries, by way of how Go works, it gives you the repo locations:

  • “github.com/bxcodec/faker” – faker – Faker generates data based on a Struct, which is a pretty cool way to determine what type of data you want and to get it returned in a particularly useful format.
  • “github.com/icrowley/fake” – fake – Fake is a library inspired by the ffaker and forgery Ruby gems. Not that you’d be familiar with those, but if you are you have instant insight into how this library works.
  • “github.com/malisit/kolpa” – kolpa – This is another data generator that creates fake data for various types of data, structures, strings, sentences, and more.

Continue reading “Go Library Data Generation Timings”

IDE Launcher via Amtrak Cascades to Portland for ML4ALL

Got fidgety on the train, and just wanted to write code, on the way down to Portland for ML4ALL so I wrote up some decision tree code on determining what IDE’s I want opened up. Ya know, if you do something more than twice it needs automated, so I’ve started the process of automating all startup and shutdown tasks for a day’s coding. Simplistic geeky train geek code fun code is fun geeky train code. Cheers!

[sourcecode language=”cpp”]
package main

import (
“time”
“fmt”
)

var sessionMinimal, sessionMedium, sessionLong, sessionZone time.Duration
var language string

func main() {
sessionMinimal = 15
sessionMedium = 45
sessionLong = 90
sessionZone = 180

language = “golang”

openIde(“golang”, 200)
}

func openIde(languageStack string, expectedCodingTime time.Duration) {
var ide string

switch {
case expectedCodingTime sessionZone:
ide = stackSpecific(languageStack, false, true, true)
fmt.Printf(“Launching: %s”, ide)

}
}

func stackSpecific(language string, fastLaunch bool, featureRich bool, introspective bool) string {
if fastLaunch == true && featureRich == true && introspective == true {
return “\n\nCome on, you know better. You get at best two out of three.\n\n”
}

if fastLaunch == true && featureRich == true {
return “Visual Studio Code”
}

if featureRich == true && introspective == true {
switch language {
case “SQL”:
return “DataGrip”
case “C”:
return “CLion”
case “Python”:
return “PyCharm”
case “golang”:
return “Goland”
case “java”:
return “IntelliJ”
case “scala”:
return “IntelliJ”
case “kotlin”:
return “IntelliJ”
case “dotnet”:
return “Rider”
case “csharp”:
return “Rider”
case “fsharp”:
return “Rider”
case “vbnet”:
return “Rider”
case “javascript”:
return “Webstorm”
case “hcl”:
return “IntelliJ”
case “ruby”:
return “RubyMine”
case “swift”:
return “AppCode”
case “obj-c”:
return “AppCode”
default:
return “IntelliJ”
}
}

if featureRich == true {
switch language {
case “swift”:
return “AppCode”
case “obj-c”:
return “AppCode”
default:
return “Visual Studio Code”
}
}

if introspective == true {
switch language {
case “swift”:
return “AppCode”
case “obj-c”:
return “AppCode”
default:
return “Visual Studio Code”
}
}

if fastLaunch == true {
return “Sublime”
}

return “No IDE for you.”
}
[/sourcecode]

UUID Solutions w/ Go

gopherWant a UUID generator for your Go code? It’s likely you’ll need one sometime. Well here’s a short code snippet and a review of one of the available UUID libraries available.

The library is avaliable at https://github.com/satori/go.uuid.

With test coverage this library supports the following UUID types. I’ll elaborate on what each of these types are after a code snippet or two.

  • Version 1, based on timestamp and MAC address (RFC 4122)
  • Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1)
  • Version 3, based on MD5 hashing (RFC 4122)
  • Version 4, based on random numbers (RFC 4122)
  • Version 5, based on SHA-1 hashing (RFC 4122)

First step. Get the library.

go get github.com/satori/go.uuid

Next I whipped up a code file with the example code. I’ve called mine uuid_generation.go.


package main
import (
"fmt"
"github.com/satori/go.uuid"
)
func main() {
// Creating UUID Version 4
u1 := uuid.NewV4()
fmt.Printf("UUIDv4: %s\n", u1)
// Parsing UUID from string input
u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
if err != nil {
fmt.Printf("Something gone wrong: %s", err)
}
fmt.Printf("Successfully parsed: %s", u2)
}

Stepping through the code, the import includes the library being used.

"github.com/satori/go.uuid"

Then at the very beginning of the code a new UUID v4 is created.

u1 := uuid.NewV4()

In the example, a few lines down, there is also code around parsing a UUID.

u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")

I wanted to insure the other functions worked for the other versions so I added some code to create and print out each of them. At the same time, I’ve added what each of the versions are as I worked through creating them.

Version 1

A version 1 UUID concatenates the 48-bit MAC address of the machine creating the UUID with a 60-bit timestamp. If the process clock does not advance fast enough, there is a 14-bit clock sequence that extends the timestamp to insure uniqueness. Based on these creation parameters there is a maximum of 18 sextrillion version 1 UUIDs that can be generated per node. So ya know, don’t get carried away or anything. 😛

It’s also important to note, albeit obviously, that this UUID can be tracked back to the MAC Address that was used to create it.

The code for this UUID creation is shown above in the first example.

Version 2

Version 2 is reserved for DCE Security UUIDs. It’s a bit light on details in the RFC (4122). Even though the RFC is light on details, the DCE 1.1 Authentication and Security Services specification clarifies a bit more. Overall this UUID is generally similar to a version 1 UUID except the least significant 8 bits of the clock sequence (clock_seq_low) are replaced by local domain numbers. The least significant 32 bits of the timestamp replaced by an integer identifier.

Updated code with a working example of the specific domains used to create a v2 UUID.


package main
import (
"fmt"
"github.com/satori/go.uuid"
)
func main() {
// Creating UUID Version 1
uuid1 := uuid.NewV1()
fmt.Printf("UUIDv1: %s\n", uuid1)
// Creating UUID Version 2 – Domain Person
uuid2 := uuid.NewV2(uuid.DomainPerson)
fmt.Printf("UUIDv2: %s\n", uuid2)
// Creating UUID Version 2 – Domain Group
uuid2b := uuid.NewV2(uuid.DomainGroup)
fmt.Printf("UUIDv2: %s\n", uuid2b)
// Creating UUID Version 2 – Domain Organization
uuid2c := uuid.NewV2(uuid.DomainOrg)
fmt.Printf("UUIDv2: %s\n", uuid2c)
// Creating UUID Version 4
uuid4 := uuid.NewV4()
fmt.Printf("UUIDv4: %s\n", uuid4)
// Parsing UUID from string input
u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
if err != nil {
fmt.Printf("Something gone wrong: %s", err)
}
fmt.Printf("Successfully parsed: %s\n", u2)
}

Version 3 and 5

Version 3 and 5 are similar UUIDs generated from hashing a namespace identifier and name. Version 5 uses SHA1 and version 3 uses MD5 as the hashing algorithm. The namespace identifier itself is a UUID and is used to represent the namespaces for URLs, fully qualified domain names (FQDNs), object identifiers, and X.500 distinguished names. Other UUIDs could be used as namespace designators, but the aforementioned are usually used.

To note, RFC 4122 refers version 5 (SHA1) over version 3 (MD5), and suggests against either as security credentials.

Here’s the added examples of version 3 and 5.


package main
import (
"fmt"
"github.com/satori/go.uuid"
)
func main() {
// Creating UUID Version 1
uuid1 := uuid.NewV1()
fmt.Printf("UUIDv1: %s\n", uuid1)
// Creating UUID Version 2 – Domain Person
uuid2 := uuid.NewV2(uuid.DomainPerson)
fmt.Printf("UUIDv2: %s\n", uuid2)
// Creating UUID Version 2 – Domain Group
uuid2b := uuid.NewV2(uuid.DomainGroup)
fmt.Printf("UUIDv2: %s\n", uuid2b)
// Creating UUID Version 2 – Domain Organization
uuid2c := uuid.NewV2(uuid.DomainOrg)
fmt.Printf("UUIDv2: %s\n", uuid2c)
// Creating UUID Version 3
uuid3 := uuid.NewV3(uuid.NamespaceDNS, "someplace.org")
fmt.Printf("UUIDv2: %s\n", uuid3)
// Creating UUID Version 4
uuid4 := uuid.NewV4()
fmt.Printf("UUIDv4: %s\n", uuid4)
// Creating UUID Version 5
uuid5 := uuid.NewV5(uuid.NamespaceURL, "blaghdblagh.com")
fmt.Printf("UUIDv5: %s\n", uuid5)
// Parsing UUID from string input
u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
if err != nil {
fmt.Printf("Something gone wrong: %s", err)
}
fmt.Printf("Successfully parsed: %s\n", u2)
}

Enjoy those UUIDs, happy coding!

Building a Data Thrashing CLI Tool in Go

I need a tool just to do some testing against an API end point. I figured I’d throw one together real quick in Go. With a few libraries it’s just a few steps to get the job done. The following is that project. Eventually I’ll create the services that will run in some containers I’ll throw into a Kubernetes cluster, but for now, it’s all CLI. Onward.The first thing I’ll need is Cobra. Continue reading “Building a Data Thrashing CLI Tool in Go”