Unverified Commit f4b2abe9 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #66933 from deads2k/kubectl-07-rollout

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. switching rolling update to external clients Switches rolling update to use external clients. This is a pretty strange looking command. @kubernetes/sig-cli-maintainers /assign @soltysh ```release-note NONE ```
parents 0c8fe56e 029b4388
......@@ -877,19 +877,6 @@ func WaitForObservedDeployment(getDeploymentFunc func() (*apps.Deployment, error
})
}
// TODO: remove the duplicate
// WaitForObservedInternalDeployment polls for deployment to be updated so that deployment.Status.ObservedGeneration >= desiredGeneration.
// Returns error if polling timesout.
func WaitForObservedDeploymentInternal(getDeploymentFunc func() (*internalextensions.Deployment, error), desiredGeneration int64, interval, timeout time.Duration) error {
return wait.Poll(interval, timeout, func() (bool, error) {
deployment, err := getDeploymentFunc()
if err != nil {
return false, err
}
return deployment.Status.ObservedGeneration >= desiredGeneration, nil
})
}
// ResolveFenceposts resolves both maxSurge and maxUnavailable. This needs to happen in one
// step. For example:
//
......
......@@ -40,8 +40,7 @@ go_test(
"//pkg/api/testapi:go_default_library",
"//pkg/api/testing:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
"//pkg/kubectl/scheme:go_default_library",
"//pkg/kubectl/util:go_default_library",
"//staging/src/k8s.io/api/apps/v1:go_default_library",
"//staging/src/k8s.io/api/apps/v1beta1:go_default_library",
......@@ -63,8 +62,10 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/client-go/rest:go_default_library",
"//staging/src/k8s.io/client-go/rest/fake:go_default_library",
......@@ -118,9 +119,6 @@ go_library(
"//pkg/apis/core:go_default_library",
"//pkg/apis/core/v1:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/apps/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion:go_default_library",
"//pkg/controller/deployment/util:go_default_library",
"//pkg/credentialprovider:go_default_library",
"//pkg/kubectl/apps:go_default_library",
......@@ -160,6 +158,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
"//staging/src/k8s.io/client-go/rest:go_default_library",
"//staging/src/k8s.io/client-go/scale:go_default_library",
"//staging/src/k8s.io/client-go/util/integer:go_default_library",
......
......@@ -58,7 +58,6 @@ go_library(
deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/kubectl:go_default_library",
"//pkg/kubectl/apply/parse:go_default_library",
"//pkg/kubectl/apply/strategy:go_default_library",
......
......@@ -25,14 +25,14 @@ import (
"github.com/spf13/cobra"
"k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/client-go/kubernetes"
scaleclient "k8s.io/client-go/scale"
"k8s.io/kubernetes/pkg/api/legacyscheme"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
......@@ -99,13 +99,13 @@ type RollingUpdateOptions struct {
EnforceNamespace bool
ScaleClient scaleclient.ScalesGetter
ClientSet internalclientset.Interface
ClientSet kubernetes.Interface
Builder *resource.Builder
ShouldValidate bool
Validator func(bool) (validation.Schema, error)
FindNewName func(*api.ReplicationController) string
FindNewName func(*corev1.ReplicationController) string
PrintFlags *genericclioptions.PrintFlags
ToPrinter func(string) (printers.ResourcePrinter, error)
......@@ -204,7 +204,7 @@ func (o *RollingUpdateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, a
o.ShouldValidate = cmdutil.GetFlagBool(cmd, "validate")
o.Validator = f.Validator
o.FindNewName = func(obj *api.ReplicationController) string {
o.FindNewName = func(obj *corev1.ReplicationController) string {
return findNewName(args, obj)
}
......@@ -219,11 +219,7 @@ func (o *RollingUpdateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, a
return err
}
clientConfig, err := f.ToRESTConfig()
if err != nil {
return err
}
o.ClientSet, err = internalclientset.NewForConfig(clientConfig)
o.ClientSet, err = f.KubernetesClientSet()
if err != nil {
return err
}
......@@ -251,9 +247,9 @@ func (o *RollingUpdateOptions) Run() error {
filename = o.FilenameOptions.Filenames[0]
}
coreClient := o.ClientSet.Core()
coreClient := o.ClientSet.CoreV1()
var newRc *api.ReplicationController
var newRc *corev1.ReplicationController
// fetch rc
oldRc, err := coreClient.ReplicationControllers(o.Namespace).Get(o.OldName, metav1.GetOptions{})
if err != nil {
......@@ -295,7 +291,7 @@ func (o *RollingUpdateOptions) Run() error {
return fmt.Errorf("please make sure %s exists and is not empty", filename)
}
uncastVersionedObj, err := legacyscheme.Scheme.ConvertToVersion(infos[0].Object, v1.SchemeGroupVersion)
uncastVersionedObj, err := scheme.Scheme.ConvertToVersion(infos[0].Object, corev1.SchemeGroupVersion)
if err != nil {
glog.V(4).Infof("Object %T is not a ReplicationController", infos[0].Object)
return fmt.Errorf("%s contains a %v not a ReplicationController", filename, infos[0].Object.GetObjectKind().GroupVersionKind())
......@@ -303,12 +299,7 @@ func (o *RollingUpdateOptions) Run() error {
switch t := uncastVersionedObj.(type) {
case *v1.ReplicationController:
replicasDefaulted = t.Spec.Replicas == nil
// previous code ignored the error. Seem like it's very unlikely to fail, so ok for now.
uncastObj, err := legacyscheme.Scheme.ConvertToVersion(uncastVersionedObj, api.SchemeGroupVersion)
if err == nil {
newRc, _ = uncastObj.(*api.ReplicationController)
}
newRc = t
}
if newRc == nil {
glog.V(4).Infof("Object %T is not a ReplicationController", infos[0].Object)
......@@ -343,7 +334,7 @@ func (o *RollingUpdateOptions) Run() error {
if len(o.PullPolicy) == 0 {
return fmt.Errorf("--image-pull-policy (Always|Never|IfNotPresent) must be provided when --image is the same as existing container image")
}
config.PullPolicy = api.PullPolicy(o.PullPolicy)
config.PullPolicy = corev1.PullPolicy(o.PullPolicy)
}
newRc, err = kubectl.CreateNewControllerFromCurrentController(coreClient, codec, config)
if err != nil {
......@@ -398,7 +389,8 @@ func (o *RollingUpdateOptions) Run() error {
}
// TODO: handle scales during rolling update
if replicasDefaulted {
newRc.Spec.Replicas = oldRc.Spec.Replicas
t := *oldRc.Spec.Replicas
newRc.Spec.Replicas = &t
}
if o.DryRun {
......@@ -467,7 +459,7 @@ func (o *RollingUpdateOptions) Run() error {
return printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(newRc, nil), o.Out)
}
func findNewName(args []string, oldRc *api.ReplicationController) string {
func findNewName(args []string, oldRc *corev1.ReplicationController) string {
if len(args) >= 2 {
return args[1]
}
......
......@@ -25,19 +25,15 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/watch"
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/kubernetes/pkg/api/pod"
podv1 "k8s.io/kubernetes/pkg/api/v1/pod"
"k8s.io/kubernetes/pkg/apis/apps"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/extensions"
appsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion"
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion"
)
// ControllerHasDesiredReplicas returns a condition that will be true if and only if
// the desired replica count for a controller's ReplicaSelector equals the Replicas count.
func ControllerHasDesiredReplicas(rcClient coreclient.ReplicationControllersGetter, controller *api.ReplicationController) wait.ConditionFunc {
func ControllerHasDesiredReplicas(rcClient corev1client.ReplicationControllersGetter, controller *corev1.ReplicationController) wait.ConditionFunc {
// If we're given a controller where the status lags the spec, it either means that the controller is stale,
// or that the rc manager hasn't noticed the update yet. Polling status.Replicas is not safe in the latter case.
......@@ -52,70 +48,7 @@ func ControllerHasDesiredReplicas(rcClient coreclient.ReplicationControllersGett
// or, after this check has passed, a modification causes the rc manager to create more pods.
// This will not be an issue once we've implemented graceful delete for rcs, but till then
// concurrent stop operations on the same rc might have unintended side effects.
return ctrl.Status.ObservedGeneration >= desiredGeneration && ctrl.Status.Replicas == ctrl.Spec.Replicas, nil
}
}
// ReplicaSetHasDesiredReplicas returns a condition that will be true if and only if
// the desired replica count for a ReplicaSet's ReplicaSelector equals the Replicas count.
func ReplicaSetHasDesiredReplicas(rsClient extensionsclient.ReplicaSetsGetter, replicaSet *extensions.ReplicaSet) wait.ConditionFunc {
// If we're given a ReplicaSet where the status lags the spec, it either means that the
// ReplicaSet is stale, or that the ReplicaSet manager hasn't noticed the update yet.
// Polling status.Replicas is not safe in the latter case.
desiredGeneration := replicaSet.Generation
return func() (bool, error) {
rs, err := rsClient.ReplicaSets(replicaSet.Namespace).Get(replicaSet.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
// There's a chance a concurrent update modifies the Spec.Replicas causing this check to
// pass, or, after this check has passed, a modification causes the ReplicaSet manager to
// create more pods. This will not be an issue once we've implemented graceful delete for
// ReplicaSets, but till then concurrent stop operations on the same ReplicaSet might have
// unintended side effects.
return rs.Status.ObservedGeneration >= desiredGeneration && rs.Status.Replicas == rs.Spec.Replicas, nil
}
}
// StatefulSetHasDesiredReplicas returns a condition that checks the number of StatefulSet replicas
func StatefulSetHasDesiredReplicas(ssClient appsclient.StatefulSetsGetter, ss *apps.StatefulSet) wait.ConditionFunc {
// If we're given a StatefulSet where the status lags the spec, it either means that the
// StatefulSet is stale, or that the StatefulSet manager hasn't noticed the update yet.
// Polling status.Replicas is not safe in the latter case.
desiredGeneration := ss.Generation
return func() (bool, error) {
ss, err := ssClient.StatefulSets(ss.Namespace).Get(ss.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
// There's a chance a concurrent update modifies the Spec.Replicas causing this check to
// pass, or, after this check has passed, a modification causes the StatefulSet manager to
// create more pods. This will not be an issue once we've implemented graceful delete for
// StatefulSet, but till then concurrent stop operations on the same StatefulSet might have
// unintended side effects.
return ss.Status.ObservedGeneration != nil && *ss.Status.ObservedGeneration >= desiredGeneration && ss.Status.Replicas == ss.Spec.Replicas, nil
}
}
// DeploymentHasDesiredReplicas returns a condition that will be true if and only if
// the desired replica count for a deployment equals its updated replicas count.
// (non-terminated pods that have the desired template spec).
func DeploymentHasDesiredReplicas(dClient extensionsclient.DeploymentsGetter, deployment *extensions.Deployment) wait.ConditionFunc {
// If we're given a deployment where the status lags the spec, it either
// means that the deployment is stale, or that the deployment manager hasn't
// noticed the update yet. Polling status.Replicas is not safe in the latter
// case.
desiredGeneration := deployment.Generation
return func() (bool, error) {
deployment, err := dClient.Deployments(deployment.Namespace).Get(deployment.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
return deployment.Status.ObservedGeneration >= desiredGeneration &&
deployment.Status.UpdatedReplicas == deployment.Spec.Replicas, nil
return ctrl.Status.ObservedGeneration >= desiredGeneration && ctrl.Status.Replicas == valOrZero(ctrl.Spec.Replicas), nil
}
}
......@@ -220,58 +153,3 @@ func PodNotPending(event watch.Event) (bool, error) {
}
return false, nil
}
// PodContainerRunning returns false until the named container has ContainerStatus running (at least once),
// and will return an error if the pod is deleted, runs to completion, or the container pod is not available.
func PodContainerRunning(containerName string) watch.ConditionFunc {
return func(event watch.Event) (bool, error) {
switch event.Type {
case watch.Deleted:
return false, errors.NewNotFound(schema.GroupResource{Resource: "pods"}, "")
}
switch t := event.Object.(type) {
case *api.Pod:
switch t.Status.Phase {
case api.PodRunning, api.PodPending:
case api.PodFailed, api.PodSucceeded:
return false, ErrPodCompleted
default:
return false, nil
}
for _, s := range t.Status.ContainerStatuses {
if s.Name != containerName {
continue
}
if s.State.Terminated != nil {
return false, ErrContainerTerminated
}
return s.State.Running != nil, nil
}
for _, s := range t.Status.InitContainerStatuses {
if s.Name != containerName {
continue
}
if s.State.Terminated != nil {
return false, ErrContainerTerminated
}
return s.State.Running != nil, nil
}
return false, nil
}
return false, nil
}
}
// ServiceAccountHasSecrets returns true if the service account has at least one secret,
// false if it does not, or an error.
func ServiceAccountHasSecrets(event watch.Event) (bool, error) {
switch event.Type {
case watch.Deleted:
return false, errors.NewNotFound(schema.GroupResource{Resource: "serviceaccounts"}, "")
}
switch t := event.Object.(type) {
case *api.ServiceAccount:
return len(t.Secrets) > 0, nil
}
return false, nil
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment