diff --git a/pkg/kubectl/BUILD b/pkg/kubectl/BUILD index a7a7272663..ca4c7c21e3 100644 --- a/pkg/kubectl/BUILD +++ b/pkg/kubectl/BUILD @@ -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", diff --git a/pkg/kubectl/cmd/rollout/BUILD b/pkg/kubectl/cmd/rollout/BUILD index 95e238cd73..9b3938f713 100644 --- a/pkg/kubectl/cmd/rollout/BUILD +++ b/pkg/kubectl/cmd/rollout/BUILD @@ -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", diff --git a/pkg/kubectl/cmd/rollout/rollout_undo.go b/pkg/kubectl/cmd/rollout/rollout_undo.go index f6f9aa4728..3dd2971264 100644 --- a/pkg/kubectl/cmd/rollout/rollout_undo.go +++ b/pkg/kubectl/cmd/rollout/rollout_undo.go @@ -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" @@ -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...). diff --git a/pkg/kubectl/rollback.go b/pkg/kubectl/rollback.go index 027abadc4f..b883136a6d 100644 --- a/pkg/kubectl/rollback.go +++ b/pkg/kubectl/rollback.go @@ -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" @@ -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 @@ -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, @@ -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 { 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 } @@ -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 "" @@ -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 { @@ -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) } @@ -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 { @@ -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. @@ -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{}