From e043e6e9eb214616fe4ac310eb8527abe2e17e7d Mon Sep 17 00:00:00 2001 From: Linken Dinh Date: Thu, 24 Jun 2021 15:38:44 +0200 Subject: [PATCH] error if environment variables has not been replaced --- .gitignore | 1 + go.mod | 10 +++--- go.sum | 12 +++++-- main.go | 33 ++++++++++++++++++- main_test.go | 24 ++++++++++++++ .../configs-env-not-replaced/base.toml | 5 +++ 6 files changed, 78 insertions(+), 7 deletions(-) create mode 100644 tests/fixtures/configs-env-not-replaced/base.toml diff --git a/.gitignore b/.gitignore index fb22a30..7674c0f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ ./configs/local.toml *.coverprofile +.envrc.local.sh diff --git a/go.mod b/go.mod index 90ab2f6..de5a71f 100644 --- a/go.mod +++ b/go.mod @@ -3,17 +3,19 @@ module github.com/beckend/go-config go 1.16 require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/evanphx/json-patch v0.5.2 github.com/fatih/color v1.12.0 github.com/go-playground/validator/v10 v10.6.1 - github.com/gookit/goutil v0.3.13 + github.com/gookit/goutil v0.3.14 + github.com/jeremywohl/flatten v1.0.1 // indirect github.com/json-iterator/go v1.1.11 github.com/kr/pretty v0.2.0 // indirect github.com/mileusna/conditional v0.5.0 github.com/mitchellh/mapstructure v1.4.1 - github.com/onsi/ginkgo v1.16.2 - github.com/onsi/gomega v1.12.0 - github.com/pelletier/go-toml v1.9.1 + github.com/onsi/ginkgo v1.16.4 + github.com/onsi/gomega v1.13.0 + github.com/pelletier/go-toml v1.9.3 golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect golang.org/x/sys v0.0.0-20210521203332-0cec03c779c1 // indirect diff --git a/go.sum b/go.sum index c41956e..2381689 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,6 @@ 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/evanphx/json-patch v0.5.2 h1:xVCHIVMUu1wtM/VkR9jVZ45N3FhZfYMMYGorLCR8P3k= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= -github.com/fatih/color v1.11.0 h1:l4iX0RqNnx/pU7rY2DB/I+znuYY0K3x6Ywac6EIr0PA= -github.com/fatih/color v1.11.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -39,7 +37,11 @@ github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gookit/goutil v0.3.13 h1:jdjuMjFwtcDeyYPyzwivs6ksVRGHhNjRIDfXViX8Mrc= github.com/gookit/goutil v0.3.13/go.mod h1:DdrxLZc3yakbuElOtTH8F2SWu3XhaJohgvKHSP0JRak= +github.com/gookit/goutil v0.3.14 h1:ZEdZR+Vkvcjz0SSC0MpjtD+Kwlg/uagpiddh6L2ko+0= +github.com/gookit/goutil v0.3.14/go.mod h1:YdGV0ObqRUlRq4/RzAQBHcd1Wzl/jKw7cppDBtD3q+U= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jeremywohl/flatten v1.0.1 h1:LrsxmB3hfwJuE+ptGOijix1PIfOoKLJ3Uee/mzbgtrs= +github.com/jeremywohl/flatten v1.0.1/go.mod h1:4AmD/VxjWcI5SRB0n6szE2A6s2fsNHDLO0nAlMHgfLQ= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= @@ -74,12 +76,18 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.2 h1:HFB2fbVIlhIfCfOW81bZFbiC/RvnpXSdhbF2/DJr134= github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.12.0 h1:p4oGGk2M2UJc0wWN4lHFvIB71lxsh0T/UiKCCgFADY8= github.com/onsi/gomega v1.12.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= +github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/pelletier/go-toml v1.9.1 h1:a6qW1EVNZWH9WGI6CsYdD8WAylkoXBS5yv0XHlh17Tc= github.com/pelletier/go-toml v1.9.1/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/main.go b/main.go index 8d99eec..4fefaff 100644 --- a/main.go +++ b/main.go @@ -3,19 +3,22 @@ package config import ( errors "errors" + fmt "fmt" io "io" fs "io/fs" os "os" path "path" reflect "reflect" + strings "strings" environment "github.com/beckend/go-config/pkg/environment" file "github.com/beckend/go-config/pkg/file" - "github.com/beckend/go-config/pkg/reflection" + reflection "github.com/beckend/go-config/pkg/reflection" singletons "github.com/beckend/go-config/pkg/singletons" validation "github.com/beckend/go-config/pkg/validation" walkertype "github.com/beckend/go-config/pkg/walker-type" validator "github.com/go-playground/validator/v10" + flatten "github.com/jeremywohl/flatten" envutil "github.com/gookit/goutil/envutil" jsoniter "github.com/json-iterator/go" @@ -173,6 +176,10 @@ func New(options *NewOptions) (*Config, error) { err = nil } + if err == nil { + err = validateStructNoUnmappedEnvVariables(options.ConfigUnmarshal) + } + return &Config{ ErrorsValidation: errsValidation, }, err @@ -182,3 +189,27 @@ func New(options *NewOptions) (*Config, error) { ErrorsValidation: nil, }, err } + +func validateStructNoUnmappedEnvVariables(input interface{}) (err error) { + var interfaceMapped map[string]interface{} + inrec, err := json.Marshal(input) + if err != nil { + return err + } + err = json.Unmarshal(inrec, &interfaceMapped) + if err != nil { + return err + } + + interfaceFlat, err := flatten.Flatten(interfaceMapped, "", flatten.DotStyle) + + for key, value := range interfaceFlat { + valueString := fmt.Sprintf("%v", value) + if strings.HasPrefix(valueString, "${") && strings.HasSuffix(valueString, "}") { + fmt.Printf("key: %s - environment variable not replaced: %s\n", key, valueString) + err = errors.New("validation failed due to missing replacement(s) of environment variable") + } + } + + return err +} diff --git a/main_test.go b/main_test.go index 643e576..99a8c09 100644 --- a/main_test.go +++ b/main_test.go @@ -37,6 +37,18 @@ type TestValidateStructOneFail struct { RunEnV string `validate:"required"` } +type TestValidateStructMissingEnv struct { + RunEnV string `validate:"required"` + Ntest1 struct { + Nest2 struct { + Value1 string `validate:"required"` + Nest3 struct { + Value2 string `validate:"required"` + } + } + } +} + var _ = Describe("pkg main", func() { _, pathCurrentFile, _, _ := runtime.Caller(0) pathDirCurrent, _ := filepath.Split(pathCurrentFile) @@ -215,6 +227,18 @@ var _ = Describe("pkg main", func() { }) }) + When("struct", func() { + It("local.toml has the last word.", func() { + var result TestValidateStructMissingEnv + _, err := config.New(&config.NewOptions{ + ConfigUnmarshal: &result, + PathConfigs: path.Join(pathFixtures, "configs-env-not-replaced"), + }) + + Expect(err.Error()).To(ContainSubstring("missing replacement")) + }) + }) + When("configs-custom test1.toml", func() { It("works", func() { var result map[string]interface{} diff --git a/tests/fixtures/configs-env-not-replaced/base.toml b/tests/fixtures/configs-env-not-replaced/base.toml new file mode 100644 index 0000000..2220f3a --- /dev/null +++ b/tests/fixtures/configs-env-not-replaced/base.toml @@ -0,0 +1,5 @@ +RunEnv = '${_THIS_SHOULD_NOT_EXIST}' +[Ntest1.Nest2] +Value1 = "${_THIS_SHOULD_NOT_EXIST}" +[Ntest1.Nest2.Nest3] +Value2 = "${_THIS_SHOULD_NOT_EXIST}"