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
This commit is contained in:
neha_gupta
2022-10-11 13:23:47 +05:30
committed by GitHub
parent 0739aca920
commit b9513868ed
74 changed files with 1289 additions and 304 deletions
+4 -1
View File
@@ -55,7 +55,7 @@ jobs:
with: with:
version: ${{ env.HELM_VERSION }} version: ${{ env.HELM_VERSION }}
- name: Kind Clutser - name: Kind Cluster
uses: engineerd/setup-kind@v0.5.0 uses: engineerd/setup-kind@v0.5.0
with: with:
image: kindest/node:${{ matrix.kindversion }} image: kindest/node:${{ matrix.kindversion }}
@@ -67,6 +67,9 @@ jobs:
kubectl cluster-info --context kind-kind kubectl cluster-info --context kind-kind
kubectl get nodes kubectl get nodes
sudo apt-get install -y apache2-utils 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 - name: Helm chart lint
run: | run: |
+3
View File
@@ -64,6 +64,9 @@ jobs:
kubectl cluster-info --context kind-kind kubectl cluster-info --context kind-kind
kubectl get nodes kubectl get nodes
kubectl get storageclasses.storage.k8s.io 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 - name: Dump system info
run: | run: |
+2 -2
View File
@@ -87,7 +87,7 @@ func App() *cobra.Command {
}) })
wrapper.SetFlags(rootCmd, flag.FlagSet{ 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{} groups := helptemplate.CommandGroups{}
@@ -101,7 +101,7 @@ func App() *cobra.Command {
flagExposer := helptemplate.ActsAsRootCommand(rootCmd, nil, groups...) flagExposer := helptemplate.ActsAsRootCommand(rootCmd, nil, groups...)
// show global options in usage // 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 return rootCmd
} }
+11 -2
View File
@@ -150,12 +150,21 @@ func ValidateKubeName(field string, val string) error {
return result.ErrorOrNil() 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 { func ValidateKubeReference(refName string, name string, namespace string) error {
result := &multierror.Error{} result := &multierror.Error{}
result = multierror.Append(result, result = multierror.Append(result,
ValidateKubeName(fmt.Sprintf("%v.Name", refName), name), ValidateKubeName(fmt.Sprintf("%s.Name", refName), name),
ValidateKubeName(fmt.Sprintf("%v.Namespace", refName), namespace)) validateNS(fmt.Sprintf("%s.Namespace", refName), namespace))
return result.ErrorOrNil() return result.ErrorOrNil()
} }
+4 -4
View File
@@ -136,16 +136,16 @@ func (c *MessageQueueTrigger) Update(mqTrigger *fv1.MessageQueueTrigger) (*metav
} }
func (c *MessageQueueTrigger) Delete(m *metav1.ObjectMeta) error { func (c *MessageQueueTrigger) Delete(m *metav1.ObjectMeta) error {
relativeUrl := fmt.Sprintf("triggers/messagequeue/%v", m.Name) relativeUrl := fmt.Sprintf("triggers/messagequeue/%s", m.Name)
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace) relativeUrl += fmt.Sprintf("?namespace=%s", m.Namespace)
return c.client.Delete(relativeUrl) return c.client.Delete(relativeUrl)
} }
func (c *MessageQueueTrigger) List(mqType string, ns string) ([]fv1.MessageQueueTrigger, error) { 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 { if len(mqType) > 0 {
// TODO remove this, replace with field selector // 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) resp, err := c.client.Get(relativeUrl)
+1 -1
View File
@@ -76,7 +76,7 @@ func Commands() *cobra.Command {
RunE: wrapper.Wrapper(List), RunE: wrapper.Wrapper(List),
} }
wrapper.SetFlags(listCmd, flag.FlagSet{ wrapper.SetFlags(listCmd, flag.FlagSet{
Optional: []flag.Flag{flag.NamespaceCanary}, Optional: []flag.Flag{flag.NamespaceCanary, flag.AllNamespaces},
}) })
command := &cobra.Command{ command := &cobra.Command{
+6 -3
View File
@@ -47,20 +47,23 @@ func (opts *CreateSubCommand) do(input cli.Input) error {
return opts.run(input) 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 // canary configs can be created for functions in the same namespace
name := input.String(flagkey.CanaryName) name := input.String(flagkey.CanaryName)
ht := input.String(flagkey.CanaryHTTPTriggerName) ht := input.String(flagkey.CanaryHTTPTriggerName)
newFunc := input.String(flagkey.CanaryNewFunc) newFunc := input.String(flagkey.CanaryNewFunc)
oldFunc := input.String(flagkey.CanaryOldFunc) 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) incrementStep := input.Int(flagkey.CanaryWeightIncrement)
failureThreshold := input.Int(flagkey.CanaryFailureThreshold) failureThreshold := input.Int(flagkey.CanaryFailureThreshold)
incrementInterval := input.String(flagkey.CanaryIncrementInterval) incrementInterval := input.String(flagkey.CanaryIncrementInterval)
// check for time parsing // check for time parsing
_, err := time.ParseDuration(incrementInterval) _, err = time.ParseDuration(incrementInterval)
if err != nil { if err != nil {
return errors.Wrap(err, "error parsing time duration") return errors.Wrap(err, "error parsing time duration")
} }
+7 -3
View File
@@ -36,13 +36,17 @@ func Delete(input cli.Input) error {
return (&DeleteSubCommand{}).run(input) 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{ m := &metav1.ObjectMeta{
Name: input.String(flagkey.CanaryName), 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 err != nil {
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
return nil return nil
+9 -2
View File
@@ -27,6 +27,7 @@ import (
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type GetSubCommand struct { type GetSubCommand struct {
@@ -37,10 +38,16 @@ func Get(input cli.Input) error {
return (&GetSubCommand{}).run(input) 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{ canaryCfg, err := opts.Client().V1().CanaryConfig().Get(&metav1.ObjectMeta{
Name: input.String(flagkey.CanaryName), Name: input.String(flagkey.CanaryName),
Namespace: input.String(flagkey.NamespaceCanary), Namespace: namespace,
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "error getting canary config") return errors.Wrap(err, "error getting canary config")
+15 -4
View File
@@ -23,9 +23,11 @@ import (
"github.com/pkg/errors" "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/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type ListSubCommand struct { type ListSubCommand struct {
@@ -45,13 +47,22 @@ func (opts *ListSubCommand) do(input cli.Input) error {
return opts.run(input) return opts.run(input)
} }
func (opts *ListSubCommand) complete(input cli.Input) error { func (opts *ListSubCommand) complete(input cli.Input) (err error) {
opts.namespace = input.String(flagkey.NamespaceCanary) _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespaceCanary)
if err != nil {
return errors.Wrap(err, "error in listing canary config ")
}
return nil return nil
} }
func (opts *ListSubCommand) run(input cli.Input) error { func (opts *ListSubCommand) run(input cli.Input) (err error) {
canaryCfgs, err := opts.Client().V1().CanaryConfig().List(opts.namespace)
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 { if err != nil {
return errors.Wrap(err, "error listing canary config") return errors.Wrap(err, "error listing canary config")
} }
+7 -3
View File
@@ -27,6 +27,7 @@ import (
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type UpdateSubCommand struct { type UpdateSubCommand struct {
@@ -46,16 +47,19 @@ func (opts *UpdateSubCommand) do(input cli.Input) error {
return opts.run(input) 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 // get the current config
name := input.String(flagkey.CanaryName) 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) incrementStep := input.Int(flagkey.CanaryWeightIncrement)
failureThreshold := input.Int(flagkey.CanaryFailureThreshold) failureThreshold := input.Int(flagkey.CanaryFailureThreshold)
incrementInterval := input.String(flagkey.CanaryIncrementInterval) incrementInterval := input.String(flagkey.CanaryIncrementInterval)
// check for time parsing // check for time parsing
_, err := time.ParseDuration(incrementInterval) _, err = time.ParseDuration(incrementInterval)
if err != nil { if err != nil {
return errors.Wrap(err, "error parsing time duration") return errors.Wrap(err, "error parsing time duration")
} }
+1 -1
View File
@@ -81,7 +81,7 @@ func Commands() *cobra.Command {
RunE: wrapper.Wrapper(List), RunE: wrapper.Wrapper(List),
} }
wrapper.SetFlags(listCmd, flag.FlagSet{ wrapper.SetFlags(listCmd, flag.FlagSet{
Optional: []flag.Flag{flag.NamespaceEnvironment}, Optional: []flag.Flag{flag.NamespaceEnvironment, flag.AllNamespaces},
}) })
listPodsCmd := &cobra.Command{ listPodsCmd := &cobra.Command{
+26 -8
View File
@@ -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. // run write the resource to a spec file or create a fission CRD with remote fission server.
// It also prints warning/error if necessary. // 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 m := opts.env.ObjectMeta
envList, err := opts.Client().V1().Environment().List(m.Namespace) 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) 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 // if we're writing a spec, don't call the API
// save to spec file or display the spec to console // save to spec file or display the spec to console
if input.Bool(flagkey.SpecDry) { if input.Bool(flagkey.SpecDry) {
err = opts.env.Validate()
if err != nil {
return fv1.AggregateValidationErrors("Environment", err)
}
return spec.SpecDry(*opts.env) return spec.SpecDry(*opts.env)
} }
if input.Bool(flagkey.SpecSave) { 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) specFile := fmt.Sprintf("env-%v.yaml", m.Name)
err = spec.SpecSave(*opts.env, specFile) err = spec.SpecSave(*opts.env, specFile)
if err != nil { if err != nil {
@@ -90,6 +107,12 @@ func (opts *CreateSubCommand) run(input cli.Input) error {
return nil 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) _, err = opts.Client().V1().Environment().Create(opts.env)
if err != nil { if err != nil {
return errors.Wrap(err, "error creating environment") return errors.Wrap(err, "error creating environment")
@@ -105,7 +128,7 @@ func createEnvironmentFromCmd(input cli.Input) (*fv1.Environment, error) {
envName := input.String(flagkey.EnvName) envName := input.String(flagkey.EnvName)
envImg := input.String(flagkey.EnvImage) envImg := input.String(flagkey.EnvImage)
envNamespace := input.String(flagkey.NamespaceEnvironment)
envBuildCmd := input.String(flagkey.EnvBuildcommand) envBuildCmd := input.String(flagkey.EnvBuildcommand)
envExternalNetwork := input.Bool(flagkey.EnvExternalNetwork) envExternalNetwork := input.Bool(flagkey.EnvExternalNetwork)
keepArchive := input.Bool(flagkey.EnvKeeparchive) keepArchive := input.Bool(flagkey.EnvKeeparchive)
@@ -165,8 +188,7 @@ func createEnvironmentFromCmd(input cli.Input) (*fv1.Environment, error) {
APIVersion: fv1.CRD_VERSION, APIVersion: fv1.CRD_VERSION,
}, },
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: envName, Name: envName,
Namespace: envNamespace,
}, },
Spec: fv1.EnvironmentSpec{ Spec: fv1.EnvironmentSpec{
Version: envVersion, Version: envVersion,
@@ -196,10 +218,6 @@ func createEnvironmentFromCmd(input cli.Input) (*fv1.Environment, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = env.Validate()
if err != nil {
return nil, fv1.AggregateValidationErrors("Environment", err)
}
return env, nil return env, nil
} }
+11 -3
View File
@@ -24,6 +24,7 @@ import (
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "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" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util" "github.com/fission/fission/pkg/fission-cli/util"
) )
@@ -36,10 +37,17 @@ func Delete(input cli.Input) error {
return (&DeleteSubCommand{}).do(input) 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{ m := &metav1.ObjectMeta{
Name: input.String(flagkey.EnvName), Name: input.String(flagkey.EnvName),
Namespace: input.String(flagkey.NamespaceEnvironment), Namespace: currentContextNS,
} }
if !input.Bool(flagkey.EnvForce) { 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 err != nil {
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
return nil return nil
+9 -2
View File
@@ -27,6 +27,7 @@ import (
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type GetSubCommand struct { type GetSubCommand struct {
@@ -37,10 +38,16 @@ func Get(input cli.Input) error {
return (&GetSubCommand{}).do(input) 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{ m := &metav1.ObjectMeta{
Name: input.String(flagkey.EnvName), Name: input.String(flagkey.EnvName),
Namespace: input.String(flagkey.NamespaceEnvironment), Namespace: currentNS,
} }
env, err := opts.Client().V1().Environment().Get(m) env, err := opts.Client().V1().Environment().Get(m)
+20 -5
View File
@@ -23,9 +23,11 @@ import (
"github.com/pkg/errors" "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/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type ListSubCommand struct { type ListSubCommand struct {
@@ -36,20 +38,33 @@ func List(input cli.Input) error {
return (&ListSubCommand{}).do(input) return (&ListSubCommand{}).do(input)
} }
func (opts *ListSubCommand) do(input cli.Input) error { func (opts *ListSubCommand) do(input cli.Input) (err error) {
envs, err := opts.Client().V1().Environment().List(input.String(flagkey.NamespaceEnvironment))
_, 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 { if err != nil {
return errors.Wrap(err, "error listing environments") return errors.Wrap(err, "error listing environments")
} }
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) 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 { 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.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.Cpu(), env.Spec.Resources.Limits.Cpu(),
env.Spec.Resources.Requests.Memory(), env.Spec.Resources.Limits.Memory(), 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() w.Flush()
+10 -4
View File
@@ -28,6 +28,7 @@ import (
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
"github.com/fission/fission/pkg/utils" "github.com/fission/fission/pkg/utils"
) )
@@ -39,13 +40,18 @@ func ListPods(input cli.Input) error {
return (&ListPodsSubCommand{}).do(input) 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 // validate environment
_, err := opts.Client().V1().Environment().Get( _, err = opts.Client().V1().Environment().Get(
&metav1.ObjectMeta{ &metav1.ObjectMeta{
Name: input.String(flagkey.EnvName), Name: input.String(flagkey.EnvName),
Namespace: input.String(flagkey.NamespaceEnvironment), Namespace: currentNS,
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "error getting environment") return errors.Wrap(err, "error getting environment")
@@ -54,7 +60,7 @@ func (opts *ListPodsSubCommand) do(input cli.Input) error {
m := &metav1.ObjectMeta{ m := &metav1.ObjectMeta{
Name: input.String(flagkey.EnvName), Name: input.String(flagkey.EnvName),
Labels: map[string]string{ Labels: map[string]string{
v1.ENVIRONMENT_NAMESPACE: input.String(flagkey.NamespaceEnvironment), v1.ENVIRONMENT_NAMESPACE: currentNS,
v1.EXECUTOR_TYPE: input.String(flagkey.EnvExecutorType), v1.EXECUTOR_TYPE: input.String(flagkey.EnvExecutorType),
}, },
} }
+10 -2
View File
@@ -52,10 +52,15 @@ func (opts *UpdateSubCommand) do(input cli.Input) error {
return opts.run(input) 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{ env, err := opts.Client().V1().Environment().Get(&metav1.ObjectMeta{
Name: input.String(flagkey.EnvName), Name: input.String(flagkey.EnvName),
Namespace: input.String(flagkey.NamespaceEnvironment), Namespace: currentContextNS,
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "error finding environment") 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.ImagePullSecret = input.String(flagkey.EnvImagePullSecret)
} }
env.Spec.Resources.Requests = make(v1.ResourceList)
env.Spec.Resources.Limits = make(v1.ResourceList)
if input.IsSet(flagkey.RuntimeMincpu) { if input.IsSet(flagkey.RuntimeMincpu) {
mincpu := input.Int(flagkey.RuntimeMincpu) mincpu := input.Int(flagkey.RuntimeMincpu)
cpuRequest, err := resource.ParseQuantity(strconv.Itoa(mincpu) + "m") cpuRequest, err := resource.ParseQuantity(strconv.Itoa(mincpu) + "m")
+2 -3
View File
@@ -49,8 +49,7 @@ func Commands() *cobra.Command {
flag.RunTimeMinCPU, flag.RunTimeMaxCPU, flag.RunTimeMinMemory, flag.RunTimeMinCPU, flag.RunTimeMaxCPU, flag.RunTimeMinMemory,
flag.RunTimeMaxMemory, flag.ReplicasMin, flag.RunTimeMaxMemory, flag.ReplicasMin,
flag.ReplicasMax, flag.RunTimeTargetCPU, flag.ReplicasMax, flag.RunTimeTargetCPU,
flag.NamespaceFunction, flag.SpecSave, flag.SpecDry},
flag.NamespaceFunction, flag.NamespaceEnvironment, flag.SpecSave, flag.SpecDry},
}) })
getCmd := &cobra.Command{ getCmd := &cobra.Command{
@@ -121,7 +120,7 @@ func Commands() *cobra.Command {
RunE: wrapper.Wrapper(List), RunE: wrapper.Wrapper(List),
} }
wrapper.SetFlags(listCmd, flag.FlagSet{ wrapper.SetFlags(listCmd, flag.FlagSet{
Optional: []flag.Flag{flag.NamespaceFunction}, Optional: []flag.Flag{flag.NamespaceFunction, flag.AllNamespaces},
}) })
logsCmd := &cobra.Command{ logsCmd := &cobra.Command{
+59 -36
View File
@@ -64,14 +64,17 @@ func (opts *CreateSubCommand) do(input cli.Input) error {
func (opts *CreateSubCommand) complete(input cli.Input) error { func (opts *CreateSubCommand) complete(input cli.Input) error {
fnName := input.String(flagkey.FnName) 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 // user wants a spec, create a yaml file with package and function
toSpec := false toSpec := false
if input.Bool(flagkey.SpecSave) { if input.Bool(flagkey.SpecSave) {
toSpec = true toSpec = true
opts.specFile = fmt.Sprintf("function-%v.yaml", fnName) opts.specFile = fmt.Sprintf("function-%s.yaml", fnName)
} }
specDir := util.GetSpecDir(input) specDir := util.GetSpecDir(input)
specIgnore := util.GetSpecIgnore(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 // check for unique function names within a namespace
fn, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ fn, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{
Name: input.String(flagkey.FnName), Name: input.String(flagkey.FnName),
Namespace: input.String(flagkey.NamespaceFunction), Namespace: fnNamespace,
}) })
if err != nil && !ferror.IsNotFound(err) { if err != nil && !ferror.IsNotFound(err) {
return err return err
@@ -135,17 +138,19 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
fr, err := spec.ReadSpecs(specDir, specIgnore, false) fr, err := spec.ReadSpecs(specDir, specIgnore, false)
if err != nil { 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{ ObjectMeta: metav1.ObjectMeta{
Name: pkgName, Name: pkgName,
Namespace: fnNamespace, Namespace: userProvidedNS,
}, },
}, true, false) }, true, false)
if obj == nil { 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) pkg = obj.(*fv1.Package)
pkgMetadata = &pkg.ObjectMeta pkgMetadata = &pkg.ObjectMeta
} else { } else {
@@ -155,7 +160,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
Name: pkgName, Name: pkgName,
}) })
if err != nil { 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 pkgMetadata = &pkg.ObjectMeta
} }
@@ -164,7 +169,6 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
if envName != input.String(flagkey.FnEnvironmentName) { 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") 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 { } else {
// need to specify environment for creating new package // need to specify environment for creating new package
envName = input.String(flagkey.FnEnvironmentName) envName = input.String(flagkey.FnEnvironmentName)
@@ -176,29 +180,29 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
fr, err := spec.ReadSpecs(specDir, specIgnore, false) fr, err := spec.ReadSpecs(specDir, specIgnore, false)
if err != nil { 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{ exists, err := fr.ExistsInSpecs(fv1.Environment{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: envName, Name: envName,
Namespace: envNamespace, Namespace: userProvidedNS,
}, },
}) })
if err != nil { if err != nil {
return err return err
} }
if !exists { 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)) fnName, envName))
} }
} else { } else {
_, err := opts.Client().V1().Environment().Get(&metav1.ObjectMeta{ _, err := opts.Client().V1().Environment().Get(&metav1.ObjectMeta{
Namespace: envNamespace, Namespace: fnNamespace,
Name: envName, Name: envName,
}) })
if err != nil { if err != nil {
if e, ok := err.(ferror.Error); ok && e.Code == ferror.ErrorNotFound { 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 <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 <image>`\n", envName, envName, fnNamespace))
} else { } else {
return errors.Wrap(err, "error retrieving environment information") 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()) pkgName := generatePackageName(fnName, id.String())
// create new package in the same namespace as the function. // create new package in the same namespace as the function.
pkgMetadata, err = _package.CreatePackage(input, opts.Client(), pkgName, fnNamespace, envName, envNamespace, pkgMetadata, err = _package.CreatePackage(input, opts.Client(), pkgName, fnNamespace, envName,
srcArchiveFiles, deployArchiveFiles, buildcmd, specDir, opts.specFile, noZip) srcArchiveFiles, deployArchiveFiles, buildcmd, specDir, opts.specFile, noZip, userProvidedNS)
if err != nil { if err != nil {
return errors.Wrap(err, "error creating package") 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) 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 { 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) return errors.Wrapf(err, "error checking configmap %s", cfgMapName)
} }
} }
newCfgMap := fv1.ConfigMapReference{
Name: cfgMapName,
Namespace: fnNamespace,
}
cfgmaps = append(cfgmaps, newCfgMap)
} }
} } else {
for _, cfgMapName := range cfgMapNames { for _, cfgMapName := range cfgMapNames {
newCfgMap := fv1.ConfigMapReference{ newCfgMap := fv1.ConfigMapReference{
Name: cfgMapName, Name: cfgMapName,
Namespace: fnNamespace, 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{ opts.function.Spec.Environment = fv1.EnvironmentReference{
Name: envName, Name: envName,
Namespace: envNamespace, Namespace: fnNamespace,
} }
opts.function.Spec.Package = fv1.FunctionPackageRef{ opts.function.Spec.Package = fv1.FunctionPackageRef{
FunctionName: entrypoint, 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 return nil
} }
@@ -336,12 +359,12 @@ func generatePackageName(fnName string, id string) string {
lastIndexOfChar int lastIndexOfChar int
) )
if lenFnName+lenId <= 62 { if lenFnName+lenId <= 62 {
return fmt.Sprintf("%v-%v", fnName, id) return fmt.Sprintf("%s-%s", fnName, id)
} }
lastIndexOfChar = lenFnName - (lenFnName + lenId - 62) lastIndexOfChar = lenFnName - (lenFnName + lenId - 62)
pkgName := fmt.Sprintf("%v-%v", fnName[:lastIndexOfChar], id) pkgName := fmt.Sprintf("%v-%s", fnName[:lastIndexOfChar], id)
console.Info(fmt.Sprintf("Generated package %v from function to acceptable character limit", pkgName)) console.Info(fmt.Sprintf("Generated package %s from function to acceptable character limit", pkgName))
return pkgName return pkgName
} }
@@ -367,7 +390,7 @@ func (opts *CreateSubCommand) run(input cli.Input) error {
return errors.Wrap(err, "error creating function") 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. // Allow the user to specify an HTTP trigger while creating a function.
triggerUrl := input.String(flagkey.HtUrl) 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") 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 return nil
} }
+9 -4
View File
@@ -37,19 +37,24 @@ func Delete(input cli.Input) error {
} }
func (opts *DeleteSubCommand) do(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{ m := &metav1.ObjectMeta{
Name: input.String(flagkey.FnName), 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 err != nil {
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
return nil 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 return nil
} }
+6 -1
View File
@@ -25,6 +25,7 @@ import (
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type GetSubCommand struct { type GetSubCommand struct {
@@ -36,9 +37,13 @@ func Get(input cli.Input) error {
} }
func (opts *GetSubCommand) do(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{ fn, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{
Name: input.String(flagkey.FnName), Name: input.String(flagkey.FnName),
Namespace: input.String(flagkey.NamespaceFunction), Namespace: namespace,
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "error getting function") return errors.Wrap(err, "error getting function")
+7 -1
View File
@@ -25,6 +25,7 @@ import (
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type GetMetaSubCommand struct { type GetMetaSubCommand struct {
@@ -36,9 +37,14 @@ func GetMeta(input cli.Input) error {
} }
func (opts *GetMetaSubCommand) do(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{ fn, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{
Name: input.String(flagkey.FnName), Name: input.String(flagkey.FnName),
Namespace: input.String(flagkey.NamespaceFunction), Namespace: namespace,
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "error getting function") return errors.Wrap(err, "error getting function")
+16 -5
View File
@@ -24,9 +24,11 @@ import (
"github.com/pkg/errors" "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/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type ListSubCommand struct { type ListSubCommand struct {
@@ -38,16 +40,24 @@ func List(input cli.Input) error {
} }
func (opts *ListSubCommand) do(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 { if err != nil {
return errors.Wrap(err, "error listing functions") return errors.Wrap(err, "error listing functions")
} }
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) 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 { for _, f := range fns {
secrets := f.Spec.Secrets secrets := f.Spec.Secrets
configMaps := f.Spec.ConfigMaps configMaps := f.Spec.ConfigMaps
@@ -59,7 +69,7 @@ func (opts *ListSubCommand) do(input cli.Input) error {
configMapList = append(configMapList, configMap.Name) 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.ObjectMeta.Name, f.Spec.Environment.Name,
f.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType, f.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType,
f.Spec.InvokeStrategy.ExecutionStrategy.MinScale, 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.Requests.Memory().String(),
f.Spec.Resources.Limits.Memory().String(), f.Spec.Resources.Limits.Memory().String(),
strings.Join(secretsList, ","), strings.Join(secretsList, ","),
strings.Join(configMapList, ",")) strings.Join(configMapList, ","),
f.ObjectMeta.Namespace)
} }
w.Flush() w.Flush()
+6 -1
View File
@@ -40,6 +40,11 @@ func Log(input cli.Input) error {
} }
func (opts *LogSubCommand) do(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) dbType := input.String(flagkey.FnLogDBType)
fnPod := input.String(flagkey.FnLogPod) fnPod := input.String(flagkey.FnLogPod)
kubeContext := input.String(flagkey.KubeContext) 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{ f, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{
Name: input.String(flagkey.FnName), Name: input.String(flagkey.FnName),
Namespace: input.String(flagkey.NamespaceFunction), Namespace: namespace,
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "error getting function") return errors.Wrap(err, "error getting function")
+9 -3
View File
@@ -28,6 +28,7 @@ import (
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
"github.com/fission/fission/pkg/utils" "github.com/fission/fission/pkg/utils"
) )
@@ -41,10 +42,15 @@ func ListPods(input cli.Input) error {
func (opts *ListPodsSubCommand) do(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 // validate function
_, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ _, err = opts.Client().V1().Function().Get(&metav1.ObjectMeta{
Name: input.String(flagkey.FnName), Name: input.String(flagkey.FnName),
Namespace: input.String(flagkey.NamespaceFunction), Namespace: namespace,
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "error getting function") return errors.Wrap(err, "error getting function")
@@ -53,7 +59,7 @@ func (opts *ListPodsSubCommand) do(input cli.Input) error {
m := &metav1.ObjectMeta{ m := &metav1.ObjectMeta{
Name: input.String(flagkey.FnName), Name: input.String(flagkey.FnName),
Labels: map[string]string{ Labels: map[string]string{
v1.FUNCTION_NAMESPACE: input.String(flagkey.NamespaceFunction), v1.FUNCTION_NAMESPACE: namespace,
}, },
} }
@@ -55,7 +55,11 @@ func (opts *RunContainerSubCommand) do(input cli.Input) error {
func (opts *RunContainerSubCommand) complete(input cli.Input) error { func (opts *RunContainerSubCommand) complete(input cli.Input) error {
fnName := input.String(flagkey.FnName) 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 // user wants a spec, create a yaml file with package and function
toSpec := false toSpec := false
@@ -68,7 +72,7 @@ func (opts *RunContainerSubCommand) complete(input cli.Input) error {
// check for unique function names within a namespace // check for unique function names within a namespace
fn, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ fn, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{
Name: input.String(flagkey.FnName), Name: input.String(flagkey.FnName),
Namespace: input.String(flagkey.NamespaceFunction), Namespace: fnNamespace,
}) })
if err != nil && !ferror.IsNotFound(err) { if err != nil && !ferror.IsNotFound(err) {
return err return err
+7 -1
View File
@@ -51,9 +51,15 @@ func Test(input cli.Input) error {
} }
func (opts *TestSubCommand) do(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{ m := &metav1.ObjectMeta{
Name: input.String(flagkey.FnName), Name: input.String(flagkey.FnName),
Namespace: input.String(flagkey.NamespaceFunction), Namespace: namespace,
} }
kubeContext := input.String(flagkey.KubeContext) kubeContext := input.String(flagkey.KubeContext)
routerURL := os.Getenv("FISSION_ROUTER") routerURL := os.Getenv("FISSION_ROUTER")
+5 -2
View File
@@ -51,11 +51,14 @@ func (opts *UpdateSubCommand) do(input cli.Input) error {
func (opts *UpdateSubCommand) complete(input cli.Input) error { func (opts *UpdateSubCommand) complete(input cli.Input) error {
fnName := input.String(flagkey.FnName) 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{ function, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{
Name: input.String(flagkey.FnName), Name: input.String(flagkey.FnName),
Namespace: input.String(flagkey.NamespaceFunction), Namespace: fnNamespace,
}) })
if err != nil { if err != nil {
return errors.Wrap(err, fmt.Sprintf("read function '%v'", fnName)) return errors.Wrap(err, fmt.Sprintf("read function '%v'", fnName))
@@ -52,11 +52,15 @@ func (opts *UpdateContainerSubCommand) do(input cli.Input) error {
func (opts *UpdateContainerSubCommand) complete(input cli.Input) error { func (opts *UpdateContainerSubCommand) complete(input cli.Input) error {
fnName := input.String(flagkey.FnName) 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{ function, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{
Name: input.String(flagkey.FnName), Name: input.String(flagkey.FnName),
Namespace: input.String(flagkey.NamespaceFunction), Namespace: fnNamespace,
}) })
if err != nil { if err != nil {
return errors.Wrap(err, fmt.Sprintf("read function '%v'", fnName)) return errors.Wrap(err, fmt.Sprintf("read function '%v'", fnName))
+1 -1
View File
@@ -79,7 +79,7 @@ func Commands() *cobra.Command {
RunE: wrapper.Wrapper(List), RunE: wrapper.Wrapper(List),
} }
wrapper.SetFlags(listCmd, flag.FlagSet{ wrapper.SetFlags(listCmd, flag.FlagSet{
Optional: []flag.Flag{flag.NamespaceTrigger, flag.HtFnFilter}, Optional: []flag.Flag{flag.NamespaceTrigger, flag.HtFnFilter, flag.AllNamespaces},
}) })
command := &cobra.Command{ command := &cobra.Command{
+34 -17
View File
@@ -76,19 +76,10 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
} }
triggerName = id.String() triggerName = id.String()
} }
fnNamespace := input.String(flagkey.NamespaceFunction)
m := &metav1.ObjectMeta{ userProvidedNS, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction)
Name: triggerName, if err != nil {
Namespace: fnNamespace, return errors.Wrap(err, "error in deleting function ")
}
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")
} }
triggerUrl := input.String(flagkey.HtUrl) triggerUrl := input.String(flagkey.HtUrl)
@@ -130,9 +121,24 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
return err 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 // For Specs, the spec validate checks for function reference
if input.Bool(flagkey.SpecSave) { 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) specDir := util.GetSpecDir(input)
specIgnore := util.GetSpecIgnore(input) specIgnore := util.GetSpecIgnore(input)
fr, err := spec.ReadSpecs(specDir, specIgnore, false) 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{ exists, err := fr.ExistsInSpecs(fv1.Function{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: fn, Name: fn,
Namespace: fnNamespace, Namespace: userProvidedNS,
}, },
}) })
if err != nil { if err != nil {
@@ -155,6 +161,20 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
} }
} }
} else { } 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) err = util.CheckFunctionExistence(opts.Client(), functionList, fnNamespace)
if err != nil { if err != nil {
console.Warn(err.Error()) console.Warn(err.Error())
@@ -172,10 +192,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
host := input.String(flagkey.HtHost) host := input.String(flagkey.HtHost)
opts.trigger = &fv1.HTTPTrigger{ opts.trigger = &fv1.HTTPTrigger{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: m,
Name: triggerName,
Namespace: fnNamespace,
},
Spec: fv1.HTTPTriggerSpec{ Spec: fv1.HTTPTriggerSpec{
Host: host, Host: host,
RelativeURL: triggerUrl, RelativeURL: triggerUrl,
+6 -2
View File
@@ -49,7 +49,7 @@ func (opts *DeleteSubCommand) do(input cli.Input) error {
return opts.run(input) 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.triggerName = input.String(flagkey.HtName)
opts.functionName = input.String(flagkey.HtFnName) opts.functionName = input.String(flagkey.HtFnName)
if len(opts.triggerName) == 0 && len(opts.functionName) == 0 { 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 { } 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) 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 return nil
} }
+11 -5
View File
@@ -29,6 +29,7 @@ import (
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type GetSubCommand struct { type GetSubCommand struct {
@@ -43,10 +44,15 @@ func (opts *GetSubCommand) do(input cli.Input) error {
return opts.run(input) 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{ m := &metav1.ObjectMeta{
Name: input.String(flagkey.HtName), Name: input.String(flagkey.HtName),
Namespace: input.String(flagkey.NamespaceFunction), Namespace: namespace,
} }
ht, err := opts.Client().V1().HTTPTrigger().Get(m) ht, err := opts.Client().V1().HTTPTrigger().Get(m)
if err != nil { if err != nil {
@@ -60,7 +66,7 @@ func (opts *GetSubCommand) run(input cli.Input) error {
func printHtSummary(triggers []fv1.HTTPTrigger) { func printHtSummary(triggers []fv1.HTTPTrigger) {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) 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 { for _, trigger := range triggers {
function := "" function := ""
if trigger.Spec.FunctionReference.Type == fv1.FunctionReferenceTypeFunctionName { if trigger.Spec.FunctionReference.Type == fv1.FunctionReferenceTypeFunctionName {
@@ -93,8 +99,8 @@ func printHtSummary(triggers []fv1.HTTPTrigger) {
if len(trigger.Spec.Methods) > 0 { if len(trigger.Spec.Methods) > 0 {
methods = trigger.Spec.Methods 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", 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.Name, methods, trigger.Spec.RelativeURL, function, trigger.Spec.CreateIngress, host, path, trigger.Spec.IngressConfig.TLS, ann, trigger.ObjectMeta.Namespace)
} }
w.Flush() w.Flush()
} }
+15 -2
View File
@@ -23,6 +23,7 @@ import (
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type ListSubCommand struct { type ListSubCommand struct {
@@ -37,8 +38,20 @@ func (opts *ListSubCommand) do(input cli.Input) error {
return opts.run(input) return opts.run(input)
} }
func (opts *ListSubCommand) run(input cli.Input) error { func (opts *ListSubCommand) run(input cli.Input) (err error) {
hts, err := opts.Client().V1().HTTPTrigger().List(input.String(flagkey.NamespaceTrigger))
_, 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 { if err != nil {
return errors.Wrap(err, "error listing HTTP triggers") return errors.Wrap(err, "error listing HTTP triggers")
} }
+6 -2
View File
@@ -48,9 +48,13 @@ func (opts *UpdateSubCommand) do(input cli.Input) error {
return opts.run(input) 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) 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{ ht, err := opts.Client().V1().HTTPTrigger().Get(&metav1.ObjectMeta{
Name: htName, Name: htName,
+1 -1
View File
@@ -55,7 +55,7 @@ func Commands() *cobra.Command {
RunE: wrapper.Wrapper(List), RunE: wrapper.Wrapper(List),
} }
wrapper.SetFlags(listCmd, flag.FlagSet{ wrapper.SetFlags(listCmd, flag.FlagSet{
Optional: []flag.Flag{flag.NamespaceTrigger}, Optional: []flag.Flag{flag.NamespaceTrigger, flag.AllNamespaces},
}) })
command := &cobra.Command{ command := &cobra.Command{
+8 -4
View File
@@ -60,8 +60,12 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
watchName = id.String() watchName = id.String()
} }
fnName := input.String(flagkey.KwFnName) 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) objType := input.String(flagkey.KwObjType)
if input.Bool(flagkey.SpecSave) { if input.Bool(flagkey.SpecSave) {
@@ -75,7 +79,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
exists, err := fr.ExistsInSpecs(fv1.Function{ exists, err := fr.ExistsInSpecs(fv1.Function{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: fnName, Name: fnName,
Namespace: fnNamespace, Namespace: namespace,
}, },
}) })
if err != nil { if err != nil {
@@ -90,7 +94,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
opts.watcher = &fv1.KubernetesWatchTrigger{ opts.watcher = &fv1.KubernetesWatchTrigger{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: watchName, Name: watchName,
Namespace: fnNamespace, Namespace: namespace,
}, },
Spec: fv1.KubernetesWatchTriggerSpec{ Spec: fv1.KubernetesWatchTriggerSpec{
Namespace: namespace, Namespace: namespace,
+5 -2
View File
@@ -46,9 +46,12 @@ func (opts *DeleteSubCommand) do(input cli.Input) error {
return opts.run(input) 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.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 return nil
} }
+14 -4
View File
@@ -23,9 +23,11 @@ import (
"github.com/pkg/errors" "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/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type ListSubCommand struct { type ListSubCommand struct {
@@ -45,13 +47,21 @@ func (opts *ListSubCommand) do(input cli.Input) error {
return opts.run(input) return opts.run(input)
} }
func (opts *ListSubCommand) complete(input cli.Input) error { func (opts *ListSubCommand) complete(input cli.Input) (err error) {
opts.namespace = input.String(flagkey.NamespaceTrigger) _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespaceTrigger)
if err != nil {
return errors.Wrap(err, "error listing kubewatchers")
}
return nil return nil
} }
func (opts *ListSubCommand) run(input cli.Input) error { func (opts *ListSubCommand) run(input cli.Input) (err error) {
ws, err := opts.Client().V1().KubeWatcher().List(opts.namespace) 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 { if err != nil {
return errors.Wrap(err, "error listing kubewatchers") return errors.Wrap(err, "error listing kubewatchers")
} }
+1 -1
View File
@@ -71,7 +71,7 @@ func Commands() *cobra.Command {
RunE: wrapper.Wrapper(List), RunE: wrapper.Wrapper(List),
} }
wrapper.SetFlags(listCmd, flag.FlagSet{ wrapper.SetFlags(listCmd, flag.FlagSet{
Optional: []flag.Flag{flag.NamespaceTrigger}, Optional: []flag.Flag{flag.NamespaceTrigger, flag.AllNamespaces},
}) })
command := &cobra.Command{ command := &cobra.Command{
+19 -7
View File
@@ -61,7 +61,11 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
mqtName = id.String() mqtName = id.String()
} }
fnName := input.String(flagkey.MqtFnName) 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) mqtKind := input.String(flagkey.MqtKind)
@@ -94,7 +98,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
contentType = "application/json" contentType = "application/json"
} }
err := checkMQTopicAvailability(mqType, mqtKind, topic, respTopic) err = checkMQTopicAvailability(mqType, mqtKind, topic, respTopic)
if err != nil { if err != nil {
return err return err
} }
@@ -136,7 +140,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
exists, err := fr.ExistsInSpecs(fv1.Function{ exists, err := fr.ExistsInSpecs(fv1.Function{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: fnName, Name: fnName,
Namespace: fnNamespace, Namespace: userProvidedNS,
}, },
}) })
if err != nil { if err != nil {
@@ -153,11 +157,19 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
} }
} }
opts.trigger = &fv1.MessageQueueTrigger{ m := metav1.ObjectMeta{
ObjectMeta: metav1.ObjectMeta{ Name: mqtName,
Namespace: fnNamespace,
}
if input.Bool(flagkey.SpecSave) || input.Bool(flagkey.SpecDry) {
m = metav1.ObjectMeta{
Name: mqtName, Name: mqtName,
Namespace: fnNamespace, Namespace: userProvidedNS,
}, }
}
opts.trigger = &fv1.MessageQueueTrigger{
ObjectMeta: m,
Spec: fv1.MessageQueueTriggerSpec{ Spec: fv1.MessageQueueTriggerSpec{
FunctionReference: fv1.FunctionReference{ FunctionReference: fv1.FunctionReference{
Type: fv1.FunctionReferenceTypeFunctionName, Type: fv1.FunctionReferenceTypeFunctionName,
+8 -2
View File
@@ -45,10 +45,16 @@ func (opts *DeleteSubCommand) do(input cli.Input) error {
return opts.run(input) 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{ opts.metadata = &metav1.ObjectMeta{
Name: input.String(flagkey.MqtName), Name: input.String(flagkey.MqtName),
Namespace: input.String(flagkey.NamespaceTrigger), Namespace: namespace,
} }
return nil return nil
} }
+19 -8
View File
@@ -23,9 +23,11 @@ import (
"github.com/pkg/errors" "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/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type ListSubCommand struct { type ListSubCommand struct {
@@ -45,24 +47,33 @@ func (opts *ListSubCommand) do(input cli.Input) error {
return opts.run(input) return opts.run(input)
} }
func (opts *ListSubCommand) complete(input cli.Input) error { func (opts *ListSubCommand) complete(input cli.Input) (err error) {
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 return nil
} }
func (opts *ListSubCommand) run(input cli.Input) error { func (opts *ListSubCommand) run(input cli.Input) (err error) {
mqts, err := opts.Client().V1().MessageQueueTrigger().List(input.String(flagkey.MqtMQType), opts.namespace)
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 { if err != nil {
return errors.Wrap(err, "error listing message queue triggers") return errors.Wrap(err, "error listing message queue triggers")
} }
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) 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", 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") "NAME", "FUNCTION_NAME", "MESSAGE_QUEUE_TYPE", "TOPIC", "RESPONSE_TOPIC", "ERROR_TOPIC", "MAX_RETRIES", "PUB_MSG_CONTENT_TYPE", "NAMESPACE")
for _, mqt := range mqts { for _, mqt := range mqts {
fmt.Fprintf(w, "%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\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.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() w.Flush()
+14 -2
View File
@@ -25,6 +25,7 @@ import (
fv1 "github.com/fission/fission/pkg/apis/core/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/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "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" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util" "github.com/fission/fission/pkg/fission-cli/util"
) )
@@ -46,10 +47,15 @@ func (opts *UpdateSubCommand) do(input cli.Input) error {
return opts.run(input) 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{ mqt, err := opts.Client().V1().MessageQueueTrigger().Get(&metav1.ObjectMeta{
Name: input.String(flagkey.MqtName), Name: input.String(flagkey.MqtName),
Namespace: input.String(flagkey.NamespaceTrigger), Namespace: namespace,
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "error getting message queue trigger") return errors.Wrap(err, "error getting message queue trigger")
@@ -93,6 +99,12 @@ func (opts *UpdateSubCommand) complete(input cli.Input) error {
updated = true updated = true
} }
if len(fnName) > 0 { 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 mqt.Spec.FunctionReference.Name = fnName
updated = true updated = true
} }
+2 -2
View File
@@ -33,7 +33,7 @@ func Commands() *cobra.Command {
Required: []flag.Flag{flag.PkgEnvironment}, Required: []flag.Flag{flag.PkgEnvironment},
Optional: []flag.Flag{flag.PkgName, flag.PkgCode, flag.PkgSrcArchive, flag.PkgDeployArchive, Optional: []flag.Flag{flag.PkgName, flag.PkgCode, flag.PkgSrcArchive, flag.PkgDeployArchive,
flag.PkgSrcChecksum, flag.PkgDeployChecksum, flag.PkgInsecure, flag.PkgBuildCmd, 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{ getSrcCmd := &cobra.Command{
@@ -84,7 +84,7 @@ func Commands() *cobra.Command {
RunE: wrapper.Wrapper(List), RunE: wrapper.Wrapper(List),
} }
wrapper.SetFlags(listCmd, flag.FlagSet{ 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{ infoCmd := &cobra.Command{
+26 -12
View File
@@ -63,9 +63,13 @@ func (opts *CreateSubCommand) run(input cli.Input) error {
} }
} }
pkgNamespace := input.String(flagkey.NamespacePackage)
envName := input.String(flagkey.PkgEnvironment) 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) srcArchiveFiles := input.StringSlice(flagkey.PkgSrcArchive)
deployArchiveFiles := input.StringSlice(flagkey.PkgDeployArchive) deployArchiveFiles := input.StringSlice(flagkey.PkgDeployArchive)
buildcmd := input.String(flagkey.PkgBuildCmd) buildcmd := input.String(flagkey.PkgBuildCmd)
@@ -100,30 +104,30 @@ func (opts *CreateSubCommand) run(input cli.Input) error {
exists, err := fr.ExistsInSpecs(fv1.Environment{ exists, err := fr.ExistsInSpecs(fv1.Environment{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: envName, Name: envName,
Namespace: envNamespace, Namespace: userProvidedNS,
}, },
}) })
if err != nil { if err != nil {
return err return err
} }
if !exists { if !exists {
console.Warn(fmt.Sprintf("Package '%v' references unknown Environment '%v', please create it before applying spec", console.Warn(fmt.Sprintf("Package '%s' references unknown Environment '%s' in Namespace '%s', please create it before applying spec",
pkgName, envName)) pkgName, envName, userProvidedNS))
} }
specDir = util.GetSpecDir(input) 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, _, err = CreatePackage(input, opts.Client(), pkgName, pkgNamespace, envName,
srcArchiveFiles, deployArchiveFiles, buildcmd, specDir, specFile, noZip) srcArchiveFiles, deployArchiveFiles, buildcmd, specDir, specFile, noZip, userProvidedNS)
return err return err
} }
// TODO: get all necessary value from CLI input directly // 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, 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) (*metav1.ObjectMeta, error) { srcArchiveFiles []string, deployArchiveFiles []string, buildcmd string, specDir string, specFile string, noZip bool, userProvidedNS string) (*metav1.ObjectMeta, error) {
insecure := input.Bool(flagkey.PkgInsecure) insecure := input.Bool(flagkey.PkgInsecure)
deployChecksum := input.String(flagkey.PkgDeployChecksum) deployChecksum := input.String(flagkey.PkgDeployChecksum)
@@ -131,10 +135,19 @@ func CreatePackage(input cli.Input, client client.Interface, pkgName string, pkg
pkgSpec := fv1.PackageSpec{ pkgSpec := fv1.PackageSpec{
Environment: fv1.EnvironmentReference{ Environment: fv1.EnvironmentReference{
Namespace: envNamespace, Namespace: pkgNamespace,
Name: envName, 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 var pkgStatus fv1.BuildStatus = fv1.BuildStatusSucceeded
if len(deployArchiveFiles) > 0 { if len(deployArchiveFiles) > 0 {
@@ -177,7 +190,7 @@ func CreatePackage(input cli.Input, client client.Interface, pkgName string, pkg
pkg := &fv1.Package{ pkg := &fv1.Package{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: pkgName, Name: pkgName,
Namespace: pkgNamespace, Namespace: userProvidedNS,
}, },
Spec: pkgSpec, Spec: pkgSpec,
Status: fv1.PackageStatus{ Status: fv1.PackageStatus{
@@ -210,6 +223,7 @@ func CreatePackage(input cli.Input, client client.Interface, pkgName string, pkg
} }
return &pkg.ObjectMeta, nil return &pkg.ObjectMeta, nil
} else { } else {
pkg.ObjectMeta.Namespace = pkgNamespace
pkgMetadata, err := client.V1().Package().Create(pkg) pkgMetadata, err := client.V1().Package().Create(pkg)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "error creating package") return nil, errors.Wrap(err, "error creating package")
+7 -2
View File
@@ -22,6 +22,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 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/controller/client"
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
@@ -49,9 +50,13 @@ func (opts *DeleteSubCommand) do(input cli.Input) error {
return opts.run(input) 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.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.deleteOrphans = input.Bool(flagkey.PkgOrphan)
opts.force = input.Bool(flagkey.PkgForce) opts.force = input.Bool(flagkey.PkgForce)
+6 -2
View File
@@ -28,6 +28,7 @@ import (
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
pkgutil "github.com/fission/fission/pkg/fission-cli/cmd/package/util" pkgutil "github.com/fission/fission/pkg/fission-cli/cmd/package/util"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
const ( const (
@@ -58,9 +59,12 @@ func (opts *GetSubCommand) do(input cli.Input) error {
return opts.run(input) 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.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) opts.output = input.String(flagkey.PkgOutput)
return nil return nil
} }
+8 -2
View File
@@ -22,10 +22,12 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 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/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
pkgutil "github.com/fission/fission/pkg/fission-cli/cmd/package/util" pkgutil "github.com/fission/fission/pkg/fission-cli/cmd/package/util"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type InfoSubCommand struct { type InfoSubCommand struct {
@@ -46,9 +48,13 @@ func (opts *InfoSubCommand) do(input cli.Input) error {
return opts.run(input) 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.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 return nil
} }
+17 -6
View File
@@ -25,9 +25,11 @@ import (
"github.com/pkg/errors" "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/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type ListSubCommand struct { type ListSubCommand struct {
@@ -49,16 +51,25 @@ func (opts *ListSubCommand) do(input cli.Input) error {
return opts.run(input) 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) // option for the user to list all orphan packages (not referenced by any function)
opts.listOrphans = input.Bool(flagkey.PkgOrphan) opts.listOrphans = input.Bool(flagkey.PkgOrphan)
opts.status = input.String(flagkey.PkgStatus) 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 return nil
} }
func (opts *ListSubCommand) run(input cli.Input) error { func (opts *ListSubCommand) run(input cli.Input) (err error) {
pkgList, err := opts.Client().V1().Package().List(opts.pkgNamespace)
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 { if err != nil {
return err return err
} }
@@ -69,7 +80,7 @@ func (opts *ListSubCommand) run(input cli.Input) error {
}) })
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) 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 { for _, pkg := range pkgList {
show := true show := true
@@ -87,7 +98,7 @@ func (opts *ListSubCommand) run(input cli.Input) error {
show = false show = false
} }
if show { 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)
} }
} }
+6 -2
View File
@@ -26,6 +26,7 @@ import (
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type RebuildSubCommand struct { type RebuildSubCommand struct {
@@ -46,9 +47,12 @@ func (opts *RebuildSubCommand) do(input cli.Input) error {
return opts.run(input) 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.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 return nil
} }
+6 -9
View File
@@ -29,6 +29,7 @@ import (
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type UpdateSubCommand struct { type UpdateSubCommand struct {
@@ -50,9 +51,12 @@ func (opts *UpdateSubCommand) do(input cli.Input) error {
return opts.run(input) 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.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) opts.force = input.Bool(flagkey.PkgForce)
return nil 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) { func UpdatePackage(input cli.Input, client client.Interface, pkg *fv1.Package) (*metav1.ObjectMeta, error) {
envName := input.String(flagkey.PkgEnvironment) envName := input.String(flagkey.PkgEnvironment)
envNamespace := input.String(flagkey.NamespaceEnvironment)
srcArchiveFiles := input.StringSlice(flagkey.PkgSrcArchive) srcArchiveFiles := input.StringSlice(flagkey.PkgSrcArchive)
deployArchiveFiles := input.StringSlice(flagkey.PkgDeployArchive) deployArchiveFiles := input.StringSlice(flagkey.PkgDeployArchive)
buildcmd := input.String(flagkey.PkgBuildCmd) buildcmd := input.String(flagkey.PkgBuildCmd)
@@ -119,12 +122,6 @@ func UpdatePackage(input cli.Input, client client.Interface, pkg *fv1.Package) (
needToUpdate = true needToUpdate = true
} }
if input.IsSet(flagkey.NamespaceEnvironment) {
pkg.Spec.Environment.Namespace = envNamespace
needToRebuild = true
needToUpdate = true
}
if input.IsSet(flagkey.PkgBuildCmd) { if input.IsSet(flagkey.PkgBuildCmd) {
pkg.Spec.BuildCommand = buildcmd pkg.Spec.BuildCommand = buildcmd
needToRebuild = true needToRebuild = true
+68 -1
View File
@@ -62,6 +62,67 @@ func Apply(input cli.Input) error {
func (opts *ApplySubCommand) do(input cli.Input) error { func (opts *ApplySubCommand) do(input cli.Input) error {
return opts.run(input) 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 { 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") return errors.Wrap(err, "error reading specs")
} }
err = opts.insertNamespace(input, fr)
if err != nil {
return errors.Wrap(err, "error reading specs")
}
if validateSpecs { if validateSpecs {
err = Validate(input) err = validateForApply(input, fr)
if err != nil { if err != nil {
return errors.Wrap(err, "abort applying resources") 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 { for _, o := range fr.Packages {
// apply deploymentConfig so we can find our objects on future apply invocations // apply deploymentConfig so we can find our objects on future apply invocations
applyDeploymentConfig(&o.ObjectMeta, fr) 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 // index desired state
desired[mapKey(&o.ObjectMeta)] = true desired[mapKey(&o.ObjectMeta)] = true
+4 -3
View File
@@ -48,7 +48,8 @@ func Commands() *cobra.Command {
RunE: wrapper.Wrapper(Apply), RunE: wrapper.Wrapper(Apply),
} }
wrapper.SetFlags(applyCmd, flag.FlagSet{ 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{ destroyCmd := &cobra.Command{
@@ -57,7 +58,7 @@ func Commands() *cobra.Command {
RunE: wrapper.Wrapper(Destroy), RunE: wrapper.Wrapper(Destroy),
} }
wrapper.SetFlags(destroyCmd, flag.FlagSet{ wrapper.SetFlags(destroyCmd, flag.FlagSet{
Optional: []flag.Flag{flag.SpecDir, flag.SpecIgnore}, Optional: []flag.Flag{flag.SpecDir, flag.SpecIgnore, flag.ForceDelete},
}) })
listCmd := &cobra.Command{ listCmd := &cobra.Command{
@@ -66,7 +67,7 @@ func Commands() *cobra.Command {
RunE: wrapper.Wrapper(List), RunE: wrapper.Wrapper(List),
} }
wrapper.SetFlags(listCmd, flag.FlagSet{ 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{ command := &cobra.Command{
+243 -6
View File
@@ -17,12 +17,19 @@ limitations under the License.
package spec package spec
import ( import (
"fmt"
"strings"
"github.com/pkg/errors" "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/controller/client"
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "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/fission-cli/util"
"github.com/fission/fission/pkg/utils"
) )
type DestroySubCommand struct { type DestroySubCommand struct {
@@ -49,12 +56,26 @@ func (opts *DestroySubCommand) run(input cli.Input) error {
return errors.Wrap(err, "error reading specs") return errors.Wrap(err, "error reading specs")
} }
// set desired state to nothing, but keep the UID so "apply" can find it if !input.Bool(flagkey.ForceDelete) {
emptyFr := FissionResources{} err = opts.insertNSToResource(input, fr)
emptyFr.DeploymentConfig = fr.DeploymentConfig 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 // "apply" the empty state
err = deleteResources(opts.Client(), &emptyFr) 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 { if err != nil {
return errors.Wrap(err, "error deleting resources") return errors.Wrap(err, "error deleting resources")
} }
@@ -62,7 +83,7 @@ func (opts *DestroySubCommand) run(input cli.Input) error {
return nil return nil
} }
func deleteResources(fclient client.Interface, fr *FissionResources) error { func forceDeleteResources(fclient client.Interface, fr *FissionResources) error {
var err error var err error
@@ -103,3 +124,219 @@ func deleteResources(fclient client.Interface, fr *FissionResources) error {
return nil 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
}
+61 -34
View File
@@ -60,63 +60,90 @@ func (opts *ListSubCommand) run(input cli.Input) error {
deployID = fr.DeploymentConfig.UID deployID = fr.DeploymentConfig.UID
} }
allfn, err := getAllFunctions(opts.Client()) _, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment)
if err != nil { 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) specfns := getAppliedFunctions(allfn, deployID)
ShowFunctions(specfns) ShowFunctions(specfns)
allenvs, err := getAllEnvironments(opts.Client()) var allenvs []fv1.Environment
allenvs, err = getAllEnvironments(opts.Client(), namespace)
if err != nil { 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) specenvs := getAppliedEnvironments(allenvs, deployID)
ShowEnvironments(specenvs) ShowEnvironments(specenvs)
pkglists, err := getAllPackages(opts.Client()) var pkglists []fv1.Package
pkglists, err = getAllPackages(opts.Client(), namespace)
if err != nil { 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) specPkgs := getAppliedPackages(pkglists, deployID)
ShowPackages(specPkgs) ShowPackages(specPkgs)
canaryCfgs, err := getAllCanaryConfigs(opts.Client()) var canaryCfgs []fv1.CanaryConfig
canaryCfgs, err = getAllCanaryConfigs(opts.Client(), namespace)
if err != nil { 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) specCanaryCfgs := getAppliedCanaryConfigs(canaryCfgs, deployID)
ShowCanaryConfigs(specCanaryCfgs) ShowCanaryConfigs(specCanaryCfgs)
hts, err := getAllHTTPTriggers(opts.Client()) var hts []fv1.HTTPTrigger
hts, err = getAllHTTPTriggers(opts.Client(), namespace)
if err != nil { 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) specHTTPTriggers := getAppliedHTTPTriggers(hts, deployID)
ShowHTTPTriggers(specHTTPTriggers) 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 { 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) specMessageQueueTriggers := getAppliedMessageQueueTriggers(mqts, deployID)
ShowMQTriggers(specMessageQueueTriggers) ShowMQTriggers(specMessageQueueTriggers)
tts, err := getAllTimeTriggers(opts.Client()) var tts []fv1.TimeTrigger
tts, err = getAllTimeTriggers(opts.Client(), namespace)
if err != nil { 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) specTimeTriggers := getAppliedTimeTriggers(tts, deployID)
ShowTimeTriggers(specTimeTriggers) ShowTimeTriggers(specTimeTriggers)
kws, err := getAllKubeWatchTriggers(opts.Client()) var kws []fv1.KubernetesWatchTrigger
kws, err = getAllKubeWatchTriggers(opts.Client(), namespace)
if err != nil { 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) specKubeWatchers := getSpecKubeWatchers(kws, deployID)
ShowAppliedKubeWatchers(specKubeWatchers) ShowAppliedKubeWatchers(specKubeWatchers)
return nil return err
} }
func getAppliedFunctions(fns []fv1.Function, deployID string) []fv1.Function { 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 // getAllFunctions get lists of functions in provided namespaces
func getAllFunctions(client client.Interface) ([]fv1.Function, error) { func getAllFunctions(client client.Interface, namespace string) ([]fv1.Function, error) {
fns, err := client.V1().Function().List("") fns, err := client.V1().Function().List(namespace)
if err != nil { if err != nil {
return nil, errors.Errorf("Unable to get Functions %v", err.Error()) 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 // getAllEnvironments get lists of environments in all namespaces
func getAllEnvironments(client client.Interface) ([]fv1.Environment, error) { func getAllEnvironments(client client.Interface, namespace string) ([]fv1.Environment, error) {
envs, err := client.V1().Environment().List("") envs, err := client.V1().Environment().List(namespace)
if err != nil { if err != nil {
return nil, errors.Errorf("Unable to get Environments %v", err.Error()) 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 // getAllPackages get lists of packages in all namespaces
func getAllPackages(client client.Interface) ([]fv1.Package, error) { func getAllPackages(client client.Interface, namespace string) ([]fv1.Package, error) {
pkgList, err := client.V1().Package().List("") pkgList, err := client.V1().Package().List(namespace)
if err != nil { if err != nil {
return nil, errors.Errorf("Unable to get Packages %v", err.Error()) 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 // getAllCanaryConfigs get lists of canary configs in all namespaces
func getAllCanaryConfigs(client client.Interface) ([]fv1.CanaryConfig, error) { func getAllCanaryConfigs(client client.Interface, namespace string) ([]fv1.CanaryConfig, error) {
canaryCfgs, err := client.V1().CanaryConfig().List("") canaryCfgs, err := client.V1().CanaryConfig().List(namespace)
if err != nil { if err != nil {
return nil, errors.Errorf("Unable to get Canary Configs %v", err.Error()) 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 // getAllHTTPTriggers get lists of HTTP Triggers in all namespaces
func getAllHTTPTriggers(client client.Interface) ([]fv1.HTTPTrigger, error) { func getAllHTTPTriggers(client client.Interface, namespace string) ([]fv1.HTTPTrigger, error) {
hts, err := client.V1().HTTPTrigger().List("") hts, err := client.V1().HTTPTrigger().List(namespace)
if err != nil { if err != nil {
return nil, errors.Errorf("Unable to get HTTP Triggers %v", err.Error()) 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 // getAllMessageQueueTriggers get lists of MessageQueue Triggers in all namespaces
func getAllMessageQueueTriggers(client client.Interface, mqttype string) ([]fv1.MessageQueueTrigger, error) { func getAllMessageQueueTriggers(client client.Interface, mqttype string, namespace string) ([]fv1.MessageQueueTrigger, error) {
mqts, err := client.V1().MessageQueueTrigger().List(mqttype, "") mqts, err := client.V1().MessageQueueTrigger().List(mqttype, namespace)
if err != nil { if err != nil {
return nil, errors.Errorf("Unable to get MessageQueue Triggers %v", err.Error()) 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 // getAllTimeTriggers get lists of Time Triggers in all namespaces
func getAllTimeTriggers(client client.Interface) ([]fv1.TimeTrigger, error) { func getAllTimeTriggers(client client.Interface, namespace string) ([]fv1.TimeTrigger, error) {
tts, err := client.V1().TimeTrigger().List("") tts, err := client.V1().TimeTrigger().List(namespace)
if err != nil { if err != nil {
return nil, errors.Errorf("Unable to get Time Triggers %v", err.Error()) 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 // getAllKubeWatchTriggers get lists of Kube Watchers in all namespaces
func getAllKubeWatchTriggers(client client.Interface) ([]fv1.KubernetesWatchTrigger, error) { func getAllKubeWatchTriggers(client client.Interface, namespace string) ([]fv1.KubernetesWatchTrigger, error) {
ws, err := client.V1().KubeWatcher().List("") ws, err := client.V1().KubeWatcher().List(namespace)
if err != nil { if err != nil {
return nil, errors.Errorf("Unable to get Kube Watchers %v", err.Error()) return nil, errors.Errorf("Unable to get Kube Watchers %v", err.Error())
} }
+1 -1
View File
@@ -491,7 +491,7 @@ func (fr *FissionResources) Validate(input cli.Input) ([]string, error) {
for _, f := range fr.Functions { for _, f := range fr.Functions {
if _, ok := environments[fmt.Sprintf("%s:%s", f.Spec.Environment.Name, f.Spec.Environment.Namespace)]; !ok { 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 strategy := f.Spec.InvokeStrategy.ExecutionStrategy
if strategy.ExecutorType == fv1.ExecutorTypeNewdeploy && strategy.SpecializationTimeout < fv1.DefaultSpecializationTimeOut { if strategy.ExecutorType == fv1.ExecutorTypeNewdeploy && strategy.SpecializationTimeout < fv1.DefaultSpecializationTimeOut {
+26 -14
View File
@@ -48,17 +48,29 @@ func Validate(input cli.Input) error {
} }
func (opts *ValidateSubCommand) do(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 // this will error on parse errors and on duplicates
specDir := util.GetSpecDir(input) specDir := util.GetSpecDir(input)
specIgnore := util.GetSpecIgnore(input) specIgnore := util.GetSpecIgnore(input)
fr, err := ReadSpecs(specDir, specIgnore, false)
if err != nil { // If the call for validate is from apply spec we already have a parsed fission resource
return errors.Wrap(err, "error reading specs") 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) 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") 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 { if err != nil {
return errors.Wrap(err, "name conflict error") 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. // the same name is already present in the same cluster namespace.
// If a same name resource exists in the same namespace, a name // If a same name resource exists in the same namespace, a name
// conflict error will be returned. // 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 deployUID := fr.DeploymentConfig.UID
result := utils.MultiErrorWithFormat() result := utils.MultiErrorWithFormat()
fnList, err := getAllFunctions(c) fnList, err := getAllFunctions(c, namespace)
if err != nil { if err != nil {
return errors.Errorf("Unable to get Functions %v", err.Error()) 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 { if err != nil {
return errors.Errorf("Unable to get Environments %v", err.Error()) 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 { if err != nil {
return errors.Errorf("Unable to get Packages %v", err.Error()) 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 { if err != nil {
return errors.Errorf("Unable to get HTTPTrigger %v", err.Error()) 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 { if err != nil {
return errors.Errorf("Unable to get Message Queue Trigger %v", err.Error()) 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 { if err != nil {
return errors.Errorf("Unable to get Time Trigger %v", err.Error()) 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 { if err != nil {
return errors.Errorf("Unable to get Kubernetes Watch Trigger %v", err.Error()) return errors.Errorf("Unable to get Kubernetes Watch Trigger %v", err.Error())
} }
+1 -1
View File
@@ -64,7 +64,7 @@ func Commands() *cobra.Command {
RunE: wrapper.Wrapper(List), RunE: wrapper.Wrapper(List),
} }
wrapper.SetFlags(listCmd, flag.FlagSet{ wrapper.SetFlags(listCmd, flag.FlagSet{
Optional: []flag.Flag{flag.NamespaceTrigger}, Optional: []flag.Flag{flag.NamespaceTrigger, flag.AllNamespaces},
}) })
showCmd := &cobra.Command{ showCmd := &cobra.Command{
+19 -7
View File
@@ -53,7 +53,7 @@ func (opts *CreateSubCommand) do(input cli.Input) error {
return opts.run(input) 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) name := input.String(flagkey.TtName)
if len(name) == 0 { if len(name) == 0 {
id, err := uuid.NewV4() 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") 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) cronSpec := input.String(flagkey.TtCron)
if len(cronSpec) == 0 { if len(cronSpec) == 0 {
@@ -86,7 +89,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
exists, err := fr.ExistsInSpecs(fv1.Function{ exists, err := fr.ExistsInSpecs(fv1.Function{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: fnName, Name: fnName,
Namespace: fnNamespace, Namespace: userProvidedNS,
}, },
}) })
if err != nil { if err != nil {
@@ -98,11 +101,20 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
} }
} }
opts.trigger = &fv1.TimeTrigger{ m := metav1.ObjectMeta{
ObjectMeta: metav1.ObjectMeta{ Name: name,
Namespace: fnNamespace,
}
if input.Bool(flagkey.SpecSave) || input.Bool(flagkey.SpecDry) {
m = metav1.ObjectMeta{
Name: name, Name: name,
Namespace: fnNamespace, Namespace: userProvidedNS,
}, }
}
opts.trigger = &fv1.TimeTrigger{
ObjectMeta: m,
Spec: fv1.TimeTriggerSpec{ Spec: fv1.TimeTriggerSpec{
Cron: cronSpec, Cron: cronSpec,
FunctionReference: fv1.FunctionReference{ FunctionReference: fv1.FunctionReference{
+8 -3
View File
@@ -36,13 +36,18 @@ func Delete(input cli.Input) error {
return (&DeleteSubCommand{}).do(input) 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{ m := &metav1.ObjectMeta{
Name: input.String(flagkey.TtName), 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 err != nil {
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
return nil return nil
+15 -3
View File
@@ -23,9 +23,11 @@ import (
"github.com/pkg/errors" "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/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type ListSubCommand struct { type ListSubCommand struct {
@@ -36,9 +38,19 @@ func List(input cli.Input) error {
return (&ListSubCommand{}).do(input) return (&ListSubCommand{}).do(input)
} }
func (opts *ListSubCommand) do(input cli.Input) error { func (opts *ListSubCommand) do(input cli.Input) (err error) {
ttNs := input.String(flagkey.NamespaceTrigger) _, ttNs, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger)
tts, err := opts.Client().V1().TimeTrigger().List(ttNs) 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 { if err != nil {
return errors.Wrap(err, "list Time triggers") return errors.Wrap(err, "list Time triggers")
} }
+12 -4
View File
@@ -25,7 +25,9 @@ import (
fv1 "github.com/fission/fission/pkg/apis/core/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/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd" "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" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util"
) )
type UpdateSubCommand struct { type UpdateSubCommand struct {
@@ -46,9 +48,13 @@ func (opts *UpdateSubCommand) do(input cli.Input) error {
} }
func (opts *UpdateSubCommand) complete(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{ tt, err := opts.Client().V1().TimeTrigger().Get(&metav1.ObjectMeta{
Name: input.String(flagkey.TtName), Name: input.String(flagkey.TtName),
Namespace: input.String(flagkey.NamespaceTrigger), Namespace: namespace,
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "error getting time trigger") return errors.Wrap(err, "error getting time trigger")
@@ -61,11 +67,13 @@ func (opts *UpdateSubCommand) complete(input cli.Input) error {
updated = true 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") fnName := input.String("function")
if len(fnName) > 0 { 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 tt.Spec.FunctionReference.Name = fnName
updated = true updated = true
} }
+15 -13
View File
@@ -21,8 +21,6 @@ import (
"net/http" "net/http"
"time" "time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
fv1 "github.com/fission/fission/pkg/apis/core/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1"
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
"github.com/fission/fission/pkg/fission-cli/util" "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\""} 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\""} 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} Namespace = Flag{Type: String, Name: flagkey.Namespace, Short: "n", Usage: "If present, the namespace scope for this CLI request"}
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}
RunTimeMinCPU = Flag{Type: Int, Name: flagkey.RuntimeMincpu, Usage: "Minimum CPU to be assigned to pod (In millicore, minimum 1)"} NamespaceFunction = Flag{Type: String, Name: flagkey.NamespaceFunction, Aliases: []string{"fns"}, Usage: "Namespace for function object", Deprecated: true, Substitute: flagkey.Namespace}
RunTimeMaxCPU = Flag{Type: Int, Name: flagkey.RuntimeMaxcpu, Usage: "Maximum CPU to be assigned to pod (In millicore, minimum 1)"} NamespaceEnvironment = Flag{Type: String, Name: flagkey.NamespaceEnvironment, Aliases: []string{"envns"}, Usage: "Namespace for environment object", Deprecated: true, Substitute: flagkey.Namespace}
RunTimeTargetCPU = Flag{Type: Int, Name: flagkey.RuntimeTargetcpu, Usage: "Target average CPU usage percentage across pods for scaling", DefaultValue: 80} NamespacePackage = Flag{Type: String, Name: flagkey.NamespacePackage, Aliases: []string{"pkgns"}, Usage: "Namespace for package object", Deprecated: true, Substitute: flagkey.Namespace}
RunTimeMinMemory = Flag{Type: Int, Name: flagkey.RuntimeMinmemory, Usage: "Minimum memory to be assigned to pod (In megabyte)"} NamespaceTrigger = Flag{Type: String, Name: flagkey.NamespaceTrigger, Aliases: []string{"triggerns"}, Usage: "Namespace for trigger object", Deprecated: true, Substitute: flagkey.Namespace}
RunTimeMaxMemory = Flag{Type: Int, Name: flagkey.RuntimeMaxmemory, Usage: "Maximum memory to be assigned to pod (In megabyte)"} 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} 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} 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"} KwName = Flag{Type: String, Name: flagkey.KwName, Usage: "Watch name"}
KwFnName = Flag{Type: String, Name: flagkey.KwFnName, Usage: "Function 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"} 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"} KwLabels = Flag{Type: String, Name: flagkey.KwLabels, Usage: "Label selector of the form a=b,c=d"}
+4
View File
@@ -38,6 +38,10 @@ const (
NamespacePackage = "pkgNamespace" NamespacePackage = "pkgNamespace"
NamespaceTrigger = "triggerNamespace" NamespaceTrigger = "triggerNamespace"
NamespaceCanary = "canaryNamespace" NamespaceCanary = "canaryNamespace"
Namespace = "namespace"
ForceNamespace = "force-namespace"
AllNamespaces = "all-namespaces"
ForceDelete = "force"
RuntimeMincpu = "mincpu" RuntimeMincpu = "mincpu"
RuntimeMaxcpu = "maxcpu" RuntimeMaxcpu = "maxcpu"
+64 -6
View File
@@ -104,11 +104,8 @@ func KubifyName(old string) string {
return newName return newName
} }
// GetKubernetesClient builds a new kubernetes client. If the KUBECONFIG func getLoadingRules() (loadingRules *clientcmd.ClientConfigLoadingRules, err error) {
// environment variable is empty or doesn't exist, ~/.kube/config is used for loadingRules = clientcmd.NewDefaultClientConfigLoadingRules()
// the kube config path
func GetKubernetesClient(kubeContext string) (*restclient.Config, kubernetes.Interface, error) {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
kubeConfigPath := os.Getenv("KUBECONFIG") kubeConfigPath := os.Getenv("KUBECONFIG")
if len(kubeConfigPath) == 0 { if len(kubeConfigPath) == 0 {
@@ -126,7 +123,7 @@ func GetKubernetesClient(kubeContext string) (*restclient.Config, kubernetes.Int
kubeConfigPath = filepath.Join(homeDir, ".kube", "config") kubeConfigPath = filepath.Join(homeDir, ".kube", "config")
if _, err := os.Stat(kubeConfigPath); os.IsNotExist(err) { 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.") "Set the KUBECONFIG environment variable to your kubeconfig's path.")
} }
loadingRules.ExplicitPath = kubeConfigPath loadingRules.ExplicitPath = kubeConfigPath
@@ -134,6 +131,17 @@ func GetKubernetesClient(kubeContext string) (*restclient.Config, kubernetes.Int
} else { } else {
console.Verbose(2, "Using kubeconfig from environment %q", kubeConfigPath) 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( config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
loadingRules, &clientcmd.ConfigOverrides{CurrentContext: kubeContext}).ClientConfig() loadingRules, &clientcmd.ConfigOverrides{CurrentContext: kubeContext}).ClientConfig()
@@ -149,6 +157,25 @@ func GetKubernetesClient(kubeContext string) (*restclient.Config, kubernetes.Int
return config, clientset, nil 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 // 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) { func CheckFunctionExistence(client client.Interface, functions []string, fnNamespace string) (err error) {
fnMissing := make([]string, 0) fnMissing := make([]string, 0)
@@ -459,3 +486,34 @@ func GetStorageURL(ctx context.Context, kubeContext string) (*url.URL, error) {
return serverURL, nil 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
}
+8
View File
@@ -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)
}
+4
View File
@@ -101,6 +101,10 @@ main() {
$ROOT/test/tests/test_fn_update/test_secret_update.sh \ $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_nd_pkg_update.sh \
$ROOT/test/tests/test_fn_update/test_poolmgr_nd.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 set -e
+39
View File
@@ -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"
+43
View File
@@ -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"
+45
View File
@@ -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"
+43
View File
@@ -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"
+32
View File
@@ -43,6 +43,38 @@ clean_resource_by_id() {
set -e 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() { test_fn() {
if [ -z $FISSION_ROUTER ]; then if [ -z $FISSION_ROUTER ]; then
log "Environment FISSION_ROUTER not set" log "Environment FISSION_ROUTER not set"