Skip to content

Commit 3cc73c6

Browse files
author
OpenShift Bot
authored
Merge pull request #14936 from tnozicka/fix-minreadyseconds-for-dc
Merged by openshift-bot
2 parents ecd7763 + 953dac8 commit 3cc73c6

File tree

5 files changed

+81
-39
lines changed

5 files changed

+81
-39
lines changed

pkg/deploy/util/util.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,9 @@ func MakeDeploymentV1(config *deployapi.DeploymentConfig, codec runtime.Codec) (
406406
},
407407
Spec: v1.ReplicationControllerSpec{
408408
// The deployment should be inactive initially
409-
Replicas: &zero,
410-
Selector: selector,
409+
Replicas: &zero,
410+
Selector: selector,
411+
MinReadySeconds: config.Spec.MinReadySeconds,
411412
Template: &v1.PodTemplateSpec{
412413
ObjectMeta: metav1.ObjectMeta{
413414
Labels: podLabels,

test/extended/deployments/deployments.go

Lines changed: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package deployments
22

33
import (
4+
//"errors"
45
"fmt"
56
"math/rand"
67
"strings"
@@ -9,11 +10,11 @@ import (
910
g "github.com/onsi/ginkgo"
1011
o "github.com/onsi/gomega"
1112

12-
"k8s.io/apimachinery/pkg/api/errors"
13+
kerrors "k8s.io/apimachinery/pkg/api/errors"
1314
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14-
"k8s.io/apimachinery/pkg/labels"
1515
"k8s.io/apimachinery/pkg/types"
1616
"k8s.io/apimachinery/pkg/util/wait"
17+
"k8s.io/apimachinery/pkg/watch"
1718
kapiv1 "k8s.io/kubernetes/pkg/api/v1"
1819
kcontroller "k8s.io/kubernetes/pkg/controller"
1920
e2e "k8s.io/kubernetes/test/e2e/framework"
@@ -382,7 +383,7 @@ var _ = g.Describe("deploymentconfigs", func() {
382383
var istag *imageapi.ImageStreamTag
383384
pollErr := wait.PollImmediate(100*time.Millisecond, 1*time.Minute, func() (bool, error) {
384385
istag, err = oc.Client().ImageStreamTags(oc.Namespace()).Get("sample-stream", "deployed")
385-
if errors.IsNotFound(err) {
386+
if kerrors.IsNotFound(err) {
386387
return false, nil
387388
}
388389
if err != nil {
@@ -882,53 +883,85 @@ var _ = g.Describe("deploymentconfigs", func() {
882883
})
883884

884885
g.Describe("with minimum ready seconds set [Conformance]", func() {
886+
dc := readDCFixtureOrDie(minReadySecondsFixture)
887+
rcName := func(i int) string { return fmt.Sprintf("%s-%d", dc.Name, i) }
885888
g.AfterEach(func() {
886-
failureTrap(oc, "minreadytest", g.CurrentGinkgoTestDescription().Failed)
889+
failureTrap(oc, dc.Name, g.CurrentGinkgoTestDescription().Failed)
887890
})
888891

889892
g.It("should not transition the deployment to Complete before satisfied", func() {
890-
_, name, err := createFixture(oc, minReadySecondsFixture)
893+
namespace := oc.Namespace()
894+
watcher, err := oc.KubeClient().CoreV1().ReplicationControllers(namespace).Watch(metav1.SingleObject(metav1.ObjectMeta{Name: rcName(1), ResourceVersion: ""}))
891895
o.Expect(err).NotTo(o.HaveOccurred())
892896

893-
g.By("verifying the deployment is marked running")
894-
o.Expect(waitForLatestCondition(oc, name, deploymentRunTimeout, deploymentRunning)).NotTo(o.HaveOccurred())
895-
896-
g.By("verifying that all pods are ready")
897-
config, err := oc.Client().DeploymentConfigs(oc.Namespace()).Get(name, metav1.GetOptions{})
897+
o.Expect(dc.Spec.Triggers).To(o.BeNil())
898+
// FIXME: remove when tests are migrated to the new client
899+
// (the old one incorrectly translates nil into an empty array)
900+
dc.Spec.Triggers = append(dc.Spec.Triggers, deployapi.DeploymentTriggerPolicy{Type: deployapi.DeploymentTriggerOnConfigChange})
901+
dc, err = oc.Client().DeploymentConfigs(namespace).Create(dc)
898902
o.Expect(err).NotTo(o.HaveOccurred())
899903

900-
selector := labels.Set(config.Spec.Selector).AsSelector()
901-
opts := metav1.ListOptions{LabelSelector: selector.String()}
902-
ready := 0
903-
if err := wait.PollImmediate(500*time.Millisecond, 3*time.Minute, func() (bool, error) {
904-
pods, err := oc.KubeClient().CoreV1().Pods(oc.Namespace()).List(opts)
905-
if err != nil {
906-
return false, nil
904+
g.By("verifying the deployment is created")
905+
rcEvent, err := watch.Until(deploymentChangeTimeout, watcher, func(event watch.Event) (bool, error) {
906+
if event.Type == watch.Added {
907+
return true, nil
907908
}
909+
return false, fmt.Errorf("different kind of event appeared while waiting for Added event: %#v", event)
910+
})
911+
o.Expect(err).NotTo(o.HaveOccurred())
912+
rc1 := rcEvent.Object.(*kapiv1.ReplicationController)
908913

909-
ready = 0
910-
for i := range pods.Items {
911-
pod := pods.Items[i]
912-
if kapiv1.IsPodReady(&pod) {
913-
ready++
914-
}
915-
}
914+
g.By("verifying that all pods are ready")
915+
rc1, err = waitForRCModification(oc, namespace, rc1.Name, deploymentRunTimeout,
916+
rc1.GetResourceVersion(), func(rc *kapiv1.ReplicationController) (bool, error) {
917+
return rc.Status.ReadyReplicas == dc.Spec.Replicas, nil
918+
})
919+
o.Expect(err).NotTo(o.HaveOccurred())
920+
o.Expect(rc1.Status.AvailableReplicas).To(o.BeZero())
916921

917-
return len(pods.Items) == ready, nil
918-
}); err != nil {
919-
o.Expect(fmt.Errorf("deployment config %q never became ready (ready: %d, desired: %d)",
920-
config.Name, ready, config.Spec.Replicas)).NotTo(o.HaveOccurred())
922+
g.By("verifying that the deployment is still running")
923+
if deployutil.IsTerminatedDeployment(rc1) {
924+
o.Expect(fmt.Errorf("expected deployment %q not to have terminated", rc1.Name)).NotTo(o.HaveOccurred())
921925
}
922926

923-
g.By("verifying that the deployment is still running")
924-
latestName := deployutil.DeploymentNameForConfigVersion(name, config.Status.LatestVersion)
925-
latest, err := oc.InternalKubeClient().Core().ReplicationControllers(oc.Namespace()).Get(latestName, metav1.GetOptions{})
926-
o.Expect(err).NotTo(o.HaveOccurred())
927+
g.By("waiting for the deployment to finish")
928+
rc1, err = waitForRCModification(oc, namespace, rc1.Name,
929+
deploymentChangeTimeout+time.Duration(dc.Spec.MinReadySeconds)*time.Second,
930+
rc1.GetResourceVersion(), func(rc *kapiv1.ReplicationController) (bool, error) {
931+
if rc.Status.AvailableReplicas == dc.Spec.Replicas {
932+
return true, nil
933+
}
927934

928-
if deployutil.IsTerminatedDeployment(latest) {
929-
o.Expect(fmt.Errorf("expected deployment %q not to have terminated", latest.Name)).NotTo(o.HaveOccurred())
935+
// FIXME: There is a race between deployer pod updating phase and RC updating AvailableReplicas
936+
// FIXME: Enable this when we switch pod acceptors to use RC AvailableReplicas with MinReadySecondsSet
937+
//if deployutil.DeploymentStatusFor(rc) == deployapi.DeploymentStatusComplete {
938+
// e2e.Logf("Failed RC: %#v", rc)
939+
// return false, errors.New("deployment shouldn't be completed before ReadyReplicas become AvailableReplicas")
940+
//}
941+
return false, nil
942+
})
943+
o.Expect(err).NotTo(o.HaveOccurred())
944+
o.Expect(rc1.Status.AvailableReplicas).To(o.Equal(dc.Spec.Replicas))
945+
// FIXME: There is a race between deployer pod updating phase and RC updating AvailableReplicas
946+
// FIXME: Enable this when we switch pod acceptors to use RC AvailableReplicas with MinReadySecondsSet
947+
//// Deployment status can't be updated yet but should be right after
948+
//o.Expect(deployutil.DeploymentStatusFor(rc1)).To(o.Equal(deployapi.DeploymentStatusRunning))
949+
// It should finish right after
950+
// FIXME: remove this condition when the above is fixed
951+
if deployutil.DeploymentStatusFor(rc1) != deployapi.DeploymentStatusComplete {
952+
// FIXME: remove this assertion when the above is fixed
953+
o.Expect(deployutil.DeploymentStatusFor(rc1)).To(o.Equal(deployapi.DeploymentStatusRunning))
954+
rc1, err = waitForRCModification(oc, namespace, rc1.Name, deploymentChangeTimeout,
955+
rc1.GetResourceVersion(), func(rc *kapiv1.ReplicationController) (bool, error) {
956+
return deployutil.DeploymentStatusFor(rc) == deployapi.DeploymentStatusComplete, nil
957+
})
958+
o.Expect(err).NotTo(o.HaveOccurred())
930959
}
931-
o.Expect(waitForLatestCondition(oc, name, deploymentRunTimeout, deploymentRunning)).NotTo(o.HaveOccurred())
960+
961+
// We might check that minReadySecond passed between pods becoming ready
962+
// and available but I don't think there is a way to get a timestamp from events
963+
// and other ways are just flaky.
964+
// But since we are reusing MinReadySeconds and AvailableReplicas from RC it should be tested there
932965
})
933966
})
934967

test/extended/deployments/util.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,3 +559,11 @@ func readDCFixture(path string) (*deployapi.DeploymentConfig, error) {
559559
err = deployapiv1.Convert_v1_DeploymentConfig_To_apps_DeploymentConfig(dcv1, dc, nil)
560560
return dc, err
561561
}
562+
563+
func readDCFixtureOrDie(path string) *deployapi.DeploymentConfig {
564+
data, err := readDCFixture(path)
565+
if err != nil {
566+
panic(err)
567+
}
568+
return data
569+
}

test/extended/testdata/bindata.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/extended/testdata/deployments/deployment-min-ready-seconds.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ metadata:
44
name: minreadytest
55
spec:
66
replicas: 2
7-
minReadySeconds: 500
7+
minReadySeconds: 60
88
selector:
99
name: minreadytest
1010
template:

0 commit comments

Comments
 (0)