mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 18:31:15 +00:00
Merge pull request #54331 from crimsonfaith91/dfailed
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>. convert testFailedDeployment e2e test to integration test **What this PR does / why we need it**: This PR convert a deployment e2e test named "testFailedDeployment" to integration test. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: xref #52113 **Release note**: ```release-note NONE ``` /assign
This commit is contained in:
commit
84284c0ba4
@ -93,9 +93,6 @@ var _ = SIGDescribe("Deployment", func() {
|
|||||||
It("overlapping deployment should not fight with each other", func() {
|
It("overlapping deployment should not fight with each other", func() {
|
||||||
testOverlappingDeployment(f)
|
testOverlappingDeployment(f)
|
||||||
})
|
})
|
||||||
It("lack of progress should be reported in the deployment status", func() {
|
|
||||||
testFailedDeployment(f)
|
|
||||||
})
|
|
||||||
It("iterative rollouts should eventually progress", func() {
|
It("iterative rollouts should eventually progress", func() {
|
||||||
testIterativeDeployments(f)
|
testIterativeDeployments(f)
|
||||||
})
|
})
|
||||||
@ -816,46 +813,6 @@ func testOverlappingDeployment(f *framework.Framework) {
|
|||||||
Expect(rsList.Items).To(HaveLen(2))
|
Expect(rsList.Items).To(HaveLen(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
func testFailedDeployment(f *framework.Framework) {
|
|
||||||
ns := f.Namespace.Name
|
|
||||||
c := f.ClientSet
|
|
||||||
|
|
||||||
podLabels := map[string]string{"name": NginxImageName}
|
|
||||||
replicas := int32(1)
|
|
||||||
|
|
||||||
// Create a nginx deployment.
|
|
||||||
deploymentName := "progress-check"
|
|
||||||
nonExistentImage := "nginx:not-there"
|
|
||||||
ten := int32(10)
|
|
||||||
d := framework.NewDeployment(deploymentName, replicas, podLabels, NginxImageName, nonExistentImage, extensions.RecreateDeploymentStrategyType)
|
|
||||||
d.Spec.ProgressDeadlineSeconds = &ten
|
|
||||||
|
|
||||||
framework.Logf("Creating deployment %q with progressDeadlineSeconds set to %ds and a non-existent image", deploymentName, ten)
|
|
||||||
deployment, err := c.Extensions().Deployments(ns).Create(d)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
|
|
||||||
framework.Logf("Waiting for deployment %q new replica set to come up", deploymentName)
|
|
||||||
Expect(framework.WaitForDeploymentUpdatedReplicasLTE(c, ns, deploymentName, replicas, deployment.Generation))
|
|
||||||
|
|
||||||
framework.Logf("Checking deployment %q for a timeout condition", deploymentName)
|
|
||||||
Expect(framework.WaitForDeploymentWithCondition(c, ns, deploymentName, deploymentutil.TimedOutReason, extensions.DeploymentProgressing)).NotTo(HaveOccurred())
|
|
||||||
|
|
||||||
framework.Logf("Updating deployment %q with a good image", deploymentName)
|
|
||||||
deployment, err = framework.UpdateDeploymentWithRetries(c, ns, deployment.Name, func(update *extensions.Deployment) {
|
|
||||||
update.Spec.Template.Spec.Containers[0].Image = NginxImage
|
|
||||||
})
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
|
|
||||||
framework.Logf("Waiting for deployment %q new replica set to come up", deploymentName)
|
|
||||||
Expect(framework.WaitForDeploymentUpdatedReplicasLTE(c, ns, deploymentName, replicas, deployment.Generation))
|
|
||||||
|
|
||||||
framework.Logf("Waiting for deployment %q status", deploymentName)
|
|
||||||
Expect(framework.WaitForDeploymentComplete(c, deployment)).NotTo(HaveOccurred())
|
|
||||||
|
|
||||||
framework.Logf("Checking deployment %q for a complete condition", deploymentName)
|
|
||||||
Expect(framework.WaitForDeploymentWithCondition(c, ns, deploymentName, deploymentutil.NewRSAvailableReason, extensions.DeploymentProgressing)).NotTo(HaveOccurred())
|
|
||||||
}
|
|
||||||
|
|
||||||
func randomScale(d *extensions.Deployment, i int) {
|
func randomScale(d *extensions.Deployment, i int) {
|
||||||
switch r := rand.Float32(); {
|
switch r := rand.Float32(); {
|
||||||
case r < 0.3:
|
case r < 0.3:
|
||||||
|
@ -72,25 +72,7 @@ func WaitForObservedDeployment(c clientset.Interface, ns, deploymentName string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func WaitForDeploymentWithCondition(c clientset.Interface, ns, deploymentName, reason string, condType extensions.DeploymentConditionType) error {
|
func WaitForDeploymentWithCondition(c clientset.Interface, ns, deploymentName, reason string, condType extensions.DeploymentConditionType) error {
|
||||||
var deployment *extensions.Deployment
|
return testutils.WaitForDeploymentWithCondition(c, ns, deploymentName, reason, condType, Logf, Poll, pollLongTimeout)
|
||||||
pollErr := wait.PollImmediate(time.Second, 5*time.Minute, func() (bool, error) {
|
|
||||||
d, err := c.Extensions().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
deployment = d
|
|
||||||
cond := deploymentutil.GetDeploymentCondition(deployment.Status, condType)
|
|
||||||
return cond != nil && cond.Reason == reason, nil
|
|
||||||
})
|
|
||||||
if pollErr == wait.ErrWaitTimeout {
|
|
||||||
pollErr = fmt.Errorf("deployment %q never updated with the desired condition and reason: %v", deployment.Name, deployment.Status.Conditions)
|
|
||||||
_, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, c.ExtensionsV1beta1())
|
|
||||||
if err == nil {
|
|
||||||
logReplicaSetsOfDeployment(deployment, allOldRSs, newRS)
|
|
||||||
logPodsOfDeployment(c, deployment, append(allOldRSs, newRS))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pollErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WaitForDeploymentRevisionAndImage waits for the deployment's and its new RS's revision and container image to match the given revision and image.
|
// WaitForDeploymentRevisionAndImage waits for the deployment's and its new RS's revision and container image to match the given revision and image.
|
||||||
@ -145,20 +127,7 @@ func WaitForDeploymentCompleteAndCheckRolling(c clientset.Interface, d *extensio
|
|||||||
|
|
||||||
// WaitForDeploymentUpdatedReplicasLTE waits for given deployment to be observed by the controller and has at least a number of updatedReplicas
|
// WaitForDeploymentUpdatedReplicasLTE waits for given deployment to be observed by the controller and has at least a number of updatedReplicas
|
||||||
func WaitForDeploymentUpdatedReplicasLTE(c clientset.Interface, ns, deploymentName string, minUpdatedReplicas int32, desiredGeneration int64) error {
|
func WaitForDeploymentUpdatedReplicasLTE(c clientset.Interface, ns, deploymentName string, minUpdatedReplicas int32, desiredGeneration int64) error {
|
||||||
err := wait.Poll(Poll, 5*time.Minute, func() (bool, error) {
|
return testutils.WaitForDeploymentUpdatedReplicasLTE(c, ns, deploymentName, minUpdatedReplicas, desiredGeneration, Poll, pollLongTimeout)
|
||||||
deployment, err := c.Extensions().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if deployment.Status.ObservedGeneration >= desiredGeneration && deployment.Status.UpdatedReplicas >= minUpdatedReplicas {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error waiting for deployment %s to have at least %d updpatedReplicas: %v", deploymentName, minUpdatedReplicas, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WaitForDeploymentRollbackCleared waits for given deployment either started rolling back or doesn't need to rollback.
|
// WaitForDeploymentRollbackCleared waits for given deployment either started rolling back or doesn't need to rollback.
|
||||||
|
@ -633,3 +633,50 @@ func TestDeploymentLabelAdopted(t *testing.T) {
|
|||||||
t.Errorf("found mismatching pod-template-hash value: rs hash = %s whereas pod hash = %s", rsHash, podHash)
|
t.Errorf("found mismatching pod-template-hash value: rs hash = %s whereas pod hash = %s", rsHash, podHash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deployment should have a timeout condition when it fails to progress after given deadline.
|
||||||
|
func TestFailedDeployment(t *testing.T) {
|
||||||
|
s, closeFn, rm, dc, informers, c := dcSetup(t)
|
||||||
|
defer closeFn()
|
||||||
|
name := "test-failed-deployment"
|
||||||
|
ns := framework.CreateTestingNamespace(name, s, t)
|
||||||
|
defer framework.DeleteTestingNamespace(ns, s, t)
|
||||||
|
|
||||||
|
deploymentName := "progress-check"
|
||||||
|
replicas := int32(1)
|
||||||
|
three := int32(3)
|
||||||
|
tester := &deploymentTester{t: t, c: c, deployment: newDeployment(deploymentName, ns.Name, replicas)}
|
||||||
|
tester.deployment.Spec.ProgressDeadlineSeconds = &three
|
||||||
|
var err error
|
||||||
|
tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create deployment %q: %v", deploymentName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start informer and controllers
|
||||||
|
stopCh := make(chan struct{})
|
||||||
|
defer close(stopCh)
|
||||||
|
informers.Start(stopCh)
|
||||||
|
go rm.Run(5, stopCh)
|
||||||
|
go dc.Run(5, stopCh)
|
||||||
|
|
||||||
|
if err = tester.waitForDeploymentUpdatedReplicasLTE(replicas); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pods are not marked as Ready, therefore the deployment progress will eventually timeout after progressDeadlineSeconds has passed.
|
||||||
|
// Wait for the deployment to have a progress timeout condition.
|
||||||
|
if err = tester.waitForDeploymentWithCondition(deploymentutil.TimedOutReason, v1beta1.DeploymentProgressing); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manually mark pods as Ready and wait for deployment to complete.
|
||||||
|
if err := tester.waitForDeploymentCompleteAndMarkPodsReady(); err != nil {
|
||||||
|
t.Fatalf("deployment %q fails to have its status becoming valid: %v", deploymentName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the deployment to have a progress complete condition.
|
||||||
|
if err = tester.waitForDeploymentWithCondition(deploymentutil.NewRSAvailableReason, v1beta1.DeploymentProgressing); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -343,3 +343,11 @@ func (d *deploymentTester) waitForDeploymentRollbackCleared() error {
|
|||||||
func (d *deploymentTester) checkDeploymentRevisionAndImage(revision, image string) error {
|
func (d *deploymentTester) checkDeploymentRevisionAndImage(revision, image string) error {
|
||||||
return testutil.CheckDeploymentRevisionAndImage(d.c, d.deployment.Namespace, d.deployment.Name, revision, image)
|
return testutil.CheckDeploymentRevisionAndImage(d.c, d.deployment.Namespace, d.deployment.Name, revision, image)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *deploymentTester) waitForDeploymentUpdatedReplicasLTE(minUpdatedReplicas int32) error {
|
||||||
|
return testutil.WaitForDeploymentUpdatedReplicasLTE(d.c, d.deployment.Namespace, d.deployment.Name, minUpdatedReplicas, d.deployment.Generation, pollInterval, pollTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *deploymentTester) waitForDeploymentWithCondition(reason string, condType v1beta1.DeploymentConditionType) error {
|
||||||
|
return testutil.WaitForDeploymentWithCondition(d.c, d.deployment.Namespace, d.deployment.Name, reason, condType, d.t.Logf, pollInterval, pollTimeout)
|
||||||
|
}
|
||||||
|
@ -301,3 +301,42 @@ func WaitForDeploymentRollbackCleared(c clientset.Interface, ns, deploymentName
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WaitForDeploymentUpdatedReplicasLTE waits for given deployment to be observed by the controller and has at least a number of updatedReplicas
|
||||||
|
func WaitForDeploymentUpdatedReplicasLTE(c clientset.Interface, ns, deploymentName string, minUpdatedReplicas int32, desiredGeneration int64, pollInterval, pollTimeout time.Duration) error {
|
||||||
|
var deployment *extensions.Deployment
|
||||||
|
err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) {
|
||||||
|
d, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
deployment = d
|
||||||
|
return deployment.Status.ObservedGeneration >= desiredGeneration && deployment.Status.UpdatedReplicas >= minUpdatedReplicas, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error waiting for deployment %q to have at least %d updatedReplicas: %v; latest .status.updatedReplicas: %d", deploymentName, minUpdatedReplicas, err, deployment.Status.UpdatedReplicas)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WaitForDeploymentWithCondition(c clientset.Interface, ns, deploymentName, reason string, condType extensions.DeploymentConditionType, logf LogfFn, pollInterval, pollTimeout time.Duration) error {
|
||||||
|
var deployment *extensions.Deployment
|
||||||
|
pollErr := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) {
|
||||||
|
d, err := c.ExtensionsV1beta1().Deployments(ns).Get(deploymentName, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
deployment = d
|
||||||
|
cond := deploymentutil.GetDeploymentCondition(deployment.Status, condType)
|
||||||
|
return cond != nil && cond.Reason == reason, nil
|
||||||
|
})
|
||||||
|
if pollErr == wait.ErrWaitTimeout {
|
||||||
|
pollErr = fmt.Errorf("deployment %q never updated with the desired condition and reason, latest deployment conditions: %+v", deployment.Name, deployment.Status.Conditions)
|
||||||
|
_, allOldRSs, newRS, err := deploymentutil.GetAllReplicaSets(deployment, c.ExtensionsV1beta1())
|
||||||
|
if err == nil {
|
||||||
|
LogReplicaSetsOfDeployment(deployment, allOldRSs, newRS, logf)
|
||||||
|
LogPodsOfDeployment(c, deployment, append(allOldRSs, newRS), logf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pollErr
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user