cfg

package
v1.18.0 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2021 License: Apache-2.0 Imports: 7 Imported by: 6

Documentation

Overview

Package cfg manages config for outreach go services

Every go app or package that needs config should define a strongly typed struct for it

Example

type HoneycombConfig struct {
   Disable    bool       `yaml:"Disable"`
   Dataset    string     `yaml:"Dataset"`
   APIHost    string     `yaml:"APIHost"`
   SampleRate float64    `yaml:"SampleRate"`
   Key        cfg.Secret `yaml:"Key"`
}

func (x someComponent) someFunc(ctx context.Context) error {
     var hcConfig HoneycombConfig
     if err := cfg.Load("honeycomb.yaml", &hcConfig); err != nil {
         return err
     }

     ... now use the config...
}

All config structs should typically implement their own `Load()` method so that the config location is specified in one spot:

func (c *HoneycombConfig) Load() error {
    return cfg.Load("honeycomb.yaml", &c)
}

Dev environment overrides

The default directory prefix for config will be chosen to be compatible with our k8s deployment strategy.

For dev environments, the preferred path is ~/.outreach/ and this can be configured by app init using the following override:

import env "github.com/getoutreach/gobox/pkg/env"
func init() {
    env.ApplyOverrides()
}

To build with this override, the build tag or_dev should be used.

Dev environments may also need command line or environment overrides. The suggested mechanism is to add the override as part of the individual `Load()` method on the struct. At some point, we will add code generators for config (based on struct tags such as `env:OUTREACH_HONEYCOMB_KEY` or some such mechanism) and the `Load()` methods will be automatically generated with the specified overrides.

Secrets

While secrets can be accessed in an adhoc way using the secrets package, the recommended way is to fetch fixed secrets (i.e. not things like oauth tokens) via the `cfg.Secret` type. For the example above, the API key can be accessed via:

secretData, err := hcConfig.Key.Data(ctx)

Note that SecretData cannot be serialized to JSON or YAML. While it can be converted to string using an explicit conversion, the converted value should not be cached or passed to internal functions.

Example
package main

import (
	"context"
	"fmt"

	"github.com/getoutreach/gobox/pkg/cfg"
	"github.com/getoutreach/gobox/pkg/env"
	"github.com/getoutreach/gobox/pkg/secrets/secretstest"
)

func main() {
	type HoneycombConfig struct {
		Disable    bool
		Dataset    string
		APIHost    string
		SampleRate float64
		Key        cfg.Secret
	}

	expected := HoneycombConfig{
		Disable:    true,
		Dataset:    "boo",
		APIHost:    "hoo",
		SampleRate: 5.3,
		Key:        cfg.Secret{Path: "someSecretPath"},
	}

	defer env.FakeTestConfig("honeycomb.yaml", expected)()
	defer secretstest.Fake("someSecretPath", "someSecretData")()

	var hcConfig HoneycombConfig
	if err := cfg.Load("honeycomb.yaml", &hcConfig); err != nil {
		fmt.Println("Unexpected error", err)
	}

	if hcConfig != expected {
		fmt.Println("Unexpected differences")
	}

	data, err := hcConfig.Key.Data(context.Background())
	if err != nil {
		fmt.Println("Error fetching data")
	}
	if string(data) != "someSecretData" {
		fmt.Println("Unexpected secret data", data)
	}

	fmt.Println(data)

}
Output:

redacted

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Load

func Load(fileName string, ptr interface{}) error

Load uses the default config reader to load config

func SetDefaultReader

func SetDefaultReader(f Reader)

SetDefaultReader sets the default reader. Only meant for tests and dev environment overrides

Types

type Reader

type Reader func(fileName string) ([]byte, error)

Reader reads the config from the provided file

func DefaultReader

func DefaultReader() Reader

DefaultReader returns the current default reader. Only meant for tests and dev environment overrides

func (Reader) Load

func (r Reader) Load(fileName string, ptr interface{}) error

Load reads the config.

Usage:

var appConfig MyConfig
err := cfg.Load("myapp.json", &appConfig)

This parses the config using JSON. If a config has special needs, it can implement its own UnmarshalJSON (such as implementing environment overrides)

type Secret

type Secret struct {
	Path string `yaml:"Path"`
}

Secret provides access to secret config.

The actual secret should be fetched via Data() which returns a SecretData.

This type can be embedded within Config

func (Secret) Data

func (s Secret) Data(ctx context.Context) (SecretData, error)

Data fetches the data for this secret.

Do not cache this value. When passing this to internal outreach functions, pass the SecretData -- do not conver it to string first.

type SecretData

type SecretData string

SecretData just wraps strings so we don't accidentally log secret data.

Do not store SecretData -- it is only meant to be kept in scope variables and as arguments.

Do not pass the raw converted string as arguments to any outreach code, use the strong type SecretData instead

func (SecretData) Format

func (s SecretData) Format(f fmt.State, c rune)

Format implements fmt.Formatter

func (SecretData) GoString

func (s SecretData) GoString() string

GoString implements the GoStringer interface

func (SecretData) MarshalJSON

func (s SecretData) MarshalJSON() ([]byte, error)

MarshalJSON implements a dummy json.Marshaler

func (SecretData) MarshalYAML

func (s SecretData) MarshalYAML() (interface{}, error)

MarshalYAML implements a dummy yaml.Marshaler

Jump to

Keyboard shortcuts

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