psconfig

package module
v1.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 19, 2021 License: MIT Imports: 9 Imported by: 0

README

PSConfig PSConfig Tests Go Reference

PSConfig is a utility library, built to load values from AWS SSM Param Store into a custom configuration struct for your application. It is partially inspired by ianlopshire/go-ssm-config, but allows for nested configuration elements. In our projects we will typically have a config defined like this:

type HTTPConfig struct {
	Port          int           `hcl:"port"`
	ReadTimeout   time.Duration `hcl:"read_timeout"`
	WriteTimeout  time.Duration `hcl:"write_timeout"`
}

type DbConfig struct {
	Host        string `hcl:"host"`
	Username    string `hcl:"username"`
	Password    string `hcl:"password"`
	Name        string `hcl:"name"`
	Application string `hcl:"application"`
}

type ApplicationConfig struct {
	HTTP HTTPConfig `hcl:"http"`
	DB   DBConfig   `hcl:"db"`
}

This would typically be in an HCL file like:

http {
  port           = 8080
  read_timeout   = "${duration("5s")}"
  write_timeout  = "${duration("2m")}"
}

db {
  host                  = "database-server:5432"
  username              = "username"
  password              = "passw0rd!"
  application           = "fancy-application-name"
  name                  = "database_name"
}

Since we have relatively complicated configuration needs, grouping by the types of configuration made our lives easier.

Motivation

We wanted to move our configuration from templated HCL files, into the param store, to make it easier to manage configuration in general. Because of our current config structs, we needed to have something that minimized the amount of application changes we had to make, so we developed this library to allow us to load arbitrarily nested param store items into an equally arbitrarily nested config struct.

Usage

Assume you have already set some parameters in AWS SSM Param Store:

Name Value Type
/env/application/http/port 8080 String
/env/application/http/read_timeout 5s String
/env/application/http/write_timeout 8080 String
/env/application/db/host database-server:5432 String
/env/application/db/username username String
/env/application/db/password passw0rd SecureString
/env/application/db/application fancy-application-name String
/env/application/db/name database_name String

You can then write code like the following:

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"time"

	psconfig "github.com/seniorlink-vela/go-param-store-config"
)

type HTTPConfig struct {
	Port         int           `ps:"port"`
	ReadTimeout  time.Duration `ps:"read_timeout"`
	WriteTimeout time.Duration `ps:"write_timeout"`
}

type DbConfig struct {
	Host        string `ps:"host"`
	Username    string `ps:"username"`
	Password    string `ps:"password"`
	Name        string `ps:"name"`
	Application string `ps:"application"`
}

type ApplicationConfig struct {
	HTTP HTTPConfig `ps:"http"`
	DB   DbConfig   `ps:"db"`
}

func main() {
	c := &ApplicationConfig{}
	err := psconfig.Load("us-east-1", "/env/application/", c)
	if err != nil {
		log.Fatal(err.Error())
	}
	j, err := json.MarshalIndent(c, "", "  ")
	if err != nil {
		log.Fatal(err.Error())
	}
	fmt.Printf("%s\n", j)
}

The output of this is:

{
  "HTTP": {
    "Port": 8085,
    "ReadTimeout": 5000000000,
    "WriteTimeout": 120000000000
  },
  "DB": {
    "Host": "database-server:5432",
    "Username": "username",
    "Password": "passw0rd",
    "Name": "database_name",
    "Application": "fancy-application-name"
  }
}
Tags

You'll notice in the example above the struct fields are tagged with ps. This is what we use to identify which parameter store values should be placed in these fields.

Supported Struct Field Types

psconfig supports these struct field types:

  • string
  • int, int8, int16, int32, int64
  • bool
  • float32, float64
  • []string
  • struct

Licence

MIT

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// A KindError is thrown when you try to pass an invlaid type to `Load` or `Loader.Load`
	KindError = errors.New("Incorrect config argument. Must be an address to a struct.")
	// A SessionError gets thrown if you can not create an AWS session successfully
	SessionError = errors.New("Could not start AWS session.")
)

Functions

func Load

func Load(region, pathPrefix string, config interface{}) (err error)

Load is a simple utility method, that will instantiate an AWS session for you, and call Loader.Load with a new SSM provider. It's a shortcut, so you don't have to instantiate the session and ssm service yourself.

func RegisterDecodeHook added in v1.0.2

func RegisterDecodeHook(d DecodeHookFunc)

RegisterDecodeHook allows you to register your own decode hooks for use with your project. Any of the built-in decode hooks in https://github.com/mitchellh/mapstructure can be used here, and we've added StringEnvExpandHookFunc() as a convenience.

Types

type DecodeHookFunc added in v1.0.2

type DecodeHookFunc mapstructure.DecodeHookFunc

This package takes advantage of the excellent https://github.com/mitchellh/mapstructure library to do most of our conversion. That allows us to take advantage of the decode hooks functionality provided by that library. By default, we always have the mapstructure.StringToTimeDurationHookFunc hook enabled.

func StringEnvExpandHookFunc added in v1.0.2

func StringEnvExpandHookFunc() DecodeHookFunc

StringEnvExpandHookFunc returns a DecodeHookFunc that expands environment variables embedded in the values. The variables replaced would be in ${var} or $var format. (Parameters of type SecureString will not be expanded.)

type Loader

type Loader struct {
	SSM ssmiface.SSMAPI
}

This is an SSM provider. It allows us to call the AWS parameter store API to retrieve the values stored there.

func (*Loader) Load

func (l *Loader) Load(pathPrefix string, config interface{}) (err error)

Load calls the SSM Parameter Store API, and loads the values stored there into the passed config. It will automatically decrypt encrypted values. config must be a pointer to a struct.

The values are associated with your struct using the `ps` tag.

The prefixPath is the search string used to look up the associated values in the parameter store. For example, passing `/env/application` will find all of the keys and associated values nested under that prefix.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL