From e1af797fe5c8a15f765cd33e8547e02a1b0ce919 Mon Sep 17 00:00:00 2001 From: Luiz Augusto Volpi Nascimento Date: Fri, 11 Sep 2020 11:48:56 -0300 Subject: [PATCH] =?UTF-8?q?corre=C3=A7=C3=A3o=20do=20major=20v2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- v2/error.go | 15 +++ v2/examples/env/main.go | 23 +++++ v2/examples/json/config.json | 8 ++ v2/examples/json/main.go | 23 +++++ v2/examples/toml/config.toml | 5 + v2/examples/toml/main.go | 23 +++++ v2/examples/xml/config.xml | 5 + v2/examples/xml/main.go | 23 +++++ v2/examples/yaml/config.yaml | 5 + v2/examples/yaml/main.go | 23 +++++ v2/go.mod | 10 ++ v2/go.sum | 15 +++ v2/gonfig.go | 64 +++++++++++++ v2/gonfig_test.go | 176 +++++++++++++++++++++++++++++++++++ v2/test/config.json | 4 + v2/test/config.toml | 2 + v2/test/config.xml | 4 + v2/test/config.xyz | 1 + v2/test/config.yaml | 2 + v2/test/invalid_config.json | 5 + v2/test/invalid_config.toml | 2 + v2/test/invalid_config.xml | 4 + v2/test/invalid_config.yaml | 4 + 23 files changed, 446 insertions(+) create mode 100644 v2/error.go create mode 100644 v2/examples/env/main.go create mode 100644 v2/examples/json/config.json create mode 100644 v2/examples/json/main.go create mode 100644 v2/examples/toml/config.toml create mode 100644 v2/examples/toml/main.go create mode 100644 v2/examples/xml/config.xml create mode 100644 v2/examples/xml/main.go create mode 100644 v2/examples/yaml/config.yaml create mode 100644 v2/examples/yaml/main.go create mode 100644 v2/go.mod create mode 100644 v2/go.sum create mode 100644 v2/gonfig.go create mode 100644 v2/gonfig_test.go create mode 100644 v2/test/config.json create mode 100644 v2/test/config.toml create mode 100644 v2/test/config.xml create mode 100644 v2/test/config.xyz create mode 100644 v2/test/config.yaml create mode 100644 v2/test/invalid_config.json create mode 100644 v2/test/invalid_config.toml create mode 100644 v2/test/invalid_config.xml create mode 100644 v2/test/invalid_config.yaml diff --git a/v2/error.go b/v2/error.go new file mode 100644 index 0000000..19e8581 --- /dev/null +++ b/v2/error.go @@ -0,0 +1,15 @@ +package gonfig + +const ( + // LoadError = "Error loading the configuration" + LoadError = GonfigError("Error loading the configuration") + // UnsupportedFileError = "Unsupported file extension" + UnsupportedFileError = GonfigError("Unsupported file extension") +) + +// GonfigError is an error in the module. +type GonfigError string + +func (g GonfigError) Error() string { + return string(g) +} diff --git a/v2/examples/env/main.go b/v2/examples/env/main.go new file mode 100644 index 0000000..8edfe58 --- /dev/null +++ b/v2/examples/env/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + + "github.com/luizvnasc/gonfig/v2" +) + +//Config struct to store the app configuration +type Config struct { + Version string `env:"VERSION"` + Description string `env:"DESCRIPTION"` + Redis struct { + Host string `env:"REDIS_HOST"` + Port uint `env:"REDIS_PORT"` + } +} + +func main() { + var config Config + gonfig.Load(&config) + fmt.Printf("%v", config) +} diff --git a/v2/examples/json/config.json b/v2/examples/json/config.json new file mode 100644 index 0000000..6592d83 --- /dev/null +++ b/v2/examples/json/config.json @@ -0,0 +1,8 @@ +{ + "version": "1.0.0", + "desc": "An example using json", + "redis": { + "host": "127.0.0.1", + "port": 6379 + } +} diff --git a/v2/examples/json/main.go b/v2/examples/json/main.go new file mode 100644 index 0000000..ebe2e7c --- /dev/null +++ b/v2/examples/json/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + + "github.com/luizvnasc/gonfig/v2" +) + +//Config struct to store the app configuration +type Config struct { + Version string `json:"version"` + Description string `json:"desc"` + Redis struct { + Host string `json:"host"` + Port uint `json:"port"` + } `json:"redis"` +} + +func main() { + var config Config + gonfig.Load(&config, "config.json") + fmt.Printf("%v", config) +} diff --git a/v2/examples/toml/config.toml b/v2/examples/toml/config.toml new file mode 100644 index 0000000..6747ba7 --- /dev/null +++ b/v2/examples/toml/config.toml @@ -0,0 +1,5 @@ +version = "1.0.0" +desc = "An example using toml" +[redis] + host = "127.0.0.1" + port = 6379 diff --git a/v2/examples/toml/main.go b/v2/examples/toml/main.go new file mode 100644 index 0000000..e9a96c9 --- /dev/null +++ b/v2/examples/toml/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + + "github.com/luizvnasc/gonfig/v2" +) + +//Config struct to store the app configuration +type Config struct { + Version string `toml:"version"` + Description string `toml:"desc"` + Redis struct { + Host string `toml:"host"` + Port uint `toml:"port"` + } `toml:"redis"` +} + +func main() { + var config Config + gonfig.Load(&config, "config.toml") + fmt.Printf("%v", config) +} diff --git a/v2/examples/xml/config.xml b/v2/examples/xml/config.xml new file mode 100644 index 0000000..cc25761 --- /dev/null +++ b/v2/examples/xml/config.xml @@ -0,0 +1,5 @@ + + 1.0.0 + A xml exemple + + diff --git a/v2/examples/xml/main.go b/v2/examples/xml/main.go new file mode 100644 index 0000000..f4feead --- /dev/null +++ b/v2/examples/xml/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + + "github.com/luizvnasc/gonfig/v2" +) + +//Config struct to store the app configuration +type Config struct { + Version string `xml:"version"` + Description string `xml:"description"` + Redis struct { + Host string `xml:"host,attr"` + Port uint `xml:"port,attr"` + } `xml:"redis"` +} + +func main() { + var config Config + gonfig.Load(&config, "config.xml") + fmt.Printf("%v", config) +} diff --git a/v2/examples/yaml/config.yaml b/v2/examples/yaml/config.yaml new file mode 100644 index 0000000..e25ef50 --- /dev/null +++ b/v2/examples/yaml/config.yaml @@ -0,0 +1,5 @@ +version: 1.0.0 +desc: An example using yaml +redis: + host: 127.0.0.1 + port: 6379 diff --git a/v2/examples/yaml/main.go b/v2/examples/yaml/main.go new file mode 100644 index 0000000..ff0d1d8 --- /dev/null +++ b/v2/examples/yaml/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + + "github.com/luizvnasc/gonfig/v2" +) + +//Config struct to store the app configuration +type Config struct { + Version string `yaml:"version"` + Description string `yaml:"desc"` + Redis struct { + Host string `yaml:"host"` + Port uint `yaml:"port"` + } `yaml:"redis"` +} + +func main() { + var config Config + gonfig.Load(&config, "config.yaml") + fmt.Printf("%v", config) +} diff --git a/v2/go.mod b/v2/go.mod new file mode 100644 index 0000000..0981b3b --- /dev/null +++ b/v2/go.mod @@ -0,0 +1,10 @@ +module github.com/luizvnasc/gonfig/v2 + +go 1.12 + +require ( + github.com/luizvnasc/goenv v0.0.0-20191218175301-c19dd8aa8023 + github.com/pelletier/go-toml v1.6.0 + gopkg.in/yaml.v2 v2.2.7 // indirect + gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2 +) diff --git a/v2/go.sum b/v2/go.sum new file mode 100644 index 0000000..e43345f --- /dev/null +++ b/v2/go.sum @@ -0,0 +1,15 @@ +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/luizvnasc/goenv v0.0.0-20191218175301-c19dd8aa8023 h1:ObI7S/YvYRFTNWeqWvn9TPsfqu64uo9DjDc4q+7hLVc= +github.com/luizvnasc/goenv v0.0.0-20191218175301-c19dd8aa8023/go.mod h1:G9RRDiWXzqfsaLdNrhTWG2ceSs3dXQ2AAJuDQ3bR26M= +github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4= +github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2 h1:XZx7nhd5GMaZpmDaEHFVafUZC7ya0fuo7cSJ3UCKYmM= +gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v2/gonfig.go b/v2/gonfig.go new file mode 100644 index 0000000..831a6d7 --- /dev/null +++ b/v2/gonfig.go @@ -0,0 +1,64 @@ +package gonfig + +import ( + "encoding/json" + "encoding/xml" + "io/ioutil" + "os" + "path/filepath" + + "github.com/luizvnasc/goenv" + "github.com/pelletier/go-toml" + "gopkg.in/yaml.v3" +) + +type unmarshalerFunc func(data []byte, v interface{}) error + +// Load a struct with the configuration from a config file. +func Load(config interface{}, args ...string) error { + if len(args) == 0 { + err := goenv.Unmarshal(config) + return err + } + path := args[0] + unmarshaler, err := getUnmarshaler(path) + if err != nil { + return err + } + content, err := getFileContent(path) + if err != nil { + return LoadError + } + err = unmarshaler(content, config) + if err != nil { + return LoadError + } + return nil +} + +func getUnmarshaler(path string) (unmarshalerFunc, error) { + ext := filepath.Ext(path) + + switch { + case ext == ".json": + return json.Unmarshal, nil + case ext == ".xml": + return xml.Unmarshal, nil + case ext == ".yaml" || ext == ".yml": + return yaml.Unmarshal, nil + case ext == ".toml": + return toml.Unmarshal, nil + default: + return nil, UnsupportedFileError + } +} + +func getFileContent(path string) (bytes []byte, err error) { + configFile, err := os.Open(path) + if err != nil { + return + } + defer configFile.Close() + bytes, err = ioutil.ReadAll(configFile) + return +} diff --git a/v2/gonfig_test.go b/v2/gonfig_test.go new file mode 100644 index 0000000..a55a85f --- /dev/null +++ b/v2/gonfig_test.go @@ -0,0 +1,176 @@ +package gonfig_test + +import ( + "encoding/json" + "io/ioutil" + "os" + "reflect" + "testing" + + "github.com/luizvnasc/gonfig/v2" +) + +const ( + validJsonFile = "./test/config.json" + invalidJsonFile = "./test/invalid.json" + invalidJsonBodyFile = "./test/invalid_config.json" + validXMLFile = "./test/config.xml" + invalidXMLBodyFile = "./test/invalid_config.xml" + unsupportedFile = "./test/config.xyz" + validYamlFile = "./test/config.yaml" + invalidYamlBodyFile = "./test/invalid_config.yaml" + validTomlFile = "./test/config.toml" + invalidTomlBodyFile = "./test/invalid_config.toml" +) + +type SomeConfiguration struct { + Version string `json:"version" xml:"version" yaml:"version" toml:"version" env:"VERSION"` + ProjectName string `json:"project_name" xml:"project-name" yaml:"project_name" toml:"project_name" env:"PROJECT_NAME"` +} + +var configValid SomeConfiguration + +func init() { + file, err := os.Open(validJsonFile) + if err != nil { + panic("Error Loading teste sample") + } + b, err := ioutil.ReadAll(file) + if err != nil { + panic("Error Loading teste sample") + } + json.Unmarshal(b, &configValid) +} +func TestGonfig(t *testing.T) { + t.Run("JSON tests", func(t *testing.T) { + t.Run("Load a configuration from a valid json file", func(t *testing.T) { + config := SomeConfiguration{} + err := gonfig.Load(&config, validJsonFile) + if err != nil { + t.Errorf("Error loading the configuration: %v", err) + } + if !reflect.DeepEqual(config, configValid) { + t.Errorf("Error loading the configuration: expected %v, got %v", configValid, config) + } + }) + + t.Run("Load a configuration from an invalid json file", func(t *testing.T) { + config := SomeConfiguration{} + err := gonfig.Load(&config, invalidJsonFile) + if err == nil { + t.Errorf("It was expected to get an error. Got nil") + } + if err != gonfig.LoadError { + t.Errorf("Expected the error %v, got %v", gonfig.LoadError, err) + } + }) + + t.Run("Load a configuration from an invalid json body", func(t *testing.T) { + config := SomeConfiguration{} + err := gonfig.Load(&config, invalidJsonBodyFile) + if err == nil { + t.Errorf("It was expected to get an error. Got nil") + } + if err != gonfig.LoadError { + t.Errorf("Expected the error %v, got %v", gonfig.LoadError, err) + } + }) + }) + t.Run("XML tests", func(t *testing.T) { + t.Run("Load a configuration from a valid xml file", func(t *testing.T) { + config := SomeConfiguration{} + err := gonfig.Load(&config, validXMLFile) + if err != nil { + t.Errorf("Error loading the configuration: %v", err) + } + if !reflect.DeepEqual(config, configValid) { + t.Errorf("Error loading the configuration: expected %v, got %v", configValid, config) + } + }) + t.Run("Load a configuration from an invalid xml body", func(t *testing.T) { + config := SomeConfiguration{} + err := gonfig.Load(&config, invalidXMLBodyFile) + if err == nil { + t.Errorf("It was expected to get an error. Got nil") + } + if err != gonfig.LoadError { + t.Errorf("Expected the error %v, got %v", gonfig.LoadError, err) + } + }) + }) + t.Run("YAML tests", func(t *testing.T) { + t.Run("Load a configuration from a valid yaml file", func(t *testing.T) { + config := SomeConfiguration{} + err := gonfig.Load(&config, validYamlFile) + if err != nil { + t.Errorf("Error loading the configuration: %v", err) + } + if !reflect.DeepEqual(config, configValid) { + t.Errorf("Error loading the configuration: expected %v, got %v", configValid, config) + } + }) + + t.Run("Load a configuration from an invalid yaml body", func(t *testing.T) { + config := SomeConfiguration{} + err := gonfig.Load(&config, invalidYamlBodyFile) + if err == nil { + t.Errorf("It was expected to get an error. Got nil") + } + if err != gonfig.LoadError { + t.Errorf("Expected the error %v, got %v", gonfig.LoadError, err) + } + }) + }) + + t.Run("TOML tests", func(t *testing.T) { + t.Run("Load a configuration from a valid toml file", func(t *testing.T) { + config := SomeConfiguration{} + err := gonfig.Load(&config, validTomlFile) + if err != nil { + t.Errorf("Error loading the configuration: %v", err) + } + if !reflect.DeepEqual(config, configValid) { + t.Errorf("Error loading the configuration: expected %v, got %v", configValid, config) + } + }) + + t.Run("Load a configuration from an invalid toml body", func(t *testing.T) { + config := SomeConfiguration{} + err := gonfig.Load(&config, invalidTomlBodyFile) + if err == nil { + t.Errorf("It was expected to get an error. Got nil") + } + if err != gonfig.LoadError { + t.Errorf("Expected the error %v, got %v", gonfig.LoadError, err) + } + }) + }) + + t.Run("ENV tests", func(t *testing.T) { + t.Run("Load a configuration from ENV", func(t *testing.T) { + config := SomeConfiguration{} + os.Setenv("VERSION", configValid.Version) + os.Setenv("PROJECT_NAME", configValid.ProjectName) + err := gonfig.Load(&config) + if err != nil { + t.Errorf("Error loading the configuration: %v", err) + } + if !reflect.DeepEqual(config, configValid) { + t.Errorf("Error loading the configuration: expected %v, got %v", configValid, config) + } + }) + + }) + + t.Run("Unsupported file", func(t *testing.T) { + config := SomeConfiguration{} + err := gonfig.Load(&config, unsupportedFile) + if err == nil { + t.Errorf("It was expected to get an error. Got nil") + } + if err != gonfig.UnsupportedFileError { + t.Errorf("Expected the error %v, got %v", gonfig.UnsupportedFileError, err) + } + }) + +} diff --git a/v2/test/config.json b/v2/test/config.json new file mode 100644 index 0000000..031f400 --- /dev/null +++ b/v2/test/config.json @@ -0,0 +1,4 @@ +{ + "version": "1.0.0", + "project_name": "gonfig" +} diff --git a/v2/test/config.toml b/v2/test/config.toml new file mode 100644 index 0000000..f987b7f --- /dev/null +++ b/v2/test/config.toml @@ -0,0 +1,2 @@ +version = "1.0.0" +project_name = "gonfig" diff --git a/v2/test/config.xml b/v2/test/config.xml new file mode 100644 index 0000000..e8e7574 --- /dev/null +++ b/v2/test/config.xml @@ -0,0 +1,4 @@ + + 1.0.0 + gonfig + diff --git a/v2/test/config.xyz b/v2/test/config.xyz new file mode 100644 index 0000000..e89b2a4 --- /dev/null +++ b/v2/test/config.xyz @@ -0,0 +1 @@ +unsupported file \ No newline at end of file diff --git a/v2/test/config.yaml b/v2/test/config.yaml new file mode 100644 index 0000000..6c7e764 --- /dev/null +++ b/v2/test/config.yaml @@ -0,0 +1,2 @@ +version: 1.0.0 +project_name: gonfig diff --git a/v2/test/invalid_config.json b/v2/test/invalid_config.json new file mode 100644 index 0000000..d6c877c --- /dev/null +++ b/v2/test/invalid_config.json @@ -0,0 +1,5 @@ + + +

It's not JSON! + + diff --git a/v2/test/invalid_config.toml b/v2/test/invalid_config.toml new file mode 100644 index 0000000..6c7e764 --- /dev/null +++ b/v2/test/invalid_config.toml @@ -0,0 +1,2 @@ +version: 1.0.0 +project_name: gonfig diff --git a/v2/test/invalid_config.xml b/v2/test/invalid_config.xml new file mode 100644 index 0000000..2129ce1 --- /dev/null +++ b/v2/test/invalid_config.xml @@ -0,0 +1,4 @@ + + 1.0.0 + gonfig + diff --git a/v2/test/invalid_config.yaml b/v2/test/invalid_config.yaml new file mode 100644 index 0000000..f805bcf --- /dev/null +++ b/v2/test/invalid_config.yaml @@ -0,0 +1,4 @@ + +1.0.0 +gonfig +