Initial commit

master
Noah 2020-07-13 21:39:24 -07:00
commit a57ab31b71
9 changed files with 319 additions and 0 deletions

9
LICENSE.md Normal file
View File

@ -0,0 +1,9 @@
# MIT License
Copyright 2020 Noah Petherbridge
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

80
README.md Normal file
View File

@ -0,0 +1,80 @@
# YamlSettings for Go
This is a config file manager for Go, inspired by Python
[yamlsettings](https://github.com/KyleJamesWalker/yamlsettings).
## Example
Your Go code:
```go
import "git.kirsle.net/go/yamlsettings"
// Typedef for your config object.
type Config struct {
Database struct {
Host string `yaml:"host"`
Port string `yaml:"port"`
User string `yaml:"user"`
Password string `yaml:"passwd"`
} `yaml:"database"`
Redis struct {
Host string `yaml:"redis_host"`
Port int `yaml:"redis_port"`
} `yaml:"redis"`
Debug bool `yaml:"DEBUG"`
SecretKey string `yaml:"SECRET_KEY"`
}
func main() {
// Marshal your app config from the defaults + settings files.
// Only the defaults.yml should exist on disk; the settings.yml is
// optional and will be ignored if not found.
var setting Config
err := yamlsettings.LoadFiles(
"defaults.yml", "settings.yml",
&setting,
)
if err != nil {
panic(err)
}
fmt.Printf("Redis host: %s\n", settings.Redis.Host)
}
```
Your defaults.yml file can be committed to version control. It uses sensible
defaults and has dummy text in place of passwords and needed configuration:
```yaml
---
database:
host: "localhost"
port: 5432
user: "postgres"
passwd: "postgres"
redis:
host: "localhost"
port: 6379
DEBUG: false
SECRET_KEY: "!! CHANGE ME !!"
```
The settings.yml file can override values from the defaults file. This
file goes in your `.gitignore` to avoid accidentally committing secrets
to version control!
```yaml
---
database:
host: "pgprod.example.com"
user: "pgprod_admin"
passwd: "big secret long password"
SECRET_KEY: "fd09s0sfv0dhgf098sasd"
```
## License
MIT. © 2020 Noah Petherbridge.

23
example/defaults.yml Normal file
View File

@ -0,0 +1,23 @@
---
# Program Defaults, do not edit this file!!!
# All values should be overridden in the following ways:
# 1. In the 'settings.yaml' file.
# 2. With environment variables. Example myproj.databases.primary_sql.user can
# be overridden with MYPROJ_DATABASES_PRIMARY_SQL_USER.:
databases:
extra_setting: "not specified"
primary_sql:
user: my_user
passwd: password_here
host: db-bouncer-01.postgres.com:5432
db: postgres
compress: true
engine: postgresql2
redis:
redis_host: 127.0.0.1
redis_port: 6379
app_config:
DEBUG: false
SECRET_KEY: hard key to guess and keep values secret
debug_sql: false
debug_profiler: false

54
example/main.go Normal file
View File

@ -0,0 +1,54 @@
package main
import (
"encoding/json"
"fmt"
"git.kirsle.net/go/yamlsettings"
)
type MyProj struct {
Databases struct {
PrimarySQL struct {
User string `yaml:"user"`
Passwd string `yaml:"passwd"`
Host string `yaml:"host"`
DB string `yaml:"db"`
Compress bool `yaml:"compress"`
Engine string `yaml:"engine"`
} `yaml:"primary_sql"`
Redis struct {
Host string `yaml:"redis_host"`
Port int `yaml:"redis_port"`
} `yaml:"redis"`
} `yaml:"databases"`
AppConfig struct {
Debug bool `yaml:"DEBUG"`
SecretKey string `yaml:"SECRET_KEY"`
} `yaml:"app_config"`
DebugSQL bool `yaml:"debug_sql"`
DebugProfiler bool `yaml:"debug_profiler"`
}
func (c MyProj) String() string {
output, _ := json.MarshalIndent(c, "", "\t")
return string(output)
}
func main() {
var config MyProj
err := yamlsettings.LoadFiles(
"defaults.yml",
"settings.yml2",
&config,
)
if err != nil {
panic(err)
}
// Print out the final settings to terminal as JSON.
fmt.Println(config)
}

11
example/settings.yml Normal file
View File

@ -0,0 +1,11 @@
---
databases:
primary_sql:
user: root
passwd: god
redis:
redis_host: redis.example.com
app_config:
DEBUG: true
SECRET_KEY: sdfasjksdfASFAS23423f@#$%!$#VR@%UQ%
debug_sql: true

5
go.mod Normal file
View File

@ -0,0 +1,5 @@
module git.kirsle.net/go/yamlsettings
go 1.14
require gopkg.in/yaml.v2 v2.3.0

3
go.sum Normal file
View File

@ -0,0 +1,3 @@
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

50
yamlsettings.go Normal file
View File

@ -0,0 +1,50 @@
package yamlsettings
import (
"io"
"os"
"gopkg.in/yaml.v2"
)
// LoadFiles marshals your app settings from the default.yml overridden
// by the settings.yml file.
func LoadFiles(defaultsFile, settingsFile string, v interface{}) error {
// Read the defaults file.
if err := LoadFile(defaultsFile, v); err != nil {
return err
}
// Read the settings.yml. It's OK if it doesn't exist.
if err := LoadFile(settingsFile, v); err != nil && !os.IsNotExist(err) {
return err
}
return nil
}
// LoadFile opens and marshals YAML settings from a single config file.
func LoadFile(filename string, v interface{}) error {
fh, err := os.Open(filename)
if err != nil {
return err
}
dec := yaml.NewDecoder(fh)
return dec.Decode(v)
}
// LoadReaders marshals your app settings from the defaults and settings
// readers, so you can feed in YAML data from sources other than files
// on disk.
func LoadReaders(defaults, settings io.Reader, v interface{}) error {
if defaults != nil {
if err := yaml.NewDecoder(defaults).Decode(v); err != nil {
return err
}
}
if settings != nil {
return yaml.NewDecoder(settings).Decode(v)
}
return nil
}

84
yamlsettings_test.go Normal file
View File

@ -0,0 +1,84 @@
package yamlsettings_test
import (
"bytes"
"fmt"
"testing"
"git.kirsle.net/go/yamlsettings"
)
func TestLoadReaders(t *testing.T) {
type Settings struct {
Databases struct {
PrimarySQL struct {
User string `yaml:"user"`
Passwd string `yaml:"passwd"`
Host string `yaml:"host"`
DB string `yaml:"db"`
Compress bool `yaml:"compress"`
Engine string `yaml:"engine"`
} `yaml:"primary_sql"`
Redis struct {
Host string `yaml:"redis_host"`
Port int `yaml:"redis_port"`
} `yaml:"redis"`
} `yaml:"databases"`
AppConfig struct {
Debug bool `yaml:"DEBUG"`
SecretKey string `yaml:"SECRET_KEY"`
} `yaml:"app_config"`
DebugSQL bool `yaml:"debug_sql"`
DebugProfiler bool `yaml:"debug_profiler"`
}
// The defaults.yml file you can commit to version control,
// it's used as the template config that contains all options,
// has sensible defaults where possible or "CHANGE_ME" where not.
var (
defaultsYaml = bytes.NewBuffer([]byte(`---
# Program Defaults, do not edit this file!!!
# All values should be overridden in the settings.yml file.
databases:
primary_sql:
user: my_user
passwd: password_here
host: db-bouncer-01.postgres.com:5432
db: postgres
compress: true
engine: postgresql2
redis:
redis_host: 127.0.0.1
redis_port: 6379
app_config:
DEBUG: false
SECRET_KEY: hard key to guess and keep values secret
debug_sql: false
debug_profiler: false`))
settingsYaml = bytes.NewBuffer([]byte(`---
databases:
primary_sql:
user: root
passwd: god
redis:
redis_host: redis.service.com
app_config:
DEBUG: true
SECRET_KEY: sdfasjksdfASFAS23423f@#$%!$#VR@%UQ%
debug_sql: true`))
)
// Load the defaults and the optional settings file.
// yamlsettings.LoadFiles("defaults.yml", "settings.yml", &config)
var config Settings
yamlsettings.LoadReaders(defaultsYaml, settingsYaml, &config)
fmt.Printf("Redis host: %s\n", config.Databases.Redis.Host)
fmt.Printf("Secret: %s\n", config.AppConfig.SecretKey)
// Load from yaml files on disk.
yamlsettings.LoadFiles("example/defaults.yml", "example/settings.yml", &config)
fmt.Printf("Redis host: %s\n", config.Databases.Redis.Host)
}