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

kubectl rollback: remove legacyscheme dependency #69413

Merged
merged 1 commit into from
Oct 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 0 additions & 2 deletions pkg/kubectl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,9 @@ go_library(
],
importpath = "k8s.io/kubernetes/pkg/kubectl",
deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/api/v1/pod:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/core/v1:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/controller/deployment/util:go_default_library",
"//pkg/credentialprovider:go_default_library",
"//pkg/kubectl/apps:go_default_library",
Expand Down
1 change: 0 additions & 1 deletion pkg/kubectl/cmd/rollout/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ go_library(
"//build/visible_to:pkg_kubectl_cmd_rollout_CONSUMERS",
],
deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/kubectl:go_default_library",
"//pkg/kubectl/cmd/set:go_default_library",
"//pkg/kubectl/cmd/templates:go_default_library",
Expand Down
3 changes: 1 addition & 2 deletions pkg/kubectl/cmd/rollout/rollout_undo.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericclioptions/printers"
"k8s.io/cli-runtime/pkg/genericclioptions/resource"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/scheme"
Expand Down Expand Up @@ -132,7 +131,7 @@ func (o *UndoOptions) Validate() error {

func (o *UndoOptions) RunUndo() error {
r := o.Builder().
WithScheme(legacyscheme.Scheme).
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
NamespaceParam(o.Namespace).DefaultNamespace().
FilenameParam(o.EnforceNamespace, &o.FilenameOptions).
ResourceTypeOrNameArgs(true, o.Resources...).
Expand Down
61 changes: 37 additions & 24 deletions pkg/kubectl/rollback.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
"syscall"

appsv1 "k8s.io/api/apps/v1"
"k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -36,11 +36,10 @@ import (
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/pkg/api/legacyscheme"
api "k8s.io/kubernetes/pkg/apis/core"
apiv1 "k8s.io/kubernetes/pkg/apis/core/v1"
"k8s.io/kubernetes/pkg/apis/extensions"
kapps "k8s.io/kubernetes/pkg/kubectl/apps"
"k8s.io/kubernetes/pkg/kubectl/scheme"
sliceutil "k8s.io/kubernetes/pkg/kubectl/util/slice"
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
// kubectl should not be taking dependencies on logic in the controllers
Expand Down Expand Up @@ -105,18 +104,33 @@ type DeploymentRollbacker struct {
}

func (r *DeploymentRollbacker) Rollback(obj runtime.Object, updatedAnnotations map[string]string, toRevision int64, dryRun bool) (string, error) {
d, ok := obj.(*extensions.Deployment)
if !ok {
return "", fmt.Errorf("passed object is not a Deployment: %#v", obj)
if toRevision < 0 {
return "", revisionNotFoundErr(toRevision)
}
accessor, err := meta.Accessor(obj)
if err != nil {
return "", fmt.Errorf("failed to create accessor for kind %v: %s", obj.GetObjectKind(), err.Error())
}
name := accessor.GetName()
namespace := accessor.GetNamespace()

// TODO: Fix this after kubectl has been removed from core. It is not possible to convert the runtime.Object
// to the external appsv1 Deployment without round-tripping through an internal version of Deployment. We're
// currently getting rid of all internal versions of resources. So we specifically request the appsv1 version
// here. This follows the same pattern as for DaemonSet and StatefulSet.
deployment, err := r.c.AppsV1().Deployments(namespace).Get(name, metav1.GetOptions{})
if err != nil {
return "", fmt.Errorf("failed to retrieve Deployment %s: %v", name, err)
}

if dryRun {
return simpleDryRun(d, r.c, toRevision)
return simpleDryRun(deployment, r.c, toRevision)
}
if d.Spec.Paused {
return "", fmt.Errorf("you cannot rollback a paused deployment; resume it first with 'kubectl rollout resume deployment/%s' and try again", d.Name)
if deployment.Spec.Paused {
return "", fmt.Errorf("you cannot rollback a paused deployment; resume it first with 'kubectl rollout resume deployment/%s' and try again", name)
}
deploymentRollback := &extensionsv1beta1.DeploymentRollback{
Name: d.Name,
Name: name,
UpdatedAnnotations: updatedAnnotations,
RollbackTo: extensionsv1beta1.RollbackConfig{
Revision: toRevision,
Expand All @@ -125,16 +139,19 @@ func (r *DeploymentRollbacker) Rollback(obj runtime.Object, updatedAnnotations m
result := ""

// Get current events
events, err := r.c.CoreV1().Events(d.Namespace).List(metav1.ListOptions{})
events, err := r.c.CoreV1().Events(namespace).List(metav1.ListOptions{})
if err != nil {
return result, err
}
// Do the rollback
if err := r.c.ExtensionsV1beta1().Deployments(d.Namespace).Rollback(deploymentRollback); err != nil {
// TODO: This is DEPRECATED. It should be updated. DaemonSets and StatefulSets implement rollback by
// patching using history (ControllerRevision data). Deployments should probably also implement
// rollback using a patch.
if err := r.c.ExtensionsV1beta1().Deployments(namespace).Rollback(deploymentRollback); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should switch to AppsV1 since extensions is deprecated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

AppsV1 does not have the method "Rollback". Deployment rollback is implemented very differently from DaemonSets and StatefulSets for some reason. I'm going to add a TODO to update the entire Deployment rollback process. But for now, I think we should keep this change as small as possible.

return result, err
}
// Watch for the changes of events
watch, err := r.c.CoreV1().Events(d.Namespace).Watch(metav1.ListOptions{Watch: true, ResourceVersion: events.ResourceVersion})
watch, err := r.c.CoreV1().Events(namespace).Watch(metav1.ListOptions{Watch: true, ResourceVersion: events.ResourceVersion})
if err != nil {
return result, err
}
Expand All @@ -152,7 +169,7 @@ func watchRollbackEvent(w watch.Interface) string {
if !ok {
return ""
}
obj, ok := event.Object.(*api.Event)
obj, ok := event.Object.(*corev1.Event)
if !ok {
w.Stop()
return ""
Expand All @@ -170,7 +187,7 @@ func watchRollbackEvent(w watch.Interface) string {

// isRollbackEvent checks if the input event is about rollback, and returns true and
// related result string back if it is.
func isRollbackEvent(e *api.Event) (bool, string) {
func isRollbackEvent(e *corev1.Event) (bool, string) {
rollbackEventReasons := []string{deploymentutil.RollbackRevisionNotFound, deploymentutil.RollbackTemplateUnchanged, deploymentutil.RollbackDone}
for _, reason := range rollbackEventReasons {
if e.Reason == reason {
Expand All @@ -183,13 +200,9 @@ func isRollbackEvent(e *api.Event) (bool, string) {
return false, ""
}

func simpleDryRun(deployment *extensions.Deployment, c kubernetes.Interface, toRevision int64) (string, error) {
externalDeployment := &appsv1.Deployment{}
if err := legacyscheme.Scheme.Convert(deployment, externalDeployment, nil); err != nil {
return "", fmt.Errorf("failed to convert deployment, %v", err)
}
func simpleDryRun(deployment *appsv1.Deployment, c kubernetes.Interface, toRevision int64) (string, error) {

_, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(externalDeployment, c.AppsV1())
_, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, c.AppsV1())
if err != nil {
return "", fmt.Errorf("failed to retrieve replica sets from deployment %s: %v", deployment.Name, err)
}
Expand All @@ -198,7 +211,7 @@ func simpleDryRun(deployment *extensions.Deployment, c kubernetes.Interface, toR
allRSs = append(allRSs, newRS)
}

revisionToSpec := make(map[int64]*v1.PodTemplateSpec)
revisionToSpec := make(map[int64]*corev1.PodTemplateSpec)
for _, rs := range allRSs {
v, err := deploymentutil.Revision(rs)
if err != nil {
Expand Down Expand Up @@ -382,7 +395,7 @@ func (r *StatefulSetRollbacker) Rollback(obj runtime.Object, updatedAnnotations
return rollbackSuccess, nil
}

var appsCodec = legacyscheme.Codecs.LegacyCodec(appsv1.SchemeGroupVersion)
var appsCodec = scheme.Codecs.LegacyCodec(appsv1.SchemeGroupVersion)

// applyRevision returns a new StatefulSet constructed by restoring the state in revision to set. If the returned error
// is nil, the returned StatefulSet is valid.
Expand Down Expand Up @@ -459,7 +472,7 @@ func findHistory(toRevision int64, allHistory []*appsv1.ControllerRevision) *app
}

// printPodTemplate converts a given pod template into a human-readable string.
func printPodTemplate(specTemplate *v1.PodTemplateSpec) (string, error) {
func printPodTemplate(specTemplate *corev1.PodTemplateSpec) (string, error) {
content := bytes.NewBuffer([]byte{})
w := printersinternal.NewPrefixWriter(content)
internalTemplate := &api.PodTemplateSpec{}
Expand Down