From a989648086c7aa916af836bd5242f57fb39da97a Mon Sep 17 00:00:00 2001 From: Stan Shulga Date: Thu, 14 Jun 2018 02:46:28 +0500 Subject: [PATCH 1/2] added simple fix in test --- utils/json_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/json_test.go b/utils/json_test.go index 0823488..d1c7f79 100644 --- a/utils/json_test.go +++ b/utils/json_test.go @@ -2,10 +2,11 @@ package utils_test import ( "encoding/json" + "testing" + "github.com/cheebo/go-config/utils" "github.com/davecgh/go-spew/spew" "github.com/stretchr/testify/assert" - "testing" ) type Race struct { @@ -42,7 +43,7 @@ func TestParse(t *testing.T) { data, err := json.Marshal(cfg) assert.NoError(err) - m := utils.JsonParse(data) + m, _ := utils.JsonParse(data) spew.Dump(m) assert.Equal(cfg.Name, m["name"].(string), "Incorrect name") assert.Equal(float64(cfg.Age), m["age"].(float64), "Incorrect age") From 1a0e568e07c54a0a83f22243f18a664c5bd10572 Mon Sep 17 00:00:00 2001 From: Stan Shulga Date: Thu, 14 Jun 2018 02:47:17 +0500 Subject: [PATCH 2/2] added kubernetes support --- sources/k8s/README.md | 14 +++++ sources/k8s/k8s.go | 140 ++++++++++++++++++++++++++++++++++++++++++ utils/json.go | 25 +++++--- 3 files changed, 170 insertions(+), 9 deletions(-) create mode 100644 sources/k8s/README.md create mode 100644 sources/k8s/k8s.go diff --git a/sources/k8s/README.md b/sources/k8s/README.md new file mode 100644 index 0000000..4642838 --- /dev/null +++ b/sources/k8s/README.md @@ -0,0 +1,14 @@ +### Usage +```go +`k8s:"a,b,c"` +``` +> Support 2 type configmaps +> 1) configmap from file +> a) configmap name (required) +> b) file name (required) +> c) override namespace or empty string +> +> 2) configmap from literal +> a) configmap name (required) +> b) empty string +> c) override namespace or empty string diff --git a/sources/k8s/k8s.go b/sources/k8s/k8s.go new file mode 100644 index 0000000..3764bcc --- /dev/null +++ b/sources/k8s/k8s.go @@ -0,0 +1,140 @@ +package k8s + +import ( + "fmt" + "reflect" + "strings" + + "github.com/cheebo/go-config" + "github.com/cheebo/go-config/utils" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +type k8s struct { + namespace string + client *kubernetes.Clientset + data map[string]interface{} + k8s map[string]interface{} + values map[string]*go_config.Variable +} + +func Source(namespace string, client *kubernetes.Clientset) go_config.Source { + return &k8s{ + namespace: namespace, + client: client, + data: make(map[string]interface{}), + } +} + +func (self *k8s) Init(vals map[string]*go_config.Variable) error { + self.values = vals + + var data interface{} + + for name, val := range vals { + name = self.name(name) + namespace := self.namespace + + tag := val.Tag.Get("k8s") + opts := strings.Split(tag, ",") + + if len(opts[0]) > 0 { + // override namespace + if len(opts) == 3 && len(opts[2]) > 0 { + namespace = opts[2] + } + + cmap, err := self.client.CoreV1().ConfigMaps(namespace).Get(opts[0], metav1.GetOptions{}) + if err != nil { + return err + } + + if len(opts) == 1 || (len(opts) > 1 && len(opts[1]) == 0) { + // from literal + data = cmap.Data + } else { + // from file + if d, ok := cmap.Data[opts[1]]; ok { + data = []byte(d) + } else { + return fmt.Errorf("CofigMap %s not contained file %s.", opts[0], opts[1]) + } + } + + switch val.Type.Kind() { + case reflect.Struct: + fallthrough + case reflect.Slice: + m, err := utils.JsonParse(data) + if err != nil { + return err + } + for n, v := range m { + self.data[name+"."+n] = v + } + default: // FIXME + //self.data[name] = data + } + } + } + return nil +} + +func (self *k8s) Int(name string) (int, error) { + val, ok := self.data[self.name(name)] + if !ok { + return 0, nil + } + return int(val.(float64)), nil +} + +func (self *k8s) Float(name string) (float64, error) { + val, ok := self.data[self.name(name)] + if !ok { + return 0, nil + } + + return float64(val.(float64)), nil +} + +func (self *k8s) UInt(name string) (uint, error) { + val, ok := self.data[self.name(name)] + if !ok { + return 0, nil + } + return uint(val.(float64)), nil +} + +func (self *k8s) String(name string) (string, error) { + val, ok := self.data[self.name(name)] + if !ok { + return "", nil + } + return val.(string), nil +} + +func (self *k8s) Bool(name string) (bool, error) { + val, ok := self.data[self.name(name)] + if !ok { + return false, nil + } + b, ok := val.(bool) + if !ok { + return false, nil + } + return b, nil +} + +func (self *k8s) Slice(name, delimiter string, kind reflect.Kind) ([]interface{}, error) { + return []interface{}{}, nil +} + +func (self *k8s) Export(opt ...go_config.SourceOpt) ([]byte, error) { + return []byte{}, nil +} + +func (self *k8s) name(name string) string { + return strings.ToLower(name) +} diff --git a/utils/json.go b/utils/json.go index 3cf8c67..4d04995 100644 --- a/utils/json.go +++ b/utils/json.go @@ -5,17 +5,24 @@ import ( "strings" ) -func JsonParse(data []byte) (map[string]interface{}, error) { - in := map[string]interface{}{} - out := map[string]interface{}{} +func JsonParse(data interface{}) (map[string]interface{}, error) { + in := make(map[string]interface{}) + out := make(map[string]interface{}) - err := json.Unmarshal(data, &in) - if err != nil { - return out, err - } + switch d := data.(type) { + case []byte: + err := json.Unmarshal(d, &in) + if err != nil { + return out, err + } - for f, v := range in { - processJSON(v, name(f, ""), out) + for f, v := range in { + processJSON(v, name(f, ""), out) + } + case map[string]string: + for f, v := range d { + processJSON(v, name(f, ""), out) + } } return out, nil }