Make kubectl commands return errors and centralize exit handling

This commit is contained in:
Jeff Lowdermilk
2015-03-09 15:08:16 -07:00
parent 7b72d9539f
commit cd7d78b696
20 changed files with 875 additions and 644 deletions

View File

@@ -49,73 +49,8 @@ func (f *Factory) NewCmdRollingUpdate(out io.Writer) *cobra.Command {
Long: rollingupdate_long,
Example: rollingupdate_example,
Run: func(cmd *cobra.Command, args []string) {
filename := util.GetFlagString(cmd, "filename")
if len(filename) == 0 {
usageError(cmd, "Must specify filename for new controller")
}
period := util.GetFlagDuration(cmd, "update-period")
interval := util.GetFlagDuration(cmd, "poll-interval")
timeout := util.GetFlagDuration(cmd, "timeout")
if len(args) != 1 {
usageError(cmd, "Must specify the controller to update")
}
oldName := args[0]
schema, err := f.Validator(cmd)
err := RunRollingUpdate(f, out, cmd, args)
util.CheckErr(err)
clientConfig, err := f.ClientConfig(cmd)
util.CheckErr(err)
cmdApiVersion := clientConfig.Version
mapper, typer := f.Object(cmd)
// TODO: use resource.Builder instead
mapping, namespace, newName, data := util.ResourceFromFile(filename, typer, mapper, schema, cmdApiVersion)
if mapping.Kind != "ReplicationController" {
usageError(cmd, "%s does not specify a valid ReplicationController", filename)
}
if oldName == newName {
usageError(cmd, "%s cannot have the same name as the existing ReplicationController %s",
filename, oldName)
}
cmdNamespace, err := f.DefaultNamespace(cmd)
util.CheckErr(err)
// TODO: use resource.Builder instead
err = util.CompareNamespace(cmdNamespace, namespace)
util.CheckErr(err)
client, err := f.Client(cmd)
util.CheckErr(err)
obj, err := mapping.Codec.Decode(data)
util.CheckErr(err)
newRc := obj.(*api.ReplicationController)
updater := kubectl.NewRollingUpdater(cmdNamespace, client)
// fetch rc
oldRc, err := client.ReplicationControllers(cmdNamespace).Get(oldName)
util.CheckErr(err)
var hasLabel bool
for key, oldValue := range oldRc.Spec.Selector {
if newValue, ok := newRc.Spec.Selector[key]; ok && newValue != oldValue {
hasLabel = true
break
}
}
if !hasLabel {
usageError(cmd, "%s must specify a matching key with non-equal value in Selector for %s",
filename, oldName)
}
// TODO: handle resizes during rolling update
if newRc.Spec.Replicas == 0 {
newRc.Spec.Replicas = oldRc.Spec.Replicas
}
err = updater.Update(out, oldRc, newRc, period, interval, timeout)
util.CheckErr(err)
fmt.Fprintf(out, "%s\n", newName)
},
}
cmd.Flags().String("update-period", updatePeriod, `Time to wait between updating pods. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`)
@@ -124,3 +59,93 @@ func (f *Factory) NewCmdRollingUpdate(out io.Writer) *cobra.Command {
cmd.Flags().StringP("filename", "f", "", "Filename or URL to file to use to create the new controller.")
return cmd
}
func RunRollingUpdate(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
filename := util.GetFlagString(cmd, "filename")
if len(filename) == 0 {
return util.UsageError(cmd, "Must specify filename for new controller")
}
period := util.GetFlagDuration(cmd, "update-period")
interval := util.GetFlagDuration(cmd, "poll-interval")
timeout := util.GetFlagDuration(cmd, "timeout")
if len(args) != 1 {
return util.UsageError(cmd, "Must specify the controller to update")
}
oldName := args[0]
schema, err := f.Validator(cmd)
if err != nil {
return err
}
clientConfig, err := f.ClientConfig(cmd)
if err != nil {
return err
}
cmdApiVersion := clientConfig.Version
mapper, typer := f.Object(cmd)
// TODO: use resource.Builder instead
mapping, namespace, newName, data, err := util.ResourceFromFile(filename, typer, mapper, schema, cmdApiVersion)
if err != nil {
return err
}
if mapping.Kind != "ReplicationController" {
return util.UsageError(cmd, "%s does not specify a valid ReplicationController", filename)
}
if oldName == newName {
return util.UsageError(cmd, "%s cannot have the same name as the existing ReplicationController %s",
filename, oldName)
}
cmdNamespace, err := f.DefaultNamespace(cmd)
if err != nil {
return err
}
// TODO: use resource.Builder instead
err = util.CompareNamespace(cmdNamespace, namespace)
if err != nil {
return err
}
client, err := f.Client(cmd)
if err != nil {
return err
}
obj, err := mapping.Codec.Decode(data)
if err != nil {
return err
}
newRc := obj.(*api.ReplicationController)
updater := kubectl.NewRollingUpdater(cmdNamespace, client)
// fetch rc
oldRc, err := client.ReplicationControllers(cmdNamespace).Get(oldName)
if err != nil {
return err
}
var hasLabel bool
for key, oldValue := range oldRc.Spec.Selector {
if newValue, ok := newRc.Spec.Selector[key]; ok && newValue != oldValue {
hasLabel = true
break
}
}
if !hasLabel {
return util.UsageError(cmd, "%s must specify a matching key with non-equal value in Selector for %s",
filename, oldName)
}
// TODO: handle resizes during rolling update
if newRc.Spec.Replicas == 0 {
newRc.Spec.Replicas = oldRc.Spec.Replicas
}
err = updater.Update(out, oldRc, newRc, period, interval, timeout)
if err != nil {
return err
}
fmt.Fprintf(out, "%s\n", newName)
return nil
}