mirror of https://github.com/openkruise/kruise.git
fix the bug that pub calculates pods(deployment) totalReplicas incorrectly (#1164)
Signed-off-by: liheng.zms <liheng.zms@alibaba-inc.com>
This commit is contained in:
parent
3dd4e7d443
commit
83029a47df
|
|
@ -137,6 +137,7 @@ func (c *commonControl) IsPodStateConsistent(pod *corev1.Pod) bool {
|
|||
sidecarSets, sidecars := getSidecarSetsInPod(pod)
|
||||
if sidecarSets.Len() > 0 && sidecars.Len() > 0 {
|
||||
if !sidecarcontrol.IsSidecarContainerUpdateCompleted(pod, sidecarSets, sidecars) {
|
||||
klog.V(5).Infof("PodUnavailableBudget check Pod(%s/%s) is inconsistent", pod.Namespace, pod.Name)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,95 +176,211 @@ var (
|
|||
func TestPubReconcile(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
getPods func() []*corev1.Pod
|
||||
getPods func(rs ...*apps.ReplicaSet) []*corev1.Pod
|
||||
getDeployment func() *apps.Deployment
|
||||
getReplicaSet func() *apps.ReplicaSet
|
||||
getReplicaSet func() []*apps.ReplicaSet
|
||||
getPub func() *policyv1alpha1.PodUnavailableBudget
|
||||
expectPubStatus func() policyv1alpha1.PodUnavailableBudgetStatus
|
||||
}{
|
||||
{
|
||||
name: "selector no matched deployment",
|
||||
getPods: func() []*corev1.Pod {
|
||||
pod := podDemo.DeepCopy()
|
||||
pod.Labels["pub-controller"] = "false"
|
||||
return []*corev1.Pod{pod}
|
||||
},
|
||||
getDeployment: func() *apps.Deployment {
|
||||
return deploymentDemo.DeepCopy()
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
return replicaSetDemo.DeepCopy()
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
return pubDemo.DeepCopy()
|
||||
},
|
||||
expectPubStatus: func() policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
return policyv1alpha1.PodUnavailableBudgetStatus{}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "selector no matched namespace deployment",
|
||||
getPods: func() []*corev1.Pod {
|
||||
pod := podDemo.DeepCopy()
|
||||
pod.Namespace = "other-ns"
|
||||
return []*corev1.Pod{pod}
|
||||
},
|
||||
getDeployment: func() *apps.Deployment {
|
||||
object := deploymentDemo.DeepCopy()
|
||||
object.Namespace = "other-ns"
|
||||
return object
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
object := replicaSetDemo.DeepCopy()
|
||||
object.Namespace = "other-ns"
|
||||
return object
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
return pubDemo.DeepCopy()
|
||||
},
|
||||
expectPubStatus: func() policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
return policyv1alpha1.PodUnavailableBudgetStatus{}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "select matched deployment, TargetReference and maxUnavailable 30%",
|
||||
getPods: func() []*corev1.Pod {
|
||||
name: "select matched deployment(replicas=0), selector and maxUnavailable 30%",
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; int32(i) < *deploymentDemo.Spec.Replicas; i++ {
|
||||
for i := 0; int32(i) < 5; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
pod.OwnerReferences = []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "ReplicaSet",
|
||||
Name: rs[0].Name,
|
||||
UID: rs[0].UID,
|
||||
Controller: utilpointer.BoolPtr(true),
|
||||
},
|
||||
}
|
||||
pod.Name = fmt.Sprintf("%s-%d", pod.Name, i)
|
||||
matchedPods = append(matchedPods, pod)
|
||||
}
|
||||
for i := 5; int32(i) < 10; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
pod.OwnerReferences = []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "ReplicaSet",
|
||||
Name: rs[1].Name,
|
||||
UID: rs[1].UID,
|
||||
Controller: utilpointer.BoolPtr(true),
|
||||
},
|
||||
}
|
||||
pod.Name = fmt.Sprintf("%s-%d", pod.Name, i)
|
||||
matchedPods = append(matchedPods, pod)
|
||||
}
|
||||
return matchedPods
|
||||
},
|
||||
getDeployment: func() *apps.Deployment {
|
||||
obj := deploymentDemo.DeepCopy()
|
||||
obj.Spec.Replicas = utilpointer.Int32(0)
|
||||
return obj
|
||||
},
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
obj1 := replicaSetDemo.DeepCopy()
|
||||
obj1.Name = "nginx-rs-1"
|
||||
obj2 := replicaSetDemo.DeepCopy()
|
||||
obj2.Name = "nginx-rs-2"
|
||||
obj2.UID = "a34b0453-3426-4685-a79c-752e7062a523"
|
||||
return []*apps.ReplicaSet{obj1, obj2}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
return pub
|
||||
},
|
||||
expectPubStatus: func() policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
return policyv1alpha1.PodUnavailableBudgetStatus{
|
||||
UnavailableAllowed: 10,
|
||||
CurrentAvailable: 10,
|
||||
DesiredAvailable: 0,
|
||||
TotalReplicas: 0,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "select matched deployment(replicas=10,maxSurge=30%,maxUnavailable=0), and pub(selector,maxUnavailable=30%)",
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; int32(i) < 10; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
pod.OwnerReferences = []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "ReplicaSet",
|
||||
Name: rs[0].Name,
|
||||
UID: rs[0].UID,
|
||||
Controller: utilpointer.BoolPtr(true),
|
||||
},
|
||||
}
|
||||
pod.Name = fmt.Sprintf("%s-%d", pod.Name, i)
|
||||
matchedPods = append(matchedPods, pod)
|
||||
}
|
||||
for i := 10; int32(i) < 13; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
pod.OwnerReferences = []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "ReplicaSet",
|
||||
Name: rs[1].Name,
|
||||
UID: rs[1].UID,
|
||||
Controller: utilpointer.BoolPtr(true),
|
||||
},
|
||||
}
|
||||
pod.Name = fmt.Sprintf("%s-%d", pod.Name, i)
|
||||
if i == 12 {
|
||||
pod.Status.Conditions = []corev1.PodCondition{
|
||||
{
|
||||
Type: corev1.PodReady,
|
||||
Status: corev1.ConditionFalse,
|
||||
},
|
||||
}
|
||||
}
|
||||
matchedPods = append(matchedPods, pod)
|
||||
}
|
||||
return matchedPods
|
||||
},
|
||||
getDeployment: func() *apps.Deployment {
|
||||
return deploymentDemo.DeepCopy()
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
return replicaSetDemo.DeepCopy()
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
obj1 := replicaSetDemo.DeepCopy()
|
||||
obj1.Name = "nginx-rs-1"
|
||||
obj2 := replicaSetDemo.DeepCopy()
|
||||
obj2.Name = "nginx-rs-2"
|
||||
obj2.UID = "a34b0453-3426-4685-a79c-752e7062a523"
|
||||
return []*apps.ReplicaSet{obj1, obj2}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
pub.Spec.Selector = nil
|
||||
pub.Spec.TargetReference = &policyv1alpha1.TargetReference{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
}
|
||||
return pub
|
||||
},
|
||||
expectPubStatus: func() policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
return policyv1alpha1.PodUnavailableBudgetStatus{
|
||||
UnavailableAllowed: 3,
|
||||
CurrentAvailable: *deploymentDemo.Spec.Replicas,
|
||||
UnavailableAllowed: 5,
|
||||
CurrentAvailable: 12,
|
||||
DesiredAvailable: 7,
|
||||
TotalReplicas: *deploymentDemo.Spec.Replicas,
|
||||
TotalReplicas: 10,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "select matched deployment(replicas=10,maxSurge=0,maxUnavailable=30%), and pub(selector,maxUnavailable=30%)",
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; int32(i) < 10; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
pod.OwnerReferences = []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "ReplicaSet",
|
||||
Name: rs[0].Name,
|
||||
UID: rs[0].UID,
|
||||
Controller: utilpointer.BoolPtr(true),
|
||||
},
|
||||
}
|
||||
pod.Name = fmt.Sprintf("%s-%d", pod.Name, i)
|
||||
t := metav1.Now()
|
||||
if i >= 7 && i < 10 {
|
||||
pod.DeletionTimestamp = &t
|
||||
}
|
||||
matchedPods = append(matchedPods, pod)
|
||||
}
|
||||
for i := 10; int32(i) < 13; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
pod.OwnerReferences = []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "ReplicaSet",
|
||||
Name: rs[1].Name,
|
||||
UID: rs[1].UID,
|
||||
Controller: utilpointer.BoolPtr(true),
|
||||
},
|
||||
}
|
||||
pod.Name = fmt.Sprintf("%s-%d", pod.Name, i)
|
||||
if i == 12 {
|
||||
pod.Status.Conditions = []corev1.PodCondition{
|
||||
{
|
||||
Type: corev1.PodReady,
|
||||
Status: corev1.ConditionFalse,
|
||||
},
|
||||
}
|
||||
}
|
||||
matchedPods = append(matchedPods, pod)
|
||||
}
|
||||
return matchedPods
|
||||
},
|
||||
getDeployment: func() *apps.Deployment {
|
||||
return deploymentDemo.DeepCopy()
|
||||
},
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
obj1 := replicaSetDemo.DeepCopy()
|
||||
obj1.Name = "nginx-rs-1"
|
||||
obj2 := replicaSetDemo.DeepCopy()
|
||||
obj2.Name = "nginx-rs-2"
|
||||
obj2.UID = "a34b0453-3426-4685-a79c-752e7062a523"
|
||||
return []*apps.ReplicaSet{obj1, obj2}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
return pub
|
||||
},
|
||||
expectPubStatus: func() policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
return policyv1alpha1.PodUnavailableBudgetStatus{
|
||||
UnavailableAllowed: 2,
|
||||
CurrentAvailable: 9,
|
||||
DesiredAvailable: 7,
|
||||
TotalReplicas: 10,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "select matched deployment(Deletion), selector and maxUnavailable 30%",
|
||||
getPods: func() []*corev1.Pod {
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; int32(i) < *deploymentDemo.Spec.Replicas; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
|
|
@ -279,12 +395,11 @@ func TestPubReconcile(t *testing.T) {
|
|||
obj.DeletionTimestamp = &t
|
||||
return obj
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
return replicaSetDemo.DeepCopy()
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
return []*apps.ReplicaSet{replicaSetDemo.DeepCopy()}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
pub.Name = "liheng"
|
||||
return pub
|
||||
},
|
||||
expectPubStatus: func() policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
|
|
@ -296,9 +411,210 @@ func TestPubReconcile(t *testing.T) {
|
|||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "select matched deployment(replicas=0,maxSurge=0,maxUnavailable=30%), and pub(targetRef,maxUnavailable=30%)",
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; int32(i) < 10; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
pod.OwnerReferences = []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "ReplicaSet",
|
||||
Name: rs[0].Name,
|
||||
UID: rs[0].UID,
|
||||
Controller: utilpointer.BoolPtr(true),
|
||||
},
|
||||
}
|
||||
pod.Name = fmt.Sprintf("%s-%d", pod.Name, i)
|
||||
matchedPods = append(matchedPods, pod)
|
||||
}
|
||||
return matchedPods
|
||||
},
|
||||
getDeployment: func() *apps.Deployment {
|
||||
obj := deploymentDemo.DeepCopy()
|
||||
obj.Spec.Replicas = utilpointer.Int32(0)
|
||||
return obj
|
||||
},
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
obj1 := replicaSetDemo.DeepCopy()
|
||||
obj1.Name = "nginx-rs-1"
|
||||
return []*apps.ReplicaSet{obj1}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
pub.Spec.Selector = nil
|
||||
pub.Spec.TargetReference = &policyv1alpha1.TargetReference{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
}
|
||||
return pub
|
||||
},
|
||||
expectPubStatus: func() policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
return policyv1alpha1.PodUnavailableBudgetStatus{
|
||||
UnavailableAllowed: 0,
|
||||
CurrentAvailable: 0,
|
||||
DesiredAvailable: 0,
|
||||
TotalReplicas: 0,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "select matched deployment(replicas=1,maxSurge=0,maxUnavailable=30%), and pub(targetRef,maxUnavailable=30%)",
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; int32(i) < 10; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
pod.OwnerReferences = []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "ReplicaSet",
|
||||
Name: rs[0].Name,
|
||||
UID: rs[0].UID,
|
||||
Controller: utilpointer.BoolPtr(true),
|
||||
},
|
||||
}
|
||||
pod.Name = fmt.Sprintf("%s-%d", pod.Name, i)
|
||||
matchedPods = append(matchedPods, pod)
|
||||
}
|
||||
return matchedPods
|
||||
},
|
||||
getDeployment: func() *apps.Deployment {
|
||||
obj := deploymentDemo.DeepCopy()
|
||||
obj.Spec.Replicas = utilpointer.Int32(1)
|
||||
return obj
|
||||
},
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
obj1 := replicaSetDemo.DeepCopy()
|
||||
obj1.Name = "nginx-rs-1"
|
||||
return []*apps.ReplicaSet{obj1}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
pub.Spec.Selector = nil
|
||||
pub.Spec.TargetReference = &policyv1alpha1.TargetReference{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
}
|
||||
return pub
|
||||
},
|
||||
expectPubStatus: func() policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
return policyv1alpha1.PodUnavailableBudgetStatus{
|
||||
UnavailableAllowed: 10,
|
||||
CurrentAvailable: 10,
|
||||
DesiredAvailable: 0,
|
||||
TotalReplicas: 1,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "select matched deployment(replicas=10,maxSurge=0,maxUnavailable=30%), and pub(targetRef,maxUnavailable=30%)",
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; int32(i) < 10; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
pod.OwnerReferences = []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "ReplicaSet",
|
||||
Name: rs[0].Name,
|
||||
UID: rs[0].UID,
|
||||
Controller: utilpointer.BoolPtr(true),
|
||||
},
|
||||
}
|
||||
if i >= 7 {
|
||||
t := metav1.Now()
|
||||
pod.DeletionTimestamp = &t
|
||||
}
|
||||
pod.Name = fmt.Sprintf("%s-%d", pod.Name, i)
|
||||
matchedPods = append(matchedPods, pod)
|
||||
}
|
||||
return matchedPods
|
||||
},
|
||||
getDeployment: func() *apps.Deployment {
|
||||
obj := deploymentDemo.DeepCopy()
|
||||
obj.Spec.Replicas = utilpointer.Int32(10)
|
||||
return obj
|
||||
},
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
obj1 := replicaSetDemo.DeepCopy()
|
||||
obj1.Name = "nginx-rs-1"
|
||||
return []*apps.ReplicaSet{obj1}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
pub.Spec.Selector = nil
|
||||
pub.Spec.TargetReference = &policyv1alpha1.TargetReference{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
}
|
||||
return pub
|
||||
},
|
||||
expectPubStatus: func() policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
return policyv1alpha1.PodUnavailableBudgetStatus{
|
||||
UnavailableAllowed: 0,
|
||||
CurrentAvailable: 7,
|
||||
DesiredAvailable: 7,
|
||||
TotalReplicas: 10,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "select matched deployment(deletion), and pub(targetRef,maxUnavailable=30%)",
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; int32(i) < 10; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
pod.OwnerReferences = []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "ReplicaSet",
|
||||
Name: rs[0].Name,
|
||||
UID: rs[0].UID,
|
||||
Controller: utilpointer.BoolPtr(true),
|
||||
},
|
||||
}
|
||||
pod.Name = fmt.Sprintf("%s-%d", pod.Name, i)
|
||||
matchedPods = append(matchedPods, pod)
|
||||
}
|
||||
return matchedPods
|
||||
},
|
||||
getDeployment: func() *apps.Deployment {
|
||||
obj := deploymentDemo.DeepCopy()
|
||||
t := metav1.Now()
|
||||
obj.DeletionTimestamp = &t
|
||||
return obj
|
||||
},
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
obj1 := replicaSetDemo.DeepCopy()
|
||||
obj1.Name = "nginx-rs-1"
|
||||
return []*apps.ReplicaSet{obj1}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
pub.Spec.Selector = nil
|
||||
pub.Spec.TargetReference = &policyv1alpha1.TargetReference{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
}
|
||||
return pub
|
||||
},
|
||||
expectPubStatus: func() policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
return policyv1alpha1.PodUnavailableBudgetStatus{
|
||||
UnavailableAllowed: 0,
|
||||
CurrentAvailable: 0,
|
||||
DesiredAvailable: 0,
|
||||
TotalReplicas: 0,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "select matched deployment, maxUnavailable 0%",
|
||||
getPods: func() []*corev1.Pod {
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; int32(i) < *deploymentDemo.Spec.Replicas; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
|
|
@ -310,8 +626,8 @@ func TestPubReconcile(t *testing.T) {
|
|||
getDeployment: func() *apps.Deployment {
|
||||
return deploymentDemo.DeepCopy()
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
return replicaSetDemo.DeepCopy()
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
return []*apps.ReplicaSet{replicaSetDemo.DeepCopy()}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
|
|
@ -332,7 +648,7 @@ func TestPubReconcile(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "select matched deployment, maxUnavailable 100%",
|
||||
getPods: func() []*corev1.Pod {
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; int32(i) < *deploymentDemo.Spec.Replicas; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
|
|
@ -344,8 +660,8 @@ func TestPubReconcile(t *testing.T) {
|
|||
getDeployment: func() *apps.Deployment {
|
||||
return deploymentDemo.DeepCopy()
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
return replicaSetDemo.DeepCopy()
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
return []*apps.ReplicaSet{replicaSetDemo.DeepCopy()}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
|
|
@ -366,7 +682,7 @@ func TestPubReconcile(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "select matched deployment, maxUnavailable 100, and expect scale 10",
|
||||
getPods: func() []*corev1.Pod {
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; int32(i) < *deploymentDemo.Spec.Replicas; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
|
|
@ -378,8 +694,8 @@ func TestPubReconcile(t *testing.T) {
|
|||
getDeployment: func() *apps.Deployment {
|
||||
return deploymentDemo.DeepCopy()
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
return replicaSetDemo.DeepCopy()
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
return []*apps.ReplicaSet{replicaSetDemo.DeepCopy()}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
|
|
@ -400,7 +716,7 @@ func TestPubReconcile(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "select matched deployment, minAvailable 100 int",
|
||||
getPods: func() []*corev1.Pod {
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; i < 5; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
|
|
@ -412,8 +728,8 @@ func TestPubReconcile(t *testing.T) {
|
|||
getDeployment: func() *apps.Deployment {
|
||||
return deploymentDemo.DeepCopy()
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
return replicaSetDemo.DeepCopy()
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
return []*apps.ReplicaSet{replicaSetDemo.DeepCopy()}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
|
|
@ -435,7 +751,7 @@ func TestPubReconcile(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "select matched deployment, minAvailable 50%",
|
||||
getPods: func() []*corev1.Pod {
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; i < 5; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
|
|
@ -447,8 +763,8 @@ func TestPubReconcile(t *testing.T) {
|
|||
getDeployment: func() *apps.Deployment {
|
||||
return deploymentDemo.DeepCopy()
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
return replicaSetDemo.DeepCopy()
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
return []*apps.ReplicaSet{replicaSetDemo.DeepCopy()}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
|
|
@ -470,7 +786,7 @@ func TestPubReconcile(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "select matched deployment, minAvailable 80%",
|
||||
getPods: func() []*corev1.Pod {
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; i < 10; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
|
|
@ -482,8 +798,8 @@ func TestPubReconcile(t *testing.T) {
|
|||
getDeployment: func() *apps.Deployment {
|
||||
return deploymentDemo.DeepCopy()
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
return replicaSetDemo.DeepCopy()
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
return []*apps.ReplicaSet{replicaSetDemo.DeepCopy()}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
|
|
@ -505,7 +821,7 @@ func TestPubReconcile(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "select matched deployment, 10 UnavailablePods and 10 DisruptionPods",
|
||||
getPods: func() []*corev1.Pod {
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; i < 100; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
|
|
@ -519,10 +835,10 @@ func TestPubReconcile(t *testing.T) {
|
|||
object.Spec.Replicas = utilpointer.Int32Ptr(100)
|
||||
return object
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
object := replicaSetDemo.DeepCopy()
|
||||
object.Spec.Replicas = utilpointer.Int32Ptr(100)
|
||||
return object
|
||||
return []*apps.ReplicaSet{object}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
|
|
@ -551,7 +867,7 @@ func TestPubReconcile(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "select matched deployment, 10 UnavailablePods, 10 DisruptionPods and 5 not ready",
|
||||
getPods: func() []*corev1.Pod {
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; i < 100; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
|
|
@ -569,10 +885,10 @@ func TestPubReconcile(t *testing.T) {
|
|||
object.Spec.Replicas = utilpointer.Int32Ptr(100)
|
||||
return object
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
object := replicaSetDemo.DeepCopy()
|
||||
object.Spec.Replicas = utilpointer.Int32Ptr(100)
|
||||
return object
|
||||
return []*apps.ReplicaSet{object}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
|
|
@ -601,7 +917,7 @@ func TestPubReconcile(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "select matched deployment, 10 UnavailablePods, 10 DisruptionPods and 5 deletion",
|
||||
getPods: func() []*corev1.Pod {
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; i < 100; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
|
|
@ -618,10 +934,10 @@ func TestPubReconcile(t *testing.T) {
|
|||
object.Spec.Replicas = utilpointer.Int32Ptr(100)
|
||||
return object
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
object := replicaSetDemo.DeepCopy()
|
||||
object.Spec.Replicas = utilpointer.Int32Ptr(100)
|
||||
return object
|
||||
return []*apps.ReplicaSet{object}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
|
|
@ -650,7 +966,7 @@ func TestPubReconcile(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "select matched deployment, 10 UnavailablePods(5 ready), 10 DisruptionPods(5 deletion)",
|
||||
getPods: func() []*corev1.Pod {
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; i < 100; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
|
|
@ -667,10 +983,10 @@ func TestPubReconcile(t *testing.T) {
|
|||
object.Spec.Replicas = utilpointer.Int32Ptr(100)
|
||||
return object
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
object := replicaSetDemo.DeepCopy()
|
||||
object.Spec.Replicas = utilpointer.Int32Ptr(100)
|
||||
return object
|
||||
return []*apps.ReplicaSet{object}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
|
|
@ -703,7 +1019,7 @@ func TestPubReconcile(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "select matched deployment, 10 UnavailablePods(5 ready), 10 DisruptionPods(5 delay) and 5 deletion",
|
||||
getPods: func() []*corev1.Pod {
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; i < 100; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
|
|
@ -720,10 +1036,10 @@ func TestPubReconcile(t *testing.T) {
|
|||
object.Spec.Replicas = utilpointer.Int32Ptr(100)
|
||||
return object
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
object := replicaSetDemo.DeepCopy()
|
||||
object.Spec.Replicas = utilpointer.Int32Ptr(100)
|
||||
return object
|
||||
return []*apps.ReplicaSet{object}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
|
|
@ -760,7 +1076,7 @@ func TestPubReconcile(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "test select matched deployment, 10 UnavailablePods(5 ready), 10 DisruptionPods(5 delay) and 5 deletion",
|
||||
getPods: func() []*corev1.Pod {
|
||||
getPods: func(rs ...*apps.ReplicaSet) []*corev1.Pod {
|
||||
var matchedPods []*corev1.Pod
|
||||
for i := 0; i < 100; i++ {
|
||||
pod := podDemo.DeepCopy()
|
||||
|
|
@ -778,10 +1094,10 @@ func TestPubReconcile(t *testing.T) {
|
|||
object.Spec.Replicas = utilpointer.Int32Ptr(100)
|
||||
return object
|
||||
},
|
||||
getReplicaSet: func() *apps.ReplicaSet {
|
||||
getReplicaSet: func() []*apps.ReplicaSet {
|
||||
object := replicaSetDemo.DeepCopy()
|
||||
object.Spec.Replicas = utilpointer.Int32Ptr(100)
|
||||
return object
|
||||
return []*apps.ReplicaSet{object}
|
||||
},
|
||||
getPub: func() *policyv1alpha1.PodUnavailableBudget {
|
||||
pub := pubDemo.DeepCopy()
|
||||
|
|
@ -824,14 +1140,15 @@ func TestPubReconcile(t *testing.T) {
|
|||
t.Run(cs.name, func(t *testing.T) {
|
||||
pub := cs.getPub()
|
||||
defer util.GlobalCache.Delete(pub)
|
||||
fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(cs.getDeployment(), cs.getReplicaSet(), pub).Build()
|
||||
for _, pod := range cs.getPods() {
|
||||
fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(cs.getDeployment(), pub).Build()
|
||||
for _, pod := range cs.getPods(cs.getReplicaSet()...) {
|
||||
podIn := pod.DeepCopy()
|
||||
err := fakeClient.Create(context.TODO(), podIn)
|
||||
if err != nil {
|
||||
t.Fatalf("create pod failed: %s", err.Error())
|
||||
}
|
||||
_ = fakeClient.Create(context.TODO(), podIn)
|
||||
}
|
||||
for _, obj := range cs.getReplicaSet() {
|
||||
_ = fakeClient.Create(context.TODO(), obj)
|
||||
}
|
||||
|
||||
controllerfinder.Finder = &controllerfinder.ControllerFinder{Client: fakeClient}
|
||||
reconciler := ReconcilePodUnavailableBudget{
|
||||
Client: fakeClient,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/dynamic"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
|
|
@ -108,27 +109,24 @@ func (r *ControllerFinder) GetExpectedScaleForPods(pods []*corev1.Pod) (int32, e
|
|||
// 1. Find the controller for each pod. If any pod has 0 controllers,
|
||||
// that's an error. With ControllerRef, a pod can only have 1 controller.
|
||||
// A mapping from controllers to their scale.
|
||||
podRefs := sets.NewString()
|
||||
controllerScale := map[types.UID]int32{}
|
||||
for _, pod := range pods {
|
||||
ref := metav1.GetControllerOf(pod)
|
||||
if ref == nil {
|
||||
continue
|
||||
}
|
||||
// If we already know the scale of the controller there is no need to do anything.
|
||||
if _, found := controllerScale[ref.UID]; found {
|
||||
// ref has already been got, so there is no need to get again
|
||||
if ref == nil || podRefs.Has(string(ref.UID)) {
|
||||
continue
|
||||
}
|
||||
podRefs.Insert(string(ref.UID))
|
||||
// Check all the supported controllers to find the desired scale.
|
||||
workload, err := r.GetScaleAndSelectorForRef(ref.APIVersion, ref.Kind, pod.Namespace, ref.Name, ref.UID)
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
if err != nil {
|
||||
return 0, err
|
||||
} else if workload != nil && workload.Metadata.DeletionTimestamp.IsZero() {
|
||||
controllerScale[ref.UID] = workload.Scale
|
||||
} else {
|
||||
controllerScale[ref.UID] = 0
|
||||
} else if workload == nil || !workload.Metadata.DeletionTimestamp.IsZero() {
|
||||
continue
|
||||
}
|
||||
controllerScale[workload.UID] = workload.Scale
|
||||
}
|
||||
|
||||
// 2. Add up all the controllers.
|
||||
var expectedCount int32
|
||||
for _, count := range controllerScale {
|
||||
|
|
|
|||
|
|
@ -34,17 +34,15 @@ import (
|
|||
|
||||
// GetPodsForRef return target workload's podList and spec.replicas.
|
||||
func (r *ControllerFinder) GetPodsForRef(apiVersion, kind, ns, name string, active bool) ([]*corev1.Pod, int32, error) {
|
||||
workloadUIDs := make([]types.UID, 0)
|
||||
var workloadUIDs []types.UID
|
||||
var workloadReplicas int32
|
||||
|
||||
switch kind {
|
||||
// ReplicaSet
|
||||
case ControllerKindRS.Kind:
|
||||
rs, err := r.getReplicaSet(ControllerReference{APIVersion: apiVersion, Kind: kind, Name: name}, ns)
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
if rs == nil || !rs.DeletionTimestamp.IsZero() {
|
||||
} else if rs == nil || !rs.DeletionTimestamp.IsZero() {
|
||||
return nil, 0, nil
|
||||
}
|
||||
workloadReplicas = *rs.Spec.Replicas
|
||||
|
|
@ -59,7 +57,7 @@ func (r *ControllerFinder) GetPodsForRef(apiVersion, kind, ns, name string, acti
|
|||
}
|
||||
workloadReplicas = obj.Scale
|
||||
workloadUIDs = append(workloadUIDs, obj.UID)
|
||||
// Deployment, Deployment-like workload, and other workload
|
||||
// Deployment, Deployment-like workload or other custom workload(support scale sub-resources)
|
||||
default:
|
||||
obj, err := r.GetScaleAndSelectorForRef(apiVersion, kind, ns, name, "")
|
||||
if err != nil {
|
||||
|
|
@ -69,11 +67,10 @@ func (r *ControllerFinder) GetPodsForRef(apiVersion, kind, ns, name string, acti
|
|||
}
|
||||
workloadReplicas = obj.Scale
|
||||
// try to get replicaSets
|
||||
rss, err := r.getReplicaSetsForDeployment(apiVersion, kind, ns, name)
|
||||
rss, err := r.getReplicaSetsForObject(obj)
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
|
||||
if len(rss) == 0 {
|
||||
workloadUIDs = append(workloadUIDs, obj.UID)
|
||||
} else {
|
||||
|
|
@ -82,6 +79,9 @@ func (r *ControllerFinder) GetPodsForRef(apiVersion, kind, ns, name string, acti
|
|||
}
|
||||
}
|
||||
}
|
||||
if workloadReplicas == 0 {
|
||||
return nil, workloadReplicas, nil
|
||||
}
|
||||
|
||||
// List all Pods owned by workload UID.
|
||||
matchedPods := make([]*corev1.Pod, 0)
|
||||
|
|
@ -107,29 +107,26 @@ func (r *ControllerFinder) GetPodsForRef(apiVersion, kind, ns, name string, acti
|
|||
return matchedPods, workloadReplicas, nil
|
||||
}
|
||||
|
||||
func (r *ControllerFinder) getReplicaSetsForDeployment(apiVersion, kind, ns, name string) ([]appsv1.ReplicaSet, error) {
|
||||
scaleNSelector, err := r.GetScaleAndSelectorForRef(apiVersion, kind, ns, name, "")
|
||||
if err != nil || scaleNSelector == nil {
|
||||
return nil, err
|
||||
}
|
||||
func (r *ControllerFinder) getReplicaSetsForObject(scale *ScaleAndSelector) ([]appsv1.ReplicaSet, error) {
|
||||
// List ReplicaSets owned by this Deployment
|
||||
rsList := &appsv1.ReplicaSetList{}
|
||||
selector, err := util.ValidatedLabelSelectorAsSelector(scaleNSelector.Selector)
|
||||
selector, err := util.ValidatedLabelSelectorAsSelector(scale.Selector)
|
||||
if err != nil {
|
||||
klog.Errorf("Deployment (%s/%s) get labelSelector failed: %s", ns, name, err.Error())
|
||||
klog.Warningf("Object (%s/%s) get labelSelector failed: %s", scale.Metadata.Namespace, scale.Metadata.Name, err.Error())
|
||||
return nil, nil
|
||||
}
|
||||
err = r.List(context.TODO(), rsList, &client.ListOptions{Namespace: ns, LabelSelector: selector})
|
||||
err = r.List(context.TODO(), rsList, &client.ListOptions{Namespace: scale.Metadata.Namespace, LabelSelector: selector}, utilclient.DisableDeepCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rss := make([]appsv1.ReplicaSet, 0)
|
||||
for i := range rsList.Items {
|
||||
rs := rsList.Items[i]
|
||||
if ref := metav1.GetControllerOf(&rs); ref != nil {
|
||||
if ref.UID == scaleNSelector.UID {
|
||||
rss = append(rss, rs)
|
||||
}
|
||||
if *rs.Spec.Replicas == 0 || !rs.DeletionTimestamp.IsZero() {
|
||||
continue
|
||||
}
|
||||
if ref := metav1.GetControllerOf(&rs); ref != nil && ref.UID == scale.UID {
|
||||
rss = append(rss, rs)
|
||||
}
|
||||
}
|
||||
return rss, nil
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ func (s *PodUnavailableBudgetTester) NewBaseDeployment(namespace string) *apps.D
|
|||
RollingUpdate: &apps.RollingUpdateDeployment{
|
||||
MaxUnavailable: &intstr.IntOrString{
|
||||
Type: intstr.String,
|
||||
StrVal: "100%",
|
||||
StrVal: "50%",
|
||||
},
|
||||
MaxSurge: &intstr.IntOrString{
|
||||
Type: intstr.Int,
|
||||
|
|
|
|||
|
|
@ -459,90 +459,132 @@ var _ = SIGDescribe("PodUnavailableBudget", func() {
|
|||
ginkgo.By("PodUnavailableBudget targetReference pods, update failed image and block done")
|
||||
})
|
||||
|
||||
/*
|
||||
ginkgo.It("PodUnavailableBudget selector two deployments, deployment.strategy.maxUnavailable=100%, pub.spec.maxUnavailable=50%, and update success image", func() {
|
||||
// create pub
|
||||
pub := tester.NewBasePub(ns)
|
||||
pub.Spec.MaxUnavailable = &intstr.IntOrString{
|
||||
Type: intstr.String,
|
||||
StrVal: "50%",
|
||||
}
|
||||
ginkgo.By(fmt.Sprintf("Creating PodUnavailableBudget(%s/%s)", pub.Namespace, pub.Name))
|
||||
tester.CreatePub(pub)
|
||||
ginkgo.It("PodUnavailableBudget selector two deployments, deployment.strategy.maxUnavailable=25% and maxSurge=25%, pub.spec.maxUnavailable=25%, and update success image", func() {
|
||||
// create pub
|
||||
var err error
|
||||
pub := tester.NewBasePub(ns)
|
||||
pub.Spec.MaxUnavailable = &intstr.IntOrString{
|
||||
Type: intstr.String,
|
||||
StrVal: "25%",
|
||||
}
|
||||
ginkgo.By(fmt.Sprintf("Creating PodUnavailableBudget(%s/%s)", pub.Namespace, pub.Name))
|
||||
tester.CreatePub(pub)
|
||||
|
||||
// create deployment1
|
||||
deployment := tester.NewBaseDeployment(ns)
|
||||
deployment.Spec.Replicas = utilpointer.Int32Ptr(5)
|
||||
deploymentIn1 := deployment.DeepCopy()
|
||||
deploymentIn1.Name = fmt.Sprintf("%s-1", deploymentIn1.Name)
|
||||
ginkgo.By(fmt.Sprintf("Creating Deployment1(%s/%s)", deploymentIn1.Namespace, deploymentIn1.Name))
|
||||
tester.CreateDeployment(deploymentIn1)
|
||||
// create deployment2
|
||||
deploymentIn2 := deployment.DeepCopy()
|
||||
deploymentIn2.Name = fmt.Sprintf("%s-2", deploymentIn1.Name)
|
||||
ginkgo.By(fmt.Sprintf("Creating Deployment2(%s/%s)", deploymentIn2.Namespace, deploymentIn2.Name))
|
||||
tester.CreateDeployment(deploymentIn2)
|
||||
// create deployment1
|
||||
deployment := tester.NewBaseDeployment(ns)
|
||||
deployment.Spec.Strategy.RollingUpdate.MaxUnavailable = &intstr.IntOrString{
|
||||
Type: intstr.String,
|
||||
StrVal: "25%",
|
||||
}
|
||||
deployment.Spec.Strategy.RollingUpdate.MaxSurge = &intstr.IntOrString{
|
||||
Type: intstr.String,
|
||||
StrVal: "25%",
|
||||
}
|
||||
deployment.Spec.Replicas = utilpointer.Int32Ptr(5)
|
||||
deploymentIn1 := deployment.DeepCopy()
|
||||
deploymentIn1.Name = fmt.Sprintf("%s-1", deploymentIn1.Name)
|
||||
ginkgo.By(fmt.Sprintf("Creating Deployment1(%s/%s)", deploymentIn1.Namespace, deploymentIn1.Name))
|
||||
tester.CreateDeployment(deploymentIn1)
|
||||
// create deployment2
|
||||
deploymentIn2 := deployment.DeepCopy()
|
||||
deploymentIn2.Name = fmt.Sprintf("%s-2", deploymentIn1.Name)
|
||||
ginkgo.By(fmt.Sprintf("Creating Deployment2(%s/%s)", deploymentIn2.Namespace, deploymentIn2.Name))
|
||||
tester.CreateDeployment(deploymentIn2)
|
||||
|
||||
ginkgo.By(fmt.Sprintf("PodUnavailableBudget(%s/%s) Status", pub.Namespace, pub.Name))
|
||||
expectStatus := &policyv1alpha1.PodUnavailableBudgetStatus{
|
||||
UnavailableAllowed: 5,
|
||||
DesiredAvailable: 5,
|
||||
CurrentAvailable: 10,
|
||||
TotalReplicas: 10,
|
||||
}
|
||||
setPubStatus(expectStatus)
|
||||
gomega.Eventually(func() *policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
pub, err = kc.PolicyV1alpha1().PodUnavailableBudgets(pub.Namespace).Get(context.TODO(), pub.Name, metav1.GetOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
nowStatus := &pub.Status
|
||||
setPubStatus(nowStatus)
|
||||
return nowStatus
|
||||
}, 30*time.Second, time.Second).Should(gomega.Equal(expectStatus))
|
||||
|
||||
// update success image
|
||||
ginkgo.By(fmt.Sprintf("update Deployment-1 and deployment-2 with success image"))
|
||||
deploymentIn1.Spec.Template.Spec.Containers[0].Image = NewWebserverImage
|
||||
_, err = c.AppsV1().Deployments(deploymentIn1.Namespace).Update(context.TODO(), deploymentIn1, metav1.UpdateOptions{})
|
||||
ginkgo.By(fmt.Sprintf("PodUnavailableBudget(%s/%s) Status", pub.Namespace, pub.Name))
|
||||
expectStatus := &policyv1alpha1.PodUnavailableBudgetStatus{
|
||||
UnavailableAllowed: 3,
|
||||
DesiredAvailable: 7,
|
||||
CurrentAvailable: 10,
|
||||
TotalReplicas: 10,
|
||||
}
|
||||
setPubStatus(expectStatus)
|
||||
gomega.Eventually(func() *policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
pub, err = kc.PolicyV1alpha1().PodUnavailableBudgets(pub.Namespace).Get(context.TODO(), pub.Name, metav1.GetOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
deploymentIn2.Spec.Template.Spec.Containers[0].Image = NewWebserverImage
|
||||
_, err = c.AppsV1().Deployments(deploymentIn2.Namespace).Update(context.TODO(), deploymentIn2, metav1.UpdateOptions{})
|
||||
nowStatus := &pub.Status
|
||||
setPubStatus(nowStatus)
|
||||
return nowStatus
|
||||
}, 30*time.Second, time.Second).Should(gomega.Equal(expectStatus))
|
||||
|
||||
// update success image
|
||||
ginkgo.By("update Deployment-1 and deployment-2 with success image")
|
||||
deploymentIn1.Spec.Template.Spec.Containers[0].Image = NewWebserverImage
|
||||
_, err = c.AppsV1().Deployments(deploymentIn1.Namespace).Update(context.TODO(), deploymentIn1, metav1.UpdateOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
deploymentIn2.Spec.Template.Spec.Containers[0].Image = NewWebserverImage
|
||||
_, err = c.AppsV1().Deployments(deploymentIn2.Namespace).Update(context.TODO(), deploymentIn2, metav1.UpdateOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
// wait 1 seconds, and check deployment, pub Status
|
||||
ginkgo.By("wait 1 seconds, and check deployment, pub Status")
|
||||
time.Sleep(time.Second)
|
||||
// check deployment
|
||||
tester.WaitForDeploymentReadyAndRunning(deploymentIn1)
|
||||
tester.WaitForDeploymentReadyAndRunning(deploymentIn2)
|
||||
// check pods
|
||||
pods, err := sidecarTester.GetSelectorPods(deployment.Namespace, deployment.Spec.Selector)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
for _, pod := range pods {
|
||||
gomega.Expect(pod.Spec.Containers[0].Image).To(gomega.Equal(NewWebserverImage))
|
||||
}
|
||||
expectStatus = &policyv1alpha1.PodUnavailableBudgetStatus{
|
||||
UnavailableAllowed: 3,
|
||||
DesiredAvailable: 7,
|
||||
CurrentAvailable: 10,
|
||||
TotalReplicas: 10,
|
||||
}
|
||||
setPubStatus(expectStatus)
|
||||
gomega.Eventually(func() *policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
pub, err = kc.PolicyV1alpha1().PodUnavailableBudgets(pub.Namespace).Get(context.TODO(), pub.Name, metav1.GetOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
nowStatus := &pub.Status
|
||||
setPubStatus(nowStatus)
|
||||
return nowStatus
|
||||
}, 5*time.Second, time.Second).Should(gomega.Equal(expectStatus))
|
||||
|
||||
// wait 1 seconds, and check deployment, pub Status
|
||||
ginkgo.By(fmt.Sprintf("wait 1 seconds, and check deployment, pub Status"))
|
||||
time.Sleep(time.Second)
|
||||
// check deployment
|
||||
tester.WaitForDeploymentMinReadyAndRunning([]*apps.Deployment{deploymentIn1, deploymentIn2}, 5)
|
||||
// check pods
|
||||
pods, err := sidecarTester.GetSelectorPods(deployment.Namespace, deployment.Spec.Selector)
|
||||
// scale down replicas = 0
|
||||
ginkgo.By("scale down Deployment-1 replicas to 0")
|
||||
deploymentIn1.Spec.Replicas = utilpointer.Int32(0)
|
||||
_, err = c.AppsV1().Deployments(deploymentIn1.Namespace).Update(context.TODO(), deploymentIn1, metav1.UpdateOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
tester.WaitForDeploymentReadyAndRunning(deploymentIn1)
|
||||
expectStatus = &policyv1alpha1.PodUnavailableBudgetStatus{
|
||||
UnavailableAllowed: 2,
|
||||
DesiredAvailable: 3,
|
||||
CurrentAvailable: 5,
|
||||
TotalReplicas: 5,
|
||||
}
|
||||
setPubStatus(expectStatus)
|
||||
gomega.Eventually(func() *policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
pub, err = kc.PolicyV1alpha1().PodUnavailableBudgets(pub.Namespace).Get(context.TODO(), pub.Name, metav1.GetOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
newPods := make([]corev1.Pod, 0)
|
||||
for _, pod := range pods {
|
||||
if !pod.DeletionTimestamp.IsZero() || pod.Spec.Containers[0].Image != NewWebserverImage {
|
||||
continue
|
||||
}
|
||||
newPods = append(newPods, *pod)
|
||||
}
|
||||
gomega.Expect(newPods).To(gomega.HaveLen(10))
|
||||
nowStatus := &pub.Status
|
||||
setPubStatus(nowStatus)
|
||||
return nowStatus
|
||||
}, 5*time.Second, time.Second).Should(gomega.Equal(expectStatus))
|
||||
|
||||
expectStatus = &policyv1alpha1.PodUnavailableBudgetStatus{
|
||||
UnavailableAllowed: 5,
|
||||
DesiredAvailable: 5,
|
||||
CurrentAvailable: 10,
|
||||
TotalReplicas: 10,
|
||||
}
|
||||
setPubStatus(expectStatus)
|
||||
gomega.Eventually(func() *policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
pub, err = kc.PolicyV1alpha1().PodUnavailableBudgets(pub.Namespace).Get(context.TODO(), pub.Name, metav1.GetOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
nowStatus := &pub.Status
|
||||
setPubStatus(nowStatus)
|
||||
return nowStatus
|
||||
}, 30*time.Second, time.Second).Should(gomega.Equal(expectStatus))
|
||||
// delete deployment directly
|
||||
err = c.AppsV1().Deployments(deploymentIn2.Namespace).Delete(context.TODO(), deploymentIn2.Name, metav1.DeleteOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
time.Sleep(time.Second * 3)
|
||||
expectStatus = &policyv1alpha1.PodUnavailableBudgetStatus{
|
||||
UnavailableAllowed: 0,
|
||||
DesiredAvailable: 0,
|
||||
CurrentAvailable: 0,
|
||||
TotalReplicas: 0,
|
||||
}
|
||||
setPubStatus(expectStatus)
|
||||
gomega.Eventually(func() *policyv1alpha1.PodUnavailableBudgetStatus {
|
||||
pub, err = kc.PolicyV1alpha1().PodUnavailableBudgets(pub.Namespace).Get(context.TODO(), pub.Name, metav1.GetOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
nowStatus := &pub.Status
|
||||
setPubStatus(nowStatus)
|
||||
return nowStatus
|
||||
}, 5*time.Second, time.Second).Should(gomega.Equal(expectStatus))
|
||||
|
||||
ginkgo.By("PodUnavailableBudget selector two deployments, deployment.strategy.maxUnavailable=100%, pub.spec.maxUnavailable=50%, and update success image done")
|
||||
})
|
||||
*/
|
||||
ginkgo.By("PodUnavailableBudget selector two deployments, deployment.strategy.maxUnavailable=100%, pub.spec.maxUnavailable=50%, and update success image done")
|
||||
})
|
||||
|
||||
ginkgo.It("PodUnavailableBudget selector SidecarSet, inject sidecar container, update failed sidecar image, block", func() {
|
||||
// create pub
|
||||
|
|
|
|||
Loading…
Reference in New Issue