123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915 |
- package util
- import (
- "fmt"
- "math"
- "sort"
- "strconv"
- "strings"
- "time"
- "k8s.io/klog"
- apps "k8s.io/api/apps/v1"
- v1 "k8s.io/api/core/v1"
- apiequality "k8s.io/apimachinery/pkg/api/equality"
- "k8s.io/apimachinery/pkg/api/meta"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/apimachinery/pkg/runtime"
- "k8s.io/apimachinery/pkg/types"
- intstrutil "k8s.io/apimachinery/pkg/util/intstr"
- "k8s.io/apimachinery/pkg/util/wait"
- appsclient "k8s.io/client-go/kubernetes/typed/apps/v1"
- "k8s.io/kubernetes/pkg/controller"
- labelsutil "k8s.io/kubernetes/pkg/util/labels"
- "k8s.io/utils/integer"
- )
- const (
-
- RevisionAnnotation = "deployment.kubernetes.io/revision"
-
- RevisionHistoryAnnotation = "deployment.kubernetes.io/revision-history"
-
-
-
- DesiredReplicasAnnotation = "deployment.kubernetes.io/desired-replicas"
-
-
-
- MaxReplicasAnnotation = "deployment.kubernetes.io/max-replicas"
-
- RollbackRevisionNotFound = "DeploymentRollbackRevisionNotFound"
-
- RollbackTemplateUnchanged = "DeploymentRollbackTemplateUnchanged"
-
- RollbackDone = "DeploymentRollback"
-
-
-
-
-
- ReplicaSetUpdatedReason = "ReplicaSetUpdated"
-
- FailedRSCreateReason = "ReplicaSetCreateError"
-
- NewReplicaSetReason = "NewReplicaSetCreated"
-
- FoundNewRSReason = "FoundNewReplicaSet"
-
-
-
- NewRSAvailableReason = "NewReplicaSetAvailable"
-
-
- TimedOutReason = "ProgressDeadlineExceeded"
-
-
- PausedDeployReason = "DeploymentPaused"
-
-
- ResumedDeployReason = "DeploymentResumed"
-
-
-
- MinimumReplicasAvailable = "MinimumReplicasAvailable"
-
-
- MinimumReplicasUnavailable = "MinimumReplicasUnavailable"
- )
- func NewDeploymentCondition(condType apps.DeploymentConditionType, status v1.ConditionStatus, reason, message string) *apps.DeploymentCondition {
- return &apps.DeploymentCondition{
- Type: condType,
- Status: status,
- LastUpdateTime: metav1.Now(),
- LastTransitionTime: metav1.Now(),
- Reason: reason,
- Message: message,
- }
- }
- func GetDeploymentCondition(status apps.DeploymentStatus, condType apps.DeploymentConditionType) *apps.DeploymentCondition {
- for i := range status.Conditions {
- c := status.Conditions[i]
- if c.Type == condType {
- return &c
- }
- }
- return nil
- }
- func SetDeploymentCondition(status *apps.DeploymentStatus, condition apps.DeploymentCondition) {
- currentCond := GetDeploymentCondition(*status, condition.Type)
- if currentCond != nil && currentCond.Status == condition.Status && currentCond.Reason == condition.Reason {
- return
- }
-
- if currentCond != nil && currentCond.Status == condition.Status {
- condition.LastTransitionTime = currentCond.LastTransitionTime
- }
- newConditions := filterOutCondition(status.Conditions, condition.Type)
- status.Conditions = append(newConditions, condition)
- }
- func RemoveDeploymentCondition(status *apps.DeploymentStatus, condType apps.DeploymentConditionType) {
- status.Conditions = filterOutCondition(status.Conditions, condType)
- }
- func filterOutCondition(conditions []apps.DeploymentCondition, condType apps.DeploymentConditionType) []apps.DeploymentCondition {
- var newConditions []apps.DeploymentCondition
- for _, c := range conditions {
- if c.Type == condType {
- continue
- }
- newConditions = append(newConditions, c)
- }
- return newConditions
- }
- func ReplicaSetToDeploymentCondition(cond apps.ReplicaSetCondition) apps.DeploymentCondition {
- return apps.DeploymentCondition{
- Type: apps.DeploymentConditionType(cond.Type),
- Status: cond.Status,
- LastTransitionTime: cond.LastTransitionTime,
- LastUpdateTime: cond.LastTransitionTime,
- Reason: cond.Reason,
- Message: cond.Message,
- }
- }
- func SetDeploymentRevision(deployment *apps.Deployment, revision string) bool {
- updated := false
- if deployment.Annotations == nil {
- deployment.Annotations = make(map[string]string)
- }
- if deployment.Annotations[RevisionAnnotation] != revision {
- deployment.Annotations[RevisionAnnotation] = revision
- updated = true
- }
- return updated
- }
- func MaxRevision(allRSs []*apps.ReplicaSet) int64 {
- max := int64(0)
- for _, rs := range allRSs {
- if v, err := Revision(rs); err != nil {
-
- klog.V(4).Infof("Error: %v. Couldn't parse revision for replica set %#v, deployment controller will skip it when reconciling revisions.", err, rs)
- } else if v > max {
- max = v
- }
- }
- return max
- }
- func LastRevision(allRSs []*apps.ReplicaSet) int64 {
- max, secMax := int64(0), int64(0)
- for _, rs := range allRSs {
- if v, err := Revision(rs); err != nil {
-
- klog.V(4).Infof("Error: %v. Couldn't parse revision for replica set %#v, deployment controller will skip it when reconciling revisions.", err, rs)
- } else if v >= max {
- secMax = max
- max = v
- } else if v > secMax {
- secMax = v
- }
- }
- return secMax
- }
- func Revision(obj runtime.Object) (int64, error) {
- acc, err := meta.Accessor(obj)
- if err != nil {
- return 0, err
- }
- v, ok := acc.GetAnnotations()[RevisionAnnotation]
- if !ok {
- return 0, nil
- }
- return strconv.ParseInt(v, 10, 64)
- }
- func SetNewReplicaSetAnnotations(deployment *apps.Deployment, newRS *apps.ReplicaSet, newRevision string, exists bool, revHistoryLimitInChars int) bool {
-
- annotationChanged := copyDeploymentAnnotationsToReplicaSet(deployment, newRS)
-
- if newRS.Annotations == nil {
- newRS.Annotations = make(map[string]string)
- }
- oldRevision, ok := newRS.Annotations[RevisionAnnotation]
-
-
-
- oldRevisionInt, err := strconv.ParseInt(oldRevision, 10, 64)
- if err != nil {
- if oldRevision != "" {
- klog.Warningf("Updating replica set revision OldRevision not int %s", err)
- return false
- }
-
- oldRevisionInt = 0
- }
- newRevisionInt, err := strconv.ParseInt(newRevision, 10, 64)
- if err != nil {
- klog.Warningf("Updating replica set revision NewRevision not int %s", err)
- return false
- }
- if oldRevisionInt < newRevisionInt {
- newRS.Annotations[RevisionAnnotation] = newRevision
- annotationChanged = true
- klog.V(4).Infof("Updating replica set %q revision to %s", newRS.Name, newRevision)
- }
-
-
-
- if ok && oldRevisionInt < newRevisionInt {
- revisionHistoryAnnotation := newRS.Annotations[RevisionHistoryAnnotation]
- oldRevisions := strings.Split(revisionHistoryAnnotation, ",")
- if len(oldRevisions[0]) == 0 {
- newRS.Annotations[RevisionHistoryAnnotation] = oldRevision
- } else {
- totalLen := len(revisionHistoryAnnotation) + len(oldRevision) + 1
-
- start := 0
- for totalLen > revHistoryLimitInChars && start < len(oldRevisions) {
- totalLen = totalLen - len(oldRevisions[start]) - 1
- start++
- }
- if totalLen <= revHistoryLimitInChars {
- oldRevisions = append(oldRevisions[start:], oldRevision)
- newRS.Annotations[RevisionHistoryAnnotation] = strings.Join(oldRevisions, ",")
- } else {
- klog.Warningf("Not appending revision due to length limit of %v reached", revHistoryLimitInChars)
- }
- }
- }
-
- if !exists && SetReplicasAnnotations(newRS, *(deployment.Spec.Replicas), *(deployment.Spec.Replicas)+MaxSurge(*deployment)) {
- annotationChanged = true
- }
- return annotationChanged
- }
- var annotationsToSkip = map[string]bool{
- v1.LastAppliedConfigAnnotation: true,
- RevisionAnnotation: true,
- RevisionHistoryAnnotation: true,
- DesiredReplicasAnnotation: true,
- MaxReplicasAnnotation: true,
- apps.DeprecatedRollbackTo: true,
- }
- func skipCopyAnnotation(key string) bool {
- return annotationsToSkip[key]
- }
- func copyDeploymentAnnotationsToReplicaSet(deployment *apps.Deployment, rs *apps.ReplicaSet) bool {
- rsAnnotationsChanged := false
- if rs.Annotations == nil {
- rs.Annotations = make(map[string]string)
- }
- for k, v := range deployment.Annotations {
-
-
-
- if skipCopyAnnotation(k) || rs.Annotations[k] == v {
- continue
- }
- rs.Annotations[k] = v
- rsAnnotationsChanged = true
- }
- return rsAnnotationsChanged
- }
- func SetDeploymentAnnotationsTo(deployment *apps.Deployment, rollbackToRS *apps.ReplicaSet) {
- deployment.Annotations = getSkippedAnnotations(deployment.Annotations)
- for k, v := range rollbackToRS.Annotations {
- if !skipCopyAnnotation(k) {
- deployment.Annotations[k] = v
- }
- }
- }
- func getSkippedAnnotations(annotations map[string]string) map[string]string {
- skippedAnnotations := make(map[string]string)
- for k, v := range annotations {
- if skipCopyAnnotation(k) {
- skippedAnnotations[k] = v
- }
- }
- return skippedAnnotations
- }
- func FindActiveOrLatest(newRS *apps.ReplicaSet, oldRSs []*apps.ReplicaSet) *apps.ReplicaSet {
- if newRS == nil && len(oldRSs) == 0 {
- return nil
- }
- sort.Sort(sort.Reverse(controller.ReplicaSetsByCreationTimestamp(oldRSs)))
- allRSs := controller.FilterActiveReplicaSets(append(oldRSs, newRS))
- switch len(allRSs) {
- case 0:
-
- if newRS != nil {
- return newRS
- }
- return oldRSs[0]
- case 1:
- return allRSs[0]
- default:
- return nil
- }
- }
- func GetDesiredReplicasAnnotation(rs *apps.ReplicaSet) (int32, bool) {
- return getIntFromAnnotation(rs, DesiredReplicasAnnotation)
- }
- func getMaxReplicasAnnotation(rs *apps.ReplicaSet) (int32, bool) {
- return getIntFromAnnotation(rs, MaxReplicasAnnotation)
- }
- func getIntFromAnnotation(rs *apps.ReplicaSet, annotationKey string) (int32, bool) {
- annotationValue, ok := rs.Annotations[annotationKey]
- if !ok {
- return int32(0), false
- }
- intValue, err := strconv.Atoi(annotationValue)
- if err != nil {
- klog.V(2).Infof("Cannot convert the value %q with annotation key %q for the replica set %q", annotationValue, annotationKey, rs.Name)
- return int32(0), false
- }
- return int32(intValue), true
- }
- func SetReplicasAnnotations(rs *apps.ReplicaSet, desiredReplicas, maxReplicas int32) bool {
- updated := false
- if rs.Annotations == nil {
- rs.Annotations = make(map[string]string)
- }
- desiredString := fmt.Sprintf("%d", desiredReplicas)
- if hasString := rs.Annotations[DesiredReplicasAnnotation]; hasString != desiredString {
- rs.Annotations[DesiredReplicasAnnotation] = desiredString
- updated = true
- }
- maxString := fmt.Sprintf("%d", maxReplicas)
- if hasString := rs.Annotations[MaxReplicasAnnotation]; hasString != maxString {
- rs.Annotations[MaxReplicasAnnotation] = maxString
- updated = true
- }
- return updated
- }
- func ReplicasAnnotationsNeedUpdate(rs *apps.ReplicaSet, desiredReplicas, maxReplicas int32) bool {
- if rs.Annotations == nil {
- return true
- }
- desiredString := fmt.Sprintf("%d", desiredReplicas)
- if hasString := rs.Annotations[DesiredReplicasAnnotation]; hasString != desiredString {
- return true
- }
- maxString := fmt.Sprintf("%d", maxReplicas)
- if hasString := rs.Annotations[MaxReplicasAnnotation]; hasString != maxString {
- return true
- }
- return false
- }
- func MaxUnavailable(deployment apps.Deployment) int32 {
- if !IsRollingUpdate(&deployment) || *(deployment.Spec.Replicas) == 0 {
- return int32(0)
- }
-
- _, maxUnavailable, _ := ResolveFenceposts(deployment.Spec.Strategy.RollingUpdate.MaxSurge, deployment.Spec.Strategy.RollingUpdate.MaxUnavailable, *(deployment.Spec.Replicas))
- if maxUnavailable > *deployment.Spec.Replicas {
- return *deployment.Spec.Replicas
- }
- return maxUnavailable
- }
- func MinAvailable(deployment *apps.Deployment) int32 {
- if !IsRollingUpdate(deployment) {
- return int32(0)
- }
- return *(deployment.Spec.Replicas) - MaxUnavailable(*deployment)
- }
- func MaxSurge(deployment apps.Deployment) int32 {
- if !IsRollingUpdate(&deployment) {
- return int32(0)
- }
-
- maxSurge, _, _ := ResolveFenceposts(deployment.Spec.Strategy.RollingUpdate.MaxSurge, deployment.Spec.Strategy.RollingUpdate.MaxUnavailable, *(deployment.Spec.Replicas))
- return maxSurge
- }
- func GetProportion(rs *apps.ReplicaSet, d apps.Deployment, deploymentReplicasToAdd, deploymentReplicasAdded int32) int32 {
- if rs == nil || *(rs.Spec.Replicas) == 0 || deploymentReplicasToAdd == 0 || deploymentReplicasToAdd == deploymentReplicasAdded {
- return int32(0)
- }
- rsFraction := getReplicaSetFraction(*rs, d)
- allowed := deploymentReplicasToAdd - deploymentReplicasAdded
- if deploymentReplicasToAdd > 0 {
-
-
-
- return integer.Int32Min(rsFraction, allowed)
- }
-
-
-
- return integer.Int32Max(rsFraction, allowed)
- }
- func getReplicaSetFraction(rs apps.ReplicaSet, d apps.Deployment) int32 {
-
- if *(d.Spec.Replicas) == int32(0) {
- return -*(rs.Spec.Replicas)
- }
- deploymentReplicas := *(d.Spec.Replicas) + MaxSurge(d)
- annotatedReplicas, ok := getMaxReplicasAnnotation(&rs)
- if !ok {
-
-
-
-
- annotatedReplicas = d.Status.Replicas
- }
-
-
- newRSsize := (float64(*(rs.Spec.Replicas) * deploymentReplicas)) / float64(annotatedReplicas)
- return integer.RoundToInt32(newRSsize) - *(rs.Spec.Replicas)
- }
- func GetAllReplicaSets(deployment *apps.Deployment, c appsclient.AppsV1Interface) ([]*apps.ReplicaSet, []*apps.ReplicaSet, *apps.ReplicaSet, error) {
- rsList, err := ListReplicaSets(deployment, RsListFromClient(c))
- if err != nil {
- return nil, nil, nil, err
- }
- oldRSes, allOldRSes := FindOldReplicaSets(deployment, rsList)
- newRS := FindNewReplicaSet(deployment, rsList)
- return oldRSes, allOldRSes, newRS, nil
- }
- func GetOldReplicaSets(deployment *apps.Deployment, c appsclient.AppsV1Interface) ([]*apps.ReplicaSet, []*apps.ReplicaSet, error) {
- rsList, err := ListReplicaSets(deployment, RsListFromClient(c))
- if err != nil {
- return nil, nil, err
- }
- oldRSes, allOldRSes := FindOldReplicaSets(deployment, rsList)
- return oldRSes, allOldRSes, nil
- }
- func GetNewReplicaSet(deployment *apps.Deployment, c appsclient.AppsV1Interface) (*apps.ReplicaSet, error) {
- rsList, err := ListReplicaSets(deployment, RsListFromClient(c))
- if err != nil {
- return nil, err
- }
- return FindNewReplicaSet(deployment, rsList), nil
- }
- func RsListFromClient(c appsclient.AppsV1Interface) RsListFunc {
- return func(namespace string, options metav1.ListOptions) ([]*apps.ReplicaSet, error) {
- rsList, err := c.ReplicaSets(namespace).List(options)
- if err != nil {
- return nil, err
- }
- var ret []*apps.ReplicaSet
- for i := range rsList.Items {
- ret = append(ret, &rsList.Items[i])
- }
- return ret, err
- }
- }
- type RsListFunc func(string, metav1.ListOptions) ([]*apps.ReplicaSet, error)
- // podListFunc returns the PodList from the Pod namespace and the List metav1.ListOptions.
- type podListFunc func(string, metav1.ListOptions) (*v1.PodList, error)
- // ListReplicaSets returns a slice of RSes the given deployment targets.
- // Note that this does NOT attempt to reconcile ControllerRef (adopt/orphan),
- // because only the controller itself should do that.
- // However, it does filter out anything whose ControllerRef doesn't match.
- func ListReplicaSets(deployment *apps.Deployment, getRSList RsListFunc) ([]*apps.ReplicaSet, error) {
-
-
- namespace := deployment.Namespace
- selector, err := metav1.LabelSelectorAsSelector(deployment.Spec.Selector)
- if err != nil {
- return nil, err
- }
- options := metav1.ListOptions{LabelSelector: selector.String()}
- all, err := getRSList(namespace, options)
- if err != nil {
- return nil, err
- }
-
- owned := make([]*apps.ReplicaSet, 0, len(all))
- for _, rs := range all {
- if metav1.IsControlledBy(rs, deployment) {
- owned = append(owned, rs)
- }
- }
- return owned, nil
- }
- func ListPods(deployment *apps.Deployment, rsList []*apps.ReplicaSet, getPodList podListFunc) (*v1.PodList, error) {
- namespace := deployment.Namespace
- selector, err := metav1.LabelSelectorAsSelector(deployment.Spec.Selector)
- if err != nil {
- return nil, err
- }
- options := metav1.ListOptions{LabelSelector: selector.String()}
- all, err := getPodList(namespace, options)
- if err != nil {
- return all, err
- }
-
-
- rsMap := make(map[types.UID]bool, len(rsList))
- for _, rs := range rsList {
- rsMap[rs.UID] = true
- }
- owned := &v1.PodList{Items: make([]v1.Pod, 0, len(all.Items))}
- for i := range all.Items {
- pod := &all.Items[i]
- controllerRef := metav1.GetControllerOf(pod)
- if controllerRef != nil && rsMap[controllerRef.UID] {
- owned.Items = append(owned.Items, *pod)
- }
- }
- return owned, nil
- }
- func EqualIgnoreHash(template1, template2 *v1.PodTemplateSpec) bool {
- t1Copy := template1.DeepCopy()
- t2Copy := template2.DeepCopy()
-
- delete(t1Copy.Labels, apps.DefaultDeploymentUniqueLabelKey)
- delete(t2Copy.Labels, apps.DefaultDeploymentUniqueLabelKey)
- return apiequality.Semantic.DeepEqual(t1Copy, t2Copy)
- }
- func FindNewReplicaSet(deployment *apps.Deployment, rsList []*apps.ReplicaSet) *apps.ReplicaSet {
- sort.Sort(controller.ReplicaSetsByCreationTimestamp(rsList))
- for i := range rsList {
- if EqualIgnoreHash(&rsList[i].Spec.Template, &deployment.Spec.Template) {
-
-
-
-
- return rsList[i]
- }
- }
-
- return nil
- }
- func FindOldReplicaSets(deployment *apps.Deployment, rsList []*apps.ReplicaSet) ([]*apps.ReplicaSet, []*apps.ReplicaSet) {
- var requiredRSs []*apps.ReplicaSet
- var allRSs []*apps.ReplicaSet
- newRS := FindNewReplicaSet(deployment, rsList)
- for _, rs := range rsList {
-
- if newRS != nil && rs.UID == newRS.UID {
- continue
- }
- allRSs = append(allRSs, rs)
- if *(rs.Spec.Replicas) != 0 {
- requiredRSs = append(requiredRSs, rs)
- }
- }
- return requiredRSs, allRSs
- }
- func SetFromReplicaSetTemplate(deployment *apps.Deployment, template v1.PodTemplateSpec) *apps.Deployment {
- deployment.Spec.Template.ObjectMeta = template.ObjectMeta
- deployment.Spec.Template.Spec = template.Spec
- deployment.Spec.Template.ObjectMeta.Labels = labelsutil.CloneAndRemoveLabel(
- deployment.Spec.Template.ObjectMeta.Labels,
- apps.DefaultDeploymentUniqueLabelKey)
- return deployment
- }
- func GetReplicaCountForReplicaSets(replicaSets []*apps.ReplicaSet) int32 {
- totalReplicas := int32(0)
- for _, rs := range replicaSets {
- if rs != nil {
- totalReplicas += *(rs.Spec.Replicas)
- }
- }
- return totalReplicas
- }
- func GetActualReplicaCountForReplicaSets(replicaSets []*apps.ReplicaSet) int32 {
- totalActualReplicas := int32(0)
- for _, rs := range replicaSets {
- if rs != nil {
- totalActualReplicas += rs.Status.Replicas
- }
- }
- return totalActualReplicas
- }
- func GetReadyReplicaCountForReplicaSets(replicaSets []*apps.ReplicaSet) int32 {
- totalReadyReplicas := int32(0)
- for _, rs := range replicaSets {
- if rs != nil {
- totalReadyReplicas += rs.Status.ReadyReplicas
- }
- }
- return totalReadyReplicas
- }
- func GetAvailableReplicaCountForReplicaSets(replicaSets []*apps.ReplicaSet) int32 {
- totalAvailableReplicas := int32(0)
- for _, rs := range replicaSets {
- if rs != nil {
- totalAvailableReplicas += rs.Status.AvailableReplicas
- }
- }
- return totalAvailableReplicas
- }
- func IsRollingUpdate(deployment *apps.Deployment) bool {
- return deployment.Spec.Strategy.Type == apps.RollingUpdateDeploymentStrategyType
- }
- func DeploymentComplete(deployment *apps.Deployment, newStatus *apps.DeploymentStatus) bool {
- return newStatus.UpdatedReplicas == *(deployment.Spec.Replicas) &&
- newStatus.Replicas == *(deployment.Spec.Replicas) &&
- newStatus.AvailableReplicas == *(deployment.Spec.Replicas) &&
- newStatus.ObservedGeneration >= deployment.Generation
- }
- func DeploymentProgressing(deployment *apps.Deployment, newStatus *apps.DeploymentStatus) bool {
- oldStatus := deployment.Status
-
- oldStatusOldReplicas := oldStatus.Replicas - oldStatus.UpdatedReplicas
- newStatusOldReplicas := newStatus.Replicas - newStatus.UpdatedReplicas
- return (newStatus.UpdatedReplicas > oldStatus.UpdatedReplicas) ||
- (newStatusOldReplicas < oldStatusOldReplicas) ||
- newStatus.ReadyReplicas > deployment.Status.ReadyReplicas ||
- newStatus.AvailableReplicas > deployment.Status.AvailableReplicas
- }
- var nowFn = func() time.Time { return time.Now() }
- func DeploymentTimedOut(deployment *apps.Deployment, newStatus *apps.DeploymentStatus) bool {
- if !HasProgressDeadline(deployment) {
- return false
- }
-
-
-
- condition := GetDeploymentCondition(*newStatus, apps.DeploymentProgressing)
- if condition == nil {
- return false
- }
-
-
-
-
-
-
-
-
-
-
-
- if condition.Reason == NewRSAvailableReason {
- return false
- }
- if condition.Reason == TimedOutReason {
- return true
- }
-
-
-
- from := condition.LastUpdateTime
- now := nowFn()
- delta := time.Duration(*deployment.Spec.ProgressDeadlineSeconds) * time.Second
- timedOut := from.Add(delta).Before(now)
- klog.V(4).Infof("Deployment %q timed out (%t) [last progress check: %v - now: %v]", deployment.Name, timedOut, from, now)
- return timedOut
- }
- func NewRSNewReplicas(deployment *apps.Deployment, allRSs []*apps.ReplicaSet, newRS *apps.ReplicaSet) (int32, error) {
- switch deployment.Spec.Strategy.Type {
- case apps.RollingUpdateDeploymentStrategyType:
-
- maxSurge, err := intstrutil.GetValueFromIntOrPercent(deployment.Spec.Strategy.RollingUpdate.MaxSurge, int(*(deployment.Spec.Replicas)), true)
- if err != nil {
- return 0, err
- }
-
- currentPodCount := GetReplicaCountForReplicaSets(allRSs)
- maxTotalPods := *(deployment.Spec.Replicas) + int32(maxSurge)
- if currentPodCount >= maxTotalPods {
-
- return *(newRS.Spec.Replicas), nil
- }
-
- scaleUpCount := maxTotalPods - currentPodCount
-
- scaleUpCount = int32(integer.IntMin(int(scaleUpCount), int(*(deployment.Spec.Replicas)-*(newRS.Spec.Replicas))))
- return *(newRS.Spec.Replicas) + scaleUpCount, nil
- case apps.RecreateDeploymentStrategyType:
- return *(deployment.Spec.Replicas), nil
- default:
- return 0, fmt.Errorf("deployment type %v isn't supported", deployment.Spec.Strategy.Type)
- }
- }
- func IsSaturated(deployment *apps.Deployment, rs *apps.ReplicaSet) bool {
- if rs == nil {
- return false
- }
- desiredString := rs.Annotations[DesiredReplicasAnnotation]
- desired, err := strconv.Atoi(desiredString)
- if err != nil {
- return false
- }
- return *(rs.Spec.Replicas) == *(deployment.Spec.Replicas) &&
- int32(desired) == *(deployment.Spec.Replicas) &&
- rs.Status.AvailableReplicas == *(deployment.Spec.Replicas)
- }
- func WaitForObservedDeployment(getDeploymentFunc func() (*apps.Deployment, error), desiredGeneration int64, interval, timeout time.Duration) error {
-
- return wait.PollImmediate(interval, timeout, func() (bool, error) {
- deployment, err := getDeploymentFunc()
- if err != nil {
- return false, err
- }
- return deployment.Status.ObservedGeneration >= desiredGeneration, nil
- })
- }
- func ResolveFenceposts(maxSurge, maxUnavailable *intstrutil.IntOrString, desired int32) (int32, int32, error) {
- surge, err := intstrutil.GetValueFromIntOrPercent(intstrutil.ValueOrDefault(maxSurge, intstrutil.FromInt(0)), int(desired), true)
- if err != nil {
- return 0, 0, err
- }
- unavailable, err := intstrutil.GetValueFromIntOrPercent(intstrutil.ValueOrDefault(maxUnavailable, intstrutil.FromInt(0)), int(desired), false)
- if err != nil {
- return 0, 0, err
- }
- if surge == 0 && unavailable == 0 {
-
-
-
-
- unavailable = 1
- }
- return int32(surge), int32(unavailable), nil
- }
- func HasProgressDeadline(d *apps.Deployment) bool {
- return d.Spec.ProgressDeadlineSeconds != nil && *d.Spec.ProgressDeadlineSeconds != math.MaxInt32
- }
- func HasRevisionHistoryLimit(d *apps.Deployment) bool {
- return d.Spec.RevisionHistoryLimit != nil && *d.Spec.RevisionHistoryLimit != math.MaxInt32
- }
|