diff --git a/cmd/fission-cli/main.go b/cmd/fission-cli/main.go index 10077935..40419030 100644 --- a/cmd/fission-cli/main.go +++ b/cmd/fission-cli/main.go @@ -20,12 +20,17 @@ import ( "os" "github.com/fission/fission/cmd/fission-cli/app" + "github.com/fission/fission/pkg/fission-cli/console" ) func main() { - err := app.App().Execute() + cmd := app.App() + cmd.SilenceErrors = true // use our own error message printer + + err := cmd.Execute() if err != nil { // let program exit with non-zero code when error occurs + console.Error(err.Error()) os.Exit(1) } } diff --git a/pkg/fission-cli/cliwrapper/driver/cobra/helptemplate/templates.go b/pkg/fission-cli/cliwrapper/driver/cobra/helptemplate/templates.go index aeb465a0..4414480b 100644 --- a/pkg/fission-cli/cliwrapper/driver/cobra/helptemplate/templates.go +++ b/pkg/fission-cli/cliwrapper/driver/cobra/helptemplate/templates.go @@ -63,10 +63,12 @@ const ( {{end}}` // SectionTipsHelp is the help template section that displays the '--help' hint. - SectionTipsHelp = `{{if .HasSubCommands}}Use "{{$rootCmd}} --help" for more information about a given command.{{end}}` + SectionTipsHelp = `{{if .HasSubCommands}}Use "{{$rootCmd}} --help" for more information about a given command. +{{end}}` // SectionTipsGlobalOptions is the help template section that displays the 'options' hint for displaying global flags. - SectionTipsGlobalOptions = `{{if $optionsCmdFor}}Use "{{$optionsCmdFor}}" for a list of global command-line options (applies to all commands).{{end}}` + SectionTipsGlobalOptions = `{{if $optionsCmdFor}}Use "{{$optionsCmdFor}}" for a list of global command-line options (applies to all commands). +{{end}}` ) // MainHelpTemplate if the template for 'help' used by most commands. diff --git a/pkg/fission-cli/cmd/spec/apply.go b/pkg/fission-cli/cmd/spec/apply.go index e36f783c..3773ee3e 100644 --- a/pkg/fission-cli/cmd/spec/apply.go +++ b/pkg/fission-cli/cmd/spec/apply.go @@ -319,7 +319,7 @@ func applyArchives(fclient *client.Client, specDir string, fr *FissionResources) if strings.HasPrefix(ar.URL, ARCHIVE_URL_PREFIX) { availableAr, ok := archiveFiles[ar.URL] if !ok { - return fmt.Errorf("unknown archive name %v", strings.TrimPrefix(ar.URL, ARCHIVE_URL_PREFIX)) + return errors.Errorf("unknown archive name %v", strings.TrimPrefix(ar.URL, ARCHIVE_URL_PREFIX)) } ar.Type = availableAr.Type ar.Literal = availableAr.Literal @@ -368,7 +368,7 @@ func applyResources(fclient *client.Client, specDir string, fr *FissionResources // spec. It may exist outside the spec, but we're going to treat // that as an error, so that we encourage self-contained specs. // Is there a good use case for non-self contained specs? - return nil, nil, fmt.Errorf("function %v/%v references package %v/%v, which doesn't exist in the specs", + return nil, nil, errors.Errorf("function %v/%v references package %v/%v, which doesn't exist in the specs", f.Metadata.Namespace, f.Metadata.Name, f.Spec.Package.PackageRef.Namespace, f.Spec.Package.PackageRef.Name) } fr.Functions[i].Spec.Package.PackageRef.ResourceVersion = m.ResourceVersion @@ -430,8 +430,7 @@ func localArchiveFromSpec(specDir string, aus *spectypes.ArchiveUploadSpec) (*fv absGlob := rootDir + "/" + relativeGlob f, err := filepath.Glob(absGlob) if err != nil { - console.Info(fmt.Sprintf("Invalid glob in archive %v: %v", aus.Name, relativeGlob)) - return nil, err + return nil, errors.Wrapf(err, "Invalid glob in archive %v: %v", aus.Name, relativeGlob) } files = append(files, f...) // xxx handle excludeGlobs here @@ -439,7 +438,7 @@ func localArchiveFromSpec(specDir string, aus *spectypes.ArchiveUploadSpec) (*fv } if len(files) == 0 { - return nil, fmt.Errorf("archive '%v' is empty", aus.Name) + return nil, errors.Errorf("archive '%v' is empty", aus.Name) } // if it's just one file, use its path directly @@ -490,7 +489,7 @@ func localArchiveFromSpec(specDir string, aus *spectypes.ArchiveUploadSpec) (*fv // checksum csum, err := utils.GetFileChecksum(archiveFileName) if err != nil { - return nil, fmt.Errorf("failed to calculate archive checksum for %v (%v): %v", aus.Name, archiveFileName, err) + return nil, errors.Errorf("failed to calculate archive checksum for %v (%v): %v", aus.Name, archiveFileName, err) } // archive object @@ -535,7 +534,7 @@ func waitForPackageBuild(fclient *client.Client, pkg *fv1.Package) (*fv1.Package return pkg, nil } if time.Since(start) > 5*time.Minute { - return nil, fmt.Errorf("package %v has been building for a while, giving up on waiting for it", pkg.Metadata.Name) + return nil, errors.Errorf("package %v has been building for a while, giving up on waiting for it", pkg.Metadata.Name) } // TODO watch instead @@ -612,7 +611,7 @@ func applyPackages(fclient *client.Client, fr *FissionResources, delete bool) (m pkg, err := waitForPackageBuild(fclient, &o) if err != nil { // log and ignore - fmt.Printf("Error waiting for package '%v' build, ignoring\n", o.Metadata.Name) + console.Warn(fmt.Sprintf("Error waiting for package '%v' build, ignoring", o.Metadata.Name)) pkg = &o } diff --git a/pkg/fission-cli/cmd/support/resources/crd.go b/pkg/fission-cli/cmd/support/resources/crd.go index 39edee1f..112c80e3 100644 --- a/pkg/fission-cli/cmd/support/resources/crd.go +++ b/pkg/fission-cli/cmd/support/resources/crd.go @@ -53,7 +53,7 @@ func (res CrdDumper) Dump(dumpDir string) { case CrdEnvironment: items, err := res.client.EnvironmentList(metav1.NamespaceAll) if err != nil { - console.Info(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) + console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) return } @@ -65,7 +65,7 @@ func (res CrdDumper) Dump(dumpDir string) { case CrdFunction: items, err := res.client.FunctionList(metav1.NamespaceAll) if err != nil { - console.Info(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) + console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) return } @@ -77,7 +77,7 @@ func (res CrdDumper) Dump(dumpDir string) { case CrdPackage: items, err := res.client.PackageList(metav1.NamespaceAll) if err != nil { - console.Info(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) + console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) return } @@ -90,7 +90,7 @@ func (res CrdDumper) Dump(dumpDir string) { case CrdHttpTrigger: items, err := res.client.HTTPTriggerList(metav1.NamespaceAll) if err != nil { - console.Info(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) + console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) return } @@ -102,7 +102,7 @@ func (res CrdDumper) Dump(dumpDir string) { case CrdKubeWatcher: items, err := res.client.WatchList(metav1.NamespaceAll) if err != nil { - console.Info(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) + console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) return } @@ -117,7 +117,7 @@ func (res CrdDumper) Dump(dumpDir string) { for _, mqType := range []string{types.MessageQueueTypeNats, types.MessageQueueTypeASQ} { l, err := res.client.MessageQueueTriggerList(mqType, metav1.NamespaceAll) if err != nil { - console.Info(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) + console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) break } triggers = append(triggers, l...) @@ -131,7 +131,7 @@ func (res CrdDumper) Dump(dumpDir string) { case CrdTimeTrigger: items, err := res.client.TimeTriggerList(metav1.NamespaceAll) if err != nil { - console.Info(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) + console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) return } @@ -141,7 +141,7 @@ func (res CrdDumper) Dump(dumpDir string) { } default: - console.Info(fmt.Sprintf("Unknown type: %v", res.crdType)) + console.Warn(fmt.Sprintf("Unknown type: %v", res.crdType)) } } diff --git a/pkg/fission-cli/cmd/support/resources/kubernetes.go b/pkg/fission-cli/cmd/support/resources/kubernetes.go index 0c73fdf1..3b1e3bf7 100644 --- a/pkg/fission-cli/cmd/support/resources/kubernetes.go +++ b/pkg/fission-cli/cmd/support/resources/kubernetes.go @@ -52,7 +52,7 @@ func NewKubernetesVersion(clientset *kubernetes.Clientset) Resource { func (res KubernetesVersion) Dump(dumpDir string) { serverVer, err := res.client.ServerVersion() if err != nil { - console.Info(fmt.Sprintf("Error setting up kubernetes client: %v", err)) + console.Error(fmt.Sprintf("Error setting up kubernetes client: %v", err)) return } @@ -80,7 +80,7 @@ func (res KubernetesObjectDumper) Dump(dumpDir string) { case KubernetesService: objs, err := res.client.CoreV1().Services(metav1.NamespaceAll).List(metav1.ListOptions{LabelSelector: res.selector}) if err != nil { - console.Info(fmt.Sprintf("Error getting %v list with selector %v: %v", res.objType, res.selector, err)) + console.Error(fmt.Sprintf("Error getting %v list with selector %v: %v", res.objType, res.selector, err)) return } @@ -93,7 +93,7 @@ func (res KubernetesObjectDumper) Dump(dumpDir string) { case KubernetesDeployment: objs, err := res.client.AppsV1().Deployments(metav1.NamespaceAll).List(metav1.ListOptions{LabelSelector: res.selector}) if err != nil { - console.Info(fmt.Sprintf("Error getting %v list with selector %v: %v", res.objType, res.selector, err)) + console.Error(fmt.Sprintf("Error getting %v list with selector %v: %v", res.objType, res.selector, err)) return } @@ -105,7 +105,7 @@ func (res KubernetesObjectDumper) Dump(dumpDir string) { case KubernetesPod: objs, err := res.client.CoreV1().Pods(metav1.NamespaceAll).List(metav1.ListOptions{LabelSelector: res.selector}) if err != nil { - console.Info(fmt.Sprintf("Error getting %v list with selector %v: %v", res.objType, res.selector, err)) + console.Error(fmt.Sprintf("Error getting %v list with selector %v: %v", res.objType, res.selector, err)) return } @@ -117,7 +117,7 @@ func (res KubernetesObjectDumper) Dump(dumpDir string) { case KubernetesHPA: objs, err := res.client.AutoscalingV2beta1().HorizontalPodAutoscalers(metav1.NamespaceAll).List(metav1.ListOptions{LabelSelector: res.selector}) if err != nil { - console.Info(fmt.Sprintf("Error getting %v list with selector %v: %v", res.objType, res.selector, err)) + console.Error(fmt.Sprintf("Error getting %v list with selector %v: %v", res.objType, res.selector, err)) return } @@ -129,7 +129,7 @@ func (res KubernetesObjectDumper) Dump(dumpDir string) { case KubernetesDaemonSet: objs, err := res.client.AppsV1().DaemonSets(metav1.NamespaceAll).List(metav1.ListOptions{LabelSelector: res.selector}) if err != nil { - console.Info(fmt.Sprintf("Error getting %v list with selector %v: %v", res.objType, res.selector, err)) + console.Error(fmt.Sprintf("Error getting %v list with selector %v: %v", res.objType, res.selector, err)) return } @@ -141,7 +141,7 @@ func (res KubernetesObjectDumper) Dump(dumpDir string) { case KubernetesNode: objs, err := res.client.CoreV1().Nodes().List(metav1.ListOptions{LabelSelector: res.selector}) if err != nil { - console.Info(fmt.Sprintf("Error getting %v list with selector %v: %v", res.objType, res.selector, err)) + console.Error(fmt.Sprintf("Error getting %v list with selector %v: %v", res.objType, res.selector, err)) return } @@ -153,7 +153,7 @@ func (res KubernetesObjectDumper) Dump(dumpDir string) { } default: - console.Info(fmt.Sprintf("Unknown type: %v", res.objType)) + console.Error(fmt.Sprintf("Unknown type: %v", res.objType)) return } } @@ -199,7 +199,7 @@ func (res KubernetesPodLogDumper) Dump(dumpDir string) { Pods(metav1.NamespaceAll). List(metav1.ListOptions{LabelSelector: res.labelSelector}) if err != nil { - console.Info(fmt.Sprintf("Error getting controller list: %v", err)) + console.Error(fmt.Sprintf("Error getting controller list: %v", err)) return } @@ -218,7 +218,7 @@ func (res KubernetesPodLogDumper) Dump(dumpDir string) { stream, err := req.Stream() if err != nil { - console.Info(fmt.Sprintf("Error streaming logs for pod %v: %v", pod.Name, err)) + console.Error(fmt.Sprintf("Error streaming logs for pod %v: %v", pod.Name, err)) return } @@ -232,13 +232,14 @@ func (res KubernetesPodLogDumper) Dump(dumpDir string) { stream.Close() break } - console.Info(fmt.Sprintf("Error reading logs from buffer: %v", err)) + console.Error(fmt.Sprintf("Error reading logs from buffer: %v", err)) return } _, err = buffer.WriteString(string(line) + "\n") if err != nil { - console.Info(fmt.Sprintf("Error writing bytes to buffer: %v", err)) + console.Error(fmt.Sprintf("Error writing bytes to buffer: %v", err)) + return } } diff --git a/pkg/fission-cli/cmd/support/resources/resource.go b/pkg/fission-cli/cmd/support/resources/resource.go index c866ef10..75c7b5ec 100644 --- a/pkg/fission-cli/cmd/support/resources/resource.go +++ b/pkg/fission-cli/cmd/support/resources/resource.go @@ -45,7 +45,7 @@ func getPodFileName(dumpdir string, pod metav1.ObjectMeta, containerName string) func writeToFile(file string, obj interface{}) { bs, err := yaml.Marshal(obj) if err != nil { - console.Info(fmt.Sprintf("Error encoding object: %v", err)) + console.Error(fmt.Sprintf("Error encoding object: %v", err)) return } @@ -57,6 +57,6 @@ func writeToFile(file string, obj interface{}) { err = ioutil.WriteFile(file, bs, 0644) if err != nil { - console.Info(fmt.Sprintf("Error writing file %v: %v", file, err)) + console.Error(fmt.Sprintf("Error writing file %v: %v", file, err)) } } diff --git a/pkg/fission-cli/console/log.go b/pkg/fission-cli/console/log.go index dc66f6b5..1fdd2132 100644 --- a/pkg/fission-cli/console/log.go +++ b/pkg/fission-cli/console/log.go @@ -19,6 +19,7 @@ package console import ( "fmt" "os" + "strings" "github.com/life1347/color" ) @@ -28,12 +29,16 @@ var ( Verbosity int ) +func Error(msg interface{}) { + os.Stderr.WriteString(fmt.Sprintf("%v: %v\n", color.RedString("Error"), trimNewline(msg))) +} + func Warn(msg interface{}) { - os.Stdout.WriteString(fmt.Sprintf("%v: %v\n", color.YellowString("Warning"), msg)) + os.Stdout.WriteString(fmt.Sprintf("%v: %v\n", color.YellowString("Warning"), trimNewline(msg))) } func Info(msg interface{}) { - os.Stderr.WriteString(fmt.Sprintf("%v\n", msg)) + os.Stderr.WriteString(fmt.Sprintf("%v\n", trimNewline(msg))) } func Verbose(verbosityLevel int, format string, args ...interface{}) { @@ -41,3 +46,7 @@ func Verbose(verbosityLevel int, format string, args ...interface{}) { fmt.Printf(format+"\n", args...) } } + +func trimNewline(m interface{}) string { + return strings.TrimSuffix(fmt.Sprintf("%v", m), "\n") +}