From 77f24717990aa795f84dc13560ba5116ef6bfaf4 Mon Sep 17 00:00:00 2001 From: Jiahui Date: Wed, 27 Apr 2022 10:42:38 +0800 Subject: [PATCH] #1339 config support to kube secret yaml (#1340) --- docs/site/src/docs/getting-started/config.md | 4 +- pkg/config/config.go | 50 ++++++++++++++++---- pkg/config/config_test.go | 42 ++++++++++++++-- pkg/config/pre_process.go | 15 ++++-- pkg/config/pre_process_test.go | 4 +- pkg/config/test/secret.yaml | 21 ++++++++ pkg/config/{ => test}/test_clusterfile.yaml | 0 pkg/config/{ => test}/tigera-operator.yaml | 0 8 files changed, 116 insertions(+), 20 deletions(-) create mode 100644 pkg/config/test/secret.yaml rename pkg/config/{ => test}/test_clusterfile.yaml (100%) rename pkg/config/{ => test}/tigera-operator.yaml (100%) diff --git a/docs/site/src/docs/getting-started/config.md b/docs/site/src/docs/getting-started/config.md index 2bb070fc857..0009e147867 100644 --- a/docs/site/src/docs/getting-started/config.md +++ b/docs/site/src/docs/getting-started/config.md @@ -211,7 +211,7 @@ metadata: name: mysql-config spec: path: etc/mysql.yaml - process: value|tojson|tobase64 # pre process pipeline + process: value|toJson|toBase64|toSecret # pre process pipeline data: config: username: root @@ -246,6 +246,8 @@ If strategy is `tojson|tobase64` the hole data will convert to json then convert You can freely combine these processors. +If process is `tosecret`, convert data will be inserted into the secret file specified by path. + This feature is useful for kubernetes secret. ## deep merge configuration (YAML format) diff --git a/pkg/config/config.go b/pkg/config/config.go index 7ad74d1778b..9653cbaf5a8 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -19,13 +19,16 @@ import ( "fmt" "io/ioutil" "path/filepath" + "strings" + + k8sv1 "k8s.io/api/core/v1" "github.com/alibaba/sealer/common" v2 "github.com/alibaba/sealer/types/api/v2" "gopkg.in/yaml.v3" - yaml2 "sigs.k8s.io/yaml" + k8sYaml "sigs.k8s.io/yaml" "github.com/alibaba/sealer/logger" v1 "github.com/alibaba/sealer/types/api/v1" @@ -97,18 +100,21 @@ func (c *Dumper) WriteFiles() (err error) { if err != nil { return err } + convertSecret := strings.Contains(config.Spec.Process, toSecretProcessorName) for _, f := range mountDirs { if !f.IsDir() { continue } configPath := filepath.Join(mountRoot, f.Name(), config.Spec.Path) - if utils.IsExist(configPath) { - //only the YAML format is supported - if config.Spec.Strategy == Merge { - configData, err = getMergeConfigData(configPath, configData) - if err != nil { - return err - } + if convertSecret { + if configData, err = convertSecretYaml(config, configPath); err != nil { + return fmt.Errorf("faild to convert to secret file: %v", err) + } + } + //only the YAML format is supported + if utils.IsExist(configPath) && !convertSecret && config.Spec.Strategy == Merge { + if configData, err = getMergeConfigData(configPath, configData); err != nil { + return err } } @@ -144,7 +150,7 @@ func getMergeConfigData(path string, data []byte) ([]byte, error) { continue } deepMerge(&configMap, &mergeConfigMap) - cfg, err := yaml2.Marshal(&configMap) + cfg, err := k8sYaml.Marshal(&configMap) if err != nil { return nil, err } @@ -173,3 +179,29 @@ func deepMerge(dst, src *map[string]interface{}) { (*dst)[srcK] = dV } } + +func convertSecretYaml(config v1.Config, configPath string) ([]byte, error) { + secret := k8sv1.Secret{} + dataMap := make(map[string]string) + if err := k8sYaml.Unmarshal([]byte(config.Spec.Data), &dataMap); err != nil { + return nil, err + } + if utils.IsExist(configPath) { + rawData, err := ioutil.ReadFile(filepath.Clean(configPath)) + if err != nil { + return nil, err + } + if err = k8sYaml.Unmarshal(rawData, &secret); err != nil { + return nil, err + } + } + if secret.Data == nil { + secret.Data = make(map[string][]byte) + } + //set secret data + for k, v := range dataMap { + v := []byte(v) + secret.Data[k] = v + } + return k8sYaml.Marshal(secret) +} diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index a3df031dfb6..2e0ec2ee441 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -15,6 +15,7 @@ package config import ( + "fmt" "io/ioutil" "testing" @@ -47,7 +48,7 @@ func TestDumper_Dump(t *testing.T) { configs: nil, clusterName: "my-cluster", }, - args{clusterfile: "test_clusterfile.yaml"}, + args{clusterfile: "test/test_clusterfile.yaml"}, false, }, } @@ -86,13 +87,13 @@ func Test_getMergeConfig(t *testing.T) { name: "test", args: args{ data: []byte("spec:\n image: kubernetes:v1.19.8"), - path: "test_clusterfile.yaml", + path: "test/test_clusterfile.yaml", }, }, { name: "test", args: args{ data: []byte("spec:\n template:\n metadata:\n labels:\n name: tigera-operatorssssss"), - path: "tigera-operator.yaml", + path: "test/tigera-operator.yaml", }, }, } @@ -110,3 +111,38 @@ func Test_getMergeConfig(t *testing.T) { }) } } + +func Test_convertSecretYaml(t *testing.T) { + testConfig := v1.Config{} + testConfig.Spec.Data = ` +global: e2FiYzogeHh4fQo= +components: e215c3FsOntjcHU6e3JlcXVlc3Q6IDEwMDBtfX19Cg==` + testConfig.Spec.Process = "value|toJson|toBase64|toSecret" + type args struct { + config v1.Config + configPath string + } + tests := []struct { + name string + args args + }{ + { + "test secret convert to file (file exist)", + args{testConfig, "test/secret.yaml"}, + }, + { + "test secret convert to file (file not exist)", + args{testConfig, "test/secret1.yaml"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := convertSecretYaml(tt.args.config, tt.args.configPath) + if err != nil { + t.Errorf("convertSecretYaml() error = %v", err) + return + } + fmt.Println(string(got)) + }) + } +} diff --git a/pkg/config/pre_process.go b/pkg/config/pre_process.go index 47a274d166d..236c3a13abe 100644 --- a/pkg/config/pre_process.go +++ b/pkg/config/pre_process.go @@ -30,6 +30,7 @@ const ( valueProcessorName = "value" toJSONProcessorName = "toJson" toBase64ProcessorName = "toBase64" + toSecretProcessorName = "toSecret" trueLabelValue = "true" trueLabelKey = "preprocess.value" ) @@ -39,11 +40,12 @@ type PreProcessor interface { } func NewProcessorsAndRun(config *v1.Config) error { - pmap := make(map[string]PreProcessor) - - pmap[valueProcessorName] = &valueProcessor{} - pmap[toJSONProcessorName] = &toJSONProcessor{} - pmap[toBase64ProcessorName] = &toBase64Processor{} + pmap := map[string]PreProcessor{ + valueProcessorName: &valueProcessor{}, + toJSONProcessorName: &toJSONProcessor{}, + toBase64ProcessorName: &toBase64Processor{}, + toSecretProcessorName: nil, + } processors := strings.Split(config.Spec.Process, "|") for _, pname := range processors { @@ -55,6 +57,9 @@ func NewProcessorsAndRun(config *v1.Config) error { logger.Warn("not found config processor: %s", pname) continue } + if prossor == nil { + continue + } if err := prossor.Process(config); err != nil { return err } diff --git a/pkg/config/pre_process_test.go b/pkg/config/pre_process_test.go index c751c469278..73c7c0554f9 100644 --- a/pkg/config/pre_process_test.go +++ b/pkg/config/pre_process_test.go @@ -23,7 +23,7 @@ import ( func TestNewProcessorsAndRun(t *testing.T) { config := &v1.Config{ Spec: v1.ConfigSpec{ - Process: "value|toJson|toBase64", + Process: "value|toJson|toBase64|toSecret", Data: ` config: usrname: root @@ -41,7 +41,7 @@ config: wantErr bool }{ { - name: "test value|toJson|toBase64", + name: "test value|toJson|toBase64|toSecret", args: args{config}, wantErr: false, }, diff --git a/pkg/config/test/secret.yaml b/pkg/config/test/secret.yaml new file mode 100644 index 00000000000..ddf5be6a31b --- /dev/null +++ b/pkg/config/test/secret.yaml @@ -0,0 +1,21 @@ +# Copyright © 2021 Alibaba Group Holding Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +data: +kind: Secret +metadata: + name: gu-demo-configuration + namespace: default +type: Opaque \ No newline at end of file diff --git a/pkg/config/test_clusterfile.yaml b/pkg/config/test/test_clusterfile.yaml similarity index 100% rename from pkg/config/test_clusterfile.yaml rename to pkg/config/test/test_clusterfile.yaml diff --git a/pkg/config/tigera-operator.yaml b/pkg/config/test/tigera-operator.yaml similarity index 100% rename from pkg/config/tigera-operator.yaml rename to pkg/config/test/tigera-operator.yaml