From 698d591788d668cfe0330919f42e848e6993c589 Mon Sep 17 00:00:00 2001 From: Vivek Singh Date: Wed, 30 Oct 2019 21:49:06 +0530 Subject: [PATCH] Provide secrets and configmaps while updating the functions (#1358) --- pkg/fission-cli/cli.go | 6 +-- pkg/fission-cli/function.go | 87 +++++++++++++++++++++++-------------- 2 files changed, 57 insertions(+), 36 deletions(-) diff --git a/pkg/fission-cli/cli.go b/pkg/fission-cli/cli.go index 39cf2070..1ad8db56 100644 --- a/pkg/fission-cli/cli.go +++ b/pkg/fission-cli/cli.go @@ -118,8 +118,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.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."} + 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. In the case of fn update the the secrets will be replaced by the provided list of secrets."} + 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. In case of fn update the configmaps will be replaced by the provided list of configmaps."} fnLogReverseQueryFlag := cli.BoolFlag{Name: "reverse, r", Usage: "specify the log reverse query base on time, it will be invalid if the 'follow' flag is specified"} 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"} @@ -131,7 +131,7 @@ func NewCliApp() *cli.App { {Name: "create", Usage: "Create new function (and optionally, an HTTP route to it)", Flags: []cli.Flag{fnNameFlag, fnNamespaceFlag, fnEnvNameFlag, envNamespaceFlag, specSaveFlag, fnCodeFlag, fnSrcArchiveFlag, fnDeployArchiveFlag, fnKeepURLFlag, fnEntryPointFlag, fnBuildCmdFlag, fnPkgNameFlag, htUrlFlag, htMethodFlag, minCpu, maxCpu, minMem, maxMem, minScale, maxScale, fnExecutorTypeFlag, targetcpu, fnCfgMapFlag, fnSecretFlag, specializationTimeoutFlag, fnExecutionTimeoutFlag}, Action: fnCreate}, {Name: "get", Usage: "Get function source code", Flags: []cli.Flag{fnNameFlag, fnNamespaceFlag}, Action: fnGet}, {Name: "getmeta", Usage: "Get function metadata", Flags: []cli.Flag{fnNameFlag, fnNamespaceFlag}, Action: fnGetMeta}, - {Name: "update", Usage: "Update function source code", Flags: []cli.Flag{fnNameFlag, fnNamespaceFlag, fnEnvNameFlag, envNamespaceFlag, fnCodeFlag, fnSrcArchiveFlag, fnDeployArchiveFlag, fnKeepURLFlag, fnEntryPointFlag, fnPkgNameFlag, pkgNamespaceFlag, fnBuildCmdFlag, fnForceFlag, minCpu, maxCpu, minMem, maxMem, minScale, maxScale, fnExecutorTypeFlag, targetcpu, specializationTimeoutFlag, fnExecutionTimeoutFlag}, Action: fnUpdate}, + {Name: "update", Usage: "Update function source code", Flags: []cli.Flag{fnNameFlag, fnNamespaceFlag, fnEnvNameFlag, envNamespaceFlag, fnCodeFlag, fnSrcArchiveFlag, fnDeployArchiveFlag, fnKeepURLFlag, fnEntryPointFlag, fnPkgNameFlag, pkgNamespaceFlag, fnBuildCmdFlag, fnForceFlag, minCpu, maxCpu, minMem, maxMem, minScale, maxScale, fnExecutorTypeFlag, targetcpu, specializationTimeoutFlag, fnExecutionTimeoutFlag, fnSecretFlag, fnCfgMapFlag}, Action: fnUpdate}, {Name: "delete", Usage: "Delete function", Flags: []cli.Flag{fnNameFlag, fnNamespaceFlag}, Action: fnDelete}, // TODO : for fnList, i feel like it's nice to allow --fns all, to list functions across all namespaces for cluster admins, although, this is against ns isolation. // so, in the future, if we end up using kubeconfig in fission cli and enforcing rolebindings to be created for users by admins etc, we can add this option at the time. diff --git a/pkg/fission-cli/function.go b/pkg/fission-cli/function.go index d5a59688..23fb16b9 100644 --- a/pkg/fission-cli/function.go +++ b/pkg/fission-cli/function.go @@ -524,54 +524,63 @@ func fnUpdate(c *cli.Context) error { buildcmd := c.String("buildcmd") force := c.Bool("force") - secretName := c.String("secret") - cfgMapName := c.String("configmap") + secretNames := c.StringSlice("secret") + cfgMapNames := c.StringSlice("configmap") + specializationTimeout := c.Int("specializationtimeout") if len(srcArchiveFiles) > 0 && len(deployArchiveFiles) > 0 { log.Fatal("Need either of --src or --deploy and not both arguments.") } - if len(secretName) > 0 { - if len(function.Spec.Secrets) > 1 { - log.Fatal("Please use 'fission spec apply' to update list of secrets") - } + var secrets []fv1.SecretReference + var configMaps []fv1.ConfigMapReference + + if len(secretNames) > 0 { // check that 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) } - function.Spec.Secrets = []fv1.SecretReference{newSecret} + + function.Spec.Secrets = secrets } - if len(cfgMapName) > 0 { - if len(function.Spec.ConfigMaps) > 1 { - log.Fatal("Please use 'fission spec apply' to update list of configmaps") - } + if len(cfgMapNames) > 0 { // check that 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 the 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 the function", cfgMapName, fnNamespace)) + } } - newCfgMap := fv1.ConfigMapReference{ - Name: cfgMapName, - Namespace: fnNamespace, + for _, cfgMapName := range cfgMapNames { + newCfgMap := fv1.ConfigMapReference{ + Name: cfgMapName, + Namespace: fnNamespace, + } + configMaps = append(configMaps, newCfgMap) } - function.Spec.ConfigMaps = []fv1.ConfigMapReference{newCfgMap} + function.Spec.ConfigMaps = configMaps } if len(envName) > 0 { @@ -710,11 +719,21 @@ func fnList(c *cli.Context) error { w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) - fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", "NAME", "ENV", "EXECUTORTYPE", "MINSCALE", "MAXSCALE", "MINCPU", "MAXCPU", "MINMEMORY", "MAXMEMORY", "TARGETCPU") + fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", "NAME", "ENV", "EXECUTORTYPE", "MINSCALE", "MAXSCALE", "MINCPU", "MAXCPU", "MINMEMORY", "MAXMEMORY", "TARGETCPU", "SECRETS", "CONFIGMAPS") for _, f := range fns { + secrets := f.Spec.Secrets + configMaps := f.Spec.ConfigMaps + var secretsList, configMapList []string + for _, secret := range secrets { + secretsList = append(secretsList, secret.Name) + } + for _, configMap := range configMaps { + configMapList = append(configMapList, configMap.Name) + } mincpu := f.Spec.Resources.Requests.Cpu mincpu().Value() - fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", + + fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", f.Metadata.Name, f.Spec.Environment.Name, f.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType, f.Spec.InvokeStrategy.ExecutionStrategy.MinScale, @@ -723,7 +742,9 @@ func fnList(c *cli.Context) error { f.Spec.Resources.Limits.Cpu().String(), f.Spec.Resources.Requests.Memory().String(), f.Spec.Resources.Limits.Memory().String(), - f.Spec.InvokeStrategy.ExecutionStrategy.TargetCPUPercent) + f.Spec.InvokeStrategy.ExecutionStrategy.TargetCPUPercent, + strings.Join(secretsList, ","), + strings.Join(configMapList, ",")) } w.Flush()