Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
1ca6120a
Commit
1ca6120a
authored
Oct 13, 2017
by
Janet Kuo
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move deployment e2e test for rollback with no revision to integration
parent
4de496d4
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
228 additions
and
104 deletions
+228
-104
aggregator.go
test/e2e/apimachinery/aggregator.go
+1
-1
deployment.go
test/e2e/apps/deployment.go
+0
-0
BUILD
test/e2e/framework/BUILD
+0
-1
deployment_util.go
test/e2e/framework/deployment_util.go
+15
-81
deployments.go
test/e2e/upgrades/apps/deployments.go
+4
-4
deployment_test.go
test/integration/deployment/deployment_test.go
+125
-8
util.go
test/integration/deployment/util.go
+83
-9
deployment.go
test/utils/deployment.go
+0
-0
No files found.
test/e2e/apimachinery/aggregator.go
View file @
1ca6120a
...
@@ -360,7 +360,7 @@ func TestSampleAPIServer(f *framework.Framework, image string) {
...
@@ -360,7 +360,7 @@ func TestSampleAPIServer(f *framework.Framework, image string) {
// kubectl get deployments -n <aggregated-api-namespace> && status == Running
// kubectl get deployments -n <aggregated-api-namespace> && status == Running
// NOTE: aggregated apis should generally be set up in there own namespace (<aggregated-api-namespace>). As the test framework
// NOTE: aggregated apis should generally be set up in there own namespace (<aggregated-api-namespace>). As the test framework
// is setting up a new namespace, we are just using that.
// is setting up a new namespace, we are just using that.
err
=
framework
.
WaitForDeployment
StatusValid
(
client
,
deployment
)
err
=
framework
.
WaitForDeployment
Complete
(
client
,
deployment
)
// We seem to need to do additional waiting until the extension api service is actually up.
// We seem to need to do additional waiting until the extension api service is actually up.
err
=
wait
.
Poll
(
100
*
time
.
Millisecond
,
30
*
time
.
Second
,
func
()
(
bool
,
error
)
{
err
=
wait
.
Poll
(
100
*
time
.
Millisecond
,
30
*
time
.
Second
,
func
()
(
bool
,
error
)
{
...
...
test/e2e/apps/deployment.go
View file @
1ca6120a
This diff is collapsed.
Click to expand it.
test/e2e/framework/BUILD
View file @
1ca6120a
...
@@ -70,7 +70,6 @@ go_library(
...
@@ -70,7 +70,6 @@ go_library(
"//pkg/master/ports:go_default_library",
"//pkg/master/ports:go_default_library",
"//pkg/ssh:go_default_library",
"//pkg/ssh:go_default_library",
"//pkg/util/file:go_default_library",
"//pkg/util/file:go_default_library",
"//pkg/util/labels:go_default_library",
"//pkg/util/system:go_default_library",
"//pkg/util/system:go_default_library",
"//pkg/util/taints:go_default_library",
"//pkg/util/taints:go_default_library",
"//pkg/util/version:go_default_library",
"//pkg/util/version:go_default_library",
...
...
test/e2e/framework/deployment_util.go
View file @
1ca6120a
...
@@ -31,7 +31,6 @@ import (
...
@@ -31,7 +31,6 @@ import (
extensionsinternal
"k8s.io/kubernetes/pkg/apis/extensions"
extensionsinternal
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
deploymentutil
"k8s.io/kubernetes/pkg/controller/deployment/util"
deploymentutil
"k8s.io/kubernetes/pkg/controller/deployment/util"
labelsutil
"k8s.io/kubernetes/pkg/util/labels"
testutils
"k8s.io/kubernetes/test/utils"
testutils
"k8s.io/kubernetes/test/utils"
)
)
...
@@ -131,69 +130,17 @@ func NewDeployment(deploymentName string, replicas int32, podLabels map[string]s
...
@@ -131,69 +130,17 @@ func NewDeployment(deploymentName string, replicas int32, podLabels map[string]s
}
}
}
}
// Waits for the deployment
status to become valid (i.e. max unavailable and max surge aren't violated anymore)
.
// Waits for the deployment
to complete, and don't check if rolling update strategy is broken
.
//
Note that the status should stay valid at all times unless shortly after a scaling event or the deployment is just created.
//
Rolling update strategy is used only during a rolling update, and can be violated in other situations,
//
To verify that the deployment status is valid and wait for the rollout to finish, use WaitForDeploymentStatus instea
d.
//
such as shortly after a scaling event or the deployment is just create
d.
func
WaitForDeployment
StatusValid
(
c
clientset
.
Interface
,
d
*
extensions
.
Deployment
)
error
{
func
WaitForDeployment
Complete
(
c
clientset
.
Interface
,
d
*
extensions
.
Deployment
)
error
{
return
testutils
.
WaitForDeployment
StatusValid
(
c
,
d
,
Logf
,
Poll
,
pollLongTimeout
)
return
testutils
.
WaitForDeployment
Complete
(
c
,
d
,
Logf
,
Poll
,
pollLongTimeout
)
}
}
// Waits for the deployment to reach desired state.
// Waits for the deployment to complete, and check rolling update strategy isn't broken at any times.
// Returns an error if the deployment's rolling update strategy (max unavailable or max surge) is broken at any times.
// Rolling update strategy should not be broken during a rolling update.
func
WaitForDeploymentStatus
(
c
clientset
.
Interface
,
d
*
extensions
.
Deployment
)
error
{
func
WaitForDeploymentCompleteAndCheckRolling
(
c
clientset
.
Interface
,
d
*
extensions
.
Deployment
)
error
{
var
(
return
testutils
.
WaitForDeploymentCompleteAndCheckRolling
(
c
,
d
,
Logf
,
Poll
,
pollLongTimeout
)
oldRSs
,
allOldRSs
,
allRSs
[]
*
extensions
.
ReplicaSet
newRS
*
extensions
.
ReplicaSet
deployment
*
extensions
.
Deployment
)
err
:=
wait
.
Poll
(
Poll
,
5
*
time
.
Minute
,
func
()
(
bool
,
error
)
{
var
err
error
deployment
,
err
=
c
.
Extensions
()
.
Deployments
(
d
.
Namespace
)
.
Get
(
d
.
Name
,
metav1
.
GetOptions
{})
if
err
!=
nil
{
return
false
,
err
}
oldRSs
,
allOldRSs
,
newRS
,
err
=
deploymentutil
.
GetAllReplicaSets
(
deployment
,
c
.
ExtensionsV1beta1
())
if
err
!=
nil
{
return
false
,
err
}
if
newRS
==
nil
{
// New RS hasn't been created yet.
return
false
,
nil
}
allRSs
=
append
(
oldRSs
,
newRS
)
// The old/new ReplicaSets need to contain the pod-template-hash label
for
i
:=
range
allRSs
{
if
!
labelsutil
.
SelectorHasLabel
(
allRSs
[
i
]
.
Spec
.
Selector
,
extensions
.
DefaultDeploymentUniqueLabelKey
)
{
return
false
,
nil
}
}
totalCreated
:=
deploymentutil
.
GetReplicaCountForReplicaSets
(
allRSs
)
maxCreated
:=
*
(
deployment
.
Spec
.
Replicas
)
+
deploymentutil
.
MaxSurge
(
*
deployment
)
if
totalCreated
>
maxCreated
{
logReplicaSetsOfDeployment
(
deployment
,
allOldRSs
,
newRS
)
logPodsOfDeployment
(
c
,
deployment
,
allRSs
)
return
false
,
fmt
.
Errorf
(
"total pods created: %d, more than the max allowed: %d"
,
totalCreated
,
maxCreated
)
}
minAvailable
:=
deploymentutil
.
MinAvailable
(
deployment
)
if
deployment
.
Status
.
AvailableReplicas
<
minAvailable
{
logReplicaSetsOfDeployment
(
deployment
,
allOldRSs
,
newRS
)
logPodsOfDeployment
(
c
,
deployment
,
allRSs
)
return
false
,
fmt
.
Errorf
(
"total pods available: %d, less than the min required: %d"
,
deployment
.
Status
.
AvailableReplicas
,
minAvailable
)
}
// When the deployment status and its underlying resources reach the desired state, we're done
return
deploymentutil
.
DeploymentComplete
(
deployment
,
&
deployment
.
Status
),
nil
})
if
err
==
wait
.
ErrWaitTimeout
{
logReplicaSetsOfDeployment
(
deployment
,
allOldRSs
,
newRS
)
logPodsOfDeployment
(
c
,
deployment
,
allRSs
)
}
if
err
!=
nil
{
return
fmt
.
Errorf
(
"error waiting for deployment %q status to match expectation: %v"
,
d
.
Name
,
err
)
}
return
nil
}
}
// 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
...
@@ -217,21 +164,7 @@ func WaitForDeploymentUpdatedReplicasLTE(c clientset.Interface, ns, deploymentNa
...
@@ -217,21 +164,7 @@ func WaitForDeploymentUpdatedReplicasLTE(c clientset.Interface, ns, deploymentNa
// 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.
// Note that rollback should be cleared shortly, so we only wait for 1 minute here to fail early.
// Note that rollback should be cleared shortly, so we only wait for 1 minute here to fail early.
func
WaitForDeploymentRollbackCleared
(
c
clientset
.
Interface
,
ns
,
deploymentName
string
)
error
{
func
WaitForDeploymentRollbackCleared
(
c
clientset
.
Interface
,
ns
,
deploymentName
string
)
error
{
err
:=
wait
.
Poll
(
Poll
,
1
*
time
.
Minute
,
func
()
(
bool
,
error
)
{
return
testutils
.
WaitForDeploymentRollbackCleared
(
c
,
ns
,
deploymentName
,
Poll
,
pollShortTimeout
)
deployment
,
err
:=
c
.
Extensions
()
.
Deployments
(
ns
)
.
Get
(
deploymentName
,
metav1
.
GetOptions
{})
if
err
!=
nil
{
return
false
,
err
}
// Rollback not set or is kicked off
if
deployment
.
Spec
.
RollbackTo
==
nil
{
return
true
,
nil
}
return
false
,
nil
})
if
err
!=
nil
{
return
fmt
.
Errorf
(
"error waiting for deployment %s rollbackTo to be cleared: %v"
,
deploymentName
,
err
)
}
return
nil
}
}
// WatchRecreateDeployment watches Recreate deployments and ensures no new pods will run at the same time with
// WatchRecreateDeployment watches Recreate deployments and ensures no new pods will run at the same time with
...
@@ -290,10 +223,6 @@ func logPodsOfDeployment(c clientset.Interface, deployment *extensions.Deploymen
...
@@ -290,10 +223,6 @@ func logPodsOfDeployment(c clientset.Interface, deployment *extensions.Deploymen
testutils
.
LogPodsOfDeployment
(
c
,
deployment
,
rsList
,
Logf
)
testutils
.
LogPodsOfDeployment
(
c
,
deployment
,
rsList
,
Logf
)
}
}
func
WaitForDeploymentCompletes
(
c
clientset
.
Interface
,
deployment
*
extensions
.
Deployment
)
error
{
return
testutils
.
WaitForDeploymentCompletes
(
c
,
deployment
,
Logf
,
Poll
,
pollLongTimeout
)
}
func
WaitForDeploymentRevision
(
c
clientset
.
Interface
,
d
*
extensions
.
Deployment
,
targetRevision
string
)
error
{
func
WaitForDeploymentRevision
(
c
clientset
.
Interface
,
d
*
extensions
.
Deployment
,
targetRevision
string
)
error
{
err
:=
wait
.
PollImmediate
(
Poll
,
pollLongTimeout
,
func
()
(
bool
,
error
)
{
err
:=
wait
.
PollImmediate
(
Poll
,
pollLongTimeout
,
func
()
(
bool
,
error
)
{
deployment
,
err
:=
c
.
ExtensionsV1beta1
()
.
Deployments
(
d
.
Namespace
)
.
Get
(
d
.
Name
,
metav1
.
GetOptions
{})
deployment
,
err
:=
c
.
ExtensionsV1beta1
()
.
Deployments
(
d
.
Namespace
)
.
Get
(
d
.
Name
,
metav1
.
GetOptions
{})
...
@@ -308,3 +237,8 @@ func WaitForDeploymentRevision(c clientset.Interface, d *extensions.Deployment,
...
@@ -308,3 +237,8 @@ func WaitForDeploymentRevision(c clientset.Interface, d *extensions.Deployment,
}
}
return
nil
return
nil
}
}
// CheckDeploymentRevisionAndImage checks if the input deployment's and its new replica set's revision and image are as expected.
func
CheckDeploymentRevisionAndImage
(
c
clientset
.
Interface
,
ns
,
deploymentName
,
revision
,
image
string
)
error
{
return
testutils
.
CheckDeploymentRevisionAndImage
(
c
,
ns
,
deploymentName
,
revision
,
image
)
}
test/e2e/upgrades/apps/deployments.go
View file @
1ca6120a
...
@@ -63,7 +63,7 @@ func (t *DeploymentUpgradeTest) Setup(f *framework.Framework) {
...
@@ -63,7 +63,7 @@ func (t *DeploymentUpgradeTest) Setup(f *framework.Framework) {
framework
.
ExpectNoError
(
err
)
framework
.
ExpectNoError
(
err
)
By
(
fmt
.
Sprintf
(
"Waiting deployment %q to complete"
,
deploymentName
))
By
(
fmt
.
Sprintf
(
"Waiting deployment %q to complete"
,
deploymentName
))
framework
.
ExpectNoError
(
framework
.
WaitForDeploymentComplete
s
(
c
,
deployment
))
framework
.
ExpectNoError
(
framework
.
WaitForDeploymentComplete
(
c
,
deployment
))
By
(
fmt
.
Sprintf
(
"Getting replicaset revision 1 of deployment %q"
,
deploymentName
))
By
(
fmt
.
Sprintf
(
"Getting replicaset revision 1 of deployment %q"
,
deploymentName
))
rsSelector
,
err
:=
metav1
.
LabelSelectorAsSelector
(
d
.
Spec
.
Selector
)
rsSelector
,
err
:=
metav1
.
LabelSelectorAsSelector
(
d
.
Spec
.
Selector
)
...
@@ -87,7 +87,7 @@ func (t *DeploymentUpgradeTest) Setup(f *framework.Framework) {
...
@@ -87,7 +87,7 @@ func (t *DeploymentUpgradeTest) Setup(f *framework.Framework) {
framework
.
ExpectNoError
(
err
)
framework
.
ExpectNoError
(
err
)
By
(
fmt
.
Sprintf
(
"Waiting deployment %q to complete"
,
deploymentName
))
By
(
fmt
.
Sprintf
(
"Waiting deployment %q to complete"
,
deploymentName
))
framework
.
ExpectNoError
(
framework
.
WaitForDeploymentComplete
s
(
c
,
deployment
))
framework
.
ExpectNoError
(
framework
.
WaitForDeploymentComplete
(
c
,
deployment
))
By
(
fmt
.
Sprintf
(
"Getting replicasets revision 1 and 2 of deployment %q"
,
deploymentName
))
By
(
fmt
.
Sprintf
(
"Getting replicasets revision 1 and 2 of deployment %q"
,
deploymentName
))
rsList
,
err
=
rsClient
.
List
(
metav1
.
ListOptions
{
LabelSelector
:
rsSelector
.
String
()})
rsList
,
err
=
rsClient
.
List
(
metav1
.
ListOptions
{
LabelSelector
:
rsSelector
.
String
()})
...
@@ -153,7 +153,7 @@ func (t *DeploymentUpgradeTest) Test(f *framework.Framework, done <-chan struct{
...
@@ -153,7 +153,7 @@ func (t *DeploymentUpgradeTest) Test(f *framework.Framework, done <-chan struct{
Expect
(
deployment
.
Annotations
[
deploymentutil
.
RevisionAnnotation
])
.
To
(
Equal
(
"2"
))
Expect
(
deployment
.
Annotations
[
deploymentutil
.
RevisionAnnotation
])
.
To
(
Equal
(
"2"
))
By
(
fmt
.
Sprintf
(
"Waiting for deployment %q to complete adoption"
,
deploymentName
))
By
(
fmt
.
Sprintf
(
"Waiting for deployment %q to complete adoption"
,
deploymentName
))
framework
.
ExpectNoError
(
framework
.
WaitForDeploymentComplete
s
(
c
,
deployment
))
framework
.
ExpectNoError
(
framework
.
WaitForDeploymentComplete
(
c
,
deployment
))
// Verify the upgraded deployment is active by scaling up the deployment by 1
// Verify the upgraded deployment is active by scaling up the deployment by 1
By
(
fmt
.
Sprintf
(
"Scaling up replicaset of deployment %q by 1"
,
deploymentName
))
By
(
fmt
.
Sprintf
(
"Scaling up replicaset of deployment %q by 1"
,
deploymentName
))
...
@@ -163,7 +163,7 @@ func (t *DeploymentUpgradeTest) Test(f *framework.Framework, done <-chan struct{
...
@@ -163,7 +163,7 @@ func (t *DeploymentUpgradeTest) Test(f *framework.Framework, done <-chan struct{
framework
.
ExpectNoError
(
err
)
framework
.
ExpectNoError
(
err
)
By
(
fmt
.
Sprintf
(
"Waiting for deployment %q to complete after scaling"
,
deploymentName
))
By
(
fmt
.
Sprintf
(
"Waiting for deployment %q to complete after scaling"
,
deploymentName
))
framework
.
ExpectNoError
(
framework
.
WaitForDeploymentComplete
s
(
c
,
deployment
))
framework
.
ExpectNoError
(
framework
.
WaitForDeploymentComplete
(
c
,
deployment
))
}
}
// Teardown cleans up any remaining resources.
// Teardown cleans up any remaining resources.
...
...
test/integration/deployment/deployment_test.go
View file @
1ca6120a
...
@@ -59,8 +59,9 @@ func TestNewDeployment(t *testing.T) {
...
@@ -59,8 +59,9 @@ func TestNewDeployment(t *testing.T) {
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
// Make sure the Deployment status becomes valid while manually marking Deployment pods as ready at the same time
// Make sure the Deployment completes while manually marking Deployment pods as ready at the same time.
if
err
:=
tester
.
waitForDeploymentStatusValidAndMarkPodsReady
();
err
!=
nil
{
// Use soft check because this deployment was just created and rolling update strategy might be violated.
if
err
:=
tester
.
waitForDeploymentCompleteAndMarkPodsReady
();
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
...
@@ -187,8 +188,9 @@ func TestPausedDeployment(t *testing.T) {
...
@@ -187,8 +188,9 @@ func TestPausedDeployment(t *testing.T) {
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
// Make sure the Deployment status becomes valid while manually marking Deployment pods as ready at the same time
// Make sure the Deployment completes while manually marking Deployment pods as ready at the same time.
if
err
:=
tester
.
waitForDeploymentStatusValidAndMarkPodsReady
();
err
!=
nil
{
// Use soft check because this deployment was just created and rolling update strategy might be violated.
if
err
:=
tester
.
waitForDeploymentCompleteAndMarkPodsReady
();
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
...
@@ -271,8 +273,9 @@ func TestScalePausedDeployment(t *testing.T) {
...
@@ -271,8 +273,9 @@ func TestScalePausedDeployment(t *testing.T) {
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
// Make sure the Deployment status becomes valid while manually marking Deployment pods as ready at the same time
// Make sure the Deployment completes while manually marking Deployment pods as ready at the same time.
if
err
:=
tester
.
waitForDeploymentStatusValidAndMarkPodsReady
();
err
!=
nil
{
// Use soft check because this deployment was just created and rolling update strategy might be violated.
if
err
:=
tester
.
waitForDeploymentCompleteAndMarkPodsReady
();
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
...
@@ -315,8 +318,9 @@ func TestScalePausedDeployment(t *testing.T) {
...
@@ -315,8 +318,9 @@ func TestScalePausedDeployment(t *testing.T) {
t
.
Errorf
(
"expected new replicaset replicas = %d, got %d"
,
newReplicas
,
*
rs
.
Spec
.
Replicas
)
t
.
Errorf
(
"expected new replicaset replicas = %d, got %d"
,
newReplicas
,
*
rs
.
Spec
.
Replicas
)
}
}
// Make sure the Deployment status becomes valid while manually marking Deployment pods as ready at the same time
// Make sure the Deployment completes while manually marking Deployment pods as ready at the same time.
if
err
:=
tester
.
waitForDeploymentStatusValidAndMarkPodsReady
();
err
!=
nil
{
// Use soft check because this deployment was just scaled and rolling update strategy might be violated.
if
err
:=
tester
.
waitForDeploymentCompleteAndMarkPodsReady
();
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
}
}
...
@@ -381,3 +385,116 @@ func TestDeploymentHashCollision(t *testing.T) {
...
@@ -381,3 +385,116 @@ func TestDeploymentHashCollision(t *testing.T) {
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
}
}
// Deployment supports rollback even when there's old replica set without revision.
func
TestRollbackDeploymentRSNoRevision
(
t
*
testing
.
T
)
{
s
,
closeFn
,
rm
,
dc
,
informers
,
c
:=
dcSetup
(
t
)
defer
closeFn
()
name
:=
"test-rollback-no-revision-deployment"
ns
:=
framework
.
CreateTestingNamespace
(
name
,
s
,
t
)
defer
framework
.
DeleteTestingNamespace
(
ns
,
s
,
t
)
// Create an old RS without revision
rsName
:=
"test-rollback-no-revision-controller"
rsReplicas
:=
int32
(
1
)
rs
:=
newReplicaSet
(
rsName
,
ns
.
Name
,
rsReplicas
)
rs
.
Annotations
=
make
(
map
[
string
]
string
)
rs
.
Annotations
[
"make"
]
=
"difference"
rs
.
Spec
.
Template
.
Spec
.
Containers
[
0
]
.
Image
=
"different-image"
_
,
err
:=
c
.
ExtensionsV1beta1
()
.
ReplicaSets
(
ns
.
Name
)
.
Create
(
rs
)
if
err
!=
nil
{
t
.
Fatalf
(
"failed to create replicaset %s: %v"
,
rsName
,
err
)
}
replicas
:=
int32
(
1
)
tester
:=
&
deploymentTester
{
t
:
t
,
c
:
c
,
deployment
:
newDeployment
(
name
,
ns
.
Name
,
replicas
)}
oriImage
:=
tester
.
deployment
.
Spec
.
Template
.
Spec
.
Containers
[
0
]
.
Image
// Create a deployment which have different template than the replica set created above.
if
tester
.
deployment
,
err
=
c
.
ExtensionsV1beta1
()
.
Deployments
(
ns
.
Name
)
.
Create
(
tester
.
deployment
);
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
)
}
// 1. Rollback to the last revision
// Since there's only 1 revision in history, it should still be revision 1
revision
:=
int64
(
0
)
rollback
:=
newDeploymentRollback
(
tester
.
deployment
.
Name
,
nil
,
revision
)
if
err
=
c
.
ExtensionsV1beta1
()
.
Deployments
(
ns
.
Name
)
.
Rollback
(
rollback
);
err
!=
nil
{
t
.
Fatalf
(
"failed to roll back deployment %s to last revision: %v"
,
tester
.
deployment
.
Name
,
err
)
}
// Wait for the deployment to start rolling back
if
err
=
tester
.
waitForDeploymentRollbackCleared
();
err
!=
nil
{
t
.
Fatalf
(
"failed to roll back deployment %s to last revision: %v"
,
tester
.
deployment
.
Name
,
err
)
}
// TODO: report RollbackRevisionNotFound in deployment status and check it here
// The pod template shouldn't change since there's no last revision
// Check if the deployment is still revision 1 and still has the old pod template
err
=
tester
.
checkDeploymentRevisionAndImage
(
"1"
,
oriImage
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// 2. Update the deployment to revision 2.
updatedImage
:=
"update"
tester
.
deployment
,
err
=
tester
.
updateDeployment
(
func
(
update
*
v1beta1
.
Deployment
)
{
update
.
Spec
.
Template
.
Spec
.
Containers
[
0
]
.
Name
=
updatedImage
update
.
Spec
.
Template
.
Spec
.
Containers
[
0
]
.
Image
=
updatedImage
})
if
err
!=
nil
{
t
.
Fatalf
(
"failed updating deployment %s: %v"
,
tester
.
deployment
.
Name
,
err
)
}
// Use observedGeneration to determine if the controller noticed the pod template update.
// Wait for the controller to notice the resume.
if
err
=
tester
.
waitForObservedDeployment
(
tester
.
deployment
.
Generation
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
// Wait for it to be updated to revision 2
if
err
=
tester
.
waitForDeploymentRevisionAndImage
(
"2"
,
updatedImage
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
// Wait for the Deployment to complete while manually marking Deployment pods as ready at the same time
if
err
=
tester
.
waitForDeploymentCompleteAndCheckRollingAndMarkPodsReady
();
err
!=
nil
{
t
.
Fatal
(
err
)
}
// 3. Update the deploymentRollback to rollback to revision 1
revision
=
int64
(
1
)
rollback
=
newDeploymentRollback
(
tester
.
deployment
.
Name
,
nil
,
revision
)
if
err
=
c
.
ExtensionsV1beta1
()
.
Deployments
(
ns
.
Name
)
.
Rollback
(
rollback
);
err
!=
nil
{
t
.
Fatalf
(
"failed to roll back deployment %s to revision %d: %v"
,
tester
.
deployment
.
Name
,
revision
,
err
)
}
// Wait for the deployment to start rolling back
if
err
=
tester
.
waitForDeploymentRollbackCleared
();
err
!=
nil
{
t
.
Fatalf
(
"failed to roll back deployment %s to revision %d: %v"
,
tester
.
deployment
.
Name
,
revision
,
err
)
}
// TODO: report RollbackDone in deployment status and check it here
// The pod template should be updated to the one in revision 1
// Wait for it to be updated to revision 3
if
err
=
tester
.
waitForDeploymentRevisionAndImage
(
"3"
,
oriImage
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
// Wait for the Deployment to complete while manually marking Deployment pods as ready at the same time
if
err
=
tester
.
waitForDeploymentCompleteAndCheckRollingAndMarkPodsReady
();
err
!=
nil
{
t
.
Fatal
(
err
)
}
}
test/integration/deployment/util.go
View file @
1ca6120a
...
@@ -41,8 +41,8 @@ const (
...
@@ -41,8 +41,8 @@ const (
pollInterval
=
100
*
time
.
Millisecond
pollInterval
=
100
*
time
.
Millisecond
pollTimeout
=
60
*
time
.
Second
pollTimeout
=
60
*
time
.
Second
fake
Image
Name
=
"fake-name"
fake
Container
Name
=
"fake-name"
fakeImage
=
"fakeimage"
fakeImage
=
"fakeimage"
)
)
var
pauseFn
=
func
(
update
*
v1beta1
.
Deployment
)
{
var
pauseFn
=
func
(
update
*
v1beta1
.
Deployment
)
{
...
@@ -87,7 +87,7 @@ func newDeployment(name, ns string, replicas int32) *v1beta1.Deployment {
...
@@ -87,7 +87,7 @@ func newDeployment(name, ns string, replicas int32) *v1beta1.Deployment {
Spec
:
v1
.
PodSpec
{
Spec
:
v1
.
PodSpec
{
Containers
:
[]
v1
.
Container
{
Containers
:
[]
v1
.
Container
{
{
{
Name
:
fake
Image
Name
,
Name
:
fake
Container
Name
,
Image
:
fakeImage
,
Image
:
fakeImage
,
},
},
},
},
...
@@ -97,6 +97,46 @@ func newDeployment(name, ns string, replicas int32) *v1beta1.Deployment {
...
@@ -97,6 +97,46 @@ func newDeployment(name, ns string, replicas int32) *v1beta1.Deployment {
}
}
}
}
func
newReplicaSet
(
name
,
ns
string
,
replicas
int32
)
*
v1beta1
.
ReplicaSet
{
return
&
v1beta1
.
ReplicaSet
{
TypeMeta
:
metav1
.
TypeMeta
{
Kind
:
"ReplicaSet"
,
APIVersion
:
"extensions/v1beta1"
,
},
ObjectMeta
:
metav1
.
ObjectMeta
{
Namespace
:
ns
,
Name
:
name
,
},
Spec
:
v1beta1
.
ReplicaSetSpec
{
Selector
:
&
metav1
.
LabelSelector
{
MatchLabels
:
testLabels
(),
},
Replicas
:
&
replicas
,
Template
:
v1
.
PodTemplateSpec
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Labels
:
testLabels
(),
},
Spec
:
v1
.
PodSpec
{
Containers
:
[]
v1
.
Container
{
{
Name
:
fakeContainerName
,
Image
:
fakeImage
,
},
},
},
},
},
}
}
func
newDeploymentRollback
(
name
string
,
annotations
map
[
string
]
string
,
revision
int64
)
*
v1beta1
.
DeploymentRollback
{
return
&
v1beta1
.
DeploymentRollback
{
Name
:
name
,
UpdatedAnnotations
:
annotations
,
RollbackTo
:
v1beta1
.
RollbackConfig
{
Revision
:
revision
},
}
}
// dcSetup sets up necessities for Deployment integration test, including master, apiserver, informers, and clientset
// dcSetup sets up necessities for Deployment integration test, including master, apiserver, informers, and clientset
func
dcSetup
(
t
*
testing
.
T
)
(
*
httptest
.
Server
,
framework
.
CloseFunc
,
*
replicaset
.
ReplicaSetController
,
*
deployment
.
DeploymentController
,
informers
.
SharedInformerFactory
,
clientset
.
Interface
)
{
func
dcSetup
(
t
*
testing
.
T
)
(
*
httptest
.
Server
,
framework
.
CloseFunc
,
*
replicaset
.
ReplicaSetController
,
*
deployment
.
DeploymentController
,
informers
.
SharedInformerFactory
,
clientset
.
Interface
)
{
masterConfig
:=
framework
.
NewIntegrationTestMasterConfig
()
masterConfig
:=
framework
.
NewIntegrationTestMasterConfig
()
...
@@ -198,18 +238,42 @@ func (d *deploymentTester) markAllPodsReady() {
...
@@ -198,18 +238,42 @@ func (d *deploymentTester) markAllPodsReady() {
}
}
}
}
func
(
d
*
deploymentTester
)
waitForDeploymentStatusValid
()
error
{
// Waits for the deployment to complete, and check rolling update strategy isn't broken at any times.
return
testutil
.
WaitForDeploymentStatusValid
(
d
.
c
,
d
.
deployment
,
d
.
t
.
Logf
,
pollInterval
,
pollTimeout
)
// Rolling update strategy should not be broken during a rolling update.
func
(
d
*
deploymentTester
)
waitForDeploymentCompleteAndCheckRolling
()
error
{
return
testutil
.
WaitForDeploymentCompleteAndCheckRolling
(
d
.
c
,
d
.
deployment
,
d
.
t
.
Logf
,
pollInterval
,
pollTimeout
)
}
}
// waitForDeploymentStatusValidAndMarkPodsReady waits for the Deployment status to become valid
// Waits for the deployment to complete, and don't check if rolling update strategy is broken.
// Rolling update strategy is used only during a rolling update, and can be violated in other situations,
// such as shortly after a scaling event or the deployment is just created.
func
(
d
*
deploymentTester
)
waitForDeploymentComplete
()
error
{
return
testutil
.
WaitForDeploymentComplete
(
d
.
c
,
d
.
deployment
,
d
.
t
.
Logf
,
pollInterval
,
pollTimeout
)
}
// waitForDeploymentCompleteAndCheckRollingAndMarkPodsReady waits for the Deployment to complete
// while marking all Deployment pods as ready at the same time.
// while marking all Deployment pods as ready at the same time.
func
(
d
*
deploymentTester
)
waitForDeploymentStatusValidAndMarkPodsReady
()
error
{
// Uses hard check to make sure rolling update strategy is not violated at any times.
func
(
d
*
deploymentTester
)
waitForDeploymentCompleteAndCheckRollingAndMarkPodsReady
()
error
{
// Manually mark all Deployment pods as ready in a separate goroutine
// Manually mark all Deployment pods as ready in a separate goroutine
go
d
.
markAllPodsReady
()
go
d
.
markAllPodsReady
()
// Make sure the Deployment status is valid while Deployment pods are becoming ready
// Wait for the Deployment status to complete while Deployment pods are becoming ready
err
:=
d
.
waitForDeploymentStatusValid
()
err
:=
d
.
waitForDeploymentCompleteAndCheckRolling
()
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to wait for Deployment %s to complete: %v"
,
d
.
deployment
.
Name
,
err
)
}
return
nil
}
// waitForDeploymentCompleteAndMarkPodsReady waits for the Deployment to complete
// while marking all Deployment pods as ready at the same time.
func
(
d
*
deploymentTester
)
waitForDeploymentCompleteAndMarkPodsReady
()
error
{
// Manually mark all Deployment pods as ready in a separate goroutine
go
d
.
markAllPodsReady
()
// Wait for the Deployment status to complete using soft check, while Deployment pods are becoming ready
err
:=
d
.
waitForDeploymentComplete
()
if
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to wait for Deployment status %s: %v"
,
d
.
deployment
.
Name
,
err
)
return
fmt
.
Errorf
(
"failed to wait for Deployment status %s: %v"
,
d
.
deployment
.
Name
,
err
)
}
}
...
@@ -260,3 +324,13 @@ func (d *deploymentTester) expectNewReplicaSet() (*v1beta1.ReplicaSet, error) {
...
@@ -260,3 +324,13 @@ func (d *deploymentTester) expectNewReplicaSet() (*v1beta1.ReplicaSet, error) {
func
(
d
*
deploymentTester
)
updateReplicaSet
(
name
string
,
applyUpdate
testutil
.
UpdateReplicaSetFunc
)
(
*
v1beta1
.
ReplicaSet
,
error
)
{
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
)
return
testutil
.
UpdateReplicaSetWithRetries
(
d
.
c
,
d
.
deployment
.
Namespace
,
name
,
applyUpdate
,
d
.
t
.
Logf
,
pollInterval
,
pollTimeout
)
}
}
// waitForDeploymentRollbackCleared waits for deployment either started rolling back or doesn't need to rollback.
func
(
d
*
deploymentTester
)
waitForDeploymentRollbackCleared
()
error
{
return
testutil
.
WaitForDeploymentRollbackCleared
(
d
.
c
,
d
.
deployment
.
Namespace
,
d
.
deployment
.
Name
,
pollInterval
,
pollTimeout
)
}
// checkDeploymentRevisionAndImage checks if the input deployment's and its new replica set's revision and image are as expected.
func
(
d
*
deploymentTester
)
checkDeploymentRevisionAndImage
(
revision
,
image
string
)
error
{
return
testutil
.
CheckDeploymentRevisionAndImage
(
d
.
c
,
d
.
deployment
.
Namespace
,
d
.
deployment
.
Name
,
revision
,
image
)
}
test/utils/deployment.go
View file @
1ca6120a
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment