From b9513868ed9617e3c3e6e779c37878d4a0030c60 Mon Sep 17 00:00:00 2001 From: neha_gupta Date: Tue, 11 Oct 2022 13:23:47 +0530 Subject: [PATCH] add namespace param for fn and env (#2556) This PR moves fission CLI as closer as possible to kubectl command behaviour. We have improved namespace handling behaviour across CLI. * add namespace param for fn and env * use common fn for ns check * update validation * default namespace for httpTrigger, env and package, config and triggers * use default ns * add namespace filter to spec * add forceNamespace flag * set current namespace * add default namespace in config * add namespace specific destroy * add all namespace in the list of resources * add namespace as global tag * use %s instead of %v * add test cases for namespace * use ns in get all functions --- .github/workflows/push_pr.yaml | 5 +- .github/workflows/upgrade_test.yaml | 3 + cmd/fission-cli/app/app.go | 4 +- pkg/apis/core/v1/validation.go | 13 +- pkg/controller/client/v1/mqtrigger.go | 8 +- pkg/fission-cli/cmd/canaryconfig/command.go | 2 +- pkg/fission-cli/cmd/canaryconfig/create.go | 9 +- pkg/fission-cli/cmd/canaryconfig/delete.go | 10 +- pkg/fission-cli/cmd/canaryconfig/get.go | 11 +- pkg/fission-cli/cmd/canaryconfig/list.go | 19 +- pkg/fission-cli/cmd/canaryconfig/update.go | 10 +- pkg/fission-cli/cmd/environment/command.go | 2 +- pkg/fission-cli/cmd/environment/create.go | 34 ++- pkg/fission-cli/cmd/environment/delete.go | 14 +- pkg/fission-cli/cmd/environment/get.go | 11 +- pkg/fission-cli/cmd/environment/list.go | 25 +- pkg/fission-cli/cmd/environment/pods.go | 14 +- pkg/fission-cli/cmd/environment/update.go | 12 +- pkg/fission-cli/cmd/function/command.go | 5 +- pkg/fission-cli/cmd/function/create.go | 95 ++++--- pkg/fission-cli/cmd/function/delete.go | 13 +- pkg/fission-cli/cmd/function/get.go | 7 +- pkg/fission-cli/cmd/function/getmeta.go | 8 +- pkg/fission-cli/cmd/function/list.go | 21 +- pkg/fission-cli/cmd/function/log.go | 7 +- pkg/fission-cli/cmd/function/pods.go | 12 +- pkg/fission-cli/cmd/function/run_container.go | 8 +- pkg/fission-cli/cmd/function/test.go | 8 +- pkg/fission-cli/cmd/function/update.go | 7 +- .../cmd/function/update_container.go | 8 +- pkg/fission-cli/cmd/httptrigger/command.go | 2 +- pkg/fission-cli/cmd/httptrigger/create.go | 51 ++-- pkg/fission-cli/cmd/httptrigger/delete.go | 8 +- pkg/fission-cli/cmd/httptrigger/get.go | 16 +- pkg/fission-cli/cmd/httptrigger/list.go | 17 +- pkg/fission-cli/cmd/httptrigger/update.go | 8 +- pkg/fission-cli/cmd/kubewatch/command.go | 2 +- pkg/fission-cli/cmd/kubewatch/create.go | 12 +- pkg/fission-cli/cmd/kubewatch/delete.go | 7 +- pkg/fission-cli/cmd/kubewatch/list.go | 18 +- pkg/fission-cli/cmd/mqtrigger/command.go | 2 +- pkg/fission-cli/cmd/mqtrigger/create.go | 26 +- pkg/fission-cli/cmd/mqtrigger/delete.go | 10 +- pkg/fission-cli/cmd/mqtrigger/list.go | 27 +- pkg/fission-cli/cmd/mqtrigger/update.go | 16 +- pkg/fission-cli/cmd/package/command.go | 4 +- pkg/fission-cli/cmd/package/create.go | 38 ++- pkg/fission-cli/cmd/package/delete.go | 9 +- pkg/fission-cli/cmd/package/get.go | 8 +- pkg/fission-cli/cmd/package/info.go | 10 +- pkg/fission-cli/cmd/package/list.go | 23 +- pkg/fission-cli/cmd/package/rebuild.go | 8 +- pkg/fission-cli/cmd/package/update.go | 15 +- pkg/fission-cli/cmd/spec/apply.go | 69 ++++- pkg/fission-cli/cmd/spec/command.go | 7 +- pkg/fission-cli/cmd/spec/destroy.go | 249 +++++++++++++++++- pkg/fission-cli/cmd/spec/list.go | 95 ++++--- pkg/fission-cli/cmd/spec/spec.go | 2 +- pkg/fission-cli/cmd/spec/validate.go | 40 ++- pkg/fission-cli/cmd/timetrigger/command.go | 2 +- pkg/fission-cli/cmd/timetrigger/create.go | 26 +- pkg/fission-cli/cmd/timetrigger/delete.go | 11 +- pkg/fission-cli/cmd/timetrigger/list.go | 18 +- pkg/fission-cli/cmd/timetrigger/update.go | 16 +- pkg/fission-cli/flag/flag.go | 28 +- pkg/fission-cli/flag/key/key.go | 4 + pkg/fission-cli/util/util.go | 70 ++++- pkg/fission-cli/util/util_test.go | 8 + test/kind_CI.sh | 4 + .../test_namespace/test_ns_current_context.sh | 39 +++ .../test_namespace/test_ns_deprecated_flag.sh | 43 +++ test/tests/test_namespace/test_ns_env.sh | 45 ++++ test/tests/test_namespace/test_ns_flag.sh | 43 +++ test/utils.sh | 32 +++ 74 files changed, 1289 insertions(+), 304 deletions(-) create mode 100755 test/tests/test_namespace/test_ns_current_context.sh create mode 100755 test/tests/test_namespace/test_ns_deprecated_flag.sh create mode 100755 test/tests/test_namespace/test_ns_env.sh create mode 100755 test/tests/test_namespace/test_ns_flag.sh diff --git a/.github/workflows/push_pr.yaml b/.github/workflows/push_pr.yaml index 1139161a..9fdcc590 100644 --- a/.github/workflows/push_pr.yaml +++ b/.github/workflows/push_pr.yaml @@ -55,7 +55,7 @@ jobs: with: version: ${{ env.HELM_VERSION }} - - name: Kind Clutser + - name: Kind Cluster uses: engineerd/setup-kind@v0.5.0 with: image: kindest/node:${{ matrix.kindversion }} @@ -67,6 +67,9 @@ jobs: kubectl cluster-info --context kind-kind kubectl get nodes sudo apt-get install -y apache2-utils + kubectl config use-context kind-kind + kubectl config set-context --current --namespace=default + kubectl config view - name: Helm chart lint run: | diff --git a/.github/workflows/upgrade_test.yaml b/.github/workflows/upgrade_test.yaml index c179e289..b16f4e46 100644 --- a/.github/workflows/upgrade_test.yaml +++ b/.github/workflows/upgrade_test.yaml @@ -64,6 +64,9 @@ jobs: kubectl cluster-info --context kind-kind kubectl get nodes kubectl get storageclasses.storage.k8s.io + kubectl config use-context kind-kind + kubectl config set-context --current --namespace=default + kubectl config view - name: Dump system info run: | diff --git a/cmd/fission-cli/app/app.go b/cmd/fission-cli/app/app.go index 96f3a746..08da49f8 100644 --- a/cmd/fission-cli/app/app.go +++ b/cmd/fission-cli/app/app.go @@ -87,7 +87,7 @@ func App() *cobra.Command { }) wrapper.SetFlags(rootCmd, flag.FlagSet{ - Global: []flag.Flag{flag.GlobalServer, flag.GlobalVerbosity, flag.KubeContext}, + Global: []flag.Flag{flag.GlobalServer, flag.GlobalVerbosity, flag.KubeContext, flag.Namespace}, }) groups := helptemplate.CommandGroups{} @@ -101,7 +101,7 @@ func App() *cobra.Command { flagExposer := helptemplate.ActsAsRootCommand(rootCmd, nil, groups...) // show global options in usage - flagExposer.ExposeFlags(rootCmd, flagkey.Server, flagkey.Verbosity, flagkey.KubeContext) + flagExposer.ExposeFlags(rootCmd, flagkey.Server, flagkey.Verbosity, flagkey.KubeContext, flagkey.Namespace) return rootCmd } diff --git a/pkg/apis/core/v1/validation.go b/pkg/apis/core/v1/validation.go index 6798f214..46455dba 100644 --- a/pkg/apis/core/v1/validation.go +++ b/pkg/apis/core/v1/validation.go @@ -150,12 +150,21 @@ func ValidateKubeName(field string, val string) error { return result.ErrorOrNil() } +// validateNS is to match the k8s behaviour. Where it is not mandatory to provide a NS. And so we validate it if user has provided one. +// Or we skip the validation on namespace. +func validateNS(refName string, namespace string) error { + if namespace != "" { + return ValidateKubeName(refName, namespace) + } + return nil +} + func ValidateKubeReference(refName string, name string, namespace string) error { result := &multierror.Error{} result = multierror.Append(result, - ValidateKubeName(fmt.Sprintf("%v.Name", refName), name), - ValidateKubeName(fmt.Sprintf("%v.Namespace", refName), namespace)) + ValidateKubeName(fmt.Sprintf("%s.Name", refName), name), + validateNS(fmt.Sprintf("%s.Namespace", refName), namespace)) return result.ErrorOrNil() } diff --git a/pkg/controller/client/v1/mqtrigger.go b/pkg/controller/client/v1/mqtrigger.go index 538c7158..02e28f7b 100644 --- a/pkg/controller/client/v1/mqtrigger.go +++ b/pkg/controller/client/v1/mqtrigger.go @@ -136,16 +136,16 @@ func (c *MessageQueueTrigger) Update(mqTrigger *fv1.MessageQueueTrigger) (*metav } func (c *MessageQueueTrigger) Delete(m *metav1.ObjectMeta) error { - relativeUrl := fmt.Sprintf("triggers/messagequeue/%v", m.Name) - relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace) + relativeUrl := fmt.Sprintf("triggers/messagequeue/%s", m.Name) + relativeUrl += fmt.Sprintf("?namespace=%s", m.Namespace) return c.client.Delete(relativeUrl) } func (c *MessageQueueTrigger) List(mqType string, ns string) ([]fv1.MessageQueueTrigger, error) { - relativeUrl := "triggers/messagequeue" + relativeUrl := fmt.Sprintf("triggers/messagequeue?namespace=%s", ns) if len(mqType) > 0 { // TODO remove this, replace with field selector - relativeUrl += fmt.Sprintf("?mqtype=%v&namespace=%v", mqType, ns) + relativeUrl += fmt.Sprintf("&mqtype=%s", mqType) } resp, err := c.client.Get(relativeUrl) diff --git a/pkg/fission-cli/cmd/canaryconfig/command.go b/pkg/fission-cli/cmd/canaryconfig/command.go index 973fee72..5d4ec6b7 100644 --- a/pkg/fission-cli/cmd/canaryconfig/command.go +++ b/pkg/fission-cli/cmd/canaryconfig/command.go @@ -76,7 +76,7 @@ func Commands() *cobra.Command { RunE: wrapper.Wrapper(List), } wrapper.SetFlags(listCmd, flag.FlagSet{ - Optional: []flag.Flag{flag.NamespaceCanary}, + Optional: []flag.Flag{flag.NamespaceCanary, flag.AllNamespaces}, }) command := &cobra.Command{ diff --git a/pkg/fission-cli/cmd/canaryconfig/create.go b/pkg/fission-cli/cmd/canaryconfig/create.go index d8e0c117..a97ee0ba 100644 --- a/pkg/fission-cli/cmd/canaryconfig/create.go +++ b/pkg/fission-cli/cmd/canaryconfig/create.go @@ -47,20 +47,23 @@ func (opts *CreateSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *CreateSubCommand) complete(input cli.Input) error { +func (opts *CreateSubCommand) complete(input cli.Input) (err error) { // canary configs can be created for functions in the same namespace name := input.String(flagkey.CanaryName) ht := input.String(flagkey.CanaryHTTPTriggerName) newFunc := input.String(flagkey.CanaryNewFunc) oldFunc := input.String(flagkey.CanaryOldFunc) - fnNs := input.String(flagkey.NamespaceFunction) + _, fnNs, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error in creating canaryconfig") + } incrementStep := input.Int(flagkey.CanaryWeightIncrement) failureThreshold := input.Int(flagkey.CanaryFailureThreshold) incrementInterval := input.String(flagkey.CanaryIncrementInterval) // check for time parsing - _, err := time.ParseDuration(incrementInterval) + _, err = time.ParseDuration(incrementInterval) if err != nil { return errors.Wrap(err, "error parsing time duration") } diff --git a/pkg/fission-cli/cmd/canaryconfig/delete.go b/pkg/fission-cli/cmd/canaryconfig/delete.go index 9d9fa797..e50f8228 100644 --- a/pkg/fission-cli/cmd/canaryconfig/delete.go +++ b/pkg/fission-cli/cmd/canaryconfig/delete.go @@ -36,13 +36,17 @@ func Delete(input cli.Input) error { return (&DeleteSubCommand{}).run(input) } -func (opts *DeleteSubCommand) run(input cli.Input) error { +func (opts *DeleteSubCommand) run(input cli.Input) (err error) { + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceCanary) + if err != nil { + return errors.Wrap(err, "error in deleting canaryConfig ") + } m := &metav1.ObjectMeta{ Name: input.String(flagkey.CanaryName), - Namespace: input.String(flagkey.NamespaceCanary), + Namespace: namespace, } - err := opts.Client().V1().CanaryConfig().Delete(m) + err = opts.Client().V1().CanaryConfig().Delete(m) if err != nil { if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { return nil diff --git a/pkg/fission-cli/cmd/canaryconfig/get.go b/pkg/fission-cli/cmd/canaryconfig/get.go index a54e3610..dd773f88 100644 --- a/pkg/fission-cli/cmd/canaryconfig/get.go +++ b/pkg/fission-cli/cmd/canaryconfig/get.go @@ -27,6 +27,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type GetSubCommand struct { @@ -37,10 +38,16 @@ func Get(input cli.Input) error { return (&GetSubCommand{}).run(input) } -func (opts *GetSubCommand) run(input cli.Input) error { +func (opts *GetSubCommand) run(input cli.Input) (err error) { + + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceCanary) + if err != nil { + return errors.Wrap(err, "error getting canary config") + } + canaryCfg, err := opts.Client().V1().CanaryConfig().Get(&metav1.ObjectMeta{ Name: input.String(flagkey.CanaryName), - Namespace: input.String(flagkey.NamespaceCanary), + Namespace: namespace, }) if err != nil { return errors.Wrap(err, "error getting canary config") diff --git a/pkg/fission-cli/cmd/canaryconfig/list.go b/pkg/fission-cli/cmd/canaryconfig/list.go index 2fe1d01b..86cb5782 100644 --- a/pkg/fission-cli/cmd/canaryconfig/list.go +++ b/pkg/fission-cli/cmd/canaryconfig/list.go @@ -23,9 +23,11 @@ import ( "github.com/pkg/errors" + v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -45,13 +47,22 @@ func (opts *ListSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *ListSubCommand) complete(input cli.Input) error { - opts.namespace = input.String(flagkey.NamespaceCanary) +func (opts *ListSubCommand) complete(input cli.Input) (err error) { + _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespaceCanary) + if err != nil { + return errors.Wrap(err, "error in listing canary config ") + } return nil } -func (opts *ListSubCommand) run(input cli.Input) error { - canaryCfgs, err := opts.Client().V1().CanaryConfig().List(opts.namespace) +func (opts *ListSubCommand) run(input cli.Input) (err error) { + + var canaryCfgs []v1.CanaryConfig + if input.Bool(flagkey.AllNamespaces) { + canaryCfgs, err = opts.Client().V1().CanaryConfig().List("") + } else { + canaryCfgs, err = opts.Client().V1().CanaryConfig().List(opts.namespace) + } if err != nil { return errors.Wrap(err, "error listing canary config") } diff --git a/pkg/fission-cli/cmd/canaryconfig/update.go b/pkg/fission-cli/cmd/canaryconfig/update.go index 6cbfc791..513e9244 100644 --- a/pkg/fission-cli/cmd/canaryconfig/update.go +++ b/pkg/fission-cli/cmd/canaryconfig/update.go @@ -27,6 +27,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type UpdateSubCommand struct { @@ -46,16 +47,19 @@ func (opts *UpdateSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *UpdateSubCommand) complete(input cli.Input) error { +func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { // get the current config name := input.String(flagkey.CanaryName) - ns := input.String(flagkey.NamespaceCanary) + _, ns, err := util.GetResourceNamespace(input, flagkey.NamespaceCanary) + if err != nil { + return errors.Wrap(err, "error updating canary config") + } incrementStep := input.Int(flagkey.CanaryWeightIncrement) failureThreshold := input.Int(flagkey.CanaryFailureThreshold) incrementInterval := input.String(flagkey.CanaryIncrementInterval) // check for time parsing - _, err := time.ParseDuration(incrementInterval) + _, err = time.ParseDuration(incrementInterval) if err != nil { return errors.Wrap(err, "error parsing time duration") } diff --git a/pkg/fission-cli/cmd/environment/command.go b/pkg/fission-cli/cmd/environment/command.go index df19f13b..e51c28de 100644 --- a/pkg/fission-cli/cmd/environment/command.go +++ b/pkg/fission-cli/cmd/environment/command.go @@ -81,7 +81,7 @@ func Commands() *cobra.Command { RunE: wrapper.Wrapper(List), } wrapper.SetFlags(listCmd, flag.FlagSet{ - Optional: []flag.Flag{flag.NamespaceEnvironment}, + Optional: []flag.Flag{flag.NamespaceEnvironment, flag.AllNamespaces}, }) listPodsCmd := &cobra.Command{ diff --git a/pkg/fission-cli/cmd/environment/create.go b/pkg/fission-cli/cmd/environment/create.go index 0acf5323..d631aaa1 100644 --- a/pkg/fission-cli/cmd/environment/create.go +++ b/pkg/fission-cli/cmd/environment/create.go @@ -63,7 +63,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { // run write the resource to a spec file or create a fission CRD with remote fission server. // It also prints warning/error if necessary. -func (opts *CreateSubCommand) run(input cli.Input) error { +func (opts *CreateSubCommand) run(input cli.Input) (err error) { m := opts.env.ObjectMeta envList, err := opts.Client().V1().Environment().List(m.Namespace) @@ -75,13 +75,30 @@ func (opts *CreateSubCommand) run(input cli.Input) error { len(envList), m.Namespace) } + userDefinedNS, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + if err != nil { + return fv1.AggregateValidationErrors("Environment", err) + } + // we use user provided NS in spec. While creating actual record we use the current context's NS. + opts.env.ObjectMeta.Namespace = userDefinedNS + // if we're writing a spec, don't call the API // save to spec file or display the spec to console if input.Bool(flagkey.SpecDry) { + err = opts.env.Validate() + if err != nil { + return fv1.AggregateValidationErrors("Environment", err) + } + return spec.SpecDry(*opts.env) } if input.Bool(flagkey.SpecSave) { + err = opts.env.Validate() + if err != nil { + return fv1.AggregateValidationErrors("Environment", err) + } + specFile := fmt.Sprintf("env-%v.yaml", m.Name) err = spec.SpecSave(*opts.env, specFile) if err != nil { @@ -90,6 +107,12 @@ func (opts *CreateSubCommand) run(input cli.Input) error { return nil } + opts.env.ObjectMeta.Namespace = currentNS + err = opts.env.Validate() + if err != nil { + return fv1.AggregateValidationErrors("Environment", err) + } + _, err = opts.Client().V1().Environment().Create(opts.env) if err != nil { return errors.Wrap(err, "error creating environment") @@ -105,7 +128,7 @@ func createEnvironmentFromCmd(input cli.Input) (*fv1.Environment, error) { envName := input.String(flagkey.EnvName) envImg := input.String(flagkey.EnvImage) - envNamespace := input.String(flagkey.NamespaceEnvironment) + envBuildCmd := input.String(flagkey.EnvBuildcommand) envExternalNetwork := input.Bool(flagkey.EnvExternalNetwork) keepArchive := input.Bool(flagkey.EnvKeeparchive) @@ -165,8 +188,7 @@ func createEnvironmentFromCmd(input cli.Input) (*fv1.Environment, error) { APIVersion: fv1.CRD_VERSION, }, ObjectMeta: metav1.ObjectMeta{ - Name: envName, - Namespace: envNamespace, + Name: envName, }, Spec: fv1.EnvironmentSpec{ Version: envVersion, @@ -196,10 +218,6 @@ func createEnvironmentFromCmd(input cli.Input) (*fv1.Environment, error) { if err != nil { return nil, err } - err = env.Validate() - if err != nil { - return nil, fv1.AggregateValidationErrors("Environment", err) - } return env, nil } diff --git a/pkg/fission-cli/cmd/environment/delete.go b/pkg/fission-cli/cmd/environment/delete.go index dc53c67e..fcb0647c 100644 --- a/pkg/fission-cli/cmd/environment/delete.go +++ b/pkg/fission-cli/cmd/environment/delete.go @@ -24,6 +24,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" + "github.com/fission/fission/pkg/fission-cli/console" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" "github.com/fission/fission/pkg/fission-cli/util" ) @@ -36,10 +37,17 @@ func Delete(input cli.Input) error { return (&DeleteSubCommand{}).do(input) } -func (opts *DeleteSubCommand) do(input cli.Input) error { +func (opts *DeleteSubCommand) do(input cli.Input) (err error) { + + _, currentContextNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + if err != nil { + return errors.Wrap(err, "error creating environment") + } + console.Verbose(2, "Namespace used to delete resource: %s ", currentContextNS) + m := &metav1.ObjectMeta{ Name: input.String(flagkey.EnvName), - Namespace: input.String(flagkey.NamespaceEnvironment), + Namespace: currentContextNS, } if !input.Bool(flagkey.EnvForce) { @@ -56,7 +64,7 @@ func (opts *DeleteSubCommand) do(input cli.Input) error { } } - err := opts.Client().V1().Environment().Delete(m) + err = opts.Client().V1().Environment().Delete(m) if err != nil { if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { return nil diff --git a/pkg/fission-cli/cmd/environment/get.go b/pkg/fission-cli/cmd/environment/get.go index c4a3612d..4c72bdbf 100644 --- a/pkg/fission-cli/cmd/environment/get.go +++ b/pkg/fission-cli/cmd/environment/get.go @@ -27,6 +27,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type GetSubCommand struct { @@ -37,10 +38,16 @@ func Get(input cli.Input) error { return (&GetSubCommand{}).do(input) } -func (opts *GetSubCommand) do(input cli.Input) error { +func (opts *GetSubCommand) do(input cli.Input) (err error) { + + _, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + if err != nil { + return errors.Wrap(err, "error creating environment") + } + m := &metav1.ObjectMeta{ Name: input.String(flagkey.EnvName), - Namespace: input.String(flagkey.NamespaceEnvironment), + Namespace: currentNS, } env, err := opts.Client().V1().Environment().Get(m) diff --git a/pkg/fission-cli/cmd/environment/list.go b/pkg/fission-cli/cmd/environment/list.go index cf98ab1f..383f43e9 100644 --- a/pkg/fission-cli/cmd/environment/list.go +++ b/pkg/fission-cli/cmd/environment/list.go @@ -23,9 +23,11 @@ import ( "github.com/pkg/errors" + v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -36,20 +38,33 @@ func List(input cli.Input) error { return (&ListSubCommand{}).do(input) } -func (opts *ListSubCommand) do(input cli.Input) error { - envs, err := opts.Client().V1().Environment().List(input.String(flagkey.NamespaceEnvironment)) +func (opts *ListSubCommand) do(input cli.Input) (err error) { + + _, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + if err != nil { + return errors.Wrap(err, "error creating environment") + } + + var envs []v1.Environment + if input.Bool(flagkey.AllNamespaces) { + envs, err = opts.Client().V1().Environment().List("") + } else { + envs, err = opts.Client().V1().Environment().List(currentNS) + } + if err != nil { return errors.Wrap(err, "error listing environments") } 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", "IMAGE", "BUILDER_IMAGE", "POOLSIZE", "MINCPU", "MAXCPU", "MINMEMORY", "MAXMEMORY", "EXTNET", "GRACETIME") + fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", "NAME", "IMAGE", "BUILDER_IMAGE", "POOLSIZE", "MINCPU", "MAXCPU", "MINMEMORY", "MAXMEMORY", "EXTNET", "GRACETIME", "NAMESPACE") for _, env := range envs { - 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\n", env.ObjectMeta.Name, env.Spec.Runtime.Image, env.Spec.Builder.Image, env.Spec.Poolsize, env.Spec.Resources.Requests.Cpu(), env.Spec.Resources.Limits.Cpu(), env.Spec.Resources.Requests.Memory(), env.Spec.Resources.Limits.Memory(), - env.Spec.AllowAccessToExternalNetwork, env.Spec.TerminationGracePeriod) + env.Spec.AllowAccessToExternalNetwork, env.Spec.TerminationGracePeriod, env.Namespace, + ) } w.Flush() diff --git a/pkg/fission-cli/cmd/environment/pods.go b/pkg/fission-cli/cmd/environment/pods.go index 810c6ad7..b536684b 100644 --- a/pkg/fission-cli/cmd/environment/pods.go +++ b/pkg/fission-cli/cmd/environment/pods.go @@ -28,6 +28,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" "github.com/fission/fission/pkg/utils" ) @@ -39,13 +40,18 @@ func ListPods(input cli.Input) error { return (&ListPodsSubCommand{}).do(input) } -func (opts *ListPodsSubCommand) do(input cli.Input) error { +func (opts *ListPodsSubCommand) do(input cli.Input) (err error) { + + _, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + if err != nil { + return errors.Wrap(err, "error creating environment") + } // validate environment - _, err := opts.Client().V1().Environment().Get( + _, err = opts.Client().V1().Environment().Get( &metav1.ObjectMeta{ Name: input.String(flagkey.EnvName), - Namespace: input.String(flagkey.NamespaceEnvironment), + Namespace: currentNS, }) if err != nil { return errors.Wrap(err, "error getting environment") @@ -54,7 +60,7 @@ func (opts *ListPodsSubCommand) do(input cli.Input) error { m := &metav1.ObjectMeta{ Name: input.String(flagkey.EnvName), Labels: map[string]string{ - v1.ENVIRONMENT_NAMESPACE: input.String(flagkey.NamespaceEnvironment), + v1.ENVIRONMENT_NAMESPACE: currentNS, v1.EXECUTOR_TYPE: input.String(flagkey.EnvExecutorType), }, } diff --git a/pkg/fission-cli/cmd/environment/update.go b/pkg/fission-cli/cmd/environment/update.go index 3d5b871c..5ac7a23b 100644 --- a/pkg/fission-cli/cmd/environment/update.go +++ b/pkg/fission-cli/cmd/environment/update.go @@ -52,10 +52,15 @@ func (opts *UpdateSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *UpdateSubCommand) complete(input cli.Input) error { +func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { + + _, currentContextNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + if err != nil { + return errors.Wrap(err, "error creating environment") + } env, err := opts.Client().V1().Environment().Get(&metav1.ObjectMeta{ Name: input.String(flagkey.EnvName), - Namespace: input.String(flagkey.NamespaceEnvironment), + Namespace: currentContextNS, }) if err != nil { return errors.Wrap(err, "error finding environment") @@ -127,6 +132,9 @@ func updateExistingEnvironmentWithCmd(env *fv1.Environment, input cli.Input) (*f env.Spec.ImagePullSecret = input.String(flagkey.EnvImagePullSecret) } + env.Spec.Resources.Requests = make(v1.ResourceList) + env.Spec.Resources.Limits = make(v1.ResourceList) + if input.IsSet(flagkey.RuntimeMincpu) { mincpu := input.Int(flagkey.RuntimeMincpu) cpuRequest, err := resource.ParseQuantity(strconv.Itoa(mincpu) + "m") diff --git a/pkg/fission-cli/cmd/function/command.go b/pkg/fission-cli/cmd/function/command.go index 9758b291..89c4f043 100644 --- a/pkg/fission-cli/cmd/function/command.go +++ b/pkg/fission-cli/cmd/function/command.go @@ -49,8 +49,7 @@ func Commands() *cobra.Command { flag.RunTimeMinCPU, flag.RunTimeMaxCPU, flag.RunTimeMinMemory, flag.RunTimeMaxMemory, flag.ReplicasMin, flag.ReplicasMax, flag.RunTimeTargetCPU, - - flag.NamespaceFunction, flag.NamespaceEnvironment, flag.SpecSave, flag.SpecDry}, + flag.NamespaceFunction, flag.SpecSave, flag.SpecDry}, }) getCmd := &cobra.Command{ @@ -121,7 +120,7 @@ func Commands() *cobra.Command { RunE: wrapper.Wrapper(List), } wrapper.SetFlags(listCmd, flag.FlagSet{ - Optional: []flag.Flag{flag.NamespaceFunction}, + Optional: []flag.Flag{flag.NamespaceFunction, flag.AllNamespaces}, }) logsCmd := &cobra.Command{ diff --git a/pkg/fission-cli/cmd/function/create.go b/pkg/fission-cli/cmd/function/create.go index 294eac87..8959b3c2 100644 --- a/pkg/fission-cli/cmd/function/create.go +++ b/pkg/fission-cli/cmd/function/create.go @@ -64,14 +64,17 @@ func (opts *CreateSubCommand) do(input cli.Input) error { func (opts *CreateSubCommand) complete(input cli.Input) error { fnName := input.String(flagkey.FnName) - fnNamespace := input.String(flagkey.NamespaceFunction) - envNamespace := input.String(flagkey.NamespaceEnvironment) + + userProvidedNS, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error retrieving namespace information") + } // user wants a spec, create a yaml file with package and function toSpec := false if input.Bool(flagkey.SpecSave) { toSpec = true - opts.specFile = fmt.Sprintf("function-%v.yaml", fnName) + opts.specFile = fmt.Sprintf("function-%s.yaml", fnName) } specDir := util.GetSpecDir(input) specIgnore := util.GetSpecIgnore(input) @@ -80,7 +83,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { // check for unique function names within a namespace fn, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ Name: input.String(flagkey.FnName), - Namespace: input.String(flagkey.NamespaceFunction), + Namespace: fnNamespace, }) if err != nil && !ferror.IsNotFound(err) { return err @@ -135,17 +138,19 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { fr, err := spec.ReadSpecs(specDir, specIgnore, false) if err != nil { - return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir)) + return errors.Wrap(err, fmt.Sprintf("error reading spec in '%s'", specDir)) } - obj := fr.SpecExists(&fv1.Package{ + + obj := fr.SpecExists(&fv1.Package{ // In case of spec I might or might not have the `fnNamespace`, how will I get pkg objectMeta here. ObjectMeta: metav1.ObjectMeta{ Name: pkgName, - Namespace: fnNamespace, + Namespace: userProvidedNS, }, }, true, false) if obj == nil { - return errors.Errorf("please create package %v spec file before referencing it", pkgName) + return errors.Errorf("please create package %s spec file with namespace %s before referencing it", pkgName, userProvidedNS) } + pkg = obj.(*fv1.Package) pkgMetadata = &pkg.ObjectMeta } else { @@ -155,7 +160,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { Name: pkgName, }) if err != nil { - return errors.Wrap(err, fmt.Sprintf("read package in '%v' in Namespace: %s. Package needs to be present in the same namespace as function", pkgName, fnNamespace)) + return errors.Wrap(err, fmt.Sprintf("read package in '%s' in Namespace: %s. Package needs to be present in the same namespace as function", pkgName, fnNamespace)) } pkgMetadata = &pkg.ObjectMeta } @@ -164,7 +169,6 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { if envName != input.String(flagkey.FnEnvironmentName) { console.Warn("Function's environment is different than package's environment, package's environment will be used for creating function") } - envNamespace = pkg.Spec.Environment.Namespace } else { // need to specify environment for creating new package envName = input.String(flagkey.FnEnvironmentName) @@ -176,29 +180,29 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { fr, err := spec.ReadSpecs(specDir, specIgnore, false) if err != nil { - return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir)) + return errors.Wrap(err, fmt.Sprintf("error reading spec in '%s'", specDir)) } exists, err := fr.ExistsInSpecs(fv1.Environment{ ObjectMeta: metav1.ObjectMeta{ Name: envName, - Namespace: envNamespace, + Namespace: userProvidedNS, }, }) if err != nil { return err } if !exists { - console.Warn(fmt.Sprintf("Function '%v' references unknown Environment '%v', please create it before applying spec", + console.Warn(fmt.Sprintf("Function '%s' references unknown Environment '%s', please create it before applying spec", fnName, envName)) } } else { _, err := opts.Client().V1().Environment().Get(&metav1.ObjectMeta{ - Namespace: envNamespace, + Namespace: fnNamespace, Name: envName, }) if err != nil { if e, ok := err.(ferror.Error); ok && e.Code == ferror.ErrorNotFound { - console.Warn(fmt.Sprintf("Environment \"%v\" does not exist. Please create the environment before executing the function. \nFor example: `fission env create --name %v --envns %v --image `\n", envName, envName, envNamespace)) + console.Warn(fmt.Sprintf("Environment \"%s\" does not exist. Please create the environment before executing the function. \nFor example: `fission env create --name %s --envns %s --image `\n", envName, envName, fnNamespace)) } else { return errors.Wrap(err, "error retrieving environment information") } @@ -228,8 +232,8 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { pkgName := generatePackageName(fnName, id.String()) // create new package in the same namespace as the function. - pkgMetadata, err = _package.CreatePackage(input, opts.Client(), pkgName, fnNamespace, envName, envNamespace, - srcArchiveFiles, deployArchiveFiles, buildcmd, specDir, opts.specFile, noZip) + pkgMetadata, err = _package.CreatePackage(input, opts.Client(), pkgName, fnNamespace, envName, + srcArchiveFiles, deployArchiveFiles, buildcmd, specDir, opts.specFile, noZip, userProvidedNS) if err != nil { return errors.Wrap(err, "error creating package") } @@ -253,15 +257,22 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { return errors.Wrapf(err, "error checking secret %s", secretName) } } + newSecret := fv1.SecretReference{ + Name: secretName, + Namespace: fnNamespace, + } + secrets = append(secrets, newSecret) + } + } else { + for _, secretName := range secretNames { + newSecret := fv1.SecretReference{ + Name: secretName, + Namespace: userProvidedNS, + } + secrets = append(secrets, newSecret) } } - for _, secretName := range secretNames { - newSecret := fv1.SecretReference{ - Name: secretName, - Namespace: fnNamespace, - } - secrets = append(secrets, newSecret) - } + } if len(cfgMapNames) > 0 { @@ -279,14 +290,20 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { return errors.Wrapf(err, "error checking configmap %s", cfgMapName) } } + newCfgMap := fv1.ConfigMapReference{ + Name: cfgMapName, + Namespace: fnNamespace, + } + cfgmaps = append(cfgmaps, newCfgMap) } - } - for _, cfgMapName := range cfgMapNames { - newCfgMap := fv1.ConfigMapReference{ - Name: cfgMapName, - Namespace: fnNamespace, + } else { + for _, cfgMapName := range cfgMapNames { + newCfgMap := fv1.ConfigMapReference{ + Name: cfgMapName, + Namespace: userProvidedNS, + } + cfgmaps = append(cfgmaps, newCfgMap) } - cfgmaps = append(cfgmaps, newCfgMap) } } @@ -314,7 +331,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { } opts.function.Spec.Environment = fv1.EnvironmentReference{ Name: envName, - Namespace: envNamespace, + Namespace: fnNamespace, } opts.function.Spec.Package = fv1.FunctionPackageRef{ FunctionName: entrypoint, @@ -325,6 +342,12 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { }, } + if toSpec { + opts.function.ObjectMeta.Namespace = userProvidedNS + opts.function.Spec.Package.PackageRef.Namespace = userProvidedNS + opts.function.Spec.Environment.Namespace = userProvidedNS + } + return nil } @@ -336,12 +359,12 @@ func generatePackageName(fnName string, id string) string { lastIndexOfChar int ) if lenFnName+lenId <= 62 { - return fmt.Sprintf("%v-%v", fnName, id) + return fmt.Sprintf("%s-%s", fnName, id) } lastIndexOfChar = lenFnName - (lenFnName + lenId - 62) - pkgName := fmt.Sprintf("%v-%v", fnName[:lastIndexOfChar], id) - console.Info(fmt.Sprintf("Generated package %v from function to acceptable character limit", pkgName)) + pkgName := fmt.Sprintf("%v-%s", fnName[:lastIndexOfChar], id) + console.Info(fmt.Sprintf("Generated package %s from function to acceptable character limit", pkgName)) return pkgName } @@ -367,7 +390,7 @@ func (opts *CreateSubCommand) run(input cli.Input) error { return errors.Wrap(err, "error creating function") } - fmt.Printf("function '%v' created\n", opts.function.ObjectMeta.Name) + fmt.Printf("function '%s' created\n", opts.function.ObjectMeta.Name) // Allow the user to specify an HTTP trigger while creating a function. triggerUrl := input.String(flagkey.HtUrl) @@ -416,7 +439,7 @@ func (opts *CreateSubCommand) run(input cli.Input) error { return errors.Wrap(err, "error creating HTTP trigger") } - fmt.Printf("route created: %v %v -> %v\n", methods, triggerUrl, opts.function.ObjectMeta.Name) + fmt.Printf("route created: %s %s -> %s\n", methods, triggerUrl, opts.function.ObjectMeta.Name) return nil } diff --git a/pkg/fission-cli/cmd/function/delete.go b/pkg/fission-cli/cmd/function/delete.go index 35b66bfc..e0095dda 100644 --- a/pkg/fission-cli/cmd/function/delete.go +++ b/pkg/fission-cli/cmd/function/delete.go @@ -37,19 +37,24 @@ func Delete(input cli.Input) error { } func (opts *DeleteSubCommand) do(input cli.Input) error { + + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error in deleting function ") + } m := &metav1.ObjectMeta{ Name: input.String(flagkey.FnName), - Namespace: input.String(flagkey.NamespaceFunction), + Namespace: namespace, } - err := opts.Client().V1().Function().Delete(m) + err = opts.Client().V1().Function().Delete(m) if err != nil { if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { return nil } - return errors.Wrap(err, fmt.Sprintf("delete function '%v'", m.Name)) + return errors.Wrap(err, fmt.Sprintf("delete function '%s'", m.Name)) } - fmt.Printf("function '%v' deleted\n", m.Name) + fmt.Printf("function '%s' deleted\n", m.Name) return nil } diff --git a/pkg/fission-cli/cmd/function/get.go b/pkg/fission-cli/cmd/function/get.go index 1148cbd0..af48081a 100644 --- a/pkg/fission-cli/cmd/function/get.go +++ b/pkg/fission-cli/cmd/function/get.go @@ -25,6 +25,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type GetSubCommand struct { @@ -36,9 +37,13 @@ func Get(input cli.Input) error { } func (opts *GetSubCommand) do(input cli.Input) error { + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error in get function ") + } fn, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ Name: input.String(flagkey.FnName), - Namespace: input.String(flagkey.NamespaceFunction), + Namespace: namespace, }) if err != nil { return errors.Wrap(err, "error getting function") diff --git a/pkg/fission-cli/cmd/function/getmeta.go b/pkg/fission-cli/cmd/function/getmeta.go index 108aa4ad..02c67ca9 100644 --- a/pkg/fission-cli/cmd/function/getmeta.go +++ b/pkg/fission-cli/cmd/function/getmeta.go @@ -25,6 +25,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type GetMetaSubCommand struct { @@ -36,9 +37,14 @@ func GetMeta(input cli.Input) error { } func (opts *GetMetaSubCommand) do(input cli.Input) error { + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error in getting meta function ") + } + fn, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ Name: input.String(flagkey.FnName), - Namespace: input.String(flagkey.NamespaceFunction), + Namespace: namespace, }) if err != nil { return errors.Wrap(err, "error getting function") diff --git a/pkg/fission-cli/cmd/function/list.go b/pkg/fission-cli/cmd/function/list.go index dee6b2d6..98a3662d 100644 --- a/pkg/fission-cli/cmd/function/list.go +++ b/pkg/fission-cli/cmd/function/list.go @@ -24,9 +24,11 @@ import ( "github.com/pkg/errors" + v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -38,16 +40,24 @@ func List(input cli.Input) error { } func (opts *ListSubCommand) do(input cli.Input) error { - ns := input.String(flagkey.NamespaceFunction) + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error in listing function ") + } - fns, err := opts.Client().V1().Function().List(ns) + var fns []v1.Function + if input.Bool(flagkey.AllNamespaces) { + fns, err = opts.Client().V1().Function().List("") + } else { + fns, err = opts.Client().V1().Function().List(namespace) + } if err != nil { return errors.Wrap(err, "error listing functions") } 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\t%v\n", "NAME", "ENV", "EXECUTORTYPE", "MINSCALE", "MAXSCALE", "MINCPU", "MAXCPU", "MINMEMORY", "MAXMEMORY", "SECRETS", "CONFIGMAPS") + 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", "SECRETS", "CONFIGMAPS", "NAMESPACE") for _, f := range fns { secrets := f.Spec.Secrets configMaps := f.Spec.ConfigMaps @@ -59,7 +69,7 @@ func (opts *ListSubCommand) do(input cli.Input) error { configMapList = append(configMapList, configMap.Name) } - fmt.Fprintf(w, "%v\t%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.ObjectMeta.Name, f.Spec.Environment.Name, f.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType, f.Spec.InvokeStrategy.ExecutionStrategy.MinScale, @@ -69,7 +79,8 @@ func (opts *ListSubCommand) do(input cli.Input) error { f.Spec.Resources.Requests.Memory().String(), f.Spec.Resources.Limits.Memory().String(), strings.Join(secretsList, ","), - strings.Join(configMapList, ",")) + strings.Join(configMapList, ","), + f.ObjectMeta.Namespace) } w.Flush() diff --git a/pkg/fission-cli/cmd/function/log.go b/pkg/fission-cli/cmd/function/log.go index 0c41cd74..b1a187db 100644 --- a/pkg/fission-cli/cmd/function/log.go +++ b/pkg/fission-cli/cmd/function/log.go @@ -40,6 +40,11 @@ func Log(input cli.Input) error { } func (opts *LogSubCommand) do(input cli.Input) error { + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error in logs for function ") + } + dbType := input.String(flagkey.FnLogDBType) fnPod := input.String(flagkey.FnLogPod) kubeContext := input.String(flagkey.KubeContext) @@ -53,7 +58,7 @@ func (opts *LogSubCommand) do(input cli.Input) error { f, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ Name: input.String(flagkey.FnName), - Namespace: input.String(flagkey.NamespaceFunction), + Namespace: namespace, }) if err != nil { return errors.Wrap(err, "error getting function") diff --git a/pkg/fission-cli/cmd/function/pods.go b/pkg/fission-cli/cmd/function/pods.go index 8972fb6f..0f6835ec 100644 --- a/pkg/fission-cli/cmd/function/pods.go +++ b/pkg/fission-cli/cmd/function/pods.go @@ -28,6 +28,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" "github.com/fission/fission/pkg/utils" ) @@ -41,10 +42,15 @@ func ListPods(input cli.Input) error { func (opts *ListPodsSubCommand) do(input cli.Input) error { + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + + if err != nil { + return errors.Wrap(err, "error in finding pod for function ") + } // validate function - _, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ + _, err = opts.Client().V1().Function().Get(&metav1.ObjectMeta{ Name: input.String(flagkey.FnName), - Namespace: input.String(flagkey.NamespaceFunction), + Namespace: namespace, }) if err != nil { return errors.Wrap(err, "error getting function") @@ -53,7 +59,7 @@ func (opts *ListPodsSubCommand) do(input cli.Input) error { m := &metav1.ObjectMeta{ Name: input.String(flagkey.FnName), Labels: map[string]string{ - v1.FUNCTION_NAMESPACE: input.String(flagkey.NamespaceFunction), + v1.FUNCTION_NAMESPACE: namespace, }, } diff --git a/pkg/fission-cli/cmd/function/run_container.go b/pkg/fission-cli/cmd/function/run_container.go index f96173b5..492ac8db 100644 --- a/pkg/fission-cli/cmd/function/run_container.go +++ b/pkg/fission-cli/cmd/function/run_container.go @@ -55,7 +55,11 @@ func (opts *RunContainerSubCommand) do(input cli.Input) error { func (opts *RunContainerSubCommand) complete(input cli.Input) error { fnName := input.String(flagkey.FnName) - fnNamespace := input.String(flagkey.NamespaceFunction) + + _, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error in running container for function ") + } // user wants a spec, create a yaml file with package and function toSpec := false @@ -68,7 +72,7 @@ func (opts *RunContainerSubCommand) complete(input cli.Input) error { // check for unique function names within a namespace fn, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ Name: input.String(flagkey.FnName), - Namespace: input.String(flagkey.NamespaceFunction), + Namespace: fnNamespace, }) if err != nil && !ferror.IsNotFound(err) { return err diff --git a/pkg/fission-cli/cmd/function/test.go b/pkg/fission-cli/cmd/function/test.go index ed7bb8e6..5582d2c6 100644 --- a/pkg/fission-cli/cmd/function/test.go +++ b/pkg/fission-cli/cmd/function/test.go @@ -51,9 +51,15 @@ func Test(input cli.Input) error { } func (opts *TestSubCommand) do(input cli.Input) error { + + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error in testing function ") + } + m := &metav1.ObjectMeta{ Name: input.String(flagkey.FnName), - Namespace: input.String(flagkey.NamespaceFunction), + Namespace: namespace, } kubeContext := input.String(flagkey.KubeContext) routerURL := os.Getenv("FISSION_ROUTER") diff --git a/pkg/fission-cli/cmd/function/update.go b/pkg/fission-cli/cmd/function/update.go index 1975549d..42c22c9d 100644 --- a/pkg/fission-cli/cmd/function/update.go +++ b/pkg/fission-cli/cmd/function/update.go @@ -51,11 +51,14 @@ func (opts *UpdateSubCommand) do(input cli.Input) error { func (opts *UpdateSubCommand) complete(input cli.Input) error { fnName := input.String(flagkey.FnName) - fnNamespace := input.String(flagkey.NamespaceFunction) + _, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error in updating function ") + } function, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ Name: input.String(flagkey.FnName), - Namespace: input.String(flagkey.NamespaceFunction), + Namespace: fnNamespace, }) if err != nil { return errors.Wrap(err, fmt.Sprintf("read function '%v'", fnName)) diff --git a/pkg/fission-cli/cmd/function/update_container.go b/pkg/fission-cli/cmd/function/update_container.go index 64b51507..13633ca3 100644 --- a/pkg/fission-cli/cmd/function/update_container.go +++ b/pkg/fission-cli/cmd/function/update_container.go @@ -52,11 +52,15 @@ func (opts *UpdateContainerSubCommand) do(input cli.Input) error { func (opts *UpdateContainerSubCommand) complete(input cli.Input) error { fnName := input.String(flagkey.FnName) - fnNamespace := input.String(flagkey.NamespaceFunction) + + _, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error in updating container for function ") + } function, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ Name: input.String(flagkey.FnName), - Namespace: input.String(flagkey.NamespaceFunction), + Namespace: fnNamespace, }) if err != nil { return errors.Wrap(err, fmt.Sprintf("read function '%v'", fnName)) diff --git a/pkg/fission-cli/cmd/httptrigger/command.go b/pkg/fission-cli/cmd/httptrigger/command.go index 7780d358..e469bf6c 100644 --- a/pkg/fission-cli/cmd/httptrigger/command.go +++ b/pkg/fission-cli/cmd/httptrigger/command.go @@ -79,7 +79,7 @@ func Commands() *cobra.Command { RunE: wrapper.Wrapper(List), } wrapper.SetFlags(listCmd, flag.FlagSet{ - Optional: []flag.Flag{flag.NamespaceTrigger, flag.HtFnFilter}, + Optional: []flag.Flag{flag.NamespaceTrigger, flag.HtFnFilter, flag.AllNamespaces}, }) command := &cobra.Command{ diff --git a/pkg/fission-cli/cmd/httptrigger/create.go b/pkg/fission-cli/cmd/httptrigger/create.go index c4f87271..4e219870 100644 --- a/pkg/fission-cli/cmd/httptrigger/create.go +++ b/pkg/fission-cli/cmd/httptrigger/create.go @@ -76,19 +76,10 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { } triggerName = id.String() } - fnNamespace := input.String(flagkey.NamespaceFunction) - m := &metav1.ObjectMeta{ - Name: triggerName, - Namespace: fnNamespace, - } - - htTrigger, err := opts.Client().V1().HTTPTrigger().Get(m) - if err != nil && !ferror.IsNotFound(err) { - return err - } - if htTrigger != nil { - return errors.New("duplicate trigger exists, choose a different name or leave it empty for fission to auto-generate it") + userProvidedNS, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error in deleting function ") } triggerUrl := input.String(flagkey.HtUrl) @@ -130,9 +121,24 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { return err } } + m := metav1.ObjectMeta{ + Name: triggerName, + Namespace: userProvidedNS, + } + + console.Warn(fmt.Sprintf("Ns: %v", userProvidedNS)) // For Specs, the spec validate checks for function reference if input.Bool(flagkey.SpecSave) { + + htTrigger, err := opts.Client().V1().HTTPTrigger().Get(&m) + if err != nil && !ferror.IsNotFound(err) { + return err + } + if htTrigger != nil { + return errors.New("duplicate trigger exists, choose a different name or leave it empty for fission to auto-generate it") + } + specDir := util.GetSpecDir(input) specIgnore := util.GetSpecIgnore(input) fr, err := spec.ReadSpecs(specDir, specIgnore, false) @@ -143,7 +149,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { exists, err := fr.ExistsInSpecs(fv1.Function{ ObjectMeta: metav1.ObjectMeta{ Name: fn, - Namespace: fnNamespace, + Namespace: userProvidedNS, }, }) if err != nil { @@ -155,6 +161,20 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { } } } else { + + m = metav1.ObjectMeta{ + Name: triggerName, + Namespace: fnNamespace, + } + + htTrigger, err := opts.Client().V1().HTTPTrigger().Get(&m) + if err != nil && !ferror.IsNotFound(err) { + return err + } + if htTrigger != nil { + return errors.New("duplicate trigger exists, choose a different name or leave it empty for fission to auto-generate it") + } + err = util.CheckFunctionExistence(opts.Client(), functionList, fnNamespace) if err != nil { console.Warn(err.Error()) @@ -172,10 +192,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { host := input.String(flagkey.HtHost) opts.trigger = &fv1.HTTPTrigger{ - ObjectMeta: metav1.ObjectMeta{ - Name: triggerName, - Namespace: fnNamespace, - }, + ObjectMeta: m, Spec: fv1.HTTPTriggerSpec{ Host: host, RelativeURL: triggerUrl, diff --git a/pkg/fission-cli/cmd/httptrigger/delete.go b/pkg/fission-cli/cmd/httptrigger/delete.go index d734e02b..3f35b9bb 100644 --- a/pkg/fission-cli/cmd/httptrigger/delete.go +++ b/pkg/fission-cli/cmd/httptrigger/delete.go @@ -49,7 +49,7 @@ func (opts *DeleteSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *DeleteSubCommand) complete(input cli.Input) error { +func (opts *DeleteSubCommand) complete(input cli.Input) (err error) { opts.triggerName = input.String(flagkey.HtName) opts.functionName = input.String(flagkey.HtFnName) if len(opts.triggerName) == 0 && len(opts.functionName) == 0 { @@ -57,7 +57,11 @@ func (opts *DeleteSubCommand) complete(input cli.Input) error { } else if len(opts.triggerName) > 0 && len(opts.functionName) > 0 { return errors.Errorf("need either of --%v or --%v and not both arguments", flagkey.HtName, flagkey.HtFnName) } - opts.namespace = input.String(flagkey.NamespaceTrigger) + + _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + if err != nil { + return errors.Wrap(err, "error in deleting function ") + } return nil } diff --git a/pkg/fission-cli/cmd/httptrigger/get.go b/pkg/fission-cli/cmd/httptrigger/get.go index 1b5f87d7..77fb4511 100644 --- a/pkg/fission-cli/cmd/httptrigger/get.go +++ b/pkg/fission-cli/cmd/httptrigger/get.go @@ -29,6 +29,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type GetSubCommand struct { @@ -43,10 +44,15 @@ func (opts *GetSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *GetSubCommand) run(input cli.Input) error { +func (opts *GetSubCommand) run(input cli.Input) (err error) { + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error in deleting function ") + } + m := &metav1.ObjectMeta{ Name: input.String(flagkey.HtName), - Namespace: input.String(flagkey.NamespaceFunction), + Namespace: namespace, } ht, err := opts.Client().V1().HTTPTrigger().Get(m) if err != nil { @@ -60,7 +66,7 @@ func (opts *GetSubCommand) run(input cli.Input) error { func printHtSummary(triggers []fv1.HTTPTrigger) { 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\n", "NAME", "METHOD", "URL", "FUNCTION(s)", "INGRESS", "HOST", "PATH", "TLS", "ANNOTATIONS") + fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", "NAME", "METHOD", "URL", "FUNCTION(s)", "INGRESS", "HOST", "PATH", "TLS", "ANNOTATIONS", "NAMESPACE") for _, trigger := range triggers { function := "" if trigger.Spec.FunctionReference.Type == fv1.FunctionReferenceTypeFunctionName { @@ -93,8 +99,8 @@ func printHtSummary(triggers []fv1.HTTPTrigger) { if len(trigger.Spec.Methods) > 0 { methods = trigger.Spec.Methods } - fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", - trigger.ObjectMeta.Name, methods, trigger.Spec.RelativeURL, function, trigger.Spec.CreateIngress, host, path, trigger.Spec.IngressConfig.TLS, ann) + fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", + trigger.ObjectMeta.Name, methods, trigger.Spec.RelativeURL, function, trigger.Spec.CreateIngress, host, path, trigger.Spec.IngressConfig.TLS, ann, trigger.ObjectMeta.Namespace) } w.Flush() } diff --git a/pkg/fission-cli/cmd/httptrigger/list.go b/pkg/fission-cli/cmd/httptrigger/list.go index 36f6aa55..cdbf9df9 100644 --- a/pkg/fission-cli/cmd/httptrigger/list.go +++ b/pkg/fission-cli/cmd/httptrigger/list.go @@ -23,6 +23,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -37,8 +38,20 @@ func (opts *ListSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *ListSubCommand) run(input cli.Input) error { - hts, err := opts.Client().V1().HTTPTrigger().List(input.String(flagkey.NamespaceTrigger)) +func (opts *ListSubCommand) run(input cli.Input) (err error) { + + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + if err != nil { + return errors.Wrap(err, "error in deleting function ") + } + + var hts []fv1.HTTPTrigger + if input.Bool(flagkey.AllNamespaces) { + hts, err = opts.Client().V1().HTTPTrigger().List("") + } else { + hts, err = opts.Client().V1().HTTPTrigger().List(namespace) + } + if err != nil { return errors.Wrap(err, "error listing HTTP triggers") } diff --git a/pkg/fission-cli/cmd/httptrigger/update.go b/pkg/fission-cli/cmd/httptrigger/update.go index 81671ee7..31010a93 100644 --- a/pkg/fission-cli/cmd/httptrigger/update.go +++ b/pkg/fission-cli/cmd/httptrigger/update.go @@ -48,9 +48,13 @@ func (opts *UpdateSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *UpdateSubCommand) complete(input cli.Input) error { +func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { htName := input.String(flagkey.HtName) - triggerNamespace := input.String(flagkey.NamespaceTrigger) + + _, triggerNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + if err != nil { + return errors.Wrap(err, "error in deleting function ") + } ht, err := opts.Client().V1().HTTPTrigger().Get(&metav1.ObjectMeta{ Name: htName, diff --git a/pkg/fission-cli/cmd/kubewatch/command.go b/pkg/fission-cli/cmd/kubewatch/command.go index 0715ffcc..7c3eef58 100644 --- a/pkg/fission-cli/cmd/kubewatch/command.go +++ b/pkg/fission-cli/cmd/kubewatch/command.go @@ -55,7 +55,7 @@ func Commands() *cobra.Command { RunE: wrapper.Wrapper(List), } wrapper.SetFlags(listCmd, flag.FlagSet{ - Optional: []flag.Flag{flag.NamespaceTrigger}, + Optional: []flag.Flag{flag.NamespaceTrigger, flag.AllNamespaces}, }) command := &cobra.Command{ diff --git a/pkg/fission-cli/cmd/kubewatch/create.go b/pkg/fission-cli/cmd/kubewatch/create.go index 7cac953b..1c4ab2fa 100644 --- a/pkg/fission-cli/cmd/kubewatch/create.go +++ b/pkg/fission-cli/cmd/kubewatch/create.go @@ -60,8 +60,12 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { watchName = id.String() } fnName := input.String(flagkey.KwFnName) - fnNamespace := input.String(flagkey.NamespaceFunction) - namespace := input.String(flagkey.KwNamespace) + + _, namespace, err := util.GetResourceNamespace(input, flagkey.KwNamespace) + if err != nil { + return errors.Wrap(err, "error in listing function ") + } + objType := input.String(flagkey.KwObjType) if input.Bool(flagkey.SpecSave) { @@ -75,7 +79,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { exists, err := fr.ExistsInSpecs(fv1.Function{ ObjectMeta: metav1.ObjectMeta{ Name: fnName, - Namespace: fnNamespace, + Namespace: namespace, }, }) if err != nil { @@ -90,7 +94,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { opts.watcher = &fv1.KubernetesWatchTrigger{ ObjectMeta: metav1.ObjectMeta{ Name: watchName, - Namespace: fnNamespace, + Namespace: namespace, }, Spec: fv1.KubernetesWatchTriggerSpec{ Namespace: namespace, diff --git a/pkg/fission-cli/cmd/kubewatch/delete.go b/pkg/fission-cli/cmd/kubewatch/delete.go index 8f6f8721..ff351dd9 100644 --- a/pkg/fission-cli/cmd/kubewatch/delete.go +++ b/pkg/fission-cli/cmd/kubewatch/delete.go @@ -46,9 +46,12 @@ func (opts *DeleteSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *DeleteSubCommand) complete(input cli.Input) error { +func (opts *DeleteSubCommand) complete(input cli.Input) (err error) { opts.name = input.String(flagkey.KwName) - opts.namespace = input.String(flagkey.NamespaceTrigger) + _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + if err != nil { + return errors.Wrap(err, "error in deleting kubewatch") + } return nil } diff --git a/pkg/fission-cli/cmd/kubewatch/list.go b/pkg/fission-cli/cmd/kubewatch/list.go index fa9faebf..05531b51 100644 --- a/pkg/fission-cli/cmd/kubewatch/list.go +++ b/pkg/fission-cli/cmd/kubewatch/list.go @@ -23,9 +23,11 @@ import ( "github.com/pkg/errors" + v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -45,13 +47,21 @@ func (opts *ListSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *ListSubCommand) complete(input cli.Input) error { - opts.namespace = input.String(flagkey.NamespaceTrigger) +func (opts *ListSubCommand) complete(input cli.Input) (err error) { + _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + if err != nil { + return errors.Wrap(err, "error listing kubewatchers") + } return nil } -func (opts *ListSubCommand) run(input cli.Input) error { - ws, err := opts.Client().V1().KubeWatcher().List(opts.namespace) +func (opts *ListSubCommand) run(input cli.Input) (err error) { + var ws []v1.KubernetesWatchTrigger + if input.Bool(flagkey.AllNamespaces) { + ws, err = opts.Client().V1().KubeWatcher().List("") + } else { + ws, err = opts.Client().V1().KubeWatcher().List(opts.namespace) + } if err != nil { return errors.Wrap(err, "error listing kubewatchers") } diff --git a/pkg/fission-cli/cmd/mqtrigger/command.go b/pkg/fission-cli/cmd/mqtrigger/command.go index f8cbdcc9..9f6573b4 100644 --- a/pkg/fission-cli/cmd/mqtrigger/command.go +++ b/pkg/fission-cli/cmd/mqtrigger/command.go @@ -71,7 +71,7 @@ func Commands() *cobra.Command { RunE: wrapper.Wrapper(List), } wrapper.SetFlags(listCmd, flag.FlagSet{ - Optional: []flag.Flag{flag.NamespaceTrigger}, + Optional: []flag.Flag{flag.NamespaceTrigger, flag.AllNamespaces}, }) command := &cobra.Command{ diff --git a/pkg/fission-cli/cmd/mqtrigger/create.go b/pkg/fission-cli/cmd/mqtrigger/create.go index aaadcecf..ef614050 100644 --- a/pkg/fission-cli/cmd/mqtrigger/create.go +++ b/pkg/fission-cli/cmd/mqtrigger/create.go @@ -61,7 +61,11 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { mqtName = id.String() } fnName := input.String(flagkey.MqtFnName) - fnNamespace := input.String(flagkey.NamespaceFunction) + + userProvidedNS, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error in deleting function ") + } mqtKind := input.String(flagkey.MqtKind) @@ -94,7 +98,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { contentType = "application/json" } - err := checkMQTopicAvailability(mqType, mqtKind, topic, respTopic) + err = checkMQTopicAvailability(mqType, mqtKind, topic, respTopic) if err != nil { return err } @@ -136,7 +140,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { exists, err := fr.ExistsInSpecs(fv1.Function{ ObjectMeta: metav1.ObjectMeta{ Name: fnName, - Namespace: fnNamespace, + Namespace: userProvidedNS, }, }) if err != nil { @@ -153,11 +157,19 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { } } - opts.trigger = &fv1.MessageQueueTrigger{ - ObjectMeta: metav1.ObjectMeta{ + m := metav1.ObjectMeta{ + Name: mqtName, + Namespace: fnNamespace, + } + + if input.Bool(flagkey.SpecSave) || input.Bool(flagkey.SpecDry) { + m = metav1.ObjectMeta{ Name: mqtName, - Namespace: fnNamespace, - }, + Namespace: userProvidedNS, + } + } + opts.trigger = &fv1.MessageQueueTrigger{ + ObjectMeta: m, Spec: fv1.MessageQueueTriggerSpec{ FunctionReference: fv1.FunctionReference{ Type: fv1.FunctionReferenceTypeFunctionName, diff --git a/pkg/fission-cli/cmd/mqtrigger/delete.go b/pkg/fission-cli/cmd/mqtrigger/delete.go index 44fe768b..a0ed824b 100644 --- a/pkg/fission-cli/cmd/mqtrigger/delete.go +++ b/pkg/fission-cli/cmd/mqtrigger/delete.go @@ -45,10 +45,16 @@ func (opts *DeleteSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *DeleteSubCommand) complete(input cli.Input) error { +func (opts *DeleteSubCommand) complete(input cli.Input) (err error) { + + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + if err != nil { + return errors.Wrap(err, "error in deleting function ") + } + opts.metadata = &metav1.ObjectMeta{ Name: input.String(flagkey.MqtName), - Namespace: input.String(flagkey.NamespaceTrigger), + Namespace: namespace, } return nil } diff --git a/pkg/fission-cli/cmd/mqtrigger/list.go b/pkg/fission-cli/cmd/mqtrigger/list.go index ec7f68f2..e0b3e953 100644 --- a/pkg/fission-cli/cmd/mqtrigger/list.go +++ b/pkg/fission-cli/cmd/mqtrigger/list.go @@ -23,9 +23,11 @@ import ( "github.com/pkg/errors" + v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -45,24 +47,33 @@ func (opts *ListSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *ListSubCommand) complete(input cli.Input) error { - opts.namespace = input.String(flagkey.NamespaceTrigger) +func (opts *ListSubCommand) complete(input cli.Input) (err error) { + _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + if err != nil { + return errors.Wrap(err, "error in deleting function ") + } return nil } -func (opts *ListSubCommand) run(input cli.Input) error { - mqts, err := opts.Client().V1().MessageQueueTrigger().List(input.String(flagkey.MqtMQType), opts.namespace) +func (opts *ListSubCommand) run(input cli.Input) (err error) { + + var mqts []v1.MessageQueueTrigger + if input.Bool(flagkey.AllNamespaces) { + mqts, err = opts.Client().V1().MessageQueueTrigger().List(input.String(flagkey.MqtMQType), "") + } else { + mqts, err = opts.Client().V1().MessageQueueTrigger().List(input.String(flagkey.MqtMQType), opts.namespace) + } if err != nil { return errors.Wrap(err, "error listing message queue triggers") } 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\n", - "NAME", "FUNCTION_NAME", "MESSAGE_QUEUE_TYPE", "TOPIC", "RESPONSE_TOPIC", "ERROR_TOPIC", "MAX_RETRIES", "PUB_MSG_CONTENT_TYPE") + fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", + "NAME", "FUNCTION_NAME", "MESSAGE_QUEUE_TYPE", "TOPIC", "RESPONSE_TOPIC", "ERROR_TOPIC", "MAX_RETRIES", "PUB_MSG_CONTENT_TYPE", "NAMESPACE") for _, mqt := range mqts { - fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", - mqt.ObjectMeta.Name, mqt.Spec.FunctionReference.Name, mqt.Spec.MessageQueueType, mqt.Spec.Topic, mqt.Spec.ResponseTopic, mqt.Spec.ErrorTopic, mqt.Spec.MaxRetries, mqt.Spec.ContentType) + fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", + mqt.ObjectMeta.Name, mqt.Spec.FunctionReference.Name, mqt.Spec.MessageQueueType, mqt.Spec.Topic, mqt.Spec.ResponseTopic, mqt.Spec.ErrorTopic, mqt.Spec.MaxRetries, mqt.Spec.ContentType, mqt.ObjectMeta.Namespace) } w.Flush() diff --git a/pkg/fission-cli/cmd/mqtrigger/update.go b/pkg/fission-cli/cmd/mqtrigger/update.go index d0454e26..5e88e81b 100644 --- a/pkg/fission-cli/cmd/mqtrigger/update.go +++ b/pkg/fission-cli/cmd/mqtrigger/update.go @@ -25,6 +25,7 @@ import ( fv1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" + "github.com/fission/fission/pkg/fission-cli/console" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" "github.com/fission/fission/pkg/fission-cli/util" ) @@ -46,10 +47,15 @@ func (opts *UpdateSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *UpdateSubCommand) complete(input cli.Input) error { +func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + if err != nil { + return errors.Wrap(err, "error in deleting function ") + } + mqt, err := opts.Client().V1().MessageQueueTrigger().Get(&metav1.ObjectMeta{ Name: input.String(flagkey.MqtName), - Namespace: input.String(flagkey.NamespaceTrigger), + Namespace: namespace, }) if err != nil { return errors.Wrap(err, "error getting message queue trigger") @@ -93,6 +99,12 @@ func (opts *UpdateSubCommand) complete(input cli.Input) error { updated = true } if len(fnName) > 0 { + functionList := []string{fnName} + err := util.CheckFunctionExistence(opts.Client(), functionList, namespace) + if err != nil { + console.Warn(err.Error()) + } + mqt.Spec.FunctionReference.Name = fnName updated = true } diff --git a/pkg/fission-cli/cmd/package/command.go b/pkg/fission-cli/cmd/package/command.go index 1d7f16b8..ea2d39cc 100644 --- a/pkg/fission-cli/cmd/package/command.go +++ b/pkg/fission-cli/cmd/package/command.go @@ -33,7 +33,7 @@ func Commands() *cobra.Command { Required: []flag.Flag{flag.PkgEnvironment}, Optional: []flag.Flag{flag.PkgName, flag.PkgCode, flag.PkgSrcArchive, flag.PkgDeployArchive, flag.PkgSrcChecksum, flag.PkgDeployChecksum, flag.PkgInsecure, flag.PkgBuildCmd, - flag.NamespacePackage, flag.NamespaceEnvironment, flag.SpecSave, flag.SpecDry}, + flag.NamespacePackage, flag.SpecSave, flag.SpecDry}, }) getSrcCmd := &cobra.Command{ @@ -84,7 +84,7 @@ func Commands() *cobra.Command { RunE: wrapper.Wrapper(List), } wrapper.SetFlags(listCmd, flag.FlagSet{ - Optional: []flag.Flag{flag.PkgOrphan, flag.PkgStatus, flag.NamespacePackage}, + Optional: []flag.Flag{flag.PkgOrphan, flag.PkgStatus, flag.NamespacePackage, flag.AllNamespaces}, }) infoCmd := &cobra.Command{ diff --git a/pkg/fission-cli/cmd/package/create.go b/pkg/fission-cli/cmd/package/create.go index 6fae780f..6f811cb9 100644 --- a/pkg/fission-cli/cmd/package/create.go +++ b/pkg/fission-cli/cmd/package/create.go @@ -63,9 +63,13 @@ func (opts *CreateSubCommand) run(input cli.Input) error { } } - pkgNamespace := input.String(flagkey.NamespacePackage) envName := input.String(flagkey.PkgEnvironment) - envNamespace := input.String(flagkey.NamespaceEnvironment) + + userProvidedNS, pkgNamespace, err := util.GetResourceNamespace(input, flagkey.NamespacePackage) + if err != nil { + return fv1.AggregateValidationErrors("Environment", err) + } + srcArchiveFiles := input.StringSlice(flagkey.PkgSrcArchive) deployArchiveFiles := input.StringSlice(flagkey.PkgDeployArchive) buildcmd := input.String(flagkey.PkgBuildCmd) @@ -100,30 +104,30 @@ func (opts *CreateSubCommand) run(input cli.Input) error { exists, err := fr.ExistsInSpecs(fv1.Environment{ ObjectMeta: metav1.ObjectMeta{ Name: envName, - Namespace: envNamespace, + Namespace: userProvidedNS, }, }) if err != nil { return err } if !exists { - console.Warn(fmt.Sprintf("Package '%v' references unknown Environment '%v', please create it before applying spec", - pkgName, envName)) + console.Warn(fmt.Sprintf("Package '%s' references unknown Environment '%s' in Namespace '%s', please create it before applying spec", + pkgName, envName, userProvidedNS)) } specDir = util.GetSpecDir(input) - specFile = fmt.Sprintf("package-%v.yaml", pkgName) + specFile = fmt.Sprintf("package-%s.yaml", pkgName) } - _, err := CreatePackage(input, opts.Client(), pkgName, pkgNamespace, envName, envNamespace, - srcArchiveFiles, deployArchiveFiles, buildcmd, specDir, specFile, noZip) + _, err = CreatePackage(input, opts.Client(), pkgName, pkgNamespace, envName, + srcArchiveFiles, deployArchiveFiles, buildcmd, specDir, specFile, noZip, userProvidedNS) return err } // TODO: get all necessary value from CLI input directly -func CreatePackage(input cli.Input, client client.Interface, pkgName string, pkgNamespace string, envName string, envNamespace string, - srcArchiveFiles []string, deployArchiveFiles []string, buildcmd string, specDir string, specFile string, noZip bool) (*metav1.ObjectMeta, error) { +func CreatePackage(input cli.Input, client client.Interface, pkgName string, pkgNamespace string, envName string, + srcArchiveFiles []string, deployArchiveFiles []string, buildcmd string, specDir string, specFile string, noZip bool, userProvidedNS string) (*metav1.ObjectMeta, error) { insecure := input.Bool(flagkey.PkgInsecure) deployChecksum := input.String(flagkey.PkgDeployChecksum) @@ -131,10 +135,19 @@ func CreatePackage(input cli.Input, client client.Interface, pkgName string, pkg pkgSpec := fv1.PackageSpec{ Environment: fv1.EnvironmentReference{ - Namespace: envNamespace, + Namespace: pkgNamespace, Name: envName, }, } + if input.Bool(flagkey.SpecSave) || input.Bool(flagkey.SpecDry) { + pkgSpec = fv1.PackageSpec{ + Environment: fv1.EnvironmentReference{ + Namespace: userProvidedNS, + Name: envName, + }, + } + } + var pkgStatus fv1.BuildStatus = fv1.BuildStatusSucceeded if len(deployArchiveFiles) > 0 { @@ -177,7 +190,7 @@ func CreatePackage(input cli.Input, client client.Interface, pkgName string, pkg pkg := &fv1.Package{ ObjectMeta: metav1.ObjectMeta{ Name: pkgName, - Namespace: pkgNamespace, + Namespace: userProvidedNS, }, Spec: pkgSpec, Status: fv1.PackageStatus{ @@ -210,6 +223,7 @@ func CreatePackage(input cli.Input, client client.Interface, pkgName string, pkg } return &pkg.ObjectMeta, nil } else { + pkg.ObjectMeta.Namespace = pkgNamespace pkgMetadata, err := client.V1().Package().Create(pkg) if err != nil { return nil, errors.Wrap(err, "error creating package") diff --git a/pkg/fission-cli/cmd/package/delete.go b/pkg/fission-cli/cmd/package/delete.go index 7becc4a5..64f7fa69 100644 --- a/pkg/fission-cli/cmd/package/delete.go +++ b/pkg/fission-cli/cmd/package/delete.go @@ -22,6 +22,7 @@ import ( "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + fv1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/controller/client" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" @@ -49,9 +50,13 @@ func (opts *DeleteSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *DeleteSubCommand) complete(input cli.Input) error { +func (opts *DeleteSubCommand) complete(input cli.Input) (err error) { opts.name = input.String(flagkey.PkgName) - opts.namespace = input.String(flagkey.NamespacePackage) + _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespacePackage) + if err != nil { + return fv1.AggregateValidationErrors("Environment", err) + } + opts.deleteOrphans = input.Bool(flagkey.PkgOrphan) opts.force = input.Bool(flagkey.PkgForce) diff --git a/pkg/fission-cli/cmd/package/get.go b/pkg/fission-cli/cmd/package/get.go index 120c1d37..0f170b07 100644 --- a/pkg/fission-cli/cmd/package/get.go +++ b/pkg/fission-cli/cmd/package/get.go @@ -28,6 +28,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cmd" pkgutil "github.com/fission/fission/pkg/fission-cli/cmd/package/util" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) const ( @@ -58,9 +59,12 @@ func (opts *GetSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *GetSubCommand) complete(input cli.Input) error { +func (opts *GetSubCommand) complete(input cli.Input) (err error) { opts.name = input.String(flagkey.PkgName) - opts.namespace = input.String(flagkey.NamespacePackage) + _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespacePackage) + if err != nil { + return fv1.AggregateValidationErrors("Environment", err) + } opts.output = input.String(flagkey.PkgOutput) return nil } diff --git a/pkg/fission-cli/cmd/package/info.go b/pkg/fission-cli/cmd/package/info.go index b8cdd5d0..3e3258ce 100644 --- a/pkg/fission-cli/cmd/package/info.go +++ b/pkg/fission-cli/cmd/package/info.go @@ -22,10 +22,12 @@ import ( "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + fv1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" pkgutil "github.com/fission/fission/pkg/fission-cli/cmd/package/util" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type InfoSubCommand struct { @@ -46,9 +48,13 @@ func (opts *InfoSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *InfoSubCommand) complete(input cli.Input) error { +func (opts *InfoSubCommand) complete(input cli.Input) (err error) { opts.name = input.String(flagkey.PkgName) - opts.namespace = input.String(flagkey.NamespacePackage) + + _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespacePackage) + if err != nil { + return fv1.AggregateValidationErrors("Environment", err) + } return nil } diff --git a/pkg/fission-cli/cmd/package/list.go b/pkg/fission-cli/cmd/package/list.go index b900bdec..21c01dcd 100644 --- a/pkg/fission-cli/cmd/package/list.go +++ b/pkg/fission-cli/cmd/package/list.go @@ -25,9 +25,11 @@ import ( "github.com/pkg/errors" + fv1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -49,16 +51,25 @@ func (opts *ListSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *ListSubCommand) complete(input cli.Input) error { +func (opts *ListSubCommand) complete(input cli.Input) (err error) { // option for the user to list all orphan packages (not referenced by any function) opts.listOrphans = input.Bool(flagkey.PkgOrphan) opts.status = input.String(flagkey.PkgStatus) - opts.pkgNamespace = input.String(flagkey.NamespacePackage) + _, opts.pkgNamespace, err = util.GetResourceNamespace(input, flagkey.NamespacePackage) + if err != nil { + return fv1.AggregateValidationErrors("Environment", err) + } return nil } -func (opts *ListSubCommand) run(input cli.Input) error { - pkgList, err := opts.Client().V1().Package().List(opts.pkgNamespace) +func (opts *ListSubCommand) run(input cli.Input) (err error) { + + var pkgList []fv1.Package + if input.Bool(flagkey.AllNamespaces) { + pkgList, err = opts.Client().V1().Package().List("") + } else { + pkgList, err = opts.Client().V1().Package().List(opts.pkgNamespace) + } if err != nil { return err } @@ -69,7 +80,7 @@ func (opts *ListSubCommand) run(input cli.Input) error { }) w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) - fmt.Fprintf(w, "%v\t%v\t%v\t%v\n", "NAME", "BUILD_STATUS", "ENV", "LASTUPDATEDAT") + fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\n", "NAME", "BUILD_STATUS", "ENV", "LASTUPDATEDAT", "NAMESPACE") for _, pkg := range pkgList { show := true @@ -87,7 +98,7 @@ func (opts *ListSubCommand) run(input cli.Input) error { show = false } if show { - fmt.Fprintf(w, "%v\t%v\t%v\t%v\n", pkg.ObjectMeta.Name, pkg.Status.BuildStatus, pkg.Spec.Environment.Name, pkg.Status.LastUpdateTimestamp.Format(time.RFC822)) + fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\n", pkg.ObjectMeta.Name, pkg.Status.BuildStatus, pkg.Spec.Environment.Name, pkg.Status.LastUpdateTimestamp.Format(time.RFC822), pkg.ObjectMeta.Namespace) } } diff --git a/pkg/fission-cli/cmd/package/rebuild.go b/pkg/fission-cli/cmd/package/rebuild.go index 4d53635a..0e9d61cb 100644 --- a/pkg/fission-cli/cmd/package/rebuild.go +++ b/pkg/fission-cli/cmd/package/rebuild.go @@ -26,6 +26,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type RebuildSubCommand struct { @@ -46,9 +47,12 @@ func (opts *RebuildSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *RebuildSubCommand) complete(input cli.Input) error { +func (opts *RebuildSubCommand) complete(input cli.Input) (err error) { opts.name = input.String(flagkey.PkgName) - opts.namespace = input.String(flagkey.NamespacePackage) + _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespacePackage) + if err != nil { + return fv1.AggregateValidationErrors("Environment", err) + } return nil } diff --git a/pkg/fission-cli/cmd/package/update.go b/pkg/fission-cli/cmd/package/update.go index e46037a2..7ff2da7e 100644 --- a/pkg/fission-cli/cmd/package/update.go +++ b/pkg/fission-cli/cmd/package/update.go @@ -29,6 +29,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type UpdateSubCommand struct { @@ -50,9 +51,12 @@ func (opts *UpdateSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *UpdateSubCommand) complete(input cli.Input) error { +func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { opts.pkgName = input.String(flagkey.PkgName) - opts.pkgNamespace = input.String(flagkey.NamespacePackage) + _, opts.pkgNamespace, err = util.GetResourceNamespace(input, flagkey.NamespacePackage) + if err != nil { + return fv1.AggregateValidationErrors("Environment", err) + } opts.force = input.Bool(flagkey.PkgForce) return nil } @@ -94,7 +98,6 @@ func (opts *UpdateSubCommand) run(input cli.Input) error { func UpdatePackage(input cli.Input, client client.Interface, pkg *fv1.Package) (*metav1.ObjectMeta, error) { envName := input.String(flagkey.PkgEnvironment) - envNamespace := input.String(flagkey.NamespaceEnvironment) srcArchiveFiles := input.StringSlice(flagkey.PkgSrcArchive) deployArchiveFiles := input.StringSlice(flagkey.PkgDeployArchive) buildcmd := input.String(flagkey.PkgBuildCmd) @@ -119,12 +122,6 @@ func UpdatePackage(input cli.Input, client client.Interface, pkg *fv1.Package) ( needToUpdate = true } - if input.IsSet(flagkey.NamespaceEnvironment) { - pkg.Spec.Environment.Namespace = envNamespace - needToRebuild = true - needToUpdate = true - } - if input.IsSet(flagkey.PkgBuildCmd) { pkg.Spec.BuildCommand = buildcmd needToRebuild = true diff --git a/pkg/fission-cli/cmd/spec/apply.go b/pkg/fission-cli/cmd/spec/apply.go index fb926e9d..1313d07a 100644 --- a/pkg/fission-cli/cmd/spec/apply.go +++ b/pkg/fission-cli/cmd/spec/apply.go @@ -62,6 +62,67 @@ func Apply(input cli.Input) error { func (opts *ApplySubCommand) do(input cli.Input) error { return opts.run(input) + +} + +// insertNamespace inserts the Namespace value if it was not provided at the time of `spec save`. +// we make sure that all component of a resource should be present in the same Namespace. i.e. +// Function's env and package should be present in same namespace +func (opts *ApplySubCommand) insertNamespace(input cli.Input, fr *FissionResources) error { + + result := utils.MultiErrorWithFormat() + _, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + if err != nil { + return fv1.AggregateValidationErrors("Environment", err) + } + + for i := range fr.Functions { + if fr.Functions[i].Namespace == "" || input.Bool(flagkey.ForceNamespace) { + fr.Functions[i].Namespace = currentNS + fr.Functions[i].Spec.Package.PackageRef.Namespace = currentNS + fr.Functions[i].Spec.Environment.Namespace = currentNS + for j := range fr.Functions[i].Spec.ConfigMaps { + fr.Functions[i].Spec.ConfigMaps[j].Namespace = currentNS + } + for j := range fr.Functions[i].Spec.Secrets { + fr.Functions[i].Spec.Secrets[j].Namespace = currentNS + } + } + } + for i := range fr.Environments { + if fr.Environments[i].Namespace == "" || input.Bool(flagkey.ForceNamespace) { + fr.Environments[i].Namespace = currentNS + } + } + for i := range fr.Packages { + if fr.Packages[i].Namespace == "" || input.Bool(flagkey.ForceNamespace) { + fr.Packages[i].Namespace = currentNS + fr.Packages[i].Spec.Environment.Namespace = currentNS + fr.Packages[i].ObjectMeta.Namespace = currentNS + } + } + for i := range fr.HttpTriggers { + if fr.HttpTriggers[i].Namespace == "" || input.Bool(flagkey.ForceNamespace) { + fr.HttpTriggers[i].Namespace = currentNS + } + } + for i := range fr.MessageQueueTriggers { + if fr.MessageQueueTriggers[i].Namespace == "" || input.Bool(flagkey.ForceNamespace) { + fr.MessageQueueTriggers[i].Namespace = currentNS + } + } + for i := range fr.TimeTriggers { + if fr.TimeTriggers[i].Namespace == "" || input.Bool(flagkey.ForceNamespace) { + fr.TimeTriggers[i].Namespace = currentNS + } + } + for i := range fr.KubernetesWatchTriggers { + if fr.KubernetesWatchTriggers[i].Namespace == "" || input.Bool(flagkey.ForceNamespace) { + fr.KubernetesWatchTriggers[i].Namespace = currentNS + } + } + + return result.ErrorOrNil() } func (opts *ApplySubCommand) run(input cli.Input) error { @@ -117,8 +178,13 @@ func (opts *ApplySubCommand) run(input cli.Input) error { return errors.Wrap(err, "error reading specs") } + err = opts.insertNamespace(input, fr) + if err != nil { + return errors.Wrap(err, "error reading specs") + } + if validateSpecs { - err = Validate(input) + err = validateForApply(input, fr) if err != nil { return errors.Wrap(err, "abort applying resources") } @@ -616,6 +682,7 @@ func applyPackages(fclient client.Interface, fr *FissionResources, delete bool, for _, o := range fr.Packages { // apply deploymentConfig so we can find our objects on future apply invocations applyDeploymentConfig(&o.ObjectMeta, fr) + console.Verbose(2, fmt.Sprintf("Package is here '%s','%s','%s','%s'", o.Namespace, o.Name, o.Spec.Environment.Namespace, o.Spec.Environment.Name)) // index desired state desired[mapKey(&o.ObjectMeta)] = true diff --git a/pkg/fission-cli/cmd/spec/command.go b/pkg/fission-cli/cmd/spec/command.go index bb798101..76d70c43 100644 --- a/pkg/fission-cli/cmd/spec/command.go +++ b/pkg/fission-cli/cmd/spec/command.go @@ -48,7 +48,8 @@ func Commands() *cobra.Command { RunE: wrapper.Wrapper(Apply), } wrapper.SetFlags(applyCmd, flag.FlagSet{ - Optional: []flag.Flag{flag.SpecDir, flag.SpecIgnore, flag.SpecDelete, flag.SpecWait, flag.SpecWatch, flag.SpecValidation, flag.SpecApplyCommitLabel, flag.SpecAllowConflicts}, + Optional: []flag.Flag{flag.SpecDir, flag.SpecIgnore, flag.SpecDelete, flag.SpecWait, flag.SpecWatch, + flag.SpecValidation, flag.SpecApplyCommitLabel, flag.SpecAllowConflicts, flag.ForceNamespace}, }) destroyCmd := &cobra.Command{ @@ -57,7 +58,7 @@ func Commands() *cobra.Command { RunE: wrapper.Wrapper(Destroy), } wrapper.SetFlags(destroyCmd, flag.FlagSet{ - Optional: []flag.Flag{flag.SpecDir, flag.SpecIgnore}, + Optional: []flag.Flag{flag.SpecDir, flag.SpecIgnore, flag.ForceDelete}, }) listCmd := &cobra.Command{ @@ -66,7 +67,7 @@ func Commands() *cobra.Command { RunE: wrapper.Wrapper(List), } wrapper.SetFlags(listCmd, flag.FlagSet{ - Optional: []flag.Flag{flag.SpecDeployID, flag.SpecDir, flag.SpecIgnore}, + Optional: []flag.Flag{flag.SpecDeployID, flag.SpecDir, flag.SpecIgnore, flag.AllNamespaces}, }) command := &cobra.Command{ diff --git a/pkg/fission-cli/cmd/spec/destroy.go b/pkg/fission-cli/cmd/spec/destroy.go index 4aae1a1f..9a831a76 100644 --- a/pkg/fission-cli/cmd/spec/destroy.go +++ b/pkg/fission-cli/cmd/spec/destroy.go @@ -17,12 +17,19 @@ limitations under the License. package spec import ( + "fmt" + "strings" + "github.com/pkg/errors" + fv1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/controller/client" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" + "github.com/fission/fission/pkg/fission-cli/console" + flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" "github.com/fission/fission/pkg/fission-cli/util" + "github.com/fission/fission/pkg/utils" ) type DestroySubCommand struct { @@ -49,12 +56,26 @@ func (opts *DestroySubCommand) run(input cli.Input) error { return errors.Wrap(err, "error reading specs") } - // set desired state to nothing, but keep the UID so "apply" can find it - emptyFr := FissionResources{} - emptyFr.DeploymentConfig = fr.DeploymentConfig + if !input.Bool(flagkey.ForceDelete) { + err = opts.insertNSToResource(input, fr) + if err != nil { + return errors.Wrap(err, "error adding namespace") + } + } else { + // if force delete set to true we fetch all resources with our deployment ID and delete them + // set desired state to nothing, but keep the UID so "apply" can find it + emptyFr := FissionResources{} + emptyFr.DeploymentConfig = fr.DeploymentConfig - // "apply" the empty state - err = deleteResources(opts.Client(), &emptyFr) + // "apply" the empty state + err = forceDeleteResources(opts.Client(), &emptyFr) + if err != nil { + return errors.Wrap(err, "error deleting resources") + } + return nil + } + forceDelete := input.Bool(flagkey.ForceDelete) + err = deleteResources(opts.Client(), fr, forceDelete) if err != nil { return errors.Wrap(err, "error deleting resources") } @@ -62,7 +83,7 @@ func (opts *DestroySubCommand) run(input cli.Input) error { return nil } -func deleteResources(fclient client.Interface, fr *FissionResources) error { +func forceDeleteResources(fclient client.Interface, fr *FissionResources) error { var err error @@ -103,3 +124,219 @@ func deleteResources(fclient client.Interface, fr *FissionResources) error { return nil } + +// insertNSToResource provides a namespace to all resource which don't have a namespace specified +// in resource +func (opts *DestroySubCommand) insertNSToResource(input cli.Input, fr *FissionResources) error { + + result := utils.MultiErrorWithFormat() + + _, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + if err != nil { + return fv1.AggregateValidationErrors("Environment", err) + } + + for i := range fr.Functions { + if fr.Functions[i].Namespace == "" { + fr.Functions[i].Namespace = currentNS + } + } + for i := range fr.Environments { + if fr.Environments[i].Namespace == "" { + fr.Environments[i].Namespace = currentNS + } + } + for i := range fr.Packages { + if fr.Packages[i].Namespace == "" { + fr.Packages[i].Namespace = currentNS + } + } + for i := range fr.HttpTriggers { + if fr.HttpTriggers[i].Namespace == "" { + fr.HttpTriggers[i].Namespace = currentNS + } + } + for i := range fr.MessageQueueTriggers { + if fr.MessageQueueTriggers[i].Namespace == "" { + fr.MessageQueueTriggers[i].Namespace = currentNS + } + } + for i := range fr.TimeTriggers { + if fr.TimeTriggers[i].Namespace == "" { + fr.TimeTriggers[i].Namespace = currentNS + } + } + for i := range fr.KubernetesWatchTriggers { + if fr.KubernetesWatchTriggers[i].Namespace == "" { + fr.KubernetesWatchTriggers[i].Namespace = currentNS + } + } + + return result.ErrorOrNil() +} + +func deleteResources(fclient client.Interface, fr *FissionResources, forceDelete bool) error { + + var err error + + err = destroyHTTPTriggers(fclient, fr) + if err != nil { + return errors.Wrap(err, "HTTPTrigger delete failed") + } + + err = destroyKubernetesWatchTriggers(fclient, fr) + if err != nil { + return errors.Wrap(err, "KubernetesWatchTrigger delete failed") + } + + err = destroyTimeTriggers(fclient, fr) + if err != nil { + return errors.Wrap(err, "TimeTrigger delete failed") + } + + err = destroyMessageQueueTriggers(fclient, fr) + if err != nil { + return errors.Wrap(err, "MessageQueueTrigger delete failed") + } + + err = destroyFunctions(fclient, fr) + if err != nil { + return errors.Wrap(err, "function delete failed") + } + + err = destroyPackages(fclient, fr) + if err != nil { + return errors.Wrap(err, "package delete failed") + } + + err = destroyEnvironments(fclient, fr) + if err != nil { + return errors.Wrap(err, "environment delete failed") + } + + return nil +} + +func destroyHTTPTriggers(fclient client.Interface, fr *FissionResources) error { + for _, o := range fr.HttpTriggers { + err := fclient.V1().HTTPTrigger().Delete(&o.ObjectMeta) + if err != nil && strings.Contains(err.Error(), "not found") { + console.Verbose(2, fmt.Sprintf("could not delete httptrigger: %s Namespace: %s", o.ObjectMeta.Name, o.ObjectMeta.Namespace)) + err = nil + continue + + } else if err != nil { + return err + } + fmt.Printf("Deleted %s %s/%s\n", o.TypeMeta.Kind, o.ObjectMeta.Namespace, o.ObjectMeta.Name) + } + return nil +} + +func destroyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources) error { + + for _, o := range fr.KubernetesWatchTriggers { + err := fclient.V1().KubeWatcher().Delete(&o.ObjectMeta) + if err != nil && strings.Contains(err.Error(), "not found") { + console.Verbose(2, fmt.Sprintf("could not delete watch: %s Namespace: %s", o.ObjectMeta.Name, o.ObjectMeta.Namespace)) + err = nil + continue + + } else if err != nil { + return err + } + fmt.Printf("Deleted %s %s/%s\n", o.TypeMeta.Kind, o.ObjectMeta.Namespace, o.ObjectMeta.Name) + } + + return nil +} + +func destroyTimeTriggers(fclient client.Interface, fr *FissionResources) error { + + for _, o := range fr.TimeTriggers { + err := fclient.V1().TimeTrigger().Delete(&o.ObjectMeta) + if err != nil && strings.Contains(err.Error(), "not found") { + console.Verbose(2, fmt.Sprintf("could not delete Time trigger: %s Namespace: %s", o.ObjectMeta.Name, o.ObjectMeta.Namespace)) + err = nil + continue + + } else if err != nil { + return err + } + fmt.Printf("Deleted %s %s/%s\n", o.TypeMeta.Kind, o.ObjectMeta.Namespace, o.ObjectMeta.Name) + } + + return nil +} + +func destroyMessageQueueTriggers(fclient client.Interface, fr *FissionResources) error { + + for _, o := range fr.MessageQueueTriggers { + err := fclient.V1().MessageQueueTrigger().Delete(&o.ObjectMeta) + if err != nil && strings.Contains(err.Error(), "not found") { + console.Verbose(2, fmt.Sprintf("could not delete Message trigger: %s Namespace: %s", o.ObjectMeta.Name, o.ObjectMeta.Namespace)) + err = nil + continue + + } else if err != nil { + return err + } + fmt.Printf("Deleted %s %s/%s\n", o.TypeMeta.Kind, o.ObjectMeta.Namespace, o.ObjectMeta.Name) + } + + return nil +} + +func destroyFunctions(fclient client.Interface, fr *FissionResources) error { + + for _, o := range fr.Functions { + err := fclient.V1().Function().Delete(&o.ObjectMeta) + if err != nil && strings.Contains(err.Error(), "not found") { + console.Verbose(2, fmt.Sprintf("could not delete Functions: %s Namespace: %s", o.ObjectMeta.Name, o.ObjectMeta.Namespace)) + err = nil + continue + + } else if err != nil { + return err + } + fmt.Printf("Deleted %s %s/%s\n", o.TypeMeta.Kind, o.ObjectMeta.Namespace, o.ObjectMeta.Name) + } + + return nil +} + +func destroyPackages(fclient client.Interface, fr *FissionResources) error { + + for _, o := range fr.Packages { + err := fclient.V1().Package().Delete(&o.ObjectMeta) + if err != nil && strings.Contains(err.Error(), "not found") { + console.Verbose(2, fmt.Sprintf("could not delete Package: %s Namespace: %s", o.ObjectMeta.Name, o.ObjectMeta.Namespace)) + err = nil + continue + + } else if err != nil { + return err + } + fmt.Printf("Deleted %s %s/%s\n", o.TypeMeta.Kind, o.ObjectMeta.Namespace, o.ObjectMeta.Name) + } + + return nil +} + +func destroyEnvironments(fclient client.Interface, fr *FissionResources) error { + + for _, o := range fr.Environments { + err := fclient.V1().Environment().Delete(&o.ObjectMeta) + if err != nil && strings.Contains(err.Error(), "not found") { + console.Verbose(2, fmt.Sprintf("could not delete Env: %s Namespace: %s", o.ObjectMeta.Name, o.ObjectMeta.Namespace)) + err = nil + continue + + } else if err != nil { + return err + } + fmt.Printf("Deleted %s %s/%s\n", o.TypeMeta.Kind, o.ObjectMeta.Namespace, o.ObjectMeta.Name) + } + + return nil +} diff --git a/pkg/fission-cli/cmd/spec/list.go b/pkg/fission-cli/cmd/spec/list.go index 14729307..fd63d90d 100644 --- a/pkg/fission-cli/cmd/spec/list.go +++ b/pkg/fission-cli/cmd/spec/list.go @@ -60,63 +60,90 @@ func (opts *ListSubCommand) run(input cli.Input) error { deployID = fr.DeploymentConfig.UID } - allfn, err := getAllFunctions(opts.Client()) + _, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) if err != nil { - return errors.Wrap(err, "error getting Functions from all namespaces") + return fv1.AggregateValidationErrors("Environment", err) + } + + if input.Bool(flagkey.AllNamespaces) { + return opts.getResource(input, "", deployID) + } else { + return opts.getResource(input, currentNS, deployID) + } + +} + +func (opts *ListSubCommand) getResource(input cli.Input, namespace string, deployID string) (err error) { + var allfn []fv1.Function + printNS := namespace + if printNS == "" { + printNS = "all" + } + + allfn, err = getAllFunctions(opts.Client(), namespace) + if err != nil { + return errors.Wrap(err, fmt.Sprintf("error getting Functions from %s namespaces", printNS)) } specfns := getAppliedFunctions(allfn, deployID) ShowFunctions(specfns) - allenvs, err := getAllEnvironments(opts.Client()) + var allenvs []fv1.Environment + allenvs, err = getAllEnvironments(opts.Client(), namespace) if err != nil { - return errors.Wrap(err, "error getting Environments from all namespaces") + return errors.Wrap(err, fmt.Sprintf("error getting Environments from %s namespaces", printNS)) } specenvs := getAppliedEnvironments(allenvs, deployID) ShowEnvironments(specenvs) - pkglists, err := getAllPackages(opts.Client()) + var pkglists []fv1.Package + pkglists, err = getAllPackages(opts.Client(), namespace) if err != nil { - return errors.Wrap(err, "error getting Packages from all namespaces") + return errors.Wrap(err, fmt.Sprintf("error getting Packages from %s namespaces", printNS)) } specPkgs := getAppliedPackages(pkglists, deployID) ShowPackages(specPkgs) - canaryCfgs, err := getAllCanaryConfigs(opts.Client()) + var canaryCfgs []fv1.CanaryConfig + canaryCfgs, err = getAllCanaryConfigs(opts.Client(), namespace) if err != nil { - return errors.Wrap(err, "error getting Canary Config from all namespaces") + return errors.Wrap(err, fmt.Sprintf("error getting Canary Config from %s namespaces", printNS)) } specCanaryCfgs := getAppliedCanaryConfigs(canaryCfgs, deployID) ShowCanaryConfigs(specCanaryCfgs) - hts, err := getAllHTTPTriggers(opts.Client()) + var hts []fv1.HTTPTrigger + hts, err = getAllHTTPTriggers(opts.Client(), namespace) if err != nil { - return errors.Wrap(err, "error getting HTTP Triggers from all namespaces") + return errors.Wrap(err, fmt.Sprintf("error getting HTTP Triggers from %s namespaces", printNS)) } specHTTPTriggers := getAppliedHTTPTriggers(hts, deployID) ShowHTTPTriggers(specHTTPTriggers) - mqts, err := getAllMessageQueueTriggers(opts.Client(), input.String(flagkey.MqtMQType)) + var mqts []fv1.MessageQueueTrigger + mqts, err = getAllMessageQueueTriggers(opts.Client(), input.String(flagkey.MqtMQType), namespace) if err != nil { - return errors.Wrap(err, "error getting MessageQueue Triggers from all namespaces") + return errors.Wrap(err, fmt.Sprintf("error getting MessageQueue Triggers from %s namespaces", printNS)) } specMessageQueueTriggers := getAppliedMessageQueueTriggers(mqts, deployID) ShowMQTriggers(specMessageQueueTriggers) - tts, err := getAllTimeTriggers(opts.Client()) + var tts []fv1.TimeTrigger + tts, err = getAllTimeTriggers(opts.Client(), namespace) if err != nil { - return errors.Wrap(err, "error getting Time Triggers from all namespaces") + return errors.Wrap(err, fmt.Sprintf("error getting Time Triggers from %s namespaces", printNS)) } specTimeTriggers := getAppliedTimeTriggers(tts, deployID) ShowTimeTriggers(specTimeTriggers) - kws, err := getAllKubeWatchTriggers(opts.Client()) + var kws []fv1.KubernetesWatchTrigger + kws, err = getAllKubeWatchTriggers(opts.Client(), namespace) if err != nil { - return errors.Wrap(err, "error getting Kube Watchers from all namespaces") + return errors.Wrap(err, fmt.Sprintf("error getting Kube Watchers from %s namespaces", printNS)) } specKubeWatchers := getSpecKubeWatchers(kws, deployID) ShowAppliedKubeWatchers(specKubeWatchers) - return nil + return err } func getAppliedFunctions(fns []fv1.Function, deployID string) []fv1.Function { @@ -392,9 +419,9 @@ func ShowAppliedKubeWatchers(ws []fv1.KubernetesWatchTrigger) { } } -// getAllFunctions get lists of functions in all namespaces -func getAllFunctions(client client.Interface) ([]fv1.Function, error) { - fns, err := client.V1().Function().List("") +// getAllFunctions get lists of functions in provided namespaces +func getAllFunctions(client client.Interface, namespace string) ([]fv1.Function, error) { + fns, err := client.V1().Function().List(namespace) if err != nil { return nil, errors.Errorf("Unable to get Functions %v", err.Error()) } @@ -402,8 +429,8 @@ func getAllFunctions(client client.Interface) ([]fv1.Function, error) { } // getAllEnvironments get lists of environments in all namespaces -func getAllEnvironments(client client.Interface) ([]fv1.Environment, error) { - envs, err := client.V1().Environment().List("") +func getAllEnvironments(client client.Interface, namespace string) ([]fv1.Environment, error) { + envs, err := client.V1().Environment().List(namespace) if err != nil { return nil, errors.Errorf("Unable to get Environments %v", err.Error()) } @@ -411,8 +438,8 @@ func getAllEnvironments(client client.Interface) ([]fv1.Environment, error) { } // getAllPackages get lists of packages in all namespaces -func getAllPackages(client client.Interface) ([]fv1.Package, error) { - pkgList, err := client.V1().Package().List("") +func getAllPackages(client client.Interface, namespace string) ([]fv1.Package, error) { + pkgList, err := client.V1().Package().List(namespace) if err != nil { return nil, errors.Errorf("Unable to get Packages %v", err.Error()) } @@ -420,8 +447,8 @@ func getAllPackages(client client.Interface) ([]fv1.Package, error) { } // getAllCanaryConfigs get lists of canary configs in all namespaces -func getAllCanaryConfigs(client client.Interface) ([]fv1.CanaryConfig, error) { - canaryCfgs, err := client.V1().CanaryConfig().List("") +func getAllCanaryConfigs(client client.Interface, namespace string) ([]fv1.CanaryConfig, error) { + canaryCfgs, err := client.V1().CanaryConfig().List(namespace) if err != nil { return nil, errors.Errorf("Unable to get Canary Configs %v", err.Error()) } @@ -429,8 +456,8 @@ func getAllCanaryConfigs(client client.Interface) ([]fv1.CanaryConfig, error) { } // getAllHTTPTriggers get lists of HTTP Triggers in all namespaces -func getAllHTTPTriggers(client client.Interface) ([]fv1.HTTPTrigger, error) { - hts, err := client.V1().HTTPTrigger().List("") +func getAllHTTPTriggers(client client.Interface, namespace string) ([]fv1.HTTPTrigger, error) { + hts, err := client.V1().HTTPTrigger().List(namespace) if err != nil { return nil, errors.Errorf("Unable to get HTTP Triggers %v", err.Error()) } @@ -438,8 +465,8 @@ func getAllHTTPTriggers(client client.Interface) ([]fv1.HTTPTrigger, error) { } // getAllMessageQueueTriggers get lists of MessageQueue Triggers in all namespaces -func getAllMessageQueueTriggers(client client.Interface, mqttype string) ([]fv1.MessageQueueTrigger, error) { - mqts, err := client.V1().MessageQueueTrigger().List(mqttype, "") +func getAllMessageQueueTriggers(client client.Interface, mqttype string, namespace string) ([]fv1.MessageQueueTrigger, error) { + mqts, err := client.V1().MessageQueueTrigger().List(mqttype, namespace) if err != nil { return nil, errors.Errorf("Unable to get MessageQueue Triggers %v", err.Error()) } @@ -447,8 +474,8 @@ func getAllMessageQueueTriggers(client client.Interface, mqttype string) ([]fv1. } // getAllTimeTriggers get lists of Time Triggers in all namespaces -func getAllTimeTriggers(client client.Interface) ([]fv1.TimeTrigger, error) { - tts, err := client.V1().TimeTrigger().List("") +func getAllTimeTriggers(client client.Interface, namespace string) ([]fv1.TimeTrigger, error) { + tts, err := client.V1().TimeTrigger().List(namespace) if err != nil { return nil, errors.Errorf("Unable to get Time Triggers %v", err.Error()) } @@ -456,8 +483,8 @@ func getAllTimeTriggers(client client.Interface) ([]fv1.TimeTrigger, error) { } // getAllKubeWatchTriggers get lists of Kube Watchers in all namespaces -func getAllKubeWatchTriggers(client client.Interface) ([]fv1.KubernetesWatchTrigger, error) { - ws, err := client.V1().KubeWatcher().List("") +func getAllKubeWatchTriggers(client client.Interface, namespace string) ([]fv1.KubernetesWatchTrigger, error) { + ws, err := client.V1().KubeWatcher().List(namespace) if err != nil { return nil, errors.Errorf("Unable to get Kube Watchers %v", err.Error()) } diff --git a/pkg/fission-cli/cmd/spec/spec.go b/pkg/fission-cli/cmd/spec/spec.go index 610e461b..ce16d6fe 100644 --- a/pkg/fission-cli/cmd/spec/spec.go +++ b/pkg/fission-cli/cmd/spec/spec.go @@ -491,7 +491,7 @@ func (fr *FissionResources) Validate(input cli.Input) ([]string, error) { for _, f := range fr.Functions { if _, ok := environments[fmt.Sprintf("%s:%s", f.Spec.Environment.Name, f.Spec.Environment.Namespace)]; !ok { - warnings = append(warnings, "Environment %s is referenced in function %s but not declared in specs", f.Spec.Environment.Name, f.ObjectMeta.Name) + warnings = append(warnings, fmt.Sprintf("Environment %s is referenced in function %s but not declared in specs", f.Spec.Environment.Name, f.ObjectMeta.Name)) } strategy := f.Spec.InvokeStrategy.ExecutionStrategy if strategy.ExecutorType == fv1.ExecutorTypeNewdeploy && strategy.SpecializationTimeout < fv1.DefaultSpecializationTimeOut { diff --git a/pkg/fission-cli/cmd/spec/validate.go b/pkg/fission-cli/cmd/spec/validate.go index b46e082b..a914019c 100644 --- a/pkg/fission-cli/cmd/spec/validate.go +++ b/pkg/fission-cli/cmd/spec/validate.go @@ -48,17 +48,29 @@ func Validate(input cli.Input) error { } func (opts *ValidateSubCommand) do(input cli.Input) error { - return opts.run(input) + return opts.run(input, nil) } -func (opts *ValidateSubCommand) run(input cli.Input) error { +func validateForApply(input cli.Input, fr *FissionResources) error { + + return (&ValidateSubCommand{}).doValidateForApply(input, fr) +} +func (opts *ValidateSubCommand) doValidateForApply(input cli.Input, fr *FissionResources) error { + return opts.run(input, fr) +} + +func (opts *ValidateSubCommand) run(input cli.Input, fr *FissionResources) (err error) { // this will error on parse errors and on duplicates specDir := util.GetSpecDir(input) specIgnore := util.GetSpecIgnore(input) - fr, err := ReadSpecs(specDir, specIgnore, false) - if err != nil { - return errors.Wrap(err, "error reading specs") + + // If the call for validate is from apply spec we already have a parsed fission resource + if fr == nil { + fr, err = ReadSpecs(specDir, specIgnore, false) + if err != nil { + return errors.Wrap(err, "error reading specs") + } } console.Infof("DeployUID: %v", fr.DeploymentConfig.UID) @@ -72,7 +84,7 @@ func (opts *ValidateSubCommand) run(input cli.Input) error { return errors.Wrap(err, "error validating specs") } - err = resourceConflictCheck(opts.Client(), fr, input.Bool(flagkey.SpecAllowConflicts)) + err = resourceConflictCheck(opts.Client(), fr, input.Bool(flagkey.SpecAllowConflicts), "") if err != nil { return errors.Wrap(err, "name conflict error") } @@ -90,11 +102,11 @@ func (opts *ValidateSubCommand) run(input cli.Input) error { // the same name is already present in the same cluster namespace. // If a same name resource exists in the same namespace, a name // conflict error will be returned. -func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowConflicts bool) error { +func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowConflicts bool, namespace string) error { deployUID := fr.DeploymentConfig.UID result := utils.MultiErrorWithFormat() - fnList, err := getAllFunctions(c) + fnList, err := getAllFunctions(c, namespace) if err != nil { return errors.Errorf("Unable to get Functions %v", err.Error()) } @@ -107,7 +119,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowCo } } - envList, err := getAllEnvironments(c) + envList, err := getAllEnvironments(c, namespace) if err != nil { return errors.Errorf("Unable to get Environments %v", err.Error()) } @@ -120,7 +132,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowCo } } - pkgList, err := getAllPackages(c) + pkgList, err := getAllPackages(c, namespace) if err != nil { return errors.Errorf("Unable to get Packages %v", err.Error()) } @@ -133,7 +145,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowCo } } - httptriggerList, err := getAllHTTPTriggers(c) + httptriggerList, err := getAllHTTPTriggers(c, namespace) if err != nil { return errors.Errorf("Unable to get HTTPTrigger %v", err.Error()) } @@ -146,7 +158,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowCo } } - mqtriggerList, err := getAllMessageQueueTriggers(c, "") + mqtriggerList, err := getAllMessageQueueTriggers(c, "", namespace) if err != nil { return errors.Errorf("Unable to get Message Queue Trigger %v", err.Error()) } @@ -159,7 +171,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowCo } } - timetriggerList, err := getAllTimeTriggers(c) + timetriggerList, err := getAllTimeTriggers(c, namespace) if err != nil { return errors.Errorf("Unable to get Time Trigger %v", err.Error()) } @@ -172,7 +184,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowCo } } - kubewatchtriggerList, err := getAllKubeWatchTriggers(c) + kubewatchtriggerList, err := getAllKubeWatchTriggers(c, namespace) if err != nil { return errors.Errorf("Unable to get Kubernetes Watch Trigger %v", err.Error()) } diff --git a/pkg/fission-cli/cmd/timetrigger/command.go b/pkg/fission-cli/cmd/timetrigger/command.go index 10b34f41..204cbd77 100644 --- a/pkg/fission-cli/cmd/timetrigger/command.go +++ b/pkg/fission-cli/cmd/timetrigger/command.go @@ -64,7 +64,7 @@ func Commands() *cobra.Command { RunE: wrapper.Wrapper(List), } wrapper.SetFlags(listCmd, flag.FlagSet{ - Optional: []flag.Flag{flag.NamespaceTrigger}, + Optional: []flag.Flag{flag.NamespaceTrigger, flag.AllNamespaces}, }) showCmd := &cobra.Command{ diff --git a/pkg/fission-cli/cmd/timetrigger/create.go b/pkg/fission-cli/cmd/timetrigger/create.go index 6c15bacc..e12dd340 100644 --- a/pkg/fission-cli/cmd/timetrigger/create.go +++ b/pkg/fission-cli/cmd/timetrigger/create.go @@ -53,7 +53,7 @@ func (opts *CreateSubCommand) do(input cli.Input) error { return opts.run(input) } -func (opts *CreateSubCommand) complete(input cli.Input) error { +func (opts *CreateSubCommand) complete(input cli.Input) (err error) { name := input.String(flagkey.TtName) if len(name) == 0 { id, err := uuid.NewV4() @@ -68,7 +68,10 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { return errors.New("Need a function name to create a trigger, use --function") } - fnNamespace := input.String(flagkey.NamespaceFunction) + userProvidedNS, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + if err != nil { + return errors.Wrap(err, "error in deleting function ") + } cronSpec := input.String(flagkey.TtCron) if len(cronSpec) == 0 { @@ -86,7 +89,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { exists, err := fr.ExistsInSpecs(fv1.Function{ ObjectMeta: metav1.ObjectMeta{ Name: fnName, - Namespace: fnNamespace, + Namespace: userProvidedNS, }, }) if err != nil { @@ -98,11 +101,20 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { } } - opts.trigger = &fv1.TimeTrigger{ - ObjectMeta: metav1.ObjectMeta{ + m := metav1.ObjectMeta{ + Name: name, + Namespace: fnNamespace, + } + + if input.Bool(flagkey.SpecSave) || input.Bool(flagkey.SpecDry) { + m = metav1.ObjectMeta{ Name: name, - Namespace: fnNamespace, - }, + Namespace: userProvidedNS, + } + } + + opts.trigger = &fv1.TimeTrigger{ + ObjectMeta: m, Spec: fv1.TimeTriggerSpec{ Cron: cronSpec, FunctionReference: fv1.FunctionReference{ diff --git a/pkg/fission-cli/cmd/timetrigger/delete.go b/pkg/fission-cli/cmd/timetrigger/delete.go index b366f401..3eb1eb35 100644 --- a/pkg/fission-cli/cmd/timetrigger/delete.go +++ b/pkg/fission-cli/cmd/timetrigger/delete.go @@ -36,13 +36,18 @@ func Delete(input cli.Input) error { return (&DeleteSubCommand{}).do(input) } -func (opts *DeleteSubCommand) do(input cli.Input) error { +func (opts *DeleteSubCommand) do(input cli.Input) (err error) { + + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + if err != nil { + return errors.Wrap(err, "error in deleting function ") + } m := &metav1.ObjectMeta{ Name: input.String(flagkey.TtName), - Namespace: input.String(flagkey.NamespaceTrigger), + Namespace: namespace, } - err := opts.Client().V1().TimeTrigger().Delete(m) + err = opts.Client().V1().TimeTrigger().Delete(m) if err != nil { if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { return nil diff --git a/pkg/fission-cli/cmd/timetrigger/list.go b/pkg/fission-cli/cmd/timetrigger/list.go index 842fde8c..7b96340c 100644 --- a/pkg/fission-cli/cmd/timetrigger/list.go +++ b/pkg/fission-cli/cmd/timetrigger/list.go @@ -23,9 +23,11 @@ import ( "github.com/pkg/errors" + v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -36,9 +38,19 @@ func List(input cli.Input) error { return (&ListSubCommand{}).do(input) } -func (opts *ListSubCommand) do(input cli.Input) error { - ttNs := input.String(flagkey.NamespaceTrigger) - tts, err := opts.Client().V1().TimeTrigger().List(ttNs) +func (opts *ListSubCommand) do(input cli.Input) (err error) { + _, ttNs, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + if err != nil { + return errors.Wrap(err, "error in deleting function ") + } + + var tts []v1.TimeTrigger + if input.Bool(flagkey.AllNamespaces) { + tts, err = opts.Client().V1().TimeTrigger().List("") + } else { + tts, err = opts.Client().V1().TimeTrigger().List(ttNs) + } + if err != nil { return errors.Wrap(err, "list Time triggers") } diff --git a/pkg/fission-cli/cmd/timetrigger/update.go b/pkg/fission-cli/cmd/timetrigger/update.go index a0ebace8..8a6ac466 100644 --- a/pkg/fission-cli/cmd/timetrigger/update.go +++ b/pkg/fission-cli/cmd/timetrigger/update.go @@ -25,7 +25,9 @@ import ( fv1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" + "github.com/fission/fission/pkg/fission-cli/console" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type UpdateSubCommand struct { @@ -46,9 +48,13 @@ func (opts *UpdateSubCommand) do(input cli.Input) error { } func (opts *UpdateSubCommand) complete(input cli.Input) error { + _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + if err != nil { + return errors.Wrap(err, "error in deleting function ") + } tt, err := opts.Client().V1().TimeTrigger().Get(&metav1.ObjectMeta{ Name: input.String(flagkey.TtName), - Namespace: input.String(flagkey.NamespaceTrigger), + Namespace: namespace, }) if err != nil { return errors.Wrap(err, "error getting time trigger") @@ -61,11 +67,13 @@ func (opts *UpdateSubCommand) complete(input cli.Input) error { updated = true } - // TODO : During update, function has to be in the same ns as the trigger object - // but since we are not checking this for other triggers too, not sure if we need a check here. - fnName := input.String("function") if len(fnName) > 0 { + functionList := []string{fnName} + err := util.CheckFunctionExistence(opts.Client(), functionList, namespace) + if err != nil { + console.Warn(err.Error()) + } tt.Spec.FunctionReference.Name = fnName updated = true } diff --git a/pkg/fission-cli/flag/flag.go b/pkg/fission-cli/flag/flag.go index 41e67d23..3c29e4be 100644 --- a/pkg/fission-cli/flag/flag.go +++ b/pkg/fission-cli/flag/flag.go @@ -21,8 +21,6 @@ import ( "net/http" "time" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - fv1 "github.com/fission/fission/pkg/apis/core/v1" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" "github.com/fission/fission/pkg/fission-cli/util" @@ -83,17 +81,21 @@ var ( Labels = Flag{Type: String, Name: flagkey.Labels, Usage: "Comma separated labels to apply to the function. E.g. --labels=\"environment=dev,application=analytics\""} Annotation = Flag{Type: StringSlice, Name: flagkey.Annotation, Usage: "Annotation to apply to the function. To mention multiple annotations --annotation=\"abc.com/team=dev\" --annotation=\"foo=bar\""} - NamespaceFunction = Flag{Type: String, Name: flagkey.NamespaceFunction, Aliases: []string{"fns"}, Usage: "Namespace for function object", DefaultValue: metav1.NamespaceDefault} - NamespaceEnvironment = Flag{Type: String, Name: flagkey.NamespaceEnvironment, Aliases: []string{"envns"}, Usage: "Namespace for environment object", DefaultValue: metav1.NamespaceDefault} - NamespacePackage = Flag{Type: String, Name: flagkey.NamespacePackage, Aliases: []string{"pkgns"}, Usage: "Namespace for package object", DefaultValue: metav1.NamespaceDefault} - NamespaceTrigger = Flag{Type: String, Name: flagkey.NamespaceTrigger, Aliases: []string{"triggerns"}, Usage: "Namespace for trigger object", DefaultValue: metav1.NamespaceDefault} - NamespaceCanary = Flag{Type: String, Name: flagkey.NamespaceCanary, Aliases: []string{"canaryns"}, Usage: "Namespace for canary config object", DefaultValue: metav1.NamespaceDefault} + Namespace = Flag{Type: String, Name: flagkey.Namespace, Short: "n", Usage: "If present, the namespace scope for this CLI request"} - RunTimeMinCPU = Flag{Type: Int, Name: flagkey.RuntimeMincpu, Usage: "Minimum CPU to be assigned to pod (In millicore, minimum 1)"} - RunTimeMaxCPU = Flag{Type: Int, Name: flagkey.RuntimeMaxcpu, Usage: "Maximum CPU to be assigned to pod (In millicore, minimum 1)"} - RunTimeTargetCPU = Flag{Type: Int, Name: flagkey.RuntimeTargetcpu, Usage: "Target average CPU usage percentage across pods for scaling", DefaultValue: 80} - RunTimeMinMemory = Flag{Type: Int, Name: flagkey.RuntimeMinmemory, Usage: "Minimum memory to be assigned to pod (In megabyte)"} - RunTimeMaxMemory = Flag{Type: Int, Name: flagkey.RuntimeMaxmemory, Usage: "Maximum memory to be assigned to pod (In megabyte)"} + NamespaceFunction = Flag{Type: String, Name: flagkey.NamespaceFunction, Aliases: []string{"fns"}, Usage: "Namespace for function object", Deprecated: true, Substitute: flagkey.Namespace} + NamespaceEnvironment = Flag{Type: String, Name: flagkey.NamespaceEnvironment, Aliases: []string{"envns"}, Usage: "Namespace for environment object", Deprecated: true, Substitute: flagkey.Namespace} + NamespacePackage = Flag{Type: String, Name: flagkey.NamespacePackage, Aliases: []string{"pkgns"}, Usage: "Namespace for package object", Deprecated: true, Substitute: flagkey.Namespace} + NamespaceTrigger = Flag{Type: String, Name: flagkey.NamespaceTrigger, Aliases: []string{"triggerns"}, Usage: "Namespace for trigger object", Deprecated: true, Substitute: flagkey.Namespace} + NamespaceCanary = Flag{Type: String, Name: flagkey.NamespaceCanary, Aliases: []string{"canaryns"}, Usage: "Namespace for canary config object", Deprecated: true, Substitute: flagkey.Namespace} + ForceNamespace = Flag{Type: Bool, Name: flagkey.ForceNamespace, Aliases: []string{"force"}, Usage: "If true, resources will be created in namespace provided by (--namespace flag ) even if spec file contains some other namespace", DefaultValue: false} + ForceDelete = Flag{Type: Bool, Name: flagkey.ForceDelete, Aliases: []string{"force"}, Usage: "Delete all resources across all namespaces present in spec"} + AllNamespaces = Flag{Type: Bool, Name: flagkey.AllNamespaces, Short: "A", Usage: "Fetch resources from all namespaces"} + RunTimeMinCPU = Flag{Type: Int, Name: flagkey.RuntimeMincpu, Usage: "Minimum CPU to be assigned to pod (In millicore, minimum 1)"} + RunTimeMaxCPU = Flag{Type: Int, Name: flagkey.RuntimeMaxcpu, Usage: "Maximum CPU to be assigned to pod (In millicore, minimum 1)"} + RunTimeTargetCPU = Flag{Type: Int, Name: flagkey.RuntimeTargetcpu, Usage: "Target average CPU usage percentage across pods for scaling", DefaultValue: 80} + RunTimeMinMemory = Flag{Type: Int, Name: flagkey.RuntimeMinmemory, Usage: "Minimum memory to be assigned to pod (In megabyte)"} + RunTimeMaxMemory = Flag{Type: Int, Name: flagkey.RuntimeMaxmemory, Usage: "Maximum memory to be assigned to pod (In megabyte)"} ReplicasMin = Flag{Type: Int, Name: flagkey.ReplicasMinscale, Usage: "Minimum number of pods (Uses resource inputs to configure HPA)", DefaultValue: 1} ReplicasMax = Flag{Type: Int, Name: flagkey.ReplicasMaxscale, Usage: "Maximum number of pods (Uses resource inputs to configure HPA)", DefaultValue: 1} @@ -186,7 +188,7 @@ var ( KwName = Flag{Type: String, Name: flagkey.KwName, Usage: "Watch name"} KwFnName = Flag{Type: String, Name: flagkey.KwFnName, Usage: "Function name"} - KwNamespace = Flag{Type: String, Name: flagkey.KwNamespace, Aliases: []string{"ns"}, Usage: "Namespace of resource to watch", DefaultValue: metav1.NamespaceDefault} + KwNamespace = Flag{Type: String, Name: flagkey.KwNamespace, Aliases: []string{"ns"}, Usage: "Namespace of resource to watch"} KwObjType = Flag{Type: String, Name: flagkey.KwObjType, Usage: "Type of resource to watch (Pod, Service, etc.)", DefaultValue: "pod"} KwLabels = Flag{Type: String, Name: flagkey.KwLabels, Usage: "Label selector of the form a=b,c=d"} diff --git a/pkg/fission-cli/flag/key/key.go b/pkg/fission-cli/flag/key/key.go index 955259d4..a15664e0 100644 --- a/pkg/fission-cli/flag/key/key.go +++ b/pkg/fission-cli/flag/key/key.go @@ -38,6 +38,10 @@ const ( NamespacePackage = "pkgNamespace" NamespaceTrigger = "triggerNamespace" NamespaceCanary = "canaryNamespace" + Namespace = "namespace" + ForceNamespace = "force-namespace" + AllNamespaces = "all-namespaces" + ForceDelete = "force" RuntimeMincpu = "mincpu" RuntimeMaxcpu = "maxcpu" diff --git a/pkg/fission-cli/util/util.go b/pkg/fission-cli/util/util.go index 0ad8e0c4..fbd9c55e 100644 --- a/pkg/fission-cli/util/util.go +++ b/pkg/fission-cli/util/util.go @@ -104,11 +104,8 @@ func KubifyName(old string) string { return newName } -// GetKubernetesClient builds a new kubernetes client. If the KUBECONFIG -// environment variable is empty or doesn't exist, ~/.kube/config is used for -// the kube config path -func GetKubernetesClient(kubeContext string) (*restclient.Config, kubernetes.Interface, error) { - loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() +func getLoadingRules() (loadingRules *clientcmd.ClientConfigLoadingRules, err error) { + loadingRules = clientcmd.NewDefaultClientConfigLoadingRules() kubeConfigPath := os.Getenv("KUBECONFIG") if len(kubeConfigPath) == 0 { @@ -126,7 +123,7 @@ func GetKubernetesClient(kubeContext string) (*restclient.Config, kubernetes.Int kubeConfigPath = filepath.Join(homeDir, ".kube", "config") if _, err := os.Stat(kubeConfigPath); os.IsNotExist(err) { - return nil, nil, errors.New("Couldn't find kubeconfig file. " + + return nil, errors.New("Couldn't find kubeconfig file. " + "Set the KUBECONFIG environment variable to your kubeconfig's path.") } loadingRules.ExplicitPath = kubeConfigPath @@ -134,6 +131,17 @@ func GetKubernetesClient(kubeContext string) (*restclient.Config, kubernetes.Int } else { console.Verbose(2, "Using kubeconfig from environment %q", kubeConfigPath) } + return loadingRules, nil +} + +// GetKubernetesClient builds a new kubernetes client. If the KUBECONFIG +// environment variable is empty or doesn't exist, ~/.kube/config is used for +// the kube config path +func GetKubernetesClient(kubeContext string) (*restclient.Config, kubernetes.Interface, error) { + loadingRules, err := getLoadingRules() + if err != nil { + return nil, nil, err + } config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( loadingRules, &clientcmd.ConfigOverrides{CurrentContext: kubeContext}).ClientConfig() @@ -149,6 +157,25 @@ func GetKubernetesClient(kubeContext string) (*restclient.Config, kubernetes.Int return config, clientset, nil } +// GetKubernetesNamespace builds a new kubernetes client. If the KUBECONFIG +// environment variable is empty or doesn't exist, ~/.kube/config is used for +// the kube config path +func GetKubernetesNamespace(kubeContext string) (currentNS string, err error) { + loadingRules, err := getLoadingRules() + if err != nil { + return "", err + } + + config1, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( + loadingRules, &clientcmd.ConfigOverrides{CurrentContext: kubeContext}).RawConfig() + if err != nil { + return "", errors.Wrap(err, "Failed to build Kubernetes config") + } + currentNS = config1.Contexts[config1.CurrentContext].Namespace + + return currentNS, nil +} + // given a list of functions, this checks if the functions actually exist on the cluster func CheckFunctionExistence(client client.Interface, functions []string, fnNamespace string) (err error) { fnMissing := make([]string, 0) @@ -459,3 +486,34 @@ func GetStorageURL(ctx context.Context, kubeContext string) (*url.URL, error) { return serverURL, nil } + +func GetResourceNamespace(input cli.Input, deprecatedFlag string) (namespace, currentNS string, err error) { + namespace = input.String(deprecatedFlag) + currentNS = namespace + + if input.String(flagkey.Namespace) != "" { + namespace = input.String(flagkey.Namespace) + currentNS = namespace + return namespace, currentNS, err + } + console.Verbose(2, "Namespace from user %s ", namespace) + + if namespace == "" { + if os.Getenv("FISSION_DEFAULT_NAMESPACE") != "" { + currentNS = os.Getenv("FISSION_DEFAULT_NAMESPACE") + } else { + kubeContext := input.String(flagkey.KubeContext) + currentNS, err = GetKubernetesNamespace(kubeContext) + if err != nil { + return namespace, currentNS, err + } + } + if currentNS == "" { + return namespace, currentNS, errors.Errorf("either set current-context or provide namespace with --namespace flag") + } + } + + console.Verbose(2, "Namespace final %s ", currentNS) + + return namespace, currentNS, nil +} diff --git a/pkg/fission-cli/util/util_test.go b/pkg/fission-cli/util/util_test.go index fd64262b..dedf0e78 100644 --- a/pkg/fission-cli/util/util_test.go +++ b/pkg/fission-cli/util/util_test.go @@ -64,3 +64,11 @@ func TestGetEnvVarFromStringSlice(t *testing.T) { }) } } + +func TestGetConfig(t *testing.T) { + response, err := GetKubernetesNamespace("") + if err != nil { + t.Log(err) + } + t.Log("Current NS: ", response) +} diff --git a/test/kind_CI.sh b/test/kind_CI.sh index d8bb536a..92199bf0 100755 --- a/test/kind_CI.sh +++ b/test/kind_CI.sh @@ -101,6 +101,10 @@ main() { $ROOT/test/tests/test_fn_update/test_secret_update.sh \ $ROOT/test/tests/test_fn_update/test_nd_pkg_update.sh \ $ROOT/test/tests/test_fn_update/test_poolmgr_nd.sh + $ROOT/test/tests/test_namespace/test_ns_current_context.sh + $ROOT/test/tests/test_namespace/test_ns_flag.sh + $ROOT/test/tests/test_namespace/test_ns_env.sh + $ROOT/test/tests/test_namespace/test_ns_deprecated_flag.sh set -e diff --git a/test/tests/test_namespace/test_ns_current_context.sh b/test/tests/test_namespace/test_ns_current_context.sh new file mode 100755 index 00000000..e8ab0efd --- /dev/null +++ b/test/tests/test_namespace/test_ns_current_context.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +set -euo pipefail +source $(dirname $0)/../../utils.sh + +TEST_ID=$(generate_test_id) +echo "TEST_ID = $TEST_ID" + +tmp_dir="/tmp/test-$TEST_ID" +mkdir -p $tmp_dir + +ROOT=$(dirname $0)/../../.. + +cleanup() { + echo "previous response" $? + log "Cleaning up..." + clean_resource_by_id $TEST_ID + rm -rf $tmp_dir +} + +if [ -z "${TEST_NOCLEANUP:-}" ]; then + trap cleanup EXIT +else + log "TEST_NOCLEANUP is set; not cleaning up test artifacts afterwards." +fi + +httptrigger=http-$TEST_ID +httptriggerurl=/url-$TEST_ID +fn_n=nbuilderhello-$TEST_ID + +cd $ROOT/examples/go/hello-world + +log "Creating httptrigger using default namespace" +fission httptrigger create --function $fn_n --url /$httptriggerurl --name $httptrigger + +log "verify trigger exists" +fission httptrigger list --namespace default | grep $httptrigger + +log "Test PASSED" diff --git a/test/tests/test_namespace/test_ns_deprecated_flag.sh b/test/tests/test_namespace/test_ns_deprecated_flag.sh new file mode 100755 index 00000000..d6475059 --- /dev/null +++ b/test/tests/test_namespace/test_ns_deprecated_flag.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +set -euo pipefail +source $(dirname $0)/../../utils.sh + +TEST_ID=$(generate_test_id) +echo "TEST_ID = $TEST_ID" + +tmp_dir="/tmp/test-$TEST_ID" +mkdir -p $tmp_dir + +TEST_NS=ns-$TEST_ID + +ROOT=$(dirname $0)/../../.. + +cleanup() { + echo "previous response" $? + log "Cleaning up..." + clean_resource_by_id_for_namespace $TEST_ID $TEST_NS + rm -rf $tmp_dir +} + +if [ -z "${TEST_NOCLEANUP:-}" ]; then + trap cleanup EXIT +else + log "TEST_NOCLEANUP is set; not cleaning up test artifacts afterwards." +fi + +httptrigger=http-$TEST_ID +httptriggerurl=/url-$TEST_ID +fn_n=nbuilderhello-$TEST_ID + +cd $ROOT/examples/go/hello-world + +kubectl create namespace $TEST_NS + +log "Creating httptrigger using deprecating flag" +fission httptrigger create --function $fn_n --url /$httptriggerurl --name $httptrigger --fnNamespace $TEST_NS + +log "verify trigger exists" +fission httptrigger list --namespace $TEST_NS | grep $httptrigger + +log "Test PASSED" diff --git a/test/tests/test_namespace/test_ns_env.sh b/test/tests/test_namespace/test_ns_env.sh new file mode 100755 index 00000000..a6cd385d --- /dev/null +++ b/test/tests/test_namespace/test_ns_env.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +set -euo pipefail +source $(dirname $0)/../../utils.sh + +TEST_ID=$(generate_test_id) +echo "TEST_ID = $TEST_ID" + +tmp_dir="/tmp/test-$TEST_ID" +mkdir -p $tmp_dir + +TEST_NS=ns-$TEST_ID + +export FISSION_DEFAULT_NAMESPACE=$TEST_NS + +ROOT=$(dirname $0)/../../.. + +cleanup() { + echo "previous response" $? + log "Cleaning up..." + clean_resource_by_id_for_namespace $TEST_ID $TEST_NS + rm -rf $tmp_dir +} + +if [ -z "${TEST_NOCLEANUP:-}" ]; then + trap cleanup EXIT +else + log "TEST_NOCLEANUP is set; not cleaning up test artifacts afterwards." +fi + +httptrigger=http-$TEST_ID +httptriggerurl=/url-$TEST_ID +fn_n=nbuilderhello-$TEST_ID + +cd $ROOT/examples/go/hello-world + +kubectl create namespace $TEST_NS + +log "Creating httptrigger in namespace using env var" +fission httptrigger create --function $fn_n --url /$httptriggerurl --name $httptrigger + +log "verify trigger exists" +fission httptrigger list --namespace $TEST_NS | grep $httptrigger + +log "Test PASSED" diff --git a/test/tests/test_namespace/test_ns_flag.sh b/test/tests/test_namespace/test_ns_flag.sh new file mode 100755 index 00000000..69a126f9 --- /dev/null +++ b/test/tests/test_namespace/test_ns_flag.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +set -euo pipefail +source $(dirname $0)/../../utils.sh + +TEST_ID=$(generate_test_id) +echo "TEST_ID = $TEST_ID" + +tmp_dir="/tmp/test-$TEST_ID" +mkdir -p $tmp_dir + +TEST_NS=ns-$TEST_ID + +ROOT=$(dirname $0)/../../.. + +cleanup() { + echo "previous response" $? + log "Cleaning up..." + clean_resource_by_id_for_namespace $TEST_ID $TEST_NS + rm -rf $tmp_dir +} + +if [ -z "${TEST_NOCLEANUP:-}" ]; then + trap cleanup EXIT +else + log "TEST_NOCLEANUP is set; not cleaning up test artifacts afterwards." +fi + +httptrigger=http-$TEST_ID +httptriggerurl=/url-$TEST_ID +fn_n=nbuilderhello-$TEST_ID + +cd $ROOT/examples/go/hello-world + +kubectl create namespace $TEST_NS + +log "Creating httptrigger in namespace provided by flag" +fission httptrigger create --function $fn_n --url /$httptriggerurl --name $httptrigger --namespace $TEST_NS + +log "verify trigger exists" +fission httptrigger list --namespace $TEST_NS | grep $httptrigger + +log "Test PASSED" diff --git a/test/utils.sh b/test/utils.sh index 9a4c7b34..3139eeeb 100755 --- a/test/utils.sh +++ b/test/utils.sh @@ -43,6 +43,38 @@ clean_resource_by_id() { set -e } +clean_resource_by_id_for_namespace() { + test_id=$1 + namespace=$2 + KUBECTL="kubectl --namespace $namespace" + set +e + echo test_id + + fn_list=$(fission function list | grep $test_id | awk '{print $1}') + for fn in $fn_list; do + fission fn delete --name $fn + done + + pkg_list=$(fission package list | grep $test_id | awk '{print $1}') + for pkg in $pkg_list; do + fission pkg info --name $pkg + fission pkg delete -f --name $pkg + done + + route_list=$(fission route list | grep $test_id | awk '{print $1}') + for route in $route_list; do + fission route delete --name $route + done + + crds=$($KUBECTL get crd | grep "fission.io" | awk '{print $1}') + crds="$crds configmaps secrets" + for crd in $crds; do + $KUBECTL get $crd -o name | grep $test_id | xargs --no-run-if-empty $KUBECTL delete + done + + set -e +} + test_fn() { if [ -z $FISSION_ROUTER ]; then log "Environment FISSION_ROUTER not set"