Skip to content

Commit

Permalink
Add replication controller renaming as a cleanup option.
Browse files Browse the repository at this point in the history
  • Loading branch information
brendandburns committed Apr 28, 2015
1 parent 45d8c97 commit 591d98b
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 15 deletions.
10 changes: 7 additions & 3 deletions docs/kubectl_rolling-update.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

```
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
Expand All @@ -24,9 +24,13 @@ $ kubectl rolling-update frontend-v1 -f frontend-v2.json
// Update pods of frontend-v1 using JSON data passed into stdin.
$ 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
// Update the pods of frontend by just changing the image, and keeping the old name
$ kubectl rolling-update frontend --image=image:v2
```

### Options
Expand Down Expand Up @@ -79,4 +83,4 @@ $ kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2
### SEE ALSO
* [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
6 changes: 5 additions & 1 deletion docs/man/man1/kubectl-rolling-update.1
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,13 @@ $ kubectl rolling\-update frontend\-v1 \-f frontend\-v2.json
// Update pods of frontend\-v1 using JSON data passed into stdin.
$ 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

// Update the pods of frontend by just changing the image, and keeping the old name
$ kubectl rolling\-update frontend \-\-image=image:v2


.fi
.RE
Expand Down
35 changes: 27 additions & 8 deletions pkg/kubectl/cmd/rollingupdate.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,18 @@ $ kubectl rolling-update frontend-v1 -f frontend-v2.json
// Update pods of frontend-v1 using JSON data passed into stdin.
$ 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
// 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 {
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.
Aliases: []string{"rollingupdate"},
Short: "Perform a rolling update of the given ReplicationController.",
Expand Down Expand Up @@ -94,9 +98,6 @@ func validateArguments(cmd *cobra.Command, args []string) (deploymentKey, filena
if len(filename) != 0 && len(image) != 0 {
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 {
return "", "", "", "", cmdutil.UsageError(cmd, "Must specify the controller to update")
}
Expand Down Expand Up @@ -133,6 +134,8 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
return err
}

keepOldName := false

mapper, typer := f.Object()
var newRc *api.ReplicationController

Expand All @@ -152,7 +155,6 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
}
}
if len(image) != 0 {
newName := args[1]
var err error
// load the old RC into the "new" RC
if newRc, err = client.ReplicationControllers(cmdNamespace).Get(oldName); err != nil {
Expand All @@ -172,10 +174,19 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
if err != nil {
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.Spec.Selector[deploymentKey] = newHash
newRc.Spec.Template.Labels[deploymentKey] = newHash
// Clear resource version after hashing so that identical updates get different hashes.
newRc.ResourceVersion = ""

if _, found := oldRc.Spec.Selector[deploymentKey]; !found {
Expand Down Expand Up @@ -219,20 +230,28 @@ 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()))
return nil
}
updateCleanupPolicy := kubectl.DeleteRollingUpdateCleanupPolicy
if keepOldName {
updateCleanupPolicy = kubectl.RenameRollingUpdateCleanupPolicy
}
err = updater.Update(&kubectl.RollingUpdaterConfig{
Out: out,
OldRc: oldRc,
NewRc: newRc,
UpdatePeriod: period,
Interval: interval,
Timeout: timeout,
CleanupPolicy: kubectl.DeleteRollingUpdateCleanupPolicy,
CleanupPolicy: updateCleanupPolicy,
})
if err != nil {
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
}

Expand Down
5 changes: 2 additions & 3 deletions pkg/kubectl/cmd/rollingupdate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,8 @@ func TestValidateArgs(t *testing.T) {
flags: map[string]string{
"image": "foo:v2",
},
args: []string{"foo"},
expectErr: true,
testName: "missing second image name",
args: []string{"foo"},
testName: "missing second image name",
},
{
flags: map[string]string{
Expand Down
23 changes: 23 additions & 0 deletions pkg/kubectl/rolling_updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ const (
DeleteRollingUpdateCleanupPolicy RollingUpdaterCleanupPolicy = "Delete"
// PreserveRollingUpdateCleanupPolicy means keep the old controller.
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
Expand Down Expand Up @@ -199,6 +202,14 @@ func (r *RollingUpdater) Update(config *RollingUpdaterConfig) error {
// delete old rc
fmt.Fprintf(out, "Update succeeded. Deleting %s\n", 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:
return nil
default:
Expand Down Expand Up @@ -243,6 +254,18 @@ func (r *RollingUpdater) updateAndWait(rc *api.ReplicationController, interval,
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.
type RollingUpdaterClient interface {
GetReplicationController(namespace, name string) (*api.ReplicationController, error)
Expand Down

0 comments on commit 591d98b

Please sign in to comment.