This was my Saturday challenge. I principally constructed this for inner use as a result of I discovered myself copying/pasting related code throughout a number of tasks, however figured any person else might be capable to get some utility from it:
Today I principally am deploying my Go code to cloud suppliers (Google Cloud, AWS, and Azure) and exposing configuration settings through secret managers (aren’t all of us?). Generally I need to run these companies domestically and inject atmosphere variables through key/worth pairs. This bundle wraps studying the important thing/worth pairs and makes use of reflection to show atmosphere variables into structs:
bundle major
import "github.com/DeanPDX/dotconfig"
// Our contrived AppConfig with env struct tags:
kind AppConfig struct {
MaxBytesPerRequest int `env:"MAX_BYTES_PER_REQUEST"`
APIVersion float64 `env:"API_VERSION"`
IsDev bool `env:"IS_DEV"`
StripeSecret string `env:"STRIPE_SECRET"`
WelcomeMessage string `env:"WELCOME_MESSAGE"`
}
func Predominant() {
config, err := dotconfig.FromFileName[AppConfig](".env")
// config is able to use. Float/bool/int values will probably be
// accurately parsed. In case you are creating domestically you'll be able to
// put an .env file in your working dir to produce the values.
// Within the cloud they need to come from a secret supervisor.
}
My aim right here was to maintain is so simple as doable. Outline your struct with env
tags that map properties to atmosphere variables. Then it “simply works” in native dev (both by setting native env variables or together with a .env
within the working dir) and within the cloud the place atmosphere variables are equipped through secret managers.
Right here’s the anticipated format for .env
recordsdata:
MAX_BYTES_PER_REQUEST='1024'
API_VERSION='1.19'
# All of those are valie for booleans:
# 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False
IS_DEV='1'
STRIPE_SECRET='sk_test_insertkeyhere'
# Proper now supporting newlines through "n" in strings:
WELCOME_MESSAGE='Hiya,nWelcome to the app!n-The App Dev Crew'
The decoding logic borrows closely from encoding/json within the stdlib. I additionally uncovered a operate referred to as FromReader within the occasion that you just need to set key/worth pairs from one thing that isn’t a file otherwise you need to handle file IO your self.
When you have any questions be happy to ask. I’m additionally open to suggestions. Once more – I wished to maintain this so simple as doable so your entire bundle proper now’s below 200 strains of code. Extra information and runnable instance within the godoc.
1 Like
Seems nice. and you’re right I additionally wanted to code one thing like this however extra particular of cousrse.
are you certain that the one quotes are ordinary in .env recordsdata?
STRIPE_SECRET=‘sk_test_insertkeyhere’
vs
STRIPE_SECRET=sk_test_insertkeyhere
are you able to make it work for each circumstances?
Must be right here:
// Flip a line into key/worth pair. Instance line:
// STRIPE_SECRET_KEY='sk_test_asDF!'
key := line[0:strings.Index(line, "='")]
worth := line[len(key)+2:]
// Trim closing single quote
worth = strings.TrimSuffix(worth, "'")
// Flip n into newlines
worth = strings.ReplaceAll(worth, `n`, "n")
os.Setenv(key, worth)
For errors / information I would want the next:
- if the .env file has an unused line.
- if a wanted entry is clean or lacking.
(simply not right here)
STRIPE_SECRET=
STRIPE_SECRET=‘’
- if there’s a typo or one thing is mispelled fallacious line.
then the person can resolve, based mostly on errors, in the event that they abort the app at init and drive the person to enter a selected subject if that is wanted.