Add replication controller renaming as a cleanup option.

This commit is contained in:
Brendan Burns 2015-04-23 16:27:19 -07:00
parent 45d8c97b0b
commit 591d98b6b2
5 changed files with 64 additions and 15 deletions

View File

@ -12,7 +12,7 @@ new PodTemplate. The new-controller.json must specify the same namespace as the
existing controller and overwrite at least one (common) label in its replicaSelector. existing controller and overwrite at least one (common) label in its replicaSelector.
``` ```
kubectl rolling-update OLD_CONTROLLER_NAME -f NEW_CONTROLLER_SPEC kubectl rolling-update OLD_CONTROLLER_NAME ([NEW_CONTROLLER_NAME] --image=NEW_CONTAINER_IMAGE | -f NEW_CONTROLLER_SPEC)
``` ```
### Examples ### Examples
@ -24,9 +24,13 @@ $ kubectl rolling-update frontend-v1 -f frontend-v2.json
// Update pods of frontend-v1 using JSON data passed into stdin. // Update pods of frontend-v1 using JSON data passed into stdin.
$ cat frontend-v2.json | kubectl rolling-update frontend-v1 -f - $ cat frontend-v2.json | kubectl rolling-update frontend-v1 -f -
// Update the pods of frontend-v1 to frontend-v2 by just changing the image // Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the
// name of the replication controller.
$ kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2 $ kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2
// Update the pods of frontend by just changing the image, and keeping the old name
$ kubectl rolling-update frontend --image=image:v2
``` ```
### Options ### Options
@ -79,4 +83,4 @@ $ kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2
### SEE ALSO ### SEE ALSO
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager * [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
###### Auto generated by spf13/cobra at 2015-04-27 22:01:46.525154396 +0000 UTC ###### Auto generated by spf13/cobra at 2015-04-27 22:44:36.84341428 +0000 UTC

View File

@ -185,9 +185,13 @@ $ kubectl rolling\-update frontend\-v1 \-f frontend\-v2.json
// Update pods of frontend\-v1 using JSON data passed into stdin. // Update pods of frontend\-v1 using JSON data passed into stdin.
$ cat frontend\-v2.json | kubectl rolling\-update frontend\-v1 \-f \- $ cat frontend\-v2.json | kubectl rolling\-update frontend\-v1 \-f \-
// Update the pods of frontend\-v1 to frontend\-v2 by just changing the image // Update the pods of frontend\-v1 to frontend\-v2 by just changing the image, and switching the
// name of the replication controller.
$ kubectl rolling\-update frontend\-v1 frontend\-v2 \-\-image=image:v2 $ kubectl rolling\-update frontend\-v1 frontend\-v2 \-\-image=image:v2
// Update the pods of frontend by just changing the image, and keeping the old name
$ kubectl rolling\-update frontend \-\-image=image:v2
.fi .fi
.RE .RE

View File

@ -51,14 +51,18 @@ $ kubectl rolling-update frontend-v1 -f frontend-v2.json
// Update pods of frontend-v1 using JSON data passed into stdin. // Update pods of frontend-v1 using JSON data passed into stdin.
$ cat frontend-v2.json | kubectl rolling-update frontend-v1 -f - $ cat frontend-v2.json | kubectl rolling-update frontend-v1 -f -
// Update the pods of frontend-v1 to frontend-v2 by just changing the image // Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the
// name of the replication controller.
$ kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2 $ kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2
// Update the pods of frontend by just changing the image, and keeping the old name
$ kubectl rolling-update frontend --image=image:v2
` `
) )
func NewCmdRollingUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command { func NewCmdRollingUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "rolling-update OLD_CONTROLLER_NAME -f NEW_CONTROLLER_SPEC", Use: "rolling-update OLD_CONTROLLER_NAME ([NEW_CONTROLLER_NAME] --image=NEW_CONTAINER_IMAGE | -f NEW_CONTROLLER_SPEC)",
// rollingupdate is deprecated. // rollingupdate is deprecated.
Aliases: []string{"rollingupdate"}, Aliases: []string{"rollingupdate"},
Short: "Perform a rolling update of the given ReplicationController.", Short: "Perform a rolling update of the given ReplicationController.",
@ -94,9 +98,6 @@ func validateArguments(cmd *cobra.Command, args []string) (deploymentKey, filena
if len(filename) != 0 && len(image) != 0 { if len(filename) != 0 && len(image) != 0 {
return "", "", "", "", cmdutil.UsageError(cmd, "--filename and --image can not both be specified") return "", "", "", "", cmdutil.UsageError(cmd, "--filename and --image can not both be specified")
} }
if len(image) > 0 && len(args) < 2 {
return "", "", "", "", cmdutil.UsageError(cmd, "You must specify a name for your new controller")
}
if len(args) < 1 { if len(args) < 1 {
return "", "", "", "", cmdutil.UsageError(cmd, "Must specify the controller to update") return "", "", "", "", cmdutil.UsageError(cmd, "Must specify the controller to update")
} }
@ -133,6 +134,8 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
return err return err
} }
keepOldName := false
mapper, typer := f.Object() mapper, typer := f.Object()
var newRc *api.ReplicationController var newRc *api.ReplicationController
@ -152,7 +155,6 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
} }
} }
if len(image) != 0 { if len(image) != 0 {
newName := args[1]
var err error var err error
// load the old RC into the "new" RC // load the old RC into the "new" RC
if newRc, err = client.ReplicationControllers(cmdNamespace).Get(oldName); err != nil { if newRc, err = client.ReplicationControllers(cmdNamespace).Get(oldName); err != nil {
@ -172,10 +174,19 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
if err != nil { if err != nil {
return err return err
} }
var newName string
if len(args) >= 2 {
newName = args[1]
} else {
keepOldName = true
newName = fmt.Sprintf("%s-%s", newRc.Name, newHash)
}
newRc.Name = newName newRc.Name = newName
newRc.Spec.Selector[deploymentKey] = newHash newRc.Spec.Selector[deploymentKey] = newHash
newRc.Spec.Template.Labels[deploymentKey] = newHash newRc.Spec.Template.Labels[deploymentKey] = newHash
// Clear resource version after hashing so that identical updates get different hashes.
newRc.ResourceVersion = "" newRc.ResourceVersion = ""
if _, found := oldRc.Spec.Selector[deploymentKey]; !found { if _, found := oldRc.Spec.Selector[deploymentKey]; !found {
@ -219,6 +230,10 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
fmt.Fprintf(out, "Rolling from:\n%s\nTo:\n%s\n", string(oldRcData.Bytes()), string(newRcData.Bytes())) fmt.Fprintf(out, "Rolling from:\n%s\nTo:\n%s\n", string(oldRcData.Bytes()), string(newRcData.Bytes()))
return nil return nil
} }
updateCleanupPolicy := kubectl.DeleteRollingUpdateCleanupPolicy
if keepOldName {
updateCleanupPolicy = kubectl.RenameRollingUpdateCleanupPolicy
}
err = updater.Update(&kubectl.RollingUpdaterConfig{ err = updater.Update(&kubectl.RollingUpdaterConfig{
Out: out, Out: out,
OldRc: oldRc, OldRc: oldRc,
@ -226,13 +241,17 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
UpdatePeriod: period, UpdatePeriod: period,
Interval: interval, Interval: interval,
Timeout: timeout, Timeout: timeout,
CleanupPolicy: kubectl.DeleteRollingUpdateCleanupPolicy, CleanupPolicy: updateCleanupPolicy,
}) })
if err != nil { if err != nil {
return err return err
} }
fmt.Fprintf(out, "%s\n", newName) if keepOldName {
fmt.Fprintf(out, "%s\n", oldName)
} else {
fmt.Fprintf(out, "%s\n", newName)
}
return nil return nil
} }

View File

@ -59,9 +59,8 @@ func TestValidateArgs(t *testing.T) {
flags: map[string]string{ flags: map[string]string{
"image": "foo:v2", "image": "foo:v2",
}, },
args: []string{"foo"}, args: []string{"foo"},
expectErr: true, testName: "missing second image name",
testName: "missing second image name",
}, },
{ {
flags: map[string]string{ flags: map[string]string{

View File

@ -66,6 +66,9 @@ const (
DeleteRollingUpdateCleanupPolicy RollingUpdaterCleanupPolicy = "Delete" DeleteRollingUpdateCleanupPolicy RollingUpdaterCleanupPolicy = "Delete"
// PreserveRollingUpdateCleanupPolicy means keep the old controller. // PreserveRollingUpdateCleanupPolicy means keep the old controller.
PreserveRollingUpdateCleanupPolicy RollingUpdaterCleanupPolicy = "Preserve" PreserveRollingUpdateCleanupPolicy RollingUpdaterCleanupPolicy = "Preserve"
// RenameRollingUpdateCleanupPolicy means delete the old controller, and rename
// the new controller to the name of the old controller.
RenameRollingUpdateCleanupPolicy RollingUpdaterCleanupPolicy = "Rename"
) )
// NewRollingUpdater creates a RollingUpdater from a client // NewRollingUpdater creates a RollingUpdater from a client
@ -199,6 +202,14 @@ func (r *RollingUpdater) Update(config *RollingUpdaterConfig) error {
// delete old rc // delete old rc
fmt.Fprintf(out, "Update succeeded. Deleting %s\n", oldName) fmt.Fprintf(out, "Update succeeded. Deleting %s\n", oldName)
return r.c.DeleteReplicationController(r.ns, oldName) return r.c.DeleteReplicationController(r.ns, oldName)
case RenameRollingUpdateCleanupPolicy:
// delete old rc
fmt.Fprintf(out, "Update succeeded. Deleting old controller: %s\n", oldName)
if err := r.c.DeleteReplicationController(r.ns, oldName); err != nil {
return err
}
fmt.Fprintf(out, "Renaming %s to %s\n", newRc.Name, oldName)
return r.rename(newRc, oldName)
case PreserveRollingUpdateCleanupPolicy: case PreserveRollingUpdateCleanupPolicy:
return nil return nil
default: default:
@ -243,6 +254,18 @@ func (r *RollingUpdater) updateAndWait(rc *api.ReplicationController, interval,
return r.c.GetReplicationController(r.ns, rc.ObjectMeta.Name) return r.c.GetReplicationController(r.ns, rc.ObjectMeta.Name)
} }
func (r *RollingUpdater) rename(rc *api.ReplicationController, newName string) error {
oldName := rc.Name
rc.Name = newName
rc.ResourceVersion = ""
_, err := r.c.CreateReplicationController(rc.Namespace, rc)
if err != nil {
return err
}
return r.c.DeleteReplicationController(rc.Namespace, oldName)
}
// RollingUpdaterClient abstracts access to ReplicationControllers. // RollingUpdaterClient abstracts access to ReplicationControllers.
type RollingUpdaterClient interface { type RollingUpdaterClient interface {
GetReplicationController(namespace, name string) (*api.ReplicationController, error) GetReplicationController(namespace, name string) (*api.ReplicationController, error)