Skip to content

Commit c19785c

Browse files
author
Kubernetes Submit Queue
authored
Merge pull request kubernetes#49674 from crimsonfaith91/rollout
Automatic merge from submit-queue (batch tested with PRs 50033, 49988, 51132, 49674, 51207) StatefulSet kubectl rollout command **What this PR does / why we need it**: This PR implements StatefulSet kubectl rollout command, covering `history`, `status`, and `undo`. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes kubernetes#49890 **Special notes for your reviewer**: **Release note**: ```release-note kubectl rollout `history`, `status`, and `undo` subcommands now support StatefulSets. ```
2 parents fe0c519 + ebdbafd commit c19785c

14 files changed

Lines changed: 310 additions & 113 deletions

hack/make-rules/test-cmd-util.sh

Lines changed: 99 additions & 46 deletions
Large diffs are not rendered by default.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
apiVersion: apps/v1beta2
2+
kind: StatefulSet
3+
metadata:
4+
name: nginx
5+
spec:
6+
selector:
7+
matchLabels:
8+
app: nginx-statefulset
9+
updateStrategy:
10+
type: RollingUpdate
11+
serviceName: "nginx"
12+
replicas: 0
13+
template:
14+
metadata:
15+
labels:
16+
app: nginx-statefulset
17+
spec:
18+
terminationGracePeriodSeconds: 5
19+
containers:
20+
- name: nginx
21+
image: gcr.io/google_containers/nginx-slim:0.8
22+
ports:
23+
- containerPort: 80
24+
name: web
25+
command:
26+
- sh
27+
- -c
28+
- 'while true; do sleep 1; done'
29+
- name: pause
30+
image: gcr.io/google-containers/pause:2.0
31+
ports:
32+
- containerPort: 81
33+
name: web-2

hack/testdata/nginx-statefulset.yaml renamed to hack/testdata/rollingupdate-statefulset.yaml

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,21 @@
1-
# A headless service to create DNS records
2-
apiVersion: v1
3-
kind: Service
4-
metadata:
5-
annotations:
6-
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
7-
name: nginx
8-
labels:
9-
app: nginx-statefulset
10-
spec:
11-
ports:
12-
- port: 80
13-
name: web
14-
# *.nginx.default.svc.cluster.local
15-
clusterIP: None
16-
selector:
17-
app: nginx-statefulset
18-
---
19-
apiVersion: apps/v1beta1
1+
apiVersion: apps/v1beta2
202
kind: StatefulSet
213
metadata:
224
name: nginx
235
spec:
6+
selector:
7+
matchLabels:
8+
app: nginx-statefulset
9+
updateStrategy:
10+
type: RollingUpdate
2411
serviceName: "nginx"
2512
replicas: 0
2613
template:
2714
metadata:
2815
labels:
2916
app: nginx-statefulset
3017
spec:
31-
terminationGracePeriodSeconds: 0
18+
terminationGracePeriodSeconds: 5
3219
containers:
3320
- name: nginx
3421
image: gcr.io/google_containers/nginx-slim:0.7

pkg/controller/statefulset/stateful_set_control.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,11 +256,11 @@ func (ssc *defaultStatefulSetControl) updateStatefulSet(
256256
collisionCount int32,
257257
pods []*v1.Pod) (*apps.StatefulSetStatus, error) {
258258
// get the current and update revisions of the set.
259-
currentSet, err := applyRevision(set, currentRevision)
259+
currentSet, err := ApplyRevision(set, currentRevision)
260260
if err != nil {
261261
return nil, err
262262
}
263-
updateSet, err := applyRevision(set, updateRevision)
263+
updateSet, err := ApplyRevision(set, updateRevision)
264264
if err != nil {
265265
return nil, err
266266
}

pkg/controller/statefulset/stateful_set_control_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1281,7 +1281,7 @@ func TestStatefulSetControlRollback(t *testing.T) {
12811281
t.Fatalf("%s: %s", test.name, err)
12821282
}
12831283
history.SortControllerRevisions(revisions)
1284-
set, err = applyRevision(set, revisions[0])
1284+
set, err = ApplyRevision(set, revisions[0])
12851285
if err != nil {
12861286
t.Fatalf("%s: %s", test.name, err)
12871287
}

pkg/controller/statefulset/stateful_set_utils.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package statefulset
1818

1919
import (
20+
"bytes"
2021
"encoding/json"
2122
"fmt"
2223
"regexp"
@@ -266,6 +267,15 @@ func newVersionedStatefulSetPod(currentSet, updateSet *apps.StatefulSet, current
266267
return pod
267268
}
268269

270+
// Match check if the given StatefulSet's template matches the template stored in the given history.
271+
func Match(ss *apps.StatefulSet, history *apps.ControllerRevision) (bool, error) {
272+
patch, err := getPatch(ss)
273+
if err != nil {
274+
return false, err
275+
}
276+
return bytes.Equal(patch, history.Data.Raw), nil
277+
}
278+
269279
// getPatch returns a strategic merge patch that can be applied to restore a StatefulSet to a
270280
// previous version. If the returned error is nil the patch is valid. The current state that we save is just the
271281
// PodSpecTemplate. We can modify this later to encompass more state (or less) and remain compatible with previously
@@ -319,9 +329,9 @@ func newRevision(set *apps.StatefulSet, revision int64, collisionCount *int32) (
319329
return cr, nil
320330
}
321331

322-
// applyRevision returns a new StatefulSet constructed by restoring the state in revision to set. If the returned error
332+
// ApplyRevision returns a new StatefulSet constructed by restoring the state in revision to set. If the returned error
323333
// is nil, the returned StatefulSet is valid.
324-
func applyRevision(set *apps.StatefulSet, revision *apps.ControllerRevision) (*apps.StatefulSet, error) {
334+
func ApplyRevision(set *apps.StatefulSet, revision *apps.ControllerRevision) (*apps.StatefulSet, error) {
325335
obj, err := scheme.Scheme.DeepCopy(set)
326336
if err != nil {
327337
return nil, err

pkg/controller/statefulset/stateful_set_utils_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ func TestCreateApplyRevision(t *testing.T) {
258258
key := "foo"
259259
expectedValue := "bar"
260260
set.Annotations[key] = expectedValue
261-
restoredSet, err := applyRevision(set, revision)
261+
restoredSet, err := ApplyRevision(set, revision)
262262
if err != nil {
263263
t.Fatal(err)
264264
}

pkg/kubectl/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ go_library(
129129
"//pkg/client/unversioned:go_default_library",
130130
"//pkg/controller/daemon:go_default_library",
131131
"//pkg/controller/deployment/util:go_default_library",
132+
"//pkg/controller/statefulset:go_default_library",
132133
"//pkg/credentialprovider:go_default_library",
133134
"//pkg/kubectl/resource:go_default_library",
134135
"//pkg/kubectl/util:go_default_library",

pkg/kubectl/cmd/rollout/rollout.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ var (
4242
4343
* deployments
4444
* daemonsets
45+
* statefulsets
4546
`)
4647
)
4748

pkg/kubectl/cmd/rollout/rollout_history.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ var (
4444
func NewCmdRolloutHistory(f cmdutil.Factory, out io.Writer) *cobra.Command {
4545
options := &resource.FilenameOptions{}
4646

47-
validArgs := []string{"deployment", "daemonset"}
47+
validArgs := []string{"deployment", "daemonset", "statefulset"}
4848
argAliases := kubectl.ResourceAliases(validArgs)
4949

5050
cmd := &cobra.Command{

0 commit comments

Comments
 (0)