Remove panics and make all errors flow to the top

This commit is contained in:
Ian Howell 2019-05-06 08:58:16 -05:00
parent 7e2609d1e8
commit 5e9a4029ec
4 changed files with 34 additions and 24 deletions

@ -1,6 +1,7 @@
package cmd
import (
"errors"
"fmt"
"io"
"os"
@ -15,7 +16,7 @@ var settings environment.AirshipADMSettings
// NewRootCmd creates the root `airshipadm` command. All other commands are
// subcommands branching from this one
func NewRootCmd(out io.Writer, client *kube.Client, args []string) *cobra.Command {
func NewRootCmd(out io.Writer, client *kube.Client, args []string) (*cobra.Command, error) {
rootCmd := &cobra.Command{
Use: "airshipadm",
Short: "airshipadm is a unified entrypoint to various airship components",
@ -25,9 +26,8 @@ func NewRootCmd(out io.Writer, client *kube.Client, args []string) *cobra.Comman
// Settings flags - This section should probably be moved to pkg/environment
rootCmd.PersistentFlags().StringVar(&settings.KubeConfigFilePath, "kubeconfig", "", "path to kubeconfig")
rootCmd.PersistentFlags().BoolVar(&settings.Debug, "debug", false, "enable verbose output")
// TODO(howell): Remove this panic
if err := rootCmd.PersistentFlags().Parse(args); err != nil {
panic(err.Error())
return nil, errors.New("could not parse flags: " + err.Error())
}
log.Init(&settings, out)
@ -36,21 +36,21 @@ func NewRootCmd(out io.Writer, client *kube.Client, args []string) *cobra.Comman
// Compound commands
rootCmd.AddCommand(NewWorkflowCommand())
return rootCmd
return rootCmd, nil
}
// Execute runs the base airshipadm command
func Execute(out io.Writer) {
// TODO(howell): Remove this panic
client, err := kube.NewForConfig(settings.KubeConfigFilePath)
if err != nil {
panic(err.Error())
}
osExitIfError(out, err)
rootCmd, err := NewRootCmd(out, client, os.Args[1:])
osExitIfError(out, err)
osExitIfError(out, rootCmd.Execute())
}
rootCmd := NewRootCmd(out, client, os.Args[1:])
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
func osExitIfError(out io.Writer, err error) {
if err != nil {
fmt.Fprintln(out, err)
os.Exit(1)
}
}

@ -23,10 +23,17 @@ func NewVersionCommand(out io.Writer, client *kube.Client) *cobra.Command {
Short: "Show the version number of airshipadm and its underlying tools",
Long: versionLong,
Run: func(cmd *cobra.Command, args []string) {
clientV := clientVersion()
kubeV, err := kubeVersion(client)
if err != nil {
fmt.Fprintf(out, "Could not get kubernetes version")
return
}
w := tabwriter.NewWriter(out, 0, 0, 1, ' ', 0)
fmt.Fprintf(w, "%s:\t%s\n", "client", clientVersion())
fmt.Fprintf(w, "%s:\t%s\n", "kubernetes server", kubeVersion(client))
w.Flush()
defer w.Flush()
fmt.Fprintf(w, "%s:\t%s\n", "client", clientV)
fmt.Fprintf(w, "%s:\t%s\n", "kubernetes server", kubeV)
},
}
return versionCmd
@ -37,11 +44,10 @@ func clientVersion() string {
return "v0.1.0"
}
func kubeVersion(client *kube.Client) string {
func kubeVersion(client *kube.Client) (string, error) {
version, err := client.Discovery().ServerVersion()
// TODO(howell): Remove this panic
if err != nil {
panic(err.Error())
return "", err
}
return version.String()
return version.String(), nil
}

@ -30,7 +30,6 @@ type CmdTest struct {
func RunCmdTests(t *testing.T, tests []CmdTest) {
t.Helper()
for _, test := range tests {
cmdOutput := executeCmd(t, test.Command)
if *shouldUpdateGolden {
@ -46,7 +45,11 @@ func executeCmd(t *testing.T, command string) []byte {
client := &kube.Client{Interface: fake.NewSimpleClientset()}
// TODO(howell): switch to shellwords (or similar)
args := strings.Fields(command)
rootCmd := cmd.NewRootCmd(&actual, client, args)
rootCmd, err := cmd.NewRootCmd(&actual, client, args)
if err != nil {
t.Fatalf(err.Error())
}
rootCmd.SetArgs(args)
if err := rootCmd.Execute(); err != nil {

@ -1,6 +1,7 @@
package kube
import (
"errors"
"os"
"path/filepath"
@ -18,7 +19,7 @@ func NewForConfig(kubeconfigFilepath string) (*Client, error) {
if kubeconfigFilepath == "" {
home, err := os.UserHomeDir()
if err != nil {
panic(err.Error())
return nil, errors.New("could not find kubernetes config file: " + err.Error())
}
kubeconfigFilepath = filepath.Join(home, ".kube", "config")
}
@ -26,13 +27,13 @@ func NewForConfig(kubeconfigFilepath string) (*Client, error) {
// use the current context in kubeconfigFilepath
config, err := clientcmd.BuildConfigFromFlags("", kubeconfigFilepath)
if err != nil {
panic(err.Error())
return nil, err
}
// create the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
return nil, err
}
return &Client{clientset}, nil
}