Merge pull request #52896 from janetkuo/deploy-hash-inte

Automatic merge from submit-queue (batch tested with PRs 52721, 53057, 52493, 52998, 52896). 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>.

Move deployment collision avoidance e2e test to integration

**What this PR does / why we need it**:

**Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: ref #52113

**Special notes for your reviewer**:

**Release note**:

```release-note
NONE
```
This commit is contained in:
Kubernetes Submit Queue
2017-09-26 15:51:25 -07:00
committed by GitHub
9 changed files with 137 additions and 87 deletions

View File

@@ -21,6 +21,7 @@ go_test(
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
],
)

View File

@@ -24,6 +24,7 @@ import (
"k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util"
"k8s.io/kubernetes/test/integration/framework"
)
@@ -171,7 +172,7 @@ func TestPausedDeployment(t *testing.T) {
}
// Resume the deployment
tester.deployment, err = tester.updateDeployment(resumeFn())
tester.deployment, err = tester.updateDeployment(resumeFn)
if err != nil {
t.Fatalf("failed to resume deployment %s: %v", tester.deployment.Name, err)
}
@@ -198,7 +199,7 @@ func TestPausedDeployment(t *testing.T) {
// Pause the deployment.
// The paused deployment shouldn't trigger a new rollout.
tester.deployment, err = tester.updateDeployment(pauseFn())
tester.deployment, err = tester.updateDeployment(pauseFn)
if err != nil {
t.Fatalf("failed to pause deployment %s: %v", tester.deployment.Name, err)
}
@@ -281,7 +282,7 @@ func TestScalePausedDeployment(t *testing.T) {
}
// Pause the deployment.
tester.deployment, err = tester.updateDeployment(pauseFn())
tester.deployment, err = tester.updateDeployment(pauseFn)
if err != nil {
t.Fatalf("failed to pause deployment %s: %v", tester.deployment.Name, err)
}
@@ -319,3 +320,64 @@ func TestScalePausedDeployment(t *testing.T) {
t.Fatal(err)
}
}
// Deployment rollout shouldn't be blocked on hash collisions
func TestDeploymentHashCollision(t *testing.T) {
s, closeFn, rm, dc, informers, c := dcSetup(t)
defer closeFn()
name := "test-hash-collision-deployment"
ns := framework.CreateTestingNamespace(name, s, t)
defer framework.DeleteTestingNamespace(ns, s, t)
replicas := int32(1)
tester := &deploymentTester{t: t, c: c, deployment: newDeployment(name, ns.Name, replicas)}
var err error
tester.deployment, err = c.ExtensionsV1beta1().Deployments(ns.Name).Create(tester.deployment)
if err != nil {
t.Fatalf("failed to create deployment %s: %v", tester.deployment.Name, 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)
// Wait for the Deployment to be updated to revision 1
if err := tester.waitForDeploymentRevisionAndImage("1", fakeImage); err != nil {
t.Fatal(err)
}
// Mock a hash collision
newRS, err := deploymentutil.GetNewReplicaSet(tester.deployment, c.ExtensionsV1beta1())
if err != nil {
t.Fatalf("failed getting new replicaset of deployment %s: %v", tester.deployment.Name, err)
}
if newRS == nil {
t.Fatalf("unable to find new replicaset of deployment %s", tester.deployment.Name)
}
_, err = tester.updateReplicaSet(newRS.Name, func(update *v1beta1.ReplicaSet) {
*update.Spec.Template.Spec.TerminationGracePeriodSeconds = int64(5)
})
if err != nil {
t.Fatalf("failed updating replicaset %s template: %v", newRS.Name, err)
}
// Expect deployment collision counter to increment
if err := wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) {
d, err := c.ExtensionsV1beta1().Deployments(ns.Name).Get(tester.deployment.Name, metav1.GetOptions{})
if err != nil {
return false, nil
}
return d.Status.CollisionCount != nil && *d.Status.CollisionCount == int32(1), nil
}); err != nil {
t.Fatalf("Failed to increment collision counter for deployment %q: %v", tester.deployment.Name, err)
}
// Expect a new ReplicaSet to be created
if err := tester.waitForDeploymentRevisionAndImage("2", fakeImage); err != nil {
t.Fatal(err)
}
}

View File

@@ -38,13 +38,21 @@ import (
)
const (
pollInterval = 1 * time.Second
pollInterval = 100 * time.Millisecond
pollTimeout = 60 * time.Second
fakeImageName = "fake-name"
fakeImage = "fakeimage"
)
var pauseFn = func(update *v1beta1.Deployment) {
update.Spec.Paused = true
}
var resumeFn = func(update *v1beta1.Deployment) {
update.Spec.Paused = false
}
type deploymentTester struct {
t *testing.T
c clientset.Interface
@@ -160,7 +168,7 @@ func (d *deploymentTester) markAllPodsReady() {
d.t.Fatalf("failed to parse Deployment selector: %v", err)
}
var readyPods int32
err = wait.Poll(100*time.Millisecond, pollTimeout, func() (bool, error) {
err = wait.PollImmediate(pollInterval, pollTimeout, func() (bool, error) {
readyPods = 0
pods, err := d.c.Core().Pods(ns).List(metav1.ListOptions{LabelSelector: selector.String()})
if err != nil {
@@ -209,7 +217,7 @@ func (d *deploymentTester) waitForDeploymentStatusValidAndMarkPodsReady() error
}
func (d *deploymentTester) updateDeployment(applyUpdate testutil.UpdateDeploymentFunc) (*v1beta1.Deployment, error) {
return testutil.UpdateDeploymentWithRetries(d.c, d.deployment.Namespace, d.deployment.Name, applyUpdate, d.t.Logf)
return testutil.UpdateDeploymentWithRetries(d.c, d.deployment.Namespace, d.deployment.Name, applyUpdate, d.t.Logf, pollInterval, pollTimeout)
}
func (d *deploymentTester) waitForObservedDeployment(desiredGeneration int64) error {
@@ -249,14 +257,6 @@ func (d *deploymentTester) expectNewReplicaSet() (*v1beta1.ReplicaSet, error) {
return rs, nil
}
func pauseFn() func(update *v1beta1.Deployment) {
return func(update *v1beta1.Deployment) {
update.Spec.Paused = true
}
}
func resumeFn() func(update *v1beta1.Deployment) {
return func(update *v1beta1.Deployment) {
update.Spec.Paused = false
}
func (d *deploymentTester) updateReplicaSet(name string, applyUpdate testutil.UpdateReplicaSetFunc) (*v1beta1.ReplicaSet, error) {
return testutil.UpdateReplicaSetWithRetries(d.c, d.deployment.Namespace, name, applyUpdate, d.t.Logf, pollInterval, pollTimeout)
}