Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StatefulSet kubectl rollout command #49674

Merged
merged 1 commit into from
Aug 25, 2017

Conversation

crimsonfaith91
Copy link
Contributor

@crimsonfaith91 crimsonfaith91 commented Jul 27, 2017

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 #49890

Special notes for your reviewer:

Release note:

kubectl rollout `history`, `status`, and `undo` subcommands now support StatefulSets.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Jul 27, 2017
@k8s-github-robot k8s-github-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. release-note Denotes a PR that will be considered when it comes time to generate release notes. labels Jul 27, 2017
@crimsonfaith91 crimsonfaith91 changed the title [WIP] StatefulSet kubectl rollout command StatefulSet kubectl rollout command Jul 27, 2017
@k8s-ci-robot k8s-ci-robot assigned janetkuo and unassigned eparis Jul 27, 2017
@k8s-github-robot k8s-github-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jul 27, 2017
@crimsonfaith91 crimsonfaith91 changed the title StatefulSet kubectl rollout command [WIP] StatefulSet kubectl rollout command Jul 27, 2017
@crimsonfaith91 crimsonfaith91 force-pushed the rollout branch 2 times, most recently from e4d5bad to c00edea Compare August 1, 2017 22:48
@crimsonfaith91 crimsonfaith91 changed the title [WIP] StatefulSet kubectl rollout command StatefulSet kubectl rollout command Aug 3, 2017
@crimsonfaith91
Copy link
Contributor Author

crimsonfaith91 commented Aug 3, 2017

@kow3ns @foxish @janetkuo
I am testing the kubectl rollout command via hack/make-rules/test-cmd.sh, but was stuck for a few days on testing existence of controllerrevision in metadata.annotations. The error message below indicates that controllerrevision cannot be found via metadata.annotations:

Get controllerrevisions {{range.items}}{{.metadata.annotations}}:{{end}}
  Expected: .*rollingupdate-statefulset-rv2.yaml --record.*
  Got:      <no value>:<no value>:

I am not sure whether statefulset handles controllerrevision similarly as daemonset. I notice that the test was not originally added in daemonset rollout command PR. It was added in another PR afterwards.

Do you have any idea why adding --record flag does not store controllerrevision info in statefulset metadata.annotations? The YAML file that creates statefulset for testing purpose can be found here. Thanks!

@crimsonfaith91 crimsonfaith91 force-pushed the rollout branch 2 times, most recently from bc999df to 99fb2e8 Compare August 3, 2017 23:54
@k8s-github-robot k8s-github-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Aug 3, 2017
@foxish
Copy link
Contributor

foxish commented Aug 4, 2017

cc @kubernetes/sig-cli-pr-reviews

@k8s-ci-robot k8s-ci-robot added the sig/cli Categorizes an issue or PR as relevant to SIG CLI. label Aug 4, 2017
containers:
- name: nginx
image: gcr.io/google_containers/nginx-slim:0.7
image: gcr.io/google-containers/pause:latest
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image does not match the name, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, i will change the container name.

@@ -461,3 +477,137 @@ func (ssc *StatefulSetController) syncStatefulSet(set *apps.StatefulSet, pods []
glog.V(4).Infof("Successfully synced StatefulSet %s/%s successful", set.Namespace, set.Name)
return nil
}

/*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this commented out code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like i have removed the codes from the newest commit.

@@ -75,3 +76,39 @@ func (s *statefulSetLister) GetPodStatefulSets(pod *v1.Pod) ([]*apps.StatefulSet

return psList, nil
}

/*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented out? needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed - i will remove it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have removed it from the newest commit, so no change is needed.

Copy link
Member

@mengqiy mengqiy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kubectl change and cmd test are mostly LGTM

if err != nil {
return nil, nil, fmt.Errorf("failed to retrieve DaemonSet %s: %v", name, err)
return nil, nil, fmt.Errorf("failed to obtain accessor for %s named %s: %v", kind, accessor.GetName(), err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accessor.GetName()

Why not simply use name? It should be identical.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya, name suffices. :)

if err != nil {
return nil, nil, err
}
historyList, err := apps.ControllerRevisions(ds.Namespace).List(metav1.ListOptions{LabelSelector: selector.String()})
historyList, err := apps.ControllerRevisions(accessor.GetNamespace()).List(metav1.ListOptions{LabelSelector: selector.String()})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accessor.GetNamespace()

Same question. Why not using namespace?

Copy link
Contributor Author

@crimsonfaith91 crimsonfaith91 Aug 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the original codes, namespace may be different from accessor.GetNamespace().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will verify whether they are the same, and remove Accessor codes if so.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they should be the same, since the logic chain is
parameters<name, namespace> -> obj -> accessor -> GetNamespace()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted! Thanks for confirming - let me remove the Accessor codes.

@@ -3627,7 +3680,7 @@ run_stateful_set_tests() {
# Pre-condition: no statefulset exists
kube::test::get_object_assert statefulset "{{range.items}}{{$id_field}}:{{end}}" ''
# Command: create statefulset
kubectl create -f hack/testdata/nginx-statefulset.yaml "${kube_flags[@]}"
kubectl create -f hack/testdata/rollingupdate-statefulset.yaml "${kube_flags[@]}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious why changing this?
If hack/testdata/nginx-statefulset.yaml is no longer needed, please delete it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initally planned to reuse nginx-statefulset.yaml, but found out that updateStrategy of the spec has to be changed. I am not sure whether it is fine to change existing YAML test files, so i created a new one.

I will remove nginx-statefulset.yaml if it is not used at other places.


image_field0="(index .spec.template.spec.containers 0).image"
image_field1="(index .spec.template.spec.containers 1).image"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove white space

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure!

- -c
- 'while true; do sleep 1; done'


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove unnecessary white space and newline.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup! i will remove it - it is an issue with my text editor.

- -c
- 'while true; do sleep 1; done'


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove unnecessary white space and newline.

@crimsonfaith91 crimsonfaith91 force-pushed the rollout branch 2 times, most recently from 198217f to 0bbd6dc Compare August 18, 2017 20:50
@crimsonfaith91
Copy link
Contributor Author

@mengqiy Addressed your feedback. Thanks! :)

@janetkuo
Copy link
Member

Do you have any idea why adding --record flag does not store controllerrevision info in statefulset metadata.annotations? The YAML file that creates statefulset for testing purpose can be found here. Thanks!

Regarding --record it probably has something to do with how kubectl apply handles --record (e.g. apply the patch first and then apply the recorded commands separately). I'll take a look.

@@ -0,0 +1,25 @@
apiVersion: apps/v1beta1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use apps/v1beta2 instead so that we make sure apps/v1beta2 StatefulSet works?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. It makes sense to use apps/v1beta2 as we are migrating to it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you change the rollingupdate-daemonset yaml files (under testdata) to apps/v1beta2 as well while you're at it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup! we should also do so for deployment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you change the rollingupdate-daemonset yaml files (under testdata) to apps/v1beta2 as well while you're at it?

Actually, we can do this separately in another PR. I'll file a PR for this, you just need to modify the statefulset manifest to use apps/v1beta2

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya, let's do it in another PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I filed #51061 for manifests other than StatefulSet

daemonset_image_field0="(index .spec.template.spec.containers 0).image"
daemonset_image_field1="(index .spec.template.spec.containers 1).image"
image_field0="(index .spec.template.spec.containers 0).image"
image_field1="(index .spec.template.spec.containers 1).image"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can replace deployment_image_field and deployment_second_image_field with these two as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted!

terminationGracePeriodSeconds: 5
containers:
- name: kubernetes-pause
image: gcr.io/google-containers/pause:latest
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use gcr.io/google_containers/nginx-slim:0.7 for this and gcr.io/google_containers/nginx-slim:0.8 for rv2 (since the name is nginx)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

noted!

# Update the statefulset (revision 2)
kubectl apply -f hack/testdata/rollingupdate-statefulset-rv2.yaml --record "${kube_flags[@]}"
kube::test::wait_object_assert statefulset "{{range.items}}{{$image_field0}}:{{end}}" "${IMAGE_STATEFULSET_R2}:"
kube::test::get_object_assert statefulset "{{range.items}}{{$container_len}}{{end}}" "1"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In DaemonSet history test I put 1 container in v1 and 2 containers in v2 intentionally, so that I can test if the apply and rollback work. Then this part is to make sure the number of containers is correct. Would you change it accordingly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't manage to get 2 containers into the statefulset YAML file a few weeks ago. Let me try again. :)

versionedAppsClient := versionedAppsClientV1beta1(h.c)
ds, allHistory, err := controlledHistories(versionedExtensionsClient, versionedAppsClient, namespace, name)
versionedExtensionsClient := versionedExtensionsClientV1beta1(h.c)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change isn't necessary (unless there's a reason to move it?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I switched the order that puts versionedExtensionsClient before versionedAppsClient. There are 2 reasons behind:
(1) it is alphabetically ordered for having versionedAppsClient before versionedExtensionsClient
(2) controlledHistories function brings argument in the order of versionedAppsClient and then versionedExtensionsClient

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay

return nil, nil, fmt.Errorf("failed to retrieve StatefulSet %s: %v", name, err)
}
labelSelector = ss.Spec.Selector
obj = ss
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a default case and return error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure!

versionedDS, allHistory, err := controlledHistories(versionedExtensionsClient, versionedAppsClient, ds.Namespace, ds.Name)
versionedExtensionsClient := versionedExtensionsClientV1beta1(r.c)
versionedObj, allHistory, err := controlledHistories(versionedAppsClient, versionedExtensionsClient, ds.Namespace, ds.Name, "DaemonSet")
versionedDS := versionedObj.(*externalextensions.DaemonSet)
if err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error check should be done immediately after where err is returned

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sense!

versionedDS, allHistory, err := controlledHistories(versionedExtensionsClient, versionedAppsClient, ds.Namespace, ds.Name)
versionedExtensionsClient := versionedExtensionsClientV1beta1(r.c)
versionedObj, allHistory, err := controlledHistories(versionedAppsClient, versionedExtensionsClient, ds.Namespace, ds.Name, "DaemonSet")
versionedDS := versionedObj.(*externalextensions.DaemonSet)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will panic if versionedObj is not a *externalextensions.DaemonSet. It's probably okay, but it'll be safer to do something like:

versionedDS, ok := versionedObj.(*externalextensions.DaemonSet)
// return an error if !ok

Same comment for the other type assertion in this PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted! Thanks for pointing it out - this is very important as i use type assertion frequently.

}

// toRevision is a non-negative integer, with 0 being reserved to indicate rolling back to previous configuration
func (r *StatefulSetRollbacker) Rollback(obj runtime.Object, updatedAnnotations map[string]string, toRevision int64, dryRun bool) (string, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of code duplication with (r *DaemonSetRollbacker) Rollback. Would you de-duplicate it (or at least part of it)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! i will carry out the de-duplication using polymorphism runtime.Object.

@janetkuo
Copy link
Member

@crimsonfaith91 there's a bug in StatefulSet update validation which caused changing the number of containers impossible for StatefulSets. I filed a patch to fix it: #51051

k8s-github-robot pushed a commit that referenced this pull request Aug 23, 2017
Automatic merge from submit-queue (batch tested with PRs 50980, 46902, 51051, 51062, 51020)

Fix StatefulSet update validation

StatefulSet update validation did not allow change to number of containers in pod template. Fix this bug so that it's possible to make this kind of change. 

Found it when suggesting test-cmd changes in #49674.

@kubernetes/sig-apps-pr-reviews @smarterclayton 

/approve no-issue
@crimsonfaith91 crimsonfaith91 force-pushed the rollout branch 2 times, most recently from d926e1b to a7b51ac Compare August 23, 2017 17:45
@@ -39,3 +26,12 @@ spec:
- sh
- -c
- 'while true; do sleep 1; done'
- name: nginx-2
image: gcr.io/google_containers/nginx-slim:0.8
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you update nginx to gcr.io/google_containers/nginx-slim:0.8 and add another container (e.g. gcr.io/google-containers/pause:2.0).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure!

kube::test::get_object_assert statefulset "{{range.items}}{{$id_field}}:{{end}}" ''

# Command: create a StatefulSet (revision 1)
kubectl apply -f hack/testdata/rollingupdate-statefulset.yaml --record "${kube_flags[@]}"
Copy link
Member

@janetkuo janetkuo Aug 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried --record locally and it did work. We need to verify controllerrevisions' annotations here first, otherwise this test might be flaky (when undo is called before StS controller creates controllerrevisions)

@@ -3007,10 +3007,10 @@ run_daemonset_history_tests() {
# Command
# Create a DaemonSet (revision 1)
kubectl apply -f hack/testdata/rollingupdate-daemonset.yaml --record "${kube_flags[@]}"
kube::test::get_object_assert controllerrevisions "{{range.items}}{{$annotations_field}}:{{end}}" ".*rollingupdate-daemonset.yaml --record.*"
kube::test::wait_object_assert controllerrevisions "{{range.items}}{{$annotations_field}}:{{end}}" ".*rollingupdate-daemonset.yaml --record.*"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@janetkuo We have to change get_object_assert to wait_object_assert here. :)

command:
- sh
- -c
- 'while true; do sleep 1; done'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't run these commands in pause. Just remove them.

- sh
- -c
- 'while true; do sleep 1; done'
- name: nginx-2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name it pause instead

kube::test::get_object_assert statefulset "{{range.items}}{{$container_len}}{{end}}" "2"
# Clean up - delete newest configuration
kubectl delete -f hack/testdata/rollingupdate-statefulset-rv2.yaml "${kube_flags[@]}"
# Post-condition: no pods from statefulset controller
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the redundant space in the beginning

@@ -175,7 +175,7 @@ func (h *DaemonSetHistoryViewer) ViewHistory(namespace, name string, revision in
if !ok {
return "", fmt.Errorf("unable to find the specified revision")
}
dsOfHistory, err := applyHistory(ds, history)
dsOfHistory, err := applyHistory(versionedObj.(*extensionsv1beta1.DaemonSet), history)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the check I suggested to make sure it won't panic

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i will check to ensure i didn't miss this in other places.

labelSelector = ss.Spec.Selector
obj = ss
default:
return nil, nil, fmt.Errorf("undefined API object kind: %s", kind)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"unsupported", not undefined

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya, as the switch case is not exhaustive, unsupported is a better word.

if err != nil {
return "", fmt.Errorf("unable to find history controlled by DaemonSet %s: %v", ds.Name, err)
}
versionedDS, ok := versionedObj.(*externalextensions.DaemonSet)
if !ok {
return "", fmt.Errorf("unable to perform type assertion for DaemonSet %s", ds.Name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If !ok, it means that the value doesn't hold the type. So the error message should say that the thing is not of DaemonSet type. Something like "unexpected non-DaemonSet object returned: %v", versionedDS.

Same for other type assertion error messages.

if h.Revision == toRevision {
// If toRevision != 0, find the history with matching revision
toHistory = h
break
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is extracted into a function, you can replace the above 2 lines with return h

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM

if toRevision == 0 {
// If toRevision == 0, find the latest revision (2nd max)
sort.Sort(historiesByRevision(allHistory))
toHistory = allHistory[len(allHistory)-2]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is now a function, you should return an error when len(allHistory) <= 1. The callers already checked it, but it's safer to check it again, so that future callers won't cause a panic (index out of range).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For len(allHistory) == 0, we should return nil.
For len(allHistory) == 1, we should return allHistory[0].

Copy link
Member

@janetkuo janetkuo Aug 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, you have to return nil for both cases. findHistory finds the history of a specific revision number. If there's only one history (let's say it's rv 5), and I asked for rv 10, you should return me nil instead of blindly return me whatever history you have.

Please add godoc for findHistory as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or you can check if allHistory[0].Revision == toRevision when the length is 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i thought about this, but the original check is shorter:

if toRevision == 0 && len(allHistory) <= 1 {

return toHistory
}

func isPodTemplateConvertible(specTemplate *v1.PodTemplateSpec) (string, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name is misleading. This function doesn't check if the given template is convertible, but converts and prints the v1 template in api template format. Name it "printTemplate" instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will printPodTemplate be better?

}

// findHistory checks whether controller revision exists for rollback purpose
func findHistory(toRevision int64, allHistory []*appsv1beta1.ControllerRevision) *appsv1beta1.ControllerRevision {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An example godoc:

// findHistory returns a controllerrevision of a specific revision from the given controllerrevisions.
// It returns nil if no such controllerrevision exists.
// If toRevision is 0, the last previously used history is returned. 

Copy link
Contributor Author

@crimsonfaith91 crimsonfaith91 Aug 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM

}

// printPodTemplate converts pod template to unversioned before printing out the template
func printPodTemplate(specTemplate *v1.PodTemplateSpec) (string, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// printPodTemplate converts a given pod template into a human-readable string

We convert it first because DescribePodTemplate only accepts internal representation of a pod template. Converting the template isn't the main thing this function does, but printing it is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will change the godoc messages accordingly.

@k8s-ci-robot
Copy link
Contributor

@crimsonfaith91: you cannot LGTM your own PR.

In response to this:

/lgtm

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@janetkuo
Copy link
Member

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Aug 24, 2017
@@ -3041,6 +3044,58 @@ run_daemonset_history_tests() {
set +o errexit
}

run_statefulset_history_tests() {
set -o nounset
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leave this set, and if you want to not fail on certain calls them put them in an "if"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i follow the template of run_daemonset_history_tests: https://github.com/kubernetes/kubernetes/blob/master/hack/make-rules/test-cmd-util.sh#L2998

If we are to remove this line for statefulset, we should also do so for daemonset.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

@spxtr
Copy link
Contributor

spxtr commented Aug 25, 2017

/approve no-issue

@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: crimsonfaith91, janetkuo, spxtr

Associated issue: 49890

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@k8s-github-robot k8s-github-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 25, 2017
@k8s-github-robot
Copy link

Automatic merge from submit-queue (batch tested with PRs 50033, 49988, 51132, 49674, 51207)

@k8s-github-robot k8s-github-robot merged commit c19785c into kubernetes:master Aug 25, 2017
@crimsonfaith91 crimsonfaith91 deleted the rollout branch August 25, 2017 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/cli Categorizes an issue or PR as relevant to SIG CLI. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

kubectl does not support rollout commands for StatefulSet
9 participants