diff --git a/pkg/fission-cli/canaryconfig.go b/pkg/fission-cli/canaryconfig.go deleted file mode 100644 index 1ebc645a..00000000 --- a/pkg/fission-cli/canaryconfig.go +++ /dev/null @@ -1,235 +0,0 @@ -/* -Copyright 2016 The Fission Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package fission_cli - -import ( - "fmt" - "os" - "text/tabwriter" - "time" - - "github.com/urfave/cli" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - fv1 "github.com/fission/fission/pkg/apis/fission.io/v1" - "github.com/fission/fission/pkg/fission-cli/log" - "github.com/fission/fission/pkg/fission-cli/util" - "github.com/fission/fission/pkg/types" -) - -func canaryConfigCreate(c *cli.Context) error { - client := util.GetApiClient(c.GlobalString("server")) - - canaryConfigName := c.String("name") - // canary configs can be created for functions in the same namespace - if len(canaryConfigName) == 0 { - log.Fatal("Need a name, use --name.") - } - - trigger := c.String("httptrigger") - newFunc := c.String("newfunction") - oldFunc := c.String("oldfunction") - ns := c.String("fnNamespace") - incrementStep := c.Int("increment-step") - failureThreshold := c.Int("failure-threshold") - incrementInterval := c.String("increment-interval") - - // check for time parsing - _, err := time.ParseDuration(incrementInterval) - util.CheckErr(err, "parsing time duration.") - - // check that the trigger exists in the same namespace. - m := &metav1.ObjectMeta{ - Name: trigger, - Namespace: ns, - } - - htTrigger, err := client.HTTPTriggerGet(m) - if err != nil { - util.CheckErr(err, "find trigger referenced in the canary config") - } - - // check that the trigger has function reference type function weights - if htTrigger.Spec.FunctionReference.Type != types.FunctionReferenceTypeFunctionWeights { - log.Fatal("Canary config cannot be created for http triggers that do not reference functions by weights") - } - - // check that the trigger references same functions in the function weights - _, ok := htTrigger.Spec.FunctionReference.FunctionWeights[newFunc] - if !ok { - log.Fatal(fmt.Sprintf("HTTP Trigger doesn't reference the function %s in Canary Config", newFunc)) - } - - _, ok = htTrigger.Spec.FunctionReference.FunctionWeights[oldFunc] - if !ok { - log.Fatal(fmt.Sprintf("HTTP Trigger doesn't reference the function %s in Canary Config", oldFunc)) - } - - // check that the functions exist in the same namespace - fnList := []string{newFunc, oldFunc} - err = util.CheckFunctionExistence(client, fnList, ns) - if err != nil { - log.Fatal(fmt.Sprintf("checkFunctionExistence err : %v", err)) - } - - // finally create canaryCfg in the same namespace as the functions referenced - canaryCfg := &fv1.CanaryConfig{ - Metadata: metav1.ObjectMeta{ - Name: canaryConfigName, - Namespace: ns, - }, - Spec: fv1.CanaryConfigSpec{ - Trigger: trigger, - NewFunction: newFunc, - OldFunction: oldFunc, - WeightIncrement: incrementStep, - WeightIncrementDuration: incrementInterval, - FailureThreshold: failureThreshold, - FailureType: fv1.FailureTypeStatusCode, - }, - Status: fv1.CanaryConfigStatus{ - Status: fv1.CanaryConfigStatusPending, - }, - } - - _, err = client.CanaryConfigCreate(canaryCfg) - util.CheckErr(err, "create canary config") - - fmt.Printf("canary config '%v' created\n", canaryConfigName) - return err -} - -func canaryConfigGet(c *cli.Context) error { - client := util.GetApiClient(c.GlobalString("server")) - - name := c.String("name") - if len(name) == 0 { - log.Fatal("Need a name, use --name.") - } - ns := c.String("canaryNamespace") - - m := &metav1.ObjectMeta{ - Name: name, - Namespace: ns, - } - - canaryCfg, err := client.CanaryConfigGet(m) - util.CheckErr(err, "get canary config") - - 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", "TRIGGER", "FUNCTION-N", "FUNCTION-N-1", "WEIGHT-INCREMENT", "INTERVAL", "FAILURE-THRESHOLD", "FAILURE-TYPE", "STATUS") - fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", - canaryCfg.Metadata.Name, canaryCfg.Spec.Trigger, canaryCfg.Spec.NewFunction, canaryCfg.Spec.OldFunction, canaryCfg.Spec.WeightIncrement, canaryCfg.Spec.WeightIncrementDuration, - canaryCfg.Spec.FailureThreshold, canaryCfg.Spec.FailureType, canaryCfg.Status.Status) - - w.Flush() - return nil -} - -func canaryConfigUpdate(c *cli.Context) error { - client := util.GetApiClient(c.GlobalString("server")) - - canaryConfigName := c.String("name") - ns := c.String("canaryNamespace") - if len(canaryConfigName) == 0 { - log.Fatal("Need a name, use --name.") - } - - incrementStep := c.Int("increment-step") - failureThreshold := c.Int("failure-threshold") - incrementInterval := c.String("increment-interval") - - // check for time parsing - _, err := time.ParseDuration(incrementInterval) - util.CheckErr(err, "parsing time duration.") - - // get the current config - m := &metav1.ObjectMeta{ - Name: canaryConfigName, - Namespace: ns, - } - - var updateNeeded bool - canaryCfg, err := client.CanaryConfigGet(m) - util.CheckErr(err, "get canary config") - - if incrementStep != canaryCfg.Spec.WeightIncrement { - canaryCfg.Spec.WeightIncrement = incrementStep - updateNeeded = true - } - - if failureThreshold != canaryCfg.Spec.FailureThreshold { - canaryCfg.Spec.FailureThreshold = failureThreshold - updateNeeded = true - } - - if incrementInterval != canaryCfg.Spec.WeightIncrementDuration { - canaryCfg.Spec.WeightIncrementDuration = incrementInterval - updateNeeded = true - } - - if updateNeeded { - canaryCfg.Status.Status = fv1.CanaryConfigStatusPending - - _, err = client.CanaryConfigUpdate(canaryCfg) - util.CheckErr(err, "update canary config") - } - - return nil -} - -func canaryConfigDelete(c *cli.Context) error { - client := util.GetApiClient(c.GlobalString("server")) - - canaryConfigName := c.String("name") - ns := c.String("canaryNamespace") - if len(canaryConfigName) == 0 { - log.Fatal("Need a name, use --name.") - } - - // get the current config - m := &metav1.ObjectMeta{ - Name: canaryConfigName, - Namespace: ns, - } - - err := client.CanaryConfigDelete(m) - util.CheckErr(err, fmt.Sprintf("delete function '%v.%v'", canaryConfigName, ns)) - - fmt.Printf("canaryconfig '%v.%v' deleted\n", canaryConfigName, ns) - return err -} - -func canaryConfigList(c *cli.Context) error { - client := util.GetApiClient(c.GlobalString("server")) - - ns := c.String("canaryNamespace") - - canaryCfgs, err := client.CanaryConfigList(ns) - util.CheckErr(err, "list canary config") - - 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", "TRIGGER", "FUNCTION-N", "FUNCTION-N-1", "WEIGHT-INCREMENT", "INTERVAL", "FAILURE-THRESHOLD", "FAILURE-TYPE", "STATUS") - for _, canaryCfg := range canaryCfgs { - fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", - canaryCfg.Metadata.Name, canaryCfg.Spec.Trigger, canaryCfg.Spec.NewFunction, canaryCfg.Spec.OldFunction, canaryCfg.Spec.WeightIncrement, canaryCfg.Spec.WeightIncrementDuration, - canaryCfg.Spec.FailureThreshold, canaryCfg.Spec.FailureType, canaryCfg.Status.Status) - } - - w.Flush() - return nil -} diff --git a/pkg/fission-cli/cli.go b/pkg/fission-cli/cli.go index a9a5e037..62c550df 100644 --- a/pkg/fission-cli/cli.go +++ b/pkg/fission-cli/cli.go @@ -29,6 +29,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/driver/urfavecli" "github.com/fission/fission/pkg/fission-cli/cmd" + "github.com/fission/fission/pkg/fission-cli/cmd/canaryconfig" "github.com/fission/fission/pkg/fission-cli/cmd/environment" "github.com/fission/fission/pkg/fission-cli/cmd/httptrigger" "github.com/fission/fission/pkg/fission-cli/cmd/kubewatch" @@ -306,11 +307,11 @@ func NewCliApp() *cli.App { incrementIntervalFlag := cli.StringFlag{Name: "increment-interval", Value: "2m", Usage: "Weight increment interval, string representation of time.Duration, ex : 1m, 2h, 2d"} failureThresholdFlag := cli.IntFlag{Name: "failure-threshold", Value: 10, Usage: "Threshold in percentage beyond which the new version of the function is considered unstable"} canarySubCommands := []cli.Command{ - {Name: "create", Usage: "Create a canary config", Flags: []cli.Flag{canaryConfigNameFlag, triggerNameFlag, newFunc, oldFunc, fnNamespaceFlag, weightIncrementFlag, incrementIntervalFlag, failureThresholdFlag}, Action: canaryConfigCreate}, - {Name: "get", Usage: "View parameters in a canary config", Flags: []cli.Flag{canaryConfigNameFlag, canaryNamespaceFlag}, Action: canaryConfigGet}, - {Name: "update", Usage: "Update parameters of a canary config", Flags: []cli.Flag{canaryConfigNameFlag, canaryNamespaceFlag, incrementIntervalFlag, weightIncrementFlag, failureThresholdFlag}, Action: canaryConfigUpdate}, - {Name: "delete", Usage: "Delete a canary config", Flags: []cli.Flag{canaryConfigNameFlag, canaryNamespaceFlag}, Action: canaryConfigDelete}, - {Name: "list", Usage: "List all canary configs in a namespace", Flags: []cli.Flag{canaryNamespaceFlag}, Action: canaryConfigList}, + {Name: "create", Usage: "Create a canary config", Flags: []cli.Flag{canaryConfigNameFlag, triggerNameFlag, newFunc, oldFunc, fnNamespaceFlag, weightIncrementFlag, incrementIntervalFlag, failureThresholdFlag}, Action: urfavecli.Wrapper(canaryconfig.Create)}, + {Name: "get", Usage: "View parameters in a canary config", Flags: []cli.Flag{canaryConfigNameFlag, canaryNamespaceFlag}, Action: urfavecli.Wrapper(canaryconfig.Get)}, + {Name: "update", Usage: "Update parameters of a canary config", Flags: []cli.Flag{canaryConfigNameFlag, canaryNamespaceFlag, incrementIntervalFlag, weightIncrementFlag, failureThresholdFlag}, Action: urfavecli.Wrapper(canaryconfig.Update)}, + {Name: "delete", Usage: "Delete a canary config", Flags: []cli.Flag{canaryConfigNameFlag, canaryNamespaceFlag}, Action: urfavecli.Wrapper(canaryconfig.Delete)}, + {Name: "list", Usage: "List all canary configs in a namespace", Flags: []cli.Flag{canaryNamespaceFlag}, Action: urfavecli.Wrapper(canaryconfig.List)}, } pluginSubCommands := []cli.Command{ diff --git a/pkg/fission-cli/cmd/canaryconfig/create.go b/pkg/fission-cli/cmd/canaryconfig/create.go new file mode 100644 index 00000000..393468ec --- /dev/null +++ b/pkg/fission-cli/cmd/canaryconfig/create.go @@ -0,0 +1,137 @@ +/* +Copyright 2019 The Fission Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package canaryconfig + +import ( + "fmt" + "time" + + "github.com/pkg/errors" + + fv1 "github.com/fission/fission/pkg/apis/fission.io/v1" + "github.com/fission/fission/pkg/controller/client" + "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" + "github.com/fission/fission/pkg/fission-cli/cmd" + "github.com/fission/fission/pkg/fission-cli/util" + "github.com/fission/fission/pkg/types" +) + +type CreateSubCommand struct { + client *client.Client + canary *fv1.CanaryConfig +} + +func Create(flags cli.Input) error { + opts := CreateSubCommand{ + client: cmd.GetServer(flags), + } + return opts.do(flags) +} + +func (opts *CreateSubCommand) do(flags cli.Input) error { + err := opts.complete(flags) + if err != nil { + return err + } + return opts.run(flags) +} + +func (opts *CreateSubCommand) complete(flags cli.Input) error { + // canary configs can be created for functions in the same namespace + + trigger := flags.String("httptrigger") + newFunc := flags.String("newfunction") + oldFunc := flags.String("oldfunction") + ns := flags.String("fnNamespace") + incrementStep := flags.Int("increment-step") + failureThreshold := flags.Int("failure-threshold") + incrementInterval := flags.String("increment-interval") + + // check for time parsing + _, err := time.ParseDuration(incrementInterval) + if err != nil { + return errors.Wrap(err, "error parsing time duration") + } + + // check that the trigger exists in the same namespace. + m, err := cmd.GetMetadata("httptrigger", "fnNamespace", flags) + if err != nil { + return errors.Wrap(err, "error finding http trigger in given namespace") + } + + htTrigger, err := opts.client.HTTPTriggerGet(m) + if err != nil { + return errors.Wrap(err, "error finding trigger referenced in the canary config") + } + + // check that the trigger has function reference type function weights + if htTrigger.Spec.FunctionReference.Type != types.FunctionReferenceTypeFunctionWeights { + return errors.New("canary config cannot be created for http triggers that do not reference functions by weights") + } + + // check that the trigger references same functions in the function weights + _, ok := htTrigger.Spec.FunctionReference.FunctionWeights[newFunc] + if !ok { + return fmt.Errorf("HTTP Trigger doesn't reference the function %s in Canary Config", newFunc) + } + + _, ok = htTrigger.Spec.FunctionReference.FunctionWeights[oldFunc] + if !ok { + return fmt.Errorf("HTTP Trigger doesn't reference the function %s in Canary Config", oldFunc) + } + + // check that the functions exist in the same namespace + fnList := []string{newFunc, oldFunc} + err = util.CheckFunctionExistence(opts.client, fnList, ns) + if err != nil { + return errors.Wrap(err, "error checking functions existence") + } + + canaryMetadata, err := cmd.GetMetadata("name", "fnNamespace", flags) + if err != nil { + return err + } + + // finally create canaryCfg in the same namespace as the functions referenced + opts.canary = &fv1.CanaryConfig{ + Metadata: *canaryMetadata, + Spec: fv1.CanaryConfigSpec{ + Trigger: trigger, + NewFunction: newFunc, + OldFunction: oldFunc, + WeightIncrement: incrementStep, + WeightIncrementDuration: incrementInterval, + FailureThreshold: failureThreshold, + FailureType: fv1.FailureTypeStatusCode, + }, + Status: fv1.CanaryConfigStatus{ + Status: fv1.CanaryConfigStatusPending, + }, + } + + return nil +} + +func (opts *CreateSubCommand) run(flags cli.Input) error { + _, err := opts.client.CanaryConfigCreate(opts.canary) + if err != nil { + return errors.Wrap(err, "error creating canary config") + } + + fmt.Printf("canary config '%v' created\n", opts.canary.Metadata.Name) + return nil +} diff --git a/pkg/fission-cli/cmd/canaryconfig/delete.go b/pkg/fission-cli/cmd/canaryconfig/delete.go new file mode 100644 index 00000000..0eb9936e --- /dev/null +++ b/pkg/fission-cli/cmd/canaryconfig/delete.go @@ -0,0 +1,52 @@ +/* +Copyright 2019 The Fission Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package canaryconfig + +import ( + "fmt" + + "github.com/pkg/errors" + + "github.com/fission/fission/pkg/controller/client" + "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" + "github.com/fission/fission/pkg/fission-cli/cmd" +) + +type DeleteSubCommand struct { + client *client.Client +} + +func Delete(flags cli.Input) error { + opts := DeleteSubCommand{ + client: cmd.GetServer(flags), + } + return opts.run(flags) +} + +func (opts *DeleteSubCommand) run(flags cli.Input) error { + metadata, err := cmd.GetMetadata("name", "canaryNamespace", flags) + if err != nil { + return err + } + err = opts.client.CanaryConfigDelete(metadata) + if err != nil { + return errors.Wrap(err, "error deleting canary config") + } + + fmt.Printf("canaryconfig '%v.%v' deleted\n", metadata.Name, metadata.Namespace) + return nil +} diff --git a/pkg/fission-cli/cmd/canaryconfig/get.go b/pkg/fission-cli/cmd/canaryconfig/get.go new file mode 100644 index 00000000..f1c34c3b --- /dev/null +++ b/pkg/fission-cli/cmd/canaryconfig/get.go @@ -0,0 +1,61 @@ +/* +Copyright 2019 The Fission Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package canaryconfig + +import ( + "fmt" + "os" + "text/tabwriter" + + "github.com/pkg/errors" + + "github.com/fission/fission/pkg/controller/client" + "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" + "github.com/fission/fission/pkg/fission-cli/cmd" +) + +type GetSubCommand struct { + client *client.Client +} + +func Get(flags cli.Input) error { + opts := GetSubCommand{ + client: cmd.GetServer(flags), + } + return opts.run(flags) +} + +func (opts *GetSubCommand) run(flags cli.Input) error { + m, err := cmd.GetMetadata("name", "canaryNamespace", flags) + if err != nil { + return err + } + + canaryCfg, err := opts.client.CanaryConfigGet(m) + if err != nil { + return errors.Wrap(err, "error getting canary config") + } + + 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", "TRIGGER", "FUNCTION-N", "FUNCTION-N-1", "WEIGHT-INCREMENT", "INTERVAL", "FAILURE-THRESHOLD", "FAILURE-TYPE", "STATUS") + fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", + canaryCfg.Metadata.Name, canaryCfg.Spec.Trigger, canaryCfg.Spec.NewFunction, canaryCfg.Spec.OldFunction, canaryCfg.Spec.WeightIncrement, canaryCfg.Spec.WeightIncrementDuration, + canaryCfg.Spec.FailureThreshold, canaryCfg.Spec.FailureType, canaryCfg.Status.Status) + + w.Flush() + return nil +} diff --git a/pkg/fission-cli/cmd/canaryconfig/list.go b/pkg/fission-cli/cmd/canaryconfig/list.go new file mode 100644 index 00000000..f30caa52 --- /dev/null +++ b/pkg/fission-cli/cmd/canaryconfig/list.go @@ -0,0 +1,72 @@ +/* +Copyright 2019 The Fission Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package canaryconfig + +import ( + "fmt" + "os" + "text/tabwriter" + + "github.com/pkg/errors" + + "github.com/fission/fission/pkg/controller/client" + "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" + "github.com/fission/fission/pkg/fission-cli/cmd" +) + +type ListSubCommand struct { + client *client.Client + namespace string +} + +func List(flags cli.Input) error { + opts := ListSubCommand{ + client: cmd.GetServer(flags), + } + return opts.do(flags) +} + +func (opts *ListSubCommand) do(flags cli.Input) error { + err := opts.complete(flags) + if err != nil { + return err + } + return opts.run(flags) +} + +func (opts *ListSubCommand) complete(flags cli.Input) error { + opts.namespace = flags.String("canaryNamespace") + return nil +} + +func (opts *ListSubCommand) run(flags cli.Input) error { + canaryCfgs, err := opts.client.CanaryConfigList(opts.namespace) + if err != nil { + return errors.Wrap(err, "error listing canary config") + } + + 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", "TRIGGER", "FUNCTION-N", "FUNCTION-N-1", "WEIGHT-INCREMENT", "INTERVAL", "FAILURE-THRESHOLD", "FAILURE-TYPE", "STATUS") + for _, canaryCfg := range canaryCfgs { + fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", + canaryCfg.Metadata.Name, canaryCfg.Spec.Trigger, canaryCfg.Spec.NewFunction, canaryCfg.Spec.OldFunction, canaryCfg.Spec.WeightIncrement, canaryCfg.Spec.WeightIncrementDuration, + canaryCfg.Spec.FailureThreshold, canaryCfg.Spec.FailureType, canaryCfg.Status.Status) + } + + w.Flush() + return nil +} diff --git a/pkg/fission-cli/cmd/canaryconfig/update.go b/pkg/fission-cli/cmd/canaryconfig/update.go new file mode 100644 index 00000000..76101c5e --- /dev/null +++ b/pkg/fission-cli/cmd/canaryconfig/update.go @@ -0,0 +1,103 @@ +/* +Copyright 2019 The Fission Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package canaryconfig + +import ( + "fmt" + "time" + + "github.com/pkg/errors" + + fv1 "github.com/fission/fission/pkg/apis/fission.io/v1" + "github.com/fission/fission/pkg/controller/client" + "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" + "github.com/fission/fission/pkg/fission-cli/cmd" +) + +type UpdateSubCommand struct { + client *client.Client + canary *fv1.CanaryConfig +} + +func Update(flags cli.Input) error { + opts := UpdateSubCommand{ + client: cmd.GetServer(flags), + } + return opts.do(flags) +} + +func (opts *UpdateSubCommand) do(flags cli.Input) error { + err := opts.complete(flags) + if err != nil { + return err + } + return opts.run(flags) +} + +func (opts *UpdateSubCommand) complete(flags cli.Input) error { + // get the current config + m, err := cmd.GetMetadata("name", "canaryNamespace", flags) + if err != nil { + return err + } + + incrementStep := flags.Int("increment-step") + failureThreshold := flags.Int("failure-threshold") + incrementInterval := flags.String("increment-interval") + + // check for time parsing + _, err = time.ParseDuration(incrementInterval) + if err != nil { + return errors.Wrap(err, "error parsing time duration") + } + + canaryCfg, err := opts.client.CanaryConfigGet(m) + if err != nil { + return errors.Wrap(err, "error getting canary config") + } + + var updateNeeded bool + + if incrementStep != canaryCfg.Spec.WeightIncrement { + canaryCfg.Spec.WeightIncrement = incrementStep + } + + if failureThreshold != canaryCfg.Spec.FailureThreshold { + canaryCfg.Spec.FailureThreshold = failureThreshold + } + + if incrementInterval != canaryCfg.Spec.WeightIncrementDuration { + canaryCfg.Spec.WeightIncrementDuration = incrementInterval + } + + if updateNeeded { + canaryCfg.Status.Status = fv1.CanaryConfigStatusPending + } + + opts.canary = canaryCfg + + return nil +} + +func (opts *UpdateSubCommand) run(flags cli.Input) error { + _, err := opts.client.CanaryConfigUpdate(opts.canary) + if err != nil { + return errors.Wrap(err, "error updating canary config") + } + fmt.Printf("canary config '%v' updated\n", opts.canary.Metadata.Name) + return nil +}