From cd3604766025af0ecc6124d9f9c8e8a329a2e1fc Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Fri, 30 Aug 2019 14:43:24 +0530 Subject: [PATCH] Support for providing multiple CMs and secrets in fn create/update (#1282) --- pkg/fission-cli/function.go | 58 ++++++++++--------- pkg/fission-cli/main.go | 4 +- .../multicfgmap.py.template | 10 ++++ .../multisecret.py.template | 10 ++++ .../test_secret_cfgmap/test_secret_cfgmap.sh | 33 +++++++++++ 5 files changed, 87 insertions(+), 28 deletions(-) create mode 100644 test/tests/test_secret_cfgmap/multicfgmap.py.template create mode 100644 test/tests/test_secret_cfgmap/multisecret.py.template diff --git a/pkg/fission-cli/function.go b/pkg/fission-cli/function.go index 28d89a8b..2b756a7c 100644 --- a/pkg/fission-cli/function.go +++ b/pkg/fission-cli/function.go @@ -226,8 +226,8 @@ func fnCreate(c *cli.Context) error { entrypoint := c.String("entrypoint") pkgName := c.String("pkg") - secretName := c.String("secret") - cfgMapName := c.String("configmap") + secretNames := c.StringSlice("secret") + cfgMapNames := c.StringSlice("configmap") invokeStrategy, err := getInvokeStrategy(c, nil) if err != nil { @@ -299,38 +299,44 @@ func fnCreate(c *cli.Context) error { var secrets []fv1.SecretReference var cfgmaps []fv1.ConfigMapReference - if len(secretName) > 0 { + if len(secretNames) > 0 { // check the referenced secret is in the same ns as the function, if not give a warning. - _, err := client.SecretGet(&metav1.ObjectMeta{ - Namespace: fnNamespace, - Name: secretName, - }) - if k8serrors.IsNotFound(err) { - log.Warn(fmt.Sprintf("Secret %s not found in Namespace: %s. Secret needs to be present in the same namespace as function", secretName, fnNamespace)) + for _, secretName := range secretNames { + _, err := client.SecretGet(&metav1.ObjectMeta{ + Namespace: fnNamespace, + Name: secretName, + }) + if k8serrors.IsNotFound(err) { + log.Warn(fmt.Sprintf("Secret %s not found in Namespace: %s. Secret needs to be present in the same namespace as function", secretName, fnNamespace)) + } } - - newSecret := fv1.SecretReference{ - Name: secretName, - Namespace: fnNamespace, + for _, secretName := range secretNames { + newSecret := fv1.SecretReference{ + Name: secretName, + Namespace: fnNamespace, + } + secrets = append(secrets, newSecret) } - secrets = []fv1.SecretReference{newSecret} } - if len(cfgMapName) > 0 { + if len(cfgMapNames) > 0 { // check the referenced cfgmap is in the same ns as the function, if not give a warning. - _, err := client.ConfigMapGet(&metav1.ObjectMeta{ - Namespace: fnNamespace, - Name: cfgMapName, - }) - if k8serrors.IsNotFound(err) { - log.Warn(fmt.Sprintf("ConfigMap %s not found in Namespace: %s. ConfigMap needs to be present in the same namespace as function", cfgMapName, fnNamespace)) + for _, cfgMapName := range cfgMapNames { + _, err := client.ConfigMapGet(&metav1.ObjectMeta{ + Namespace: fnNamespace, + Name: cfgMapName, + }) + if k8serrors.IsNotFound(err) { + log.Warn(fmt.Sprintf("ConfigMap %s not found in Namespace: %s. ConfigMap needs to be present in the same namespace as function", cfgMapName, fnNamespace)) + } } - - newCfgMap := fv1.ConfigMapReference{ - Name: cfgMapName, - Namespace: fnNamespace, + for _, cfgMapName := range cfgMapNames { + newCfgMap := fv1.ConfigMapReference{ + Name: cfgMapName, + Namespace: fnNamespace, + } + cfgmaps = append(cfgmaps, newCfgMap) } - cfgmaps = []fv1.ConfigMapReference{newCfgMap} } function := &fv1.Function{ diff --git a/pkg/fission-cli/main.go b/pkg/fission-cli/main.go index 4427d704..0dd83c0f 100644 --- a/pkg/fission-cli/main.go +++ b/pkg/fission-cli/main.go @@ -115,8 +115,8 @@ func NewCliApp() *cli.App { fnQueryFlag := cli.StringSliceFlag{Name: "query, q", Usage: "request query parameters: -q key1=value1 -q key2=value2"} fnEntryPointFlag := cli.StringFlag{Name: "entrypoint", Usage: "entry point for environment v2 to load with"} fnBuildCmdFlag := cli.StringFlag{Name: "buildcmd", Usage: "build command for builder to run with"} - fnSecretFlag := cli.StringFlag{Name: "secret", Usage: "function access to secret, should be present in the same namespace as the function"} - fnCfgMapFlag := cli.StringFlag{Name: "configmap", Usage: "function access to configmap, should be present in the same namespace as the function"} + fnSecretFlag := cli.StringSliceFlag{Name: "secret", Usage: "function access to secret, should be present in the same namespace as the function. You can provide multiple secrets using multiple --secrets flags."} + fnCfgMapFlag := cli.StringSliceFlag{Name: "configmap", Usage: "function access to configmap, should be present in the same namespace as the function. You can provide multiple configmaps using multiple --configmap flags."} fnLogCountFlag := cli.StringFlag{Name: "recordcount", Usage: "the n most recent log records"} fnForceFlag := cli.BoolFlag{Name: "force", Usage: "Force update a package even if it is used by one or more functions"} fnExecutorTypeFlag := cli.StringFlag{Name: "executortype", Value: types.ExecutorTypePoolmgr, Usage: "Executor type for execution; one of 'poolmgr', 'newdeploy' defaults to 'poolmgr'"} diff --git a/test/tests/test_secret_cfgmap/multicfgmap.py.template b/test/tests/test_secret_cfgmap/multicfgmap.py.template new file mode 100644 index 00000000..b194f11b --- /dev/null +++ b/test/tests/test_secret_cfgmap/multicfgmap.py.template @@ -0,0 +1,10 @@ +def main(): + path = "/configs/default/{{ FN_CFGMAP }}/TEST_KEY" + path1 = "/configs/default/{{ FN_CFGMAP1 }}/TEST_KEY1" + f = open(path, "r") + data = f.read() + + f1 = open(path1, "r") + data1 = f1.read() + + return data+"-"+data1, 200 diff --git a/test/tests/test_secret_cfgmap/multisecret.py.template b/test/tests/test_secret_cfgmap/multisecret.py.template new file mode 100644 index 00000000..78764be9 --- /dev/null +++ b/test/tests/test_secret_cfgmap/multisecret.py.template @@ -0,0 +1,10 @@ +def main(): + path = "/secrets/default/{{ FN_SECRET }}/TEST_KEY" + path1 = "/secrets/default/{{ FN_SECRET1 }}/TEST_KEY1" + f = open(path, "r") + data = f.read() + #print() + f1 = open(path1, "r") + data1 = f1.read() + + return data+"-"+data1, 200 diff --git a/test/tests/test_secret_cfgmap/test_secret_cfgmap.sh b/test/tests/test_secret_cfgmap/test_secret_cfgmap.sh index 72656049..420de972 100755 --- a/test/tests/test_secret_cfgmap/test_secret_cfgmap.sh +++ b/test/tests/test_secret_cfgmap/test_secret_cfgmap.sh @@ -14,7 +14,9 @@ ROOT=$(dirname $0)/../../.. env=python-$TEST_ID fn=testnormal-$TEST_ID fn_secret=testsecret-$TEST_ID +fn_secret1=testsecret1-$TEST_ID fn_cfgmap=testcfgmap-$TEST_ID +fn_cfgmap1=testcfgmap1-$TEST_ID cleanup() { log "Cleaning up..." @@ -29,7 +31,10 @@ else fi sed "s/{{ FN_SECRET }}/${fn_secret}/g" $(dirname $0)/secret.py.template > $tmp_dir/secret.py +sed -e "s/{{ FN_SECRET }}/${fn_secret}/g" -e "s/{{ FN_SECRET1 }}/${fn_secret1}/g" $(dirname $0)/multisecret.py.template > $tmp_dir/multisecret.py + sed "s/{{ FN_CFGMAP }}/${fn_cfgmap}/g" $(dirname $0)/cfgmap.py.template > $tmp_dir/cfgmap.py +sed -e "s/{{ FN_CFGMAP }}/${fn_cfgmap}/g" -e "s/{{ FN_CFGMAP1 }}/${fn_cfgmap1}/g" $(dirname $0)/multicfgmap.py.template > $tmp_dir/multicfgmap.py checkFunctionResponse() { log "Doing an HTTP GET on the function's route" @@ -68,6 +73,20 @@ sleep 5 timeout 60 bash -c "checkFunctionResponse ${fn_secret} 'TESTVALUE' 'secret'" +log "Creating second secret" +kubectl create secret generic ${fn_secret1} --from-literal=TEST_KEY1="TESTVALUE1" -n default + +log "Creating function with multiple secrets" +fission fn create --name ${fn_secret1} --env $env --code $tmp_dir/multisecret.py --secret ${fn_secret} --secret ${fn_secret1} + +log "Creating route" +fission route create --function ${fn_secret1} --url /${fn_secret1} --method GET + +log "Waiting for router to catch up" +sleep 5 + +timeout 60 bash -c "checkFunctionResponse ${fn_secret1} 'TESTVALUE-TESTVALUE1' 'multiple-secret'" + log "Creating function with newdeploy executorType and new secret value" kubectl patch secrets ${fn_secret} -p '{"data":{"TEST_KEY":"TkVXVkFMCg=="}}' -n default fission fn create --name ${fn_secret}-1 --env $env --code $tmp_dir/secret.py --secret ${fn_secret} --executortype newdeploy @@ -94,6 +113,20 @@ sleep 5 timeout 60 bash -c "checkFunctionResponse ${fn_cfgmap} 'TESTVALUE' 'configmap'" +log "Creating second configmap" +kubectl create configmap ${fn_cfgmap1} --from-literal=TEST_KEY1="TESTVALUE1" -n default + +log "Creating function with multiple configmaps" +fission fn create --name ${fn_cfgmap1} --env $env --code $tmp_dir/multicfgmap.py --configmap ${fn_cfgmap} --configmap ${fn_cfgmap1} + +log "Creating route" +fission route create --function ${fn_cfgmap1} --url /${fn_cfgmap1} --method GET + +log "Waiting for router to catch up" +sleep 5 + +timeout 60 bash -c "checkFunctionResponse ${fn_cfgmap1} 'TESTVALUE-TESTVALUE1' 'multiple-configmap'" + log "Creating function with newdeploy executorType and new configmap value" kubectl patch configmap ${fn_cfgmap} -p '{"data":{"TEST_KEY":"NEWVAL"}}' -n default fission fn create --name ${fn_cfgmap}-1 --env $env --code $tmp_dir/cfgmap.py --configmap ${fn_cfgmap} --executortype newdeploy