Introducing wordchain

A flexible Go application & library for generating random or deterministic word sequences

Sean Kane
SuperOrbital Engineer
Flipping bits on the internet since 1992.

Table of Contents

Overview

Superorbital wordchain

Superorbital spends a lot of time helping companies improve their internal computer engineering processes, and even when the basic problem is well understood, each engagement brings a lot of unique and interesting details that often require a unique solution. Even with the unique nature of each engagement we often see similar problems and pain points crop up across our customer base. Some of these problems are very large and something that might take a long term project to solve well, while others pain points are actually pretty simple to resolve with just a little bit of prioritization and focus.

Superorbital is proud to announce the release of wordchain, a simple, but flexible tool to address one of these easier pain points.

The Backstory

Early on in it’s development, Docker introduced randomized Linux container names using word pairs that consist of an adjective and the last name of a famous scientist or hacker. They even immortalized the well known fact that Steve Wozniak is not boring. As the industry started to make a concerted effort to migrate workloads off of pets and onto cattle random word-pair naming became an nice bridge between generating a completely random sequence of characters and generating something that was still somewhat memorable to human beings.

As time went on, Terraform introduced a module called random pet that can be used to apply a random name to each unique piece of infrastructure that a system needs to spin up and many other more general tools appeared, like Python’s codename.

But all of these tools tend to either only solve the problem for a single application or workflow, or are difficult to reuse everywhere in the pipeline. Installing Python to support a single CLI tool is less than ideal and environments like AWS may have hard limits on things like object names lengths, so a ten character random word pair might be much too long.

An Example Use-Case

AWS1 Elastic Load Balancer names must be unique within an account and can not be longer than 32 characters. When a human is generating the ELB name the length is unlikely to be a big issue, but it can quickly become a problem when the names are being auto-generated.

As an example, let’s imagine a CI/CD2 pipeline that runs integration tests on every PR and must create a load balancer for those tests.

To programmatically generate a name, one might combine a few available pieces of information with a random tag:

  • Company: superorbital
  • Application Name: login-service
  • Environment: development
  • AWS Region: us-east-1
  • Random Tag: elegant-bartik

Even shortened up, these names can get long very quickly:

  • so-loginsvc-dev-usge1-elegant-bartik (37 characters)

In this use-case it would be really useful to know ahead of time exactly how long each segment was going to be.

  • Company: 2 characters
  • Application Name: 8 character max
  • Environment: 3 characters (dev, tst, int, stg, prd)
  • AWS Region: 5 characters max (use1, euc1, apse1, usge1)

At this point the name (so-loginsvc-dev-usge1) is 22 characters long, so this gives us exactly 10 characters to work with for randomization.

So, how can we easily generate a string, that meets our requirements of being a fixed length, random, and memorable, in most of the environments (scripts, containers, etc.) that we are likely to regularly use?

The Solution

After re-implementing this functionality in a few projects and never stumbling across a tool that that was truly as flexible as we wanted, we decided to build wordchain.

Using wordchain it is easy to generate a random word sequence with a set length.

$ wordchain random -l 4

alto-howl

In our CI/CD pipeline use-case above, we would probably want the result to be deterministic, based on the branch name, so instead we might actually do something like this:

$ wordchain random -l 4 -s "my-pull-request-branch-name"

awry-grub

By passing in the branch name we can ensure that the result is deterministic and will remain the same for any job that is run on this branch.

Design Considerations

wordchain is designed with a few core things in mind. We wanted it to be very flexible. This primarily means that the output should be highly-configurable by the user.

wordchain makes it very easy for the user to define:

  • the number of words in the list.
  • the length of words in the list.
  • the delimiter that should be used between words.
  • a string to be prepended or appended to the results.
  • a custom list of words to pull from.

We also wanted it to be self-contained and therefore easy to use. This meant that we decide to build a tool:

  • which could be installed with a single binary.
  • which could be used as a simple REST-based3 micro-service.
  • which could be used as a library for people writing Go applications.
  • which provides an embedded word list, but allow it to be replaced.

And finally we wanted to ensure that it could provide deterministic results when desired. This is especially important in CI/CD pipelines, where you often want the results to remain unchanged on a given branch or pull request.

Usage Examples

CLI

  • Use the built-in list to get a 5 letter adjective/noun chain
$ wordchain random
sudsy-cloak
  • Use the built-in list to get a 4 letter adjective/noun chain
$ wordchain random -l 4
holy-wart
  • Adjust the words types in the chain
$ wordchain random -t adjective,adjective,noun
fried-picky-month
  • Get deterministic results from your list by providing a seed string
$ wordchain random -s "my-unique-git-branch-name"
mangy-berry

$ wordchain random -s "my-unique-git-branch-name"
mangy-berry

$ wordchain random -s "someone-elses-unique-git-branch-name"
minty-sleet

$ wordchain random -s "someone-elses-unique-git-branch-name"
minty-sleet
  • Provide a custom list to get a 3 letter adjective/noun chain
$ wordchain random -j ./data/tests/words.json -l 3
tan-nap
  • Get a 3 letter adjective/noun chain with a custom divider and pre-pended and post-pended word.
$ wordchain random -l 3 -d + -r hello -o goodbye
hello+odd+pad+goodbye
  • Get a copy of the internal word list in the valid json format
$ wordchain export > internal-word-list.json

Microservice

$ wordchain listen --port 8080
2021/03/30 11:32:02 Serving word chains at http://[::]:8080

$ curl -X POST -d '{}' -H 'Content-Type: application/json' http://127.0.0.1:8080/v1/random
"{\"chain\":\"quack-bayou\"}"

$ curl -X POST -d '{"length": 3}' -H 'Content-Type: application/json' http://127.0.0.1:8080/v1/random
"{\"chain\":\"odd-toy\"}"

$ curl -X POST -d '{"divider": "_", "length": 3, "prepend": "hello", "postpend": "adios", "seed": "deterministic" }' -H 'Content-Type: application/json' http://127.0.0.1:8080/v1/random
"{\"chain\":\"hello_bad_ace_adios\"}"

Docker

$ docker run superorbital/wordchain:latest
2021/03/30 20:35:07 Serving word chains at http://[::]:8080

$ docker run superorbital/wordchain:latest random
alpha-drink

$ docker run superorbital/wordchain:latest random -l 3
cut-oak

Library

  • In Go-based software project you can do something like this to use this as a library:
package main

import (
  types "github.com/superorbital/wordchain/types"
  words "github.com/superorbital/wordchain/words"
)

func main() {
  prefs := types.Preferences{
    WordFile: "",
    Length:   5,
    Divider:  "-",
    Prepend:  "",
    Postpend: "",
    Seed:     "",
    Type:     []string{"adjective", "noun"},
  }
  words.Random(prefs)
}

The library will expect a data file of words to exist. You can either create a valid JSON data file in your project at data/words.json or you can copy wordchain/pkged.go into your project to use the same word list that is embedded in the wordchain binary by default.

Conclusion

wordchain has helped us simplify various aspects of the projects that we have been working on, and hopefully it can also help you out. You can find the project on Github: github.com/superorbital/wordchain

Github stars, issues and pull requests are all encouraged!


  1. Amazon Web Services 

  2. Continuous integration and continuous delivery 

  3. Representational state transfer 

Sean Kane
SuperOrbital Engineer
Flipping bits on the internet since 1992.