2015-09-24 18:16:17 +00:00
/ *
2016-06-03 00:25:58 +00:00
Copyright 2015 The Kubernetes Authors .
2015-09-24 18:16:17 +00:00
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
package e2e
import (
2015-09-29 23:55:06 +00:00
"fmt"
2016-09-15 15:58:19 +00:00
"math/rand"
2016-09-02 20:54:20 +00:00
"strings"
2016-01-21 10:12:58 +00:00
"time"
2015-10-26 23:20:43 +00:00
2016-05-10 21:44:45 +00:00
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
2015-09-24 18:16:17 +00:00
"k8s.io/kubernetes/pkg/api"
2016-05-10 21:44:45 +00:00
"k8s.io/kubernetes/pkg/api/annotations"
2015-12-02 15:09:01 +00:00
"k8s.io/kubernetes/pkg/api/errors"
2016-11-18 20:55:17 +00:00
"k8s.io/kubernetes/pkg/api/v1"
extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions"
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
2016-12-03 19:06:03 +00:00
metav1 "k8s.io/kubernetes/pkg/apis/meta/v1"
2016-12-14 01:18:17 +00:00
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/extensions/v1beta1"
2016-12-14 03:39:50 +00:00
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
2016-07-05 07:29:09 +00:00
deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util"
2016-02-04 23:26:06 +00:00
"k8s.io/kubernetes/pkg/kubectl"
2016-03-11 18:34:13 +00:00
"k8s.io/kubernetes/pkg/labels"
2016-02-11 08:51:21 +00:00
"k8s.io/kubernetes/pkg/util"
2015-12-01 23:55:13 +00:00
"k8s.io/kubernetes/pkg/util/intstr"
2015-12-02 15:09:01 +00:00
"k8s.io/kubernetes/pkg/util/wait"
2016-03-11 18:34:13 +00:00
"k8s.io/kubernetes/pkg/watch"
2016-04-07 17:21:31 +00:00
"k8s.io/kubernetes/test/e2e/framework"
2015-09-24 18:16:17 +00:00
)
2016-03-06 01:40:59 +00:00
const (
// nginxImage defined in kubectl.go
nginxImageName = "nginx"
redisImage = "gcr.io/google_containers/redis:e2e"
redisImageName = "redis"
)
2016-04-07 17:21:31 +00:00
var _ = framework . KubeDescribe ( "Deployment" , func ( ) {
f := framework . NewDefaultFramework ( "deployment" )
2015-09-24 18:16:17 +00:00
2016-10-07 10:16:34 +00:00
// TODO: Add failure traps once we have JustAfterEach
// See https://github.com/onsi/ginkgo/issues/303
2015-09-24 18:16:17 +00:00
It ( "deployment should create new pods" , func ( ) {
testNewDeployment ( f )
} )
2016-10-07 10:16:34 +00:00
It ( "deployment reaping should cascade to its replica sets and pods" , func ( ) {
testDeleteDeployment ( f )
} )
2016-01-29 03:08:19 +00:00
It ( "RollingUpdateDeployment should delete old pods and create new ones" , func ( ) {
2015-09-29 23:55:06 +00:00
testRollingUpdateDeployment ( f )
} )
2016-01-14 03:11:03 +00:00
It ( "RecreateDeployment should delete old pods and create new ones" , func ( ) {
2016-01-13 03:27:26 +00:00
testRecreateDeployment ( f )
} )
2016-01-20 00:40:18 +00:00
It ( "deployment should delete old replica sets" , func ( ) {
2016-01-28 06:13:07 +00:00
testDeploymentCleanUpPolicy ( f )
} )
2016-02-24 23:00:59 +00:00
It ( "deployment should support rollover" , func ( ) {
2015-12-01 23:55:13 +00:00
testRolloverDeployment ( f )
} )
2016-02-24 23:00:59 +00:00
It ( "paused deployment should be ignored by the controller" , func ( ) {
2016-01-21 10:12:58 +00:00
testPausedDeployment ( f )
} )
2016-02-24 23:00:59 +00:00
It ( "deployment should support rollback" , func ( ) {
2016-01-15 02:04:05 +00:00
testRollbackDeployment ( f )
} )
2016-02-24 23:00:59 +00:00
It ( "deployment should support rollback when there's replica set with no revision" , func ( ) {
2016-01-20 00:40:18 +00:00
testRollbackDeploymentRSNoRevision ( f )
2016-01-15 02:04:05 +00:00
} )
2016-02-11 18:57:42 +00:00
It ( "deployment should label adopted RSs and pods" , func ( ) {
testDeploymentLabelAdopted ( f )
} )
2016-01-28 16:35:14 +00:00
It ( "paused deployment should be able to scale" , func ( ) {
testScalePausedDeployment ( f )
} )
2016-08-02 00:04:00 +00:00
It ( "scaled rollout deployment should not block on annotation check" , func ( ) {
2016-06-29 10:55:39 +00:00
testScaledRolloutDeployment ( f )
} )
2016-08-17 22:37:04 +00:00
It ( "overlapping deployment should not fight with each other" , func ( ) {
testOverlappingDeployment ( f )
} )
2016-09-15 15:58:19 +00:00
It ( "lack of progress should be reported in the deployment status" , func ( ) {
testFailedDeployment ( f )
} )
It ( "iterative rollouts should eventually progress" , func ( ) {
testIterativeDeployments ( f )
} )
2016-07-25 18:22:18 +00:00
// TODO: add tests that cover deployment.Spec.MinReadySeconds once we solved clock-skew issues
2016-10-07 10:16:34 +00:00
// See https://github.com/kubernetes/kubernetes/issues/29229
2015-09-24 18:16:17 +00:00
} )
2016-04-27 04:35:14 +00:00
func newDeployment ( deploymentName string , replicas int32 , podLabels map [ string ] string , imageName string , image string , strategyType extensions . DeploymentStrategyType , revisionHistoryLimit * int32 ) * extensions . Deployment {
2015-12-02 15:09:01 +00:00
zero := int64 ( 0 )
2015-12-01 23:55:13 +00:00
return & extensions . Deployment {
2016-11-18 20:55:17 +00:00
ObjectMeta : v1 . ObjectMeta {
2015-09-24 18:16:17 +00:00
Name : deploymentName ,
} ,
2015-10-09 22:49:10 +00:00
Spec : extensions . DeploymentSpec {
2016-11-18 20:55:17 +00:00
Replicas : func ( i int32 ) * int32 { return & i } ( replicas ) ,
2016-12-03 18:57:26 +00:00
Selector : & metav1 . LabelSelector { MatchLabels : podLabels } ,
2016-01-13 03:27:26 +00:00
Strategy : extensions . DeploymentStrategy {
Type : strategyType ,
} ,
2016-01-28 06:13:07 +00:00
RevisionHistoryLimit : revisionHistoryLimit ,
2016-11-18 20:55:17 +00:00
Template : v1 . PodTemplateSpec {
ObjectMeta : v1 . ObjectMeta {
2015-09-24 18:16:17 +00:00
Labels : podLabels ,
} ,
2016-11-18 20:55:17 +00:00
Spec : v1 . PodSpec {
2015-12-02 15:09:01 +00:00
TerminationGracePeriodSeconds : & zero ,
2016-11-18 20:55:17 +00:00
Containers : [ ] v1 . Container {
2015-09-24 18:16:17 +00:00
{
2015-12-01 23:55:13 +00:00
Name : imageName ,
Image : image ,
2015-09-24 18:16:17 +00:00
} ,
} ,
} ,
} ,
} ,
2015-12-01 23:55:13 +00:00
}
}
2016-01-15 02:04:05 +00:00
func newDeploymentRollback ( name string , annotations map [ string ] string , revision int64 ) * extensions . DeploymentRollback {
return & extensions . DeploymentRollback {
Name : name ,
UpdatedAnnotations : annotations ,
RollbackTo : extensions . RollbackConfig { Revision : revision } ,
}
}
2016-01-20 00:40:18 +00:00
// checkDeploymentRevision checks if the input deployment's and its new replica set's revision and images are as expected.
2016-09-22 15:00:19 +00:00
func checkDeploymentRevision ( c clientset . Interface , ns , deploymentName , revision , imageName , image string ) ( * extensions . Deployment , * extensions . ReplicaSet ) {
2016-12-07 14:40:26 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName , metav1 . GetOptions { } )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-20 00:40:18 +00:00
// Check revision of the new replica set of this deployment
2016-02-28 02:13:32 +00:00
newRS , err := deploymentutil . GetNewReplicaSet ( deployment , c )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-20 00:40:18 +00:00
Expect ( newRS . Annotations ) . NotTo ( Equal ( nil ) )
Expect ( newRS . Annotations [ deploymentutil . RevisionAnnotation ] ) . Should ( Equal ( revision ) )
2016-01-15 02:04:05 +00:00
// Check revision of This deployment
Expect ( deployment . Annotations ) . NotTo ( Equal ( nil ) )
Expect ( deployment . Annotations [ deploymentutil . RevisionAnnotation ] ) . Should ( Equal ( revision ) )
if len ( imageName ) > 0 {
2016-01-20 00:40:18 +00:00
// Check the image the new replica set creates
Expect ( newRS . Spec . Template . Spec . Containers [ 0 ] . Name ) . Should ( Equal ( imageName ) )
Expect ( newRS . Spec . Template . Spec . Containers [ 0 ] . Image ) . Should ( Equal ( image ) )
2016-01-15 02:04:05 +00:00
// Check the image the deployment creates
Expect ( deployment . Spec . Template . Spec . Containers [ 0 ] . Name ) . Should ( Equal ( imageName ) )
Expect ( deployment . Spec . Template . Spec . Containers [ 0 ] . Image ) . Should ( Equal ( image ) )
}
2016-01-20 00:40:18 +00:00
return deployment , newRS
2016-01-15 02:04:05 +00:00
}
2016-11-18 20:55:17 +00:00
func stopDeploymentOverlap ( c clientset . Interface , internalClient internalclientset . Interface , ns , deploymentName , overlapWith string ) {
stopDeploymentMaybeOverlap ( c , internalClient , ns , deploymentName , overlapWith )
2016-09-02 20:54:20 +00:00
}
2016-11-18 20:55:17 +00:00
func stopDeployment ( c clientset . Interface , internalClient internalclientset . Interface , ns , deploymentName string ) {
stopDeploymentMaybeOverlap ( c , internalClient , ns , deploymentName , "" )
2016-09-02 20:54:20 +00:00
}
2016-11-18 20:55:17 +00:00
func stopDeploymentMaybeOverlap ( c clientset . Interface , internalClient internalclientset . Interface , ns , deploymentName , overlapWith string ) {
2016-12-07 14:40:26 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName , metav1 . GetOptions { } )
2015-12-02 15:09:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-04-15 22:20:41 +00:00
framework . Logf ( "Deleting deployment %s" , deploymentName )
2016-11-18 20:55:17 +00:00
reaper , err := kubectl . ReaperFor ( extensionsinternal . Kind ( "Deployment" ) , internalClient )
2015-12-02 15:09:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
timeout := 1 * time . Minute
2016-10-27 06:58:20 +00:00
2015-12-02 15:09:01 +00:00
err = reaper . Stop ( ns , deployment . Name , timeout , api . NewDeleteOptions ( 0 ) )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-04-15 22:20:41 +00:00
framework . Logf ( "Ensuring deployment %s was deleted" , deploymentName )
2016-12-07 14:40:26 +00:00
_ , err = c . Extensions ( ) . Deployments ( ns ) . Get ( deployment . Name , metav1 . GetOptions { } )
2015-12-02 15:09:01 +00:00
Expect ( err ) . To ( HaveOccurred ( ) )
Expect ( errors . IsNotFound ( err ) ) . To ( BeTrue ( ) )
2016-04-15 22:20:41 +00:00
framework . Logf ( "Ensuring deployment %s's RSes were deleted" , deploymentName )
2016-12-03 18:57:26 +00:00
selector , err := metav1 . LabelSelectorAsSelector ( deployment . Spec . Selector )
2015-12-02 15:09:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-11-18 20:55:17 +00:00
options := v1 . ListOptions { LabelSelector : selector . String ( ) }
2015-12-02 15:09:01 +00:00
rss , err := c . Extensions ( ) . ReplicaSets ( ns ) . List ( options )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-09-02 20:54:20 +00:00
// RSes may be created by overlapping deployments right after this deployment is deleted, ignore them
if len ( overlapWith ) == 0 {
Expect ( rss . Items ) . Should ( HaveLen ( 0 ) )
} else {
noOverlapRSes := [ ] extensions . ReplicaSet { }
for _ , rs := range rss . Items {
if ! strings . HasPrefix ( rs . Name , overlapWith ) {
noOverlapRSes = append ( noOverlapRSes , rs )
}
}
Expect ( noOverlapRSes ) . Should ( HaveLen ( 0 ) )
}
2016-04-15 22:20:41 +00:00
framework . Logf ( "Ensuring deployment %s's Pods were deleted" , deploymentName )
2016-11-18 20:55:17 +00:00
var pods * v1 . PodList
2016-06-30 12:10:11 +00:00
if err := wait . PollImmediate ( time . Second , timeout , func ( ) ( bool , error ) {
2016-08-17 22:37:04 +00:00
pods , err = c . Core ( ) . Pods ( ns ) . List ( options )
2015-12-02 15:09:01 +00:00
if err != nil {
return false , err
}
2016-09-02 20:54:20 +00:00
// Pods may be created by overlapping deployments right after this deployment is deleted, ignore them
if len ( overlapWith ) == 0 && len ( pods . Items ) == 0 {
2015-12-02 15:09:01 +00:00
return true , nil
2016-09-02 20:54:20 +00:00
} else if len ( overlapWith ) != 0 {
2016-11-18 20:55:17 +00:00
noOverlapPods := [ ] v1 . Pod { }
2016-09-02 20:54:20 +00:00
for _ , pod := range pods . Items {
if ! strings . HasPrefix ( pod . Name , overlapWith ) {
noOverlapPods = append ( noOverlapPods , pod )
}
}
if len ( noOverlapPods ) == 0 {
return true , nil
}
2015-12-02 15:09:01 +00:00
}
return false , nil
} ) ; err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Err : %s\n. Failed to remove deployment %s pods : %+v" , err , deploymentName , pods )
2015-12-02 15:09:01 +00:00
}
}
2016-04-07 17:21:31 +00:00
func testNewDeployment ( f * framework . Framework ) {
2015-12-01 23:55:13 +00:00
ns := f . Namespace . Name
2016-09-22 15:00:19 +00:00
c := f . ClientSet
2016-01-15 05:00:58 +00:00
2016-02-29 19:03:43 +00:00
deploymentName := "test-new-deployment"
2016-03-06 01:40:59 +00:00
podLabels := map [ string ] string { "name" : nginxImageName }
2016-04-27 04:35:14 +00:00
replicas := int32 ( 1 )
2016-04-07 17:21:31 +00:00
framework . Logf ( "Creating simple deployment %s" , deploymentName )
2016-03-06 01:40:59 +00:00
d := newDeployment ( deploymentName , replicas , podLabels , nginxImageName , nginxImage , extensions . RollingUpdateDeploymentStrategyType , nil )
2016-05-05 00:37:03 +00:00
d . Annotations = map [ string ] string { "test" : "should-copy-to-replica-set" , annotations . LastAppliedConfigAnnotation : "should-not-copy-to-replica-set" }
2016-06-29 10:55:39 +00:00
deploy , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
2015-09-24 18:16:17 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-12-02 15:09:01 +00:00
2016-03-01 01:56:40 +00:00
// Wait for it to be updated to revision 1
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "1" , nginxImage )
2015-09-24 18:16:17 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-08-02 00:04:00 +00:00
err = framework . WaitForDeploymentStatus ( c , deploy )
2015-09-24 18:16:17 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-15 02:04:05 +00:00
2016-12-07 14:40:26 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName , metav1 . GetOptions { } )
2016-03-01 01:56:40 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
newRS , err := deploymentutil . GetNewReplicaSet ( deployment , c )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Check new RS annotations
2016-01-20 00:40:18 +00:00
Expect ( newRS . Annotations [ "test" ] ) . Should ( Equal ( "should-copy-to-replica-set" ) )
2016-05-05 00:37:03 +00:00
Expect ( newRS . Annotations [ annotations . LastAppliedConfigAnnotation ] ) . Should ( Equal ( "" ) )
2016-01-20 00:40:18 +00:00
Expect ( deployment . Annotations [ "test" ] ) . Should ( Equal ( "should-copy-to-replica-set" ) )
2016-05-05 00:37:03 +00:00
Expect ( deployment . Annotations [ annotations . LastAppliedConfigAnnotation ] ) . Should ( Equal ( "should-not-copy-to-replica-set" ) )
2015-09-24 18:16:17 +00:00
}
2016-10-07 10:16:34 +00:00
func testDeleteDeployment ( f * framework . Framework ) {
ns := f . Namespace . Name
c := f . ClientSet
2016-11-18 20:55:17 +00:00
internalClient := f . InternalClientset
2016-10-07 10:16:34 +00:00
deploymentName := "test-new-deployment"
podLabels := map [ string ] string { "name" : nginxImageName }
replicas := int32 ( 1 )
framework . Logf ( "Creating simple deployment %s" , deploymentName )
d := newDeployment ( deploymentName , replicas , podLabels , nginxImageName , nginxImage , extensions . RollingUpdateDeploymentStrategyType , nil )
d . Annotations = map [ string ] string { "test" : "should-copy-to-replica-set" , annotations . LastAppliedConfigAnnotation : "should-not-copy-to-replica-set" }
deploy , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Wait for it to be updated to revision 1
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "1" , nginxImage )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
err = framework . WaitForDeploymentStatus ( c , deploy )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-12-07 14:40:26 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName , metav1 . GetOptions { } )
2016-10-07 10:16:34 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
newRS , err := deploymentutil . GetNewReplicaSet ( deployment , c )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
if newRS == nil {
err = fmt . Errorf ( "expected a replica set, got nil" )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
2016-11-18 20:55:17 +00:00
stopDeployment ( c , internalClient , ns , deploymentName )
2016-10-07 10:16:34 +00:00
}
2016-04-07 17:21:31 +00:00
func testRollingUpdateDeployment ( f * framework . Framework ) {
2015-09-24 18:16:17 +00:00
ns := f . Namespace . Name
2016-09-22 15:00:19 +00:00
c := f . ClientSet
2015-09-29 23:55:06 +00:00
// Create nginx pods.
2015-10-03 01:27:37 +00:00
deploymentPodLabels := map [ string ] string { "name" : "sample-pod" }
2016-01-20 00:40:18 +00:00
rsPodLabels := map [ string ] string {
2015-10-03 01:27:37 +00:00
"name" : "sample-pod" ,
2016-03-06 01:40:59 +00:00
"pod" : nginxImageName ,
2015-10-03 01:27:37 +00:00
}
2016-02-29 19:03:43 +00:00
rsName := "test-rolling-update-controller"
2016-04-27 04:35:14 +00:00
replicas := int32 ( 3 )
2016-12-09 16:16:00 +00:00
rsRevision := "3546343826724305832"
annotations := make ( map [ string ] string )
annotations [ deploymentutil . RevisionAnnotation ] = rsRevision
rs := newRS ( rsName , replicas , rsPodLabels , nginxImageName , nginxImage )
rs . Annotations = annotations
2016-12-13 10:48:47 +00:00
By ( fmt . Sprintf ( "Creating replica set %q (going to be adopted)" , rs . Name ) )
2016-12-09 16:16:00 +00:00
_ , err := c . Extensions ( ) . ReplicaSets ( ns ) . Create ( rs )
2015-09-29 23:55:06 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Verify that the required pods have come up.
2016-10-18 13:00:38 +00:00
err = framework . VerifyPods ( c , ns , "sample-pod" , false , 3 )
2015-09-29 23:55:06 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Logf ( "error in waiting for pods to come up: %s" , err )
2015-09-29 23:55:06 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
// Create a deployment to delete nginx pods and instead bring up redis pods.
2016-02-29 19:03:43 +00:00
deploymentName := "test-rolling-update-deployment"
2016-12-13 10:48:47 +00:00
By ( fmt . Sprintf ( "Creating deployment %q" , deploymentName ) )
2016-06-29 10:55:39 +00:00
deploy , err := c . Extensions ( ) . Deployments ( ns ) . Create ( newDeployment ( deploymentName , replicas , deploymentPodLabels , redisImageName , redisImage , extensions . RollingUpdateDeploymentStrategyType , nil ) )
2015-09-29 23:55:06 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-12-09 16:16:00 +00:00
// Wait for it to be updated to revision 3546343826724305833.
2016-12-13 10:48:47 +00:00
By ( fmt . Sprintf ( "Ensuring deployment %q gets the next revision from the one the adopted replica set %q has" , deploy . Name , rs . Name ) )
2016-12-09 16:16:00 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "3546343826724305833" , redisImage )
2015-10-03 01:27:37 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-13 01:52:18 +00:00
2016-12-13 10:48:47 +00:00
By ( fmt . Sprintf ( "Ensuring status for deployment %q is the expected" , deploy . Name ) )
2016-08-02 00:04:00 +00:00
err = framework . WaitForDeploymentStatus ( c , deploy )
2016-03-01 01:56:40 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-11 18:57:42 +00:00
// There should be 1 old RS (nginx-controller, which is adopted)
2016-12-13 10:48:47 +00:00
By ( fmt . Sprintf ( "Ensuring deployment %q has one old replica set (the one it adopted)" , deploy . Name ) )
2016-12-07 14:40:26 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName , metav1 . GetOptions { } )
2016-02-11 18:57:42 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-28 02:13:32 +00:00
_ , allOldRSs , err := deploymentutil . GetOldReplicaSets ( deployment , c )
2016-02-11 18:57:42 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
Expect ( len ( allOldRSs ) ) . Should ( Equal ( 1 ) )
// The old RS should contain pod-template-hash in its selector, label, and template label
Expect ( len ( allOldRSs [ 0 ] . Labels [ extensions . DefaultDeploymentUniqueLabelKey ] ) ) . Should ( BeNumerically ( ">" , 0 ) )
Expect ( len ( allOldRSs [ 0 ] . Spec . Selector . MatchLabels [ extensions . DefaultDeploymentUniqueLabelKey ] ) ) . Should ( BeNumerically ( ">" , 0 ) )
Expect ( len ( allOldRSs [ 0 ] . Spec . Template . Labels [ extensions . DefaultDeploymentUniqueLabelKey ] ) ) . Should ( BeNumerically ( ">" , 0 ) )
2015-09-29 23:55:06 +00:00
}
2016-04-07 17:21:31 +00:00
func testRecreateDeployment ( f * framework . Framework ) {
2016-01-13 03:27:26 +00:00
ns := f . Namespace . Name
2016-09-22 15:00:19 +00:00
c := f . ClientSet
2016-01-13 03:27:26 +00:00
2016-11-10 12:30:44 +00:00
// Create a deployment that brings up redis pods.
2016-02-29 19:03:43 +00:00
deploymentName := "test-recreate-deployment"
2016-12-09 16:16:00 +00:00
By ( fmt . Sprintf ( "Creating deployment %q" , deploymentName ) )
2016-11-10 12:30:44 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Create ( newDeployment ( deploymentName , int32 ( 3 ) , map [ string ] string { "name" : "sample-pod-3" } , redisImageName , redisImage , extensions . RecreateDeploymentStrategyType , nil ) )
2016-01-13 03:27:26 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-03-01 01:56:40 +00:00
// Wait for it to be updated to revision 1
2016-12-09 16:16:00 +00:00
By ( fmt . Sprintf ( "Waiting deployment %q to be updated to revision 1" , deploymentName ) )
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "1" , redisImage )
2016-03-01 01:56:40 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-12-09 16:16:00 +00:00
By ( fmt . Sprintf ( "Waiting deployment %q to complete" , deploymentName ) )
2016-11-10 12:30:44 +00:00
Expect ( framework . WaitForDeploymentStatusValid ( c , deployment ) ) . NotTo ( HaveOccurred ( ) )
2016-01-13 03:27:26 +00:00
2016-11-10 12:30:44 +00:00
// Update deployment to delete redis pods and bring up nginx pods.
2016-12-09 16:16:00 +00:00
By ( fmt . Sprintf ( "Triggering a new rollout for deployment %q" , deploymentName ) )
2016-11-10 12:30:44 +00:00
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , deploymentName , func ( update * extensions . Deployment ) {
update . Spec . Template . Spec . Containers [ 0 ] . Name = nginxImageName
update . Spec . Template . Spec . Containers [ 0 ] . Image = nginxImage
} )
2016-01-13 03:27:26 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-11-10 12:30:44 +00:00
2016-12-09 16:16:00 +00:00
By ( fmt . Sprintf ( "Watching deployment %q to verify that new pods will not run with olds pods" , deploymentName ) )
2016-11-10 12:30:44 +00:00
Expect ( framework . WatchRecreateDeployment ( c , deployment ) ) . NotTo ( HaveOccurred ( ) )
2016-01-13 03:27:26 +00:00
}
2016-01-28 06:13:07 +00:00
// testDeploymentCleanUpPolicy tests that deployment supports cleanup policy
2016-04-07 17:21:31 +00:00
func testDeploymentCleanUpPolicy ( f * framework . Framework ) {
2016-01-28 06:13:07 +00:00
ns := f . Namespace . Name
2016-09-22 15:00:19 +00:00
c := f . ClientSet
2016-01-28 06:13:07 +00:00
// Create nginx pods.
deploymentPodLabels := map [ string ] string { "name" : "cleanup-pod" }
2016-01-20 00:40:18 +00:00
rsPodLabels := map [ string ] string {
2016-01-28 06:13:07 +00:00
"name" : "cleanup-pod" ,
2016-03-06 01:40:59 +00:00
"pod" : nginxImageName ,
2016-01-28 06:13:07 +00:00
}
2016-02-29 19:03:43 +00:00
rsName := "test-cleanup-controller"
2016-04-27 04:35:14 +00:00
replicas := int32 ( 1 )
revisionHistoryLimit := util . Int32Ptr ( 0 )
2016-03-06 01:40:59 +00:00
_ , err := c . Extensions ( ) . ReplicaSets ( ns ) . Create ( newRS ( rsName , replicas , rsPodLabels , nginxImageName , nginxImage ) )
2016-01-28 06:13:07 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Verify that the required pods have come up.
2016-10-18 13:00:38 +00:00
err = framework . VerifyPods ( c , ns , "cleanup-pod" , false , 1 )
2016-01-28 06:13:07 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Logf ( "error in waiting for pods to come up: %s" , err )
2016-01-28 06:13:07 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
// Create a deployment to delete nginx pods and instead bring up redis pods.
2016-02-29 19:03:43 +00:00
deploymentName := "test-cleanup-deployment"
2016-04-07 17:21:31 +00:00
framework . Logf ( "Creating deployment %s" , deploymentName )
2016-03-11 18:34:13 +00:00
2016-11-18 20:55:17 +00:00
pods , err := c . Core ( ) . Pods ( ns ) . List ( v1 . ListOptions { LabelSelector : labels . Everything ( ) . String ( ) } )
2016-03-11 18:34:13 +00:00
if err != nil {
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed to query for pods: %v" , err )
}
2016-11-18 20:55:17 +00:00
options := v1 . ListOptions {
2016-03-11 18:34:13 +00:00
ResourceVersion : pods . ListMeta . ResourceVersion ,
}
stopCh := make ( chan struct { } )
2016-09-22 15:00:19 +00:00
w , err := c . Core ( ) . Pods ( ns ) . Watch ( options )
2016-11-10 12:30:44 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-03-11 18:34:13 +00:00
go func ( ) {
// There should be only one pod being created, which is the pod with the redis image.
// The old RS shouldn't create new pod when deployment controller adding pod template hash label to its selector.
numPodCreation := 1
for {
select {
case event , _ := <- w . ResultChan ( ) :
if event . Type != watch . Added {
continue
}
numPodCreation --
if numPodCreation < 0 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Expect only one pod creation, the second creation event: %#v\n" , event )
2016-03-11 18:34:13 +00:00
}
2016-11-18 20:55:17 +00:00
pod , ok := event . Object . ( * v1 . Pod )
2016-03-11 18:34:13 +00:00
if ! ok {
Fail ( "Expect event Object to be a pod" )
}
if pod . Spec . Containers [ 0 ] . Name != redisImageName {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Expect the created pod to have container name %s, got pod %#v\n" , redisImageName , pod )
2016-03-11 18:34:13 +00:00
}
case <- stopCh :
return
}
}
} ( )
2016-03-06 01:40:59 +00:00
_ , err = c . Extensions ( ) . Deployments ( ns ) . Create ( newDeployment ( deploymentName , replicas , deploymentPodLabels , redisImageName , redisImage , extensions . RollingUpdateDeploymentStrategyType , revisionHistoryLimit ) )
2016-01-28 06:13:07 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-04-27 04:35:14 +00:00
err = framework . WaitForDeploymentOldRSsNum ( c , ns , deploymentName , int ( * revisionHistoryLimit ) )
2016-01-28 06:13:07 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-03-11 18:34:13 +00:00
close ( stopCh )
2016-01-28 06:13:07 +00:00
}
2015-12-01 23:55:13 +00:00
// testRolloverDeployment tests that deployment supports rollover.
// i.e. we can change desired state and kick off rolling update, then change desired state again before it finishes.
2016-04-07 17:21:31 +00:00
func testRolloverDeployment ( f * framework . Framework ) {
2015-12-01 23:55:13 +00:00
ns := f . Namespace . Name
2016-09-22 15:00:19 +00:00
c := f . ClientSet
2015-12-01 23:55:13 +00:00
podName := "rollover-pod"
deploymentPodLabels := map [ string ] string { "name" : podName }
2016-01-20 00:40:18 +00:00
rsPodLabels := map [ string ] string {
2015-12-01 23:55:13 +00:00
"name" : podName ,
2016-03-06 01:40:59 +00:00
"pod" : nginxImageName ,
2015-12-01 23:55:13 +00:00
}
2016-02-29 19:03:43 +00:00
rsName := "test-rollover-controller"
2016-04-27 04:35:14 +00:00
rsReplicas := int32 ( 4 )
2016-03-06 01:40:59 +00:00
_ , err := c . Extensions ( ) . ReplicaSets ( ns ) . Create ( newRS ( rsName , rsReplicas , rsPodLabels , nginxImageName , nginxImage ) )
2015-12-01 23:55:13 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Verify that the required pods have come up.
2016-10-18 13:00:38 +00:00
err = framework . VerifyPods ( c , ns , podName , false , rsReplicas )
2015-12-01 23:55:13 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Logf ( "error in waiting for pods to come up: %s" , err )
2015-12-01 23:55:13 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
2016-12-06 15:45:03 +00:00
// Wait for replica set to become ready before adopting it.
framework . Logf ( "Waiting for pods owned by replica set %q to become ready" , rsName )
Expect ( framework . WaitForReadyReplicaSet ( c , ns , rsName ) ) . NotTo ( HaveOccurred ( ) )
2015-12-01 23:55:13 +00:00
// Create a deployment to delete nginx pods and instead bring up redis-slave pods.
2016-07-25 18:22:18 +00:00
// We use a nonexistent image here, so that we make sure it won't finish
2016-02-29 19:03:43 +00:00
deploymentName , deploymentImageName := "test-rollover-deployment" , "redis-slave"
2016-04-27 04:35:14 +00:00
deploymentReplicas := int32 ( 4 )
2016-07-25 18:22:18 +00:00
deploymentImage := "gcr.io/google_samples/gb-redisslave:nonexistent"
2016-01-13 03:27:26 +00:00
deploymentStrategyType := extensions . RollingUpdateDeploymentStrategyType
2016-12-05 01:31:13 +00:00
framework . Logf ( "Creating deployment %q" , deploymentName )
2016-01-28 06:13:07 +00:00
newDeployment := newDeployment ( deploymentName , deploymentReplicas , deploymentPodLabels , deploymentImageName , deploymentImage , deploymentStrategyType , nil )
2015-12-01 23:55:13 +00:00
newDeployment . Spec . Strategy . RollingUpdate = & extensions . RollingUpdateDeployment {
2016-11-18 20:55:17 +00:00
MaxUnavailable : func ( i int ) * intstr . IntOrString { x := intstr . FromInt ( i ) ; return & x } ( 1 ) ,
MaxSurge : func ( i int ) * intstr . IntOrString { x := intstr . FromInt ( i ) ; return & x } ( 1 ) ,
2015-12-01 23:55:13 +00:00
}
2016-12-05 01:31:13 +00:00
newDeployment . Spec . MinReadySeconds = int32 ( 10 )
2016-01-15 05:00:58 +00:00
_ , err = c . Extensions ( ) . Deployments ( ns ) . Create ( newDeployment )
2015-12-01 23:55:13 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-12-02 15:09:01 +00:00
2016-04-15 22:20:41 +00:00
// Verify that the pods were scaled up and down as expected.
2016-12-07 14:40:26 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName , metav1 . GetOptions { } )
2016-01-13 01:52:18 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-12-05 01:31:13 +00:00
framework . Logf ( "Make sure deployment %q performs scaling operations" , deploymentName )
2016-04-15 22:20:41 +00:00
// Make sure the deployment starts to scale up and down replica sets by checking if its updated replicas >= 1
err = framework . WaitForDeploymentUpdatedReplicasLTE ( c , ns , deploymentName , 1 , deployment . Generation )
2016-01-15 02:04:05 +00:00
// Check if it's updated to revision 1 correctly
2016-12-05 01:31:13 +00:00
framework . Logf ( "Check revision of new replica set for deployment %q" , deploymentName )
2016-01-20 00:40:18 +00:00
_ , newRS := checkDeploymentRevision ( c , ns , deploymentName , "1" , deploymentImageName , deploymentImage )
2015-12-01 23:55:13 +00:00
2016-01-20 00:40:18 +00:00
// Before the deployment finishes, update the deployment to rollover the above 2 ReplicaSets and bring up redis pods.
2016-11-18 20:55:17 +00:00
Expect ( * newRS . Spec . Replicas ) . Should ( BeNumerically ( "<" , deploymentReplicas ) )
2016-12-05 01:31:13 +00:00
framework . Logf ( "Make sure deployment %q with new image" , deploymentName )
2016-03-06 01:40:59 +00:00
updatedDeploymentImageName , updatedDeploymentImage := redisImageName , redisImage
2016-04-07 17:21:31 +00:00
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , newDeployment . Name , func ( update * extensions . Deployment ) {
2016-03-02 02:05:27 +00:00
update . Spec . Template . Spec . Containers [ 0 ] . Name = updatedDeploymentImageName
2016-02-19 21:45:57 +00:00
update . Spec . Template . Spec . Containers [ 0 ] . Image = updatedDeploymentImage
} )
2015-12-01 23:55:13 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-03-01 01:56:40 +00:00
// Use observedGeneration to determine if the controller noticed the pod template update.
2016-12-05 01:31:13 +00:00
framework . Logf ( "Wait deployment %q to be observed by the deployment controller" , deploymentName )
2016-04-07 17:21:31 +00:00
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
2015-12-01 23:55:13 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-03-01 01:56:40 +00:00
// Wait for it to be updated to revision 2
2016-12-05 01:31:13 +00:00
framework . Logf ( "Wait for revision update of deployment %q to 2" , deploymentName )
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "2" , updatedDeploymentImage )
2016-03-01 01:56:40 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-12-05 01:31:13 +00:00
framework . Logf ( "Make sure deployment %q is complete" , deploymentName )
2016-08-02 00:04:00 +00:00
err = framework . WaitForDeploymentStatus ( c , deployment )
2016-03-01 01:56:40 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-12-01 23:55:13 +00:00
}
2016-01-21 10:12:58 +00:00
2016-04-07 17:21:31 +00:00
func testPausedDeployment ( f * framework . Framework ) {
2016-01-21 10:12:58 +00:00
ns := f . Namespace . Name
2016-09-22 15:00:19 +00:00
c := f . ClientSet
2016-02-29 19:03:43 +00:00
deploymentName := "test-paused-deployment"
2016-03-06 01:40:59 +00:00
podLabels := map [ string ] string { "name" : nginxImageName }
d := newDeployment ( deploymentName , 1 , podLabels , nginxImageName , nginxImage , extensions . RollingUpdateDeploymentStrategyType , nil )
2016-01-21 10:12:58 +00:00
d . Spec . Paused = true
2016-09-19 08:29:29 +00:00
tgps := int64 ( 1 )
2016-01-28 16:35:14 +00:00
d . Spec . Template . Spec . TerminationGracePeriodSeconds = & tgps
2016-04-07 17:21:31 +00:00
framework . Logf ( "Creating paused deployment %s" , deploymentName )
2016-01-15 05:00:58 +00:00
_ , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
2016-01-21 10:12:58 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Check that deployment is created fine.
2016-12-07 14:40:26 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName , metav1 . GetOptions { } )
2016-01-21 10:12:58 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Verify that there is no latest state realized for the new deployment.
2016-02-28 02:13:32 +00:00
rs , err := deploymentutil . GetNewReplicaSet ( deployment , c )
2016-01-21 10:12:58 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-20 00:40:18 +00:00
if rs != nil {
err = fmt . Errorf ( "unexpected new rs/%s for deployment/%s" , rs . Name , deployment . Name )
2016-01-21 10:12:58 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
// Update the deployment to run
2016-04-07 17:21:31 +00:00
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , d . Name , func ( update * extensions . Deployment ) {
2016-02-19 21:45:57 +00:00
update . Spec . Paused = false
} )
2016-01-21 10:12:58 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-23 14:23:14 +00:00
// Use observedGeneration to determine if the controller noticed the resume.
2016-04-07 17:21:31 +00:00
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
2016-02-23 14:23:14 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-12-03 18:57:26 +00:00
selector , err := metav1 . LabelSelectorAsSelector ( deployment . Spec . Selector )
2016-02-06 02:43:02 +00:00
if err != nil {
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
2016-11-18 20:55:17 +00:00
opts := v1 . ListOptions { LabelSelector : selector . String ( ) }
2016-01-20 00:40:18 +00:00
w , err := c . Extensions ( ) . ReplicaSets ( ns ) . Watch ( opts )
2016-01-21 10:12:58 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
select {
case <- w . ResultChan ( ) :
// this is it
case <- time . After ( time . Minute ) :
2016-01-20 00:40:18 +00:00
err = fmt . Errorf ( "expected a new replica set to be created" )
2016-01-21 10:12:58 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
2016-01-20 00:40:18 +00:00
// Pause the deployment and delete the replica set.
2016-01-21 10:12:58 +00:00
// The paused deployment shouldn't recreate a new one.
2016-04-07 17:21:31 +00:00
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , d . Name , func ( update * extensions . Deployment ) {
2016-02-19 21:45:57 +00:00
update . Spec . Paused = true
} )
2016-01-21 10:12:58 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-23 14:23:14 +00:00
// Use observedGeneration to determine if the controller noticed the pause.
2016-04-07 17:21:31 +00:00
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
2016-02-23 14:23:14 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-28 16:35:14 +00:00
// Update the deployment template - the new replicaset should stay the same
framework . Logf ( "Updating paused deployment %q" , deploymentName )
2016-09-19 08:29:29 +00:00
newTGPS := int64 ( 0 )
2016-01-28 16:35:14 +00:00
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , d . Name , func ( update * extensions . Deployment ) {
update . Spec . Template . Spec . TerminationGracePeriodSeconds = & newTGPS
} )
2016-01-21 10:12:58 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-28 16:35:14 +00:00
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
2016-01-21 10:12:58 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-28 16:35:14 +00:00
framework . Logf ( "Looking for new replicaset for paused deployment %q (there should be none)" , deploymentName )
newRS , err := deploymentutil . GetNewReplicaSet ( deployment , c )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
if newRS != nil {
err = fmt . Errorf ( "No replica set should match the deployment template but there is %q" , newRS . Name )
2016-01-21 10:12:58 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
2016-01-28 16:35:14 +00:00
_ , allOldRs , err := deploymentutil . GetOldReplicaSets ( deployment , c )
2016-01-21 10:12:58 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-28 16:35:14 +00:00
if len ( allOldRs ) != 1 {
err = fmt . Errorf ( "expected an old replica set" )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
framework . Logf ( "Comparing deployment diff with old replica set %q" , allOldRs [ 0 ] . Name )
if * allOldRs [ 0 ] . Spec . Template . Spec . TerminationGracePeriodSeconds == newTGPS {
err = fmt . Errorf ( "TerminationGracePeriodSeconds on the replica set should be %d but is %d" , tgps , newTGPS )
2016-01-21 10:12:58 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
}
2016-01-15 02:04:05 +00:00
// testRollbackDeployment tests that a deployment is created (revision 1) and updated (revision 2), and
// then rollback to revision 1 (should update template to revision 1, and then update revision 1 to 3),
// and then rollback to last revision.
2016-04-07 17:21:31 +00:00
func testRollbackDeployment ( f * framework . Framework ) {
2016-01-15 02:04:05 +00:00
ns := f . Namespace . Name
2016-09-22 15:00:19 +00:00
c := f . ClientSet
2016-01-15 02:04:05 +00:00
podName := "nginx"
deploymentPodLabels := map [ string ] string { "name" : podName }
2016-02-29 20:10:01 +00:00
// 1. Create a deployment to create nginx pods.
2016-03-06 01:40:59 +00:00
deploymentName , deploymentImageName := "test-rollback-deployment" , nginxImageName
2016-04-27 04:35:14 +00:00
deploymentReplicas := int32 ( 1 )
2016-03-06 01:40:59 +00:00
deploymentImage := nginxImage
2016-01-15 02:04:05 +00:00
deploymentStrategyType := extensions . RollingUpdateDeploymentStrategyType
2016-04-07 17:21:31 +00:00
framework . Logf ( "Creating deployment %s" , deploymentName )
2016-01-15 02:04:05 +00:00
d := newDeployment ( deploymentName , deploymentReplicas , deploymentPodLabels , deploymentImageName , deploymentImage , deploymentStrategyType , nil )
2016-05-05 20:41:49 +00:00
createAnnotation := map [ string ] string { "action" : "create" , "author" : "node" }
2016-03-17 22:39:05 +00:00
d . Annotations = createAnnotation
2016-06-29 10:55:39 +00:00
deploy , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-12-02 15:09:01 +00:00
2016-02-29 20:10:01 +00:00
// Wait for it to be updated to revision 1
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "1" , deploymentImage )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-08-02 00:04:00 +00:00
err = framework . WaitForDeploymentStatus ( c , deploy )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-03-17 22:39:05 +00:00
// Current newRS annotation should be "create"
2016-04-07 17:21:31 +00:00
err = framework . CheckNewRSAnnotations ( c , ns , deploymentName , createAnnotation )
2016-03-17 22:39:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-29 20:10:01 +00:00
// 2. Update the deployment to create redis pods.
2016-03-06 01:40:59 +00:00
updatedDeploymentImage := redisImage
updatedDeploymentImageName := redisImageName
2016-03-17 22:39:05 +00:00
updateAnnotation := map [ string ] string { "action" : "update" , "log" : "I need to update it" }
2016-04-07 17:21:31 +00:00
deployment , err := framework . UpdateDeploymentWithRetries ( c , ns , d . Name , func ( update * extensions . Deployment ) {
2016-02-19 21:45:57 +00:00
update . Spec . Template . Spec . Containers [ 0 ] . Name = updatedDeploymentImageName
update . Spec . Template . Spec . Containers [ 0 ] . Image = updatedDeploymentImage
2016-03-17 22:39:05 +00:00
update . Annotations = updateAnnotation
2016-02-19 21:45:57 +00:00
} )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-03-01 01:56:40 +00:00
// Use observedGeneration to determine if the controller noticed the pod template update.
2016-04-07 17:21:31 +00:00
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
2016-03-01 01:56:40 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-29 20:10:01 +00:00
// Wait for it to be updated to revision 2
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "2" , updatedDeploymentImage )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-08-02 00:04:00 +00:00
err = framework . WaitForDeploymentStatus ( c , deployment )
2016-02-29 20:10:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-15 02:04:05 +00:00
2016-03-17 22:39:05 +00:00
// Current newRS annotation should be "update"
2016-04-07 17:21:31 +00:00
err = framework . CheckNewRSAnnotations ( c , ns , deploymentName , updateAnnotation )
2016-03-17 22:39:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-29 20:10:01 +00:00
// 3. Update the deploymentRollback to rollback to revision 1
2016-01-15 02:04:05 +00:00
revision := int64 ( 1 )
2016-04-07 17:21:31 +00:00
framework . Logf ( "rolling back deployment %s to revision %d" , deploymentName , revision )
2016-01-15 02:04:05 +00:00
rollback := newDeploymentRollback ( deploymentName , nil , revision )
2016-01-15 05:00:58 +00:00
err = c . Extensions ( ) . Deployments ( ns ) . Rollback ( rollback )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-29 20:10:01 +00:00
// Wait for the deployment to start rolling back
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRollbackCleared ( c , ns , deploymentName )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-29 20:10:01 +00:00
// TODO: report RollbackDone in deployment status and check it here
2016-01-15 02:04:05 +00:00
2016-02-29 20:10:01 +00:00
// Wait for it to be updated to revision 3
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "3" , deploymentImage )
2016-02-29 20:10:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-08-02 00:04:00 +00:00
err = framework . WaitForDeploymentStatus ( c , deployment )
2016-02-29 20:10:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-15 02:04:05 +00:00
2016-03-17 22:39:05 +00:00
// Current newRS annotation should be "create", after the rollback
2016-04-07 17:21:31 +00:00
err = framework . CheckNewRSAnnotations ( c , ns , deploymentName , createAnnotation )
2016-03-17 22:39:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-29 20:10:01 +00:00
// 4. Update the deploymentRollback to rollback to last revision
2016-01-15 02:04:05 +00:00
revision = 0
2016-04-07 17:21:31 +00:00
framework . Logf ( "rolling back deployment %s to last revision" , deploymentName )
2016-01-15 02:04:05 +00:00
rollback = newDeploymentRollback ( deploymentName , nil , revision )
2016-01-15 05:00:58 +00:00
err = c . Extensions ( ) . Deployments ( ns ) . Rollback ( rollback )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRollbackCleared ( c , ns , deploymentName )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-29 20:10:01 +00:00
// Wait for it to be updated to revision 4
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "4" , updatedDeploymentImage )
2016-02-29 20:10:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-08-02 00:04:00 +00:00
err = framework . WaitForDeploymentStatus ( c , deployment )
2016-02-29 20:10:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-03-17 22:39:05 +00:00
// Current newRS annotation should be "update", after the rollback
2016-04-07 17:21:31 +00:00
err = framework . CheckNewRSAnnotations ( c , ns , deploymentName , updateAnnotation )
2016-03-17 22:39:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-15 02:04:05 +00:00
}
2016-01-20 00:40:18 +00:00
// testRollbackDeploymentRSNoRevision tests that deployment supports rollback even when there's old replica set without revision.
// An old replica set without revision is created, and then a deployment is created (v1). The deployment shouldn't add revision
2016-02-22 21:51:27 +00:00
// annotation to the old replica set. Then rollback the deployment to last revision, and it should fail.
// Then update the deployment to v2 and rollback it to v1 should succeed, now the deployment
// becomes v3. Then rollback the deployment to v10 (doesn't exist in history) should fail.
// Finally, rollback the deployment (v3) to v3 should be no-op.
// TODO: When we finished reporting rollback status in deployment status, check the rollback status here in each case.
2016-04-07 17:21:31 +00:00
func testRollbackDeploymentRSNoRevision ( f * framework . Framework ) {
2016-01-15 02:04:05 +00:00
ns := f . Namespace . Name
2016-09-22 15:00:19 +00:00
c := f . ClientSet
2016-01-15 02:04:05 +00:00
podName := "nginx"
deploymentPodLabels := map [ string ] string { "name" : podName }
2016-01-20 00:40:18 +00:00
rsPodLabels := map [ string ] string {
2016-01-15 02:04:05 +00:00
"name" : podName ,
2016-03-06 01:40:59 +00:00
"pod" : nginxImageName ,
2016-01-15 02:04:05 +00:00
}
2016-02-29 20:10:01 +00:00
// Create an old RS without revision
2016-02-29 19:03:43 +00:00
rsName := "test-rollback-no-revision-controller"
2016-04-27 04:35:14 +00:00
rsReplicas := int32 ( 0 )
2016-03-06 01:40:59 +00:00
rs := newRS ( rsName , rsReplicas , rsPodLabels , nginxImageName , nginxImage )
2016-01-20 00:40:18 +00:00
rs . Annotations = make ( map [ string ] string )
rs . Annotations [ "make" ] = "difference"
_ , err := c . Extensions ( ) . ReplicaSets ( ns ) . Create ( rs )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-29 20:10:01 +00:00
// 1. Create a deployment to create nginx pods, which have different template than the replica set created above.
2016-03-06 01:40:59 +00:00
deploymentName , deploymentImageName := "test-rollback-no-revision-deployment" , nginxImageName
2016-04-27 04:35:14 +00:00
deploymentReplicas := int32 ( 1 )
2016-03-06 01:40:59 +00:00
deploymentImage := nginxImage
2016-01-15 02:04:05 +00:00
deploymentStrategyType := extensions . RollingUpdateDeploymentStrategyType
2016-04-07 17:21:31 +00:00
framework . Logf ( "Creating deployment %s" , deploymentName )
2016-01-15 02:04:05 +00:00
d := newDeployment ( deploymentName , deploymentReplicas , deploymentPodLabels , deploymentImageName , deploymentImage , deploymentStrategyType , nil )
2016-06-29 10:55:39 +00:00
deploy , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-12-02 15:09:01 +00:00
2016-02-29 20:10:01 +00:00
// Wait for it to be updated to revision 1
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "1" , deploymentImage )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-08-02 00:04:00 +00:00
err = framework . WaitForDeploymentStatus ( c , deploy )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-20 00:40:18 +00:00
// Check that the replica set we created still doesn't contain revision information
2016-12-07 14:40:26 +00:00
rs , err = c . Extensions ( ) . ReplicaSets ( ns ) . Get ( rsName , metav1 . GetOptions { } )
2016-02-29 20:10:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-20 00:40:18 +00:00
Expect ( rs . Annotations [ deploymentutil . RevisionAnnotation ] ) . Should ( Equal ( "" ) )
2016-01-15 02:04:05 +00:00
2016-02-29 20:10:01 +00:00
// 2. Update the deploymentRollback to rollback to last revision
// Since there's only 1 revision in history, it should stay as revision 1
2016-01-15 02:04:05 +00:00
revision := int64 ( 0 )
2016-04-07 17:21:31 +00:00
framework . Logf ( "rolling back deployment %s to last revision" , deploymentName )
2016-01-15 02:04:05 +00:00
rollback := newDeploymentRollback ( deploymentName , nil , revision )
2016-01-15 05:00:58 +00:00
err = c . Extensions ( ) . Deployments ( ns ) . Rollback ( rollback )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-29 20:10:01 +00:00
// Wait for the deployment to start rolling back
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRollbackCleared ( c , ns , deploymentName )
2016-02-29 20:10:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-22 21:51:27 +00:00
// TODO: report RollbackRevisionNotFound in deployment status and check it here
2016-01-15 02:04:05 +00:00
2016-02-22 21:51:27 +00:00
// 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
2016-01-15 02:04:05 +00:00
checkDeploymentRevision ( c , ns , deploymentName , "1" , deploymentImageName , deploymentImage )
2016-02-29 20:10:01 +00:00
// 3. Update the deployment to create redis pods.
2016-03-06 01:40:59 +00:00
updatedDeploymentImage := redisImage
updatedDeploymentImageName := redisImageName
2016-04-07 17:21:31 +00:00
deployment , err := framework . UpdateDeploymentWithRetries ( c , ns , d . Name , func ( update * extensions . Deployment ) {
2016-02-19 21:45:57 +00:00
update . Spec . Template . Spec . Containers [ 0 ] . Name = updatedDeploymentImageName
update . Spec . Template . Spec . Containers [ 0 ] . Image = updatedDeploymentImage
} )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-03-01 01:56:40 +00:00
// Use observedGeneration to determine if the controller noticed the pod template update.
2016-04-07 17:21:31 +00:00
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
2016-03-01 01:56:40 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-29 20:10:01 +00:00
// Wait for it to be updated to revision 2
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "2" , updatedDeploymentImage )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-08-02 00:04:00 +00:00
err = framework . WaitForDeploymentStatus ( c , deployment )
2016-02-29 20:10:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-15 02:04:05 +00:00
2016-02-29 20:10:01 +00:00
// 4. Update the deploymentRollback to rollback to revision 1
2016-01-15 02:04:05 +00:00
revision = 1
2016-04-07 17:21:31 +00:00
framework . Logf ( "rolling back deployment %s to revision %d" , deploymentName , revision )
2016-01-15 02:04:05 +00:00
rollback = newDeploymentRollback ( deploymentName , nil , revision )
2016-01-15 05:00:58 +00:00
err = c . Extensions ( ) . Deployments ( ns ) . Rollback ( rollback )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-29 20:10:01 +00:00
// Wait for the deployment to start rolling back
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRollbackCleared ( c , ns , deploymentName )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-22 21:51:27 +00:00
// TODO: report RollbackDone in deployment status and check it here
2016-01-15 02:04:05 +00:00
2016-02-22 21:51:27 +00:00
// The pod template should be updated to the one in revision 1
2016-02-29 20:10:01 +00:00
// Wait for it to be updated to revision 3
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "3" , deploymentImage )
2016-02-29 20:10:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-15 02:04:05 +00:00
2016-08-02 00:04:00 +00:00
err = framework . WaitForDeploymentStatus ( c , deployment )
2016-02-29 20:10:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// 5. Update the deploymentRollback to rollback to revision 10
// Since there's no revision 10 in history, it should stay as revision 3
2016-01-15 02:04:05 +00:00
revision = 10
2016-04-07 17:21:31 +00:00
framework . Logf ( "rolling back deployment %s to revision %d" , deploymentName , revision )
2016-01-15 02:04:05 +00:00
rollback = newDeploymentRollback ( deploymentName , nil , revision )
2016-01-15 05:00:58 +00:00
err = c . Extensions ( ) . Deployments ( ns ) . Rollback ( rollback )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-29 20:10:01 +00:00
// Wait for the deployment to start rolling back
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRollbackCleared ( c , ns , deploymentName )
2016-02-29 20:10:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-22 21:51:27 +00:00
// TODO: report RollbackRevisionNotFound in deployment status and check it here
2016-01-15 02:04:05 +00:00
2016-02-22 21:51:27 +00:00
// The pod template shouldn't change since there's no revision 10
// Check if it's still revision 3 and still has the old pod template
2016-01-15 02:04:05 +00:00
checkDeploymentRevision ( c , ns , deploymentName , "3" , deploymentImageName , deploymentImage )
2016-02-29 20:10:01 +00:00
// 6. Update the deploymentRollback to rollback to revision 3
// Since it's already revision 3, it should be no-op
2016-01-15 02:04:05 +00:00
revision = 3
2016-04-07 17:21:31 +00:00
framework . Logf ( "rolling back deployment %s to revision %d" , deploymentName , revision )
2016-01-15 02:04:05 +00:00
rollback = newDeploymentRollback ( deploymentName , nil , revision )
2016-01-15 05:00:58 +00:00
err = c . Extensions ( ) . Deployments ( ns ) . Rollback ( rollback )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-29 20:10:01 +00:00
// Wait for the deployment to start rolling back
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRollbackCleared ( c , ns , deploymentName )
2016-02-29 20:10:01 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-22 21:51:27 +00:00
// TODO: report RollbackTemplateUnchanged in deployment status and check it here
2016-01-15 02:04:05 +00:00
2016-02-22 21:51:27 +00:00
// The pod template shouldn't change since it's already revision 3
// Check if it's still revision 3 and still has the old pod template
2016-01-15 02:04:05 +00:00
checkDeploymentRevision ( c , ns , deploymentName , "3" , deploymentImageName , deploymentImage )
}
2016-02-11 18:57:42 +00:00
2016-04-07 17:21:31 +00:00
func testDeploymentLabelAdopted ( f * framework . Framework ) {
2016-02-11 18:57:42 +00:00
ns := f . Namespace . Name
2016-09-22 15:00:19 +00:00
c := f . ClientSet
2016-02-11 18:57:42 +00:00
// Create nginx pods.
podName := "nginx"
podLabels := map [ string ] string { "name" : podName }
2016-02-29 19:03:43 +00:00
rsName := "test-adopted-controller"
2016-04-27 04:35:14 +00:00
replicas := int32 ( 3 )
2016-03-06 01:40:59 +00:00
image := nginxImage
2016-03-02 02:05:27 +00:00
_ , err := c . Extensions ( ) . ReplicaSets ( ns ) . Create ( newRS ( rsName , replicas , podLabels , podName , image ) )
2016-02-11 18:57:42 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Verify that the required pods have come up.
2016-10-18 13:00:38 +00:00
err = framework . VerifyPods ( c , ns , podName , false , 3 )
2016-02-11 18:57:42 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Logf ( "error in waiting for pods to come up: %s" , err )
2016-02-11 18:57:42 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
// Create a nginx deployment to adopt the old rs.
2016-02-29 19:03:43 +00:00
deploymentName := "test-adopted-deployment"
2016-04-07 17:21:31 +00:00
framework . Logf ( "Creating deployment %s" , deploymentName )
2016-06-29 10:55:39 +00:00
deploy , err := c . Extensions ( ) . Deployments ( ns ) . Create ( newDeployment ( deploymentName , replicas , podLabels , podName , image , extensions . RollingUpdateDeploymentStrategyType , nil ) )
2016-02-11 18:57:42 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-03-01 01:56:40 +00:00
// Wait for it to be updated to revision 1
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "1" , image )
2016-03-01 01:56:40 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-11 18:57:42 +00:00
2016-02-22 18:33:59 +00:00
// The RS and pods should be relabeled before the status is updated by syncRollingUpdateDeployment
2016-08-02 00:04:00 +00:00
err = framework . WaitForDeploymentStatus ( c , deploy )
2016-02-11 18:57:42 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// There should be no old RSs (overlapping RS)
2016-12-07 14:40:26 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName , metav1 . GetOptions { } )
2016-02-11 18:57:42 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-06-01 21:14:40 +00:00
oldRSs , allOldRSs , newRS , err := deploymentutil . GetAllReplicaSets ( deployment , c )
2016-02-11 18:57:42 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
Expect ( len ( oldRSs ) ) . Should ( Equal ( 0 ) )
Expect ( len ( allOldRSs ) ) . Should ( Equal ( 0 ) )
// New RS should contain pod-template-hash in its selector, label, and template label
2016-04-07 17:21:31 +00:00
err = framework . CheckRSHashLabel ( newRS )
2016-03-01 22:55:23 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-02-11 18:57:42 +00:00
// All pods targeted by the deployment should contain pod-template-hash in their labels, and there should be only 3 pods
2016-12-03 18:57:26 +00:00
selector , err := metav1 . LabelSelectorAsSelector ( deployment . Spec . Selector )
2016-02-11 18:57:42 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-11-18 20:55:17 +00:00
options := v1 . ListOptions { LabelSelector : selector . String ( ) }
2016-02-11 18:57:42 +00:00
pods , err := c . Core ( ) . Pods ( ns ) . List ( options )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-04-07 17:21:31 +00:00
err = framework . CheckPodHashLabel ( pods )
2016-03-01 22:55:23 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-04-27 04:35:14 +00:00
Expect ( int32 ( len ( pods . Items ) ) ) . Should ( Equal ( replicas ) )
2016-02-11 18:57:42 +00:00
}
2016-01-28 16:35:14 +00:00
func testScalePausedDeployment ( f * framework . Framework ) {
ns := f . Namespace . Name
2016-09-22 15:00:19 +00:00
c := f . ClientSet
2016-01-28 16:35:14 +00:00
podLabels := map [ string ] string { "name" : nginxImageName }
replicas := int32 ( 3 )
// Create a nginx deployment.
deploymentName := "nginx-deployment"
d := newDeployment ( deploymentName , replicas , podLabels , nginxImageName , nginxImage , extensions . RollingUpdateDeploymentStrategyType , nil )
framework . Logf ( "Creating deployment %q" , deploymentName )
_ , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Check that deployment is created fine.
2016-12-07 14:40:26 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName , metav1 . GetOptions { } )
2016-01-28 16:35:14 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
rs , err := deploymentutil . GetNewReplicaSet ( deployment , c )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Pause the deployment and try to scale it.
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , d . Name , func ( update * extensions . Deployment ) {
update . Spec . Paused = true
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Scale the paused deployment.
framework . Logf ( "Scaling up the paused deployment %q" , deploymentName )
newReplicas := int32 ( 5 )
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , deployment . Name , func ( update * extensions . Deployment ) {
2016-11-18 20:55:17 +00:00
update . Spec . Replicas = & newReplicas
2016-01-28 16:35:14 +00:00
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
rs , err = deploymentutil . GetNewReplicaSet ( deployment , c )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-11-18 20:55:17 +00:00
if * ( rs . Spec . Replicas ) != newReplicas {
err = fmt . Errorf ( "Expected %d replicas for the new replica set, got %d" , newReplicas , * ( rs . Spec . Replicas ) )
2016-01-28 16:35:14 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
}
2016-06-29 10:55:39 +00:00
func testScaledRolloutDeployment ( f * framework . Framework ) {
ns := f . Namespace . Name
2016-09-22 15:00:19 +00:00
c := f . ClientSet
2016-06-29 10:55:39 +00:00
podLabels := map [ string ] string { "name" : nginxImageName }
replicas := int32 ( 10 )
// Create a nginx deployment.
deploymentName := "nginx"
d := newDeployment ( deploymentName , replicas , podLabels , nginxImageName , nginxImage , extensions . RollingUpdateDeploymentStrategyType , nil )
d . Spec . Strategy . RollingUpdate = new ( extensions . RollingUpdateDeployment )
2016-11-18 20:55:17 +00:00
d . Spec . Strategy . RollingUpdate . MaxSurge = func ( i int ) * intstr . IntOrString { x := intstr . FromInt ( i ) ; return & x } ( 3 )
d . Spec . Strategy . RollingUpdate . MaxUnavailable = func ( i int ) * intstr . IntOrString { x := intstr . FromInt ( i ) ; return & x } ( 2 )
2016-06-29 10:55:39 +00:00
2016-11-06 12:48:31 +00:00
By ( fmt . Sprintf ( "Creating deployment %q" , deploymentName ) )
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
2016-06-29 10:55:39 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
By ( fmt . Sprintf ( "Waiting for observed generation %d" , deployment . Generation ) )
2016-11-06 12:48:31 +00:00
Expect ( framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation ) ) . NotTo ( HaveOccurred ( ) )
2016-06-29 10:55:39 +00:00
2016-08-02 19:11:25 +00:00
// Verify that the required pods have come up.
By ( "Waiting for all required pods to come up" )
2016-11-18 20:55:17 +00:00
err = framework . VerifyPods ( f . ClientSet , ns , nginxImageName , false , * ( deployment . Spec . Replicas ) )
2016-08-02 19:11:25 +00:00
if err != nil {
framework . Logf ( "error in waiting for pods to come up: %s" , err )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
2016-11-06 12:48:31 +00:00
By ( fmt . Sprintf ( "Waiting for deployment %q to complete" , deployment . Name ) )
Expect ( framework . WaitForDeploymentStatusValid ( c , deployment ) ) . NotTo ( HaveOccurred ( ) )
2016-06-29 10:55:39 +00:00
first , err := deploymentutil . GetNewReplicaSet ( deployment , c )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Update the deployment with a non-existent image so that the new replica set will be blocked.
By ( fmt . Sprintf ( "Updating deployment %q with a non-existent image" , deploymentName ) )
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , d . Name , func ( update * extensions . Deployment ) {
update . Spec . Template . Spec . Containers [ 0 ] . Image = "nginx:404"
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
By ( fmt . Sprintf ( "Waiting for observed generation %d" , deployment . Generation ) )
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-12-07 14:40:26 +00:00
deployment , err = c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName , metav1 . GetOptions { } )
2016-06-29 10:55:39 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-08-02 19:11:25 +00:00
if deployment . Status . AvailableReplicas < deploymentutil . MinAvailable ( deployment ) {
Expect ( fmt . Errorf ( "Observed %d available replicas, less than min required %d" , deployment . Status . AvailableReplicas , deploymentutil . MinAvailable ( deployment ) ) ) . NotTo ( HaveOccurred ( ) )
}
2016-06-29 10:55:39 +00:00
By ( fmt . Sprintf ( "Checking that the replica sets for %q are synced" , deploymentName ) )
second , err := deploymentutil . GetNewReplicaSet ( deployment , c )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-12-07 14:40:26 +00:00
first , err = c . Extensions ( ) . ReplicaSets ( first . Namespace ) . Get ( first . Name , metav1 . GetOptions { } )
2016-06-29 10:55:39 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-11-18 20:55:17 +00:00
firstCond := replicaSetHasDesiredReplicas ( c . Extensions ( ) , first )
2016-10-17 10:40:05 +00:00
err = wait . PollImmediate ( 10 * time . Millisecond , 1 * time . Minute , firstCond )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-06-29 10:55:39 +00:00
2016-11-18 20:55:17 +00:00
secondCond := replicaSetHasDesiredReplicas ( c . Extensions ( ) , second )
2016-10-17 10:40:05 +00:00
err = wait . PollImmediate ( 10 * time . Millisecond , 1 * time . Minute , secondCond )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-06-29 10:55:39 +00:00
By ( fmt . Sprintf ( "Updating the size (up) and template at the same time for deployment %q" , deploymentName ) )
newReplicas := int32 ( 20 )
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , deployment . Name , func ( update * extensions . Deployment ) {
2016-11-18 20:55:17 +00:00
update . Spec . Replicas = & newReplicas
2016-06-29 10:55:39 +00:00
update . Spec . Template . Spec . Containers [ 0 ] . Image = nautilusImage
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-10-30 14:11:40 +00:00
By ( fmt . Sprintf ( "Waiting for deployment status to sync (current available: %d, minimum available: %d)" , deployment . Status . AvailableReplicas , deploymentutil . MinAvailable ( deployment ) ) )
Expect ( framework . WaitForDeploymentStatusValid ( c , deployment ) ) . NotTo ( HaveOccurred ( ) )
2016-06-29 10:55:39 +00:00
oldRSs , _ , rs , err := deploymentutil . GetAllReplicaSets ( deployment , c )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
for _ , rs := range append ( oldRSs , rs ) {
By ( fmt . Sprintf ( "Ensuring replica set %q has the correct desiredReplicas annotation" , rs . Name ) )
desired , ok := deploymentutil . GetDesiredReplicasAnnotation ( rs )
2016-11-18 20:55:17 +00:00
if ! ok || desired == * ( deployment . Spec . Replicas ) {
2016-06-29 10:55:39 +00:00
continue
}
err = fmt . Errorf ( "unexpected desiredReplicas annotation %d for replica set %q" , desired , rs . Name )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
// Update the deployment with a non-existent image so that the new replica set will be blocked.
By ( fmt . Sprintf ( "Updating deployment %q with a non-existent image" , deploymentName ) )
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , d . Name , func ( update * extensions . Deployment ) {
update . Spec . Template . Spec . Containers [ 0 ] . Image = "nginx:404"
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
By ( fmt . Sprintf ( "Waiting for observed generation %d" , deployment . Generation ) )
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-12-07 14:40:26 +00:00
deployment , err = c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName , metav1 . GetOptions { } )
2016-06-29 10:55:39 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-08-02 19:11:25 +00:00
if deployment . Status . AvailableReplicas < deploymentutil . MinAvailable ( deployment ) {
Expect ( fmt . Errorf ( "Observed %d available replicas, less than min required %d" , deployment . Status . AvailableReplicas , deploymentutil . MinAvailable ( deployment ) ) ) . NotTo ( HaveOccurred ( ) )
}
2016-06-29 10:55:39 +00:00
By ( fmt . Sprintf ( "Checking that the replica sets for %q are synced" , deploymentName ) )
2016-12-07 14:40:26 +00:00
oldRs , err := c . Extensions ( ) . ReplicaSets ( rs . Namespace ) . Get ( rs . Name , metav1 . GetOptions { } )
2016-06-29 10:55:39 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
newRs , err := deploymentutil . GetNewReplicaSet ( deployment , c )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-11-18 20:55:17 +00:00
oldCond := replicaSetHasDesiredReplicas ( c . Extensions ( ) , oldRs )
2016-10-17 10:40:05 +00:00
err = wait . PollImmediate ( 10 * time . Millisecond , 1 * time . Minute , oldCond )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-06-29 10:55:39 +00:00
2016-11-18 20:55:17 +00:00
newCond := replicaSetHasDesiredReplicas ( c . Extensions ( ) , newRs )
2016-10-17 10:40:05 +00:00
err = wait . PollImmediate ( 10 * time . Millisecond , 1 * time . Minute , newCond )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-06-29 10:55:39 +00:00
By ( fmt . Sprintf ( "Updating the size (down) and template at the same time for deployment %q" , deploymentName ) )
newReplicas = int32 ( 5 )
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , deployment . Name , func ( update * extensions . Deployment ) {
2016-11-18 20:55:17 +00:00
update . Spec . Replicas = & newReplicas
2016-06-29 10:55:39 +00:00
update . Spec . Template . Spec . Containers [ 0 ] . Image = kittenImage
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-10-30 14:11:40 +00:00
By ( fmt . Sprintf ( "Waiting for deployment status to sync (current available: %d, minimum available: %d)" , deployment . Status . AvailableReplicas , deploymentutil . MinAvailable ( deployment ) ) )
Expect ( framework . WaitForDeploymentStatusValid ( c , deployment ) ) . NotTo ( HaveOccurred ( ) )
2016-06-29 10:55:39 +00:00
oldRSs , _ , rs , err = deploymentutil . GetAllReplicaSets ( deployment , c )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
for _ , rs := range append ( oldRSs , rs ) {
By ( fmt . Sprintf ( "Ensuring replica set %q has the correct desiredReplicas annotation" , rs . Name ) )
desired , ok := deploymentutil . GetDesiredReplicasAnnotation ( rs )
2016-11-18 20:55:17 +00:00
if ! ok || desired == * ( deployment . Spec . Replicas ) {
2016-06-29 10:55:39 +00:00
continue
}
err = fmt . Errorf ( "unexpected desiredReplicas annotation %d for replica set %q" , desired , rs . Name )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
}
2016-08-17 22:37:04 +00:00
func testOverlappingDeployment ( f * framework . Framework ) {
ns := f . Namespace . Name
2016-09-22 15:00:19 +00:00
c := f . ClientSet
2016-11-18 20:55:17 +00:00
internalClient := f . InternalClientset
2016-08-17 22:37:04 +00:00
deploymentName := "first-deployment"
podLabels := map [ string ] string { "name" : redisImageName }
replicas := int32 ( 1 )
By ( fmt . Sprintf ( "Creating deployment %q" , deploymentName ) )
d := newDeployment ( deploymentName , replicas , podLabels , redisImageName , redisImage , extensions . RollingUpdateDeploymentStrategyType , nil )
deploy , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed creating the first deployment" )
// Wait for it to be updated to revision 1
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploy . Name , "1" , redisImage )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "The first deployment failed to update to revision 1" )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
deploymentName = "second-deployment"
By ( fmt . Sprintf ( "Creating deployment %q with overlapping selector" , deploymentName ) )
2016-11-02 21:43:23 +00:00
podLabels [ "other-label" ] = "random-label"
2016-08-17 22:37:04 +00:00
d = newDeployment ( deploymentName , replicas , podLabels , nginxImageName , nginxImage , extensions . RollingUpdateDeploymentStrategyType , nil )
deployOverlapping , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed creating the second deployment" )
// Wait for overlapping annotation updated to both deployments
2016-10-17 14:26:32 +00:00
By ( "Waiting for the overlapping deployment to have overlapping annotation" )
2016-08-17 22:37:04 +00:00
err = framework . WaitForOverlappingAnnotationMatch ( c , ns , deployOverlapping . Name , deploy . Name )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed to update the second deployment's overlapping annotation" )
2016-10-17 14:26:32 +00:00
err = framework . WaitForOverlappingAnnotationMatch ( c , ns , deploy . Name , "" )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "The deployment that holds the oldest selector shouldn't have the overlapping annotation" )
2016-08-17 22:37:04 +00:00
// Only the first deployment is synced
By ( "Checking only the first overlapping deployment is synced" )
2016-11-18 20:55:17 +00:00
options := v1 . ListOptions { }
2016-08-17 22:37:04 +00:00
rsList , err := c . Extensions ( ) . ReplicaSets ( ns ) . List ( options )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed listing all replica sets in namespace %s" , ns )
Expect ( rsList . Items ) . To ( HaveLen ( int ( replicas ) ) )
Expect ( rsList . Items [ 0 ] . Spec . Template . Spec . Containers ) . To ( HaveLen ( 1 ) )
Expect ( rsList . Items [ 0 ] . Spec . Template . Spec . Containers [ 0 ] . Image ) . To ( Equal ( deploy . Spec . Template . Spec . Containers [ 0 ] . Image ) )
By ( "Deleting the first deployment" )
2016-11-18 20:55:17 +00:00
stopDeploymentOverlap ( c , internalClient , ns , deploy . Name , deployOverlapping . Name )
2016-08-17 22:37:04 +00:00
// Wait for overlapping annotation cleared
By ( "Waiting for the second deployment to clear overlapping annotation" )
err = framework . WaitForOverlappingAnnotationMatch ( c , ns , deployOverlapping . Name , "" )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed to clear the second deployment's overlapping annotation" )
// Wait for it to be updated to revision 1
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deployOverlapping . Name , "1" , nginxImage )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "The second deployment failed to update to revision 1" )
// Now the second deployment is synced
By ( "Checking the second overlapping deployment is synced" )
rsList , err = c . Extensions ( ) . ReplicaSets ( ns ) . List ( options )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed listing all replica sets in namespace %s" , ns )
Expect ( rsList . Items ) . To ( HaveLen ( int ( replicas ) ) )
Expect ( rsList . Items [ 0 ] . Spec . Template . Spec . Containers ) . To ( HaveLen ( 1 ) )
Expect ( rsList . Items [ 0 ] . Spec . Template . Spec . Containers [ 0 ] . Image ) . To ( Equal ( deployOverlapping . Spec . Template . Spec . Containers [ 0 ] . Image ) )
deploymentName = "third-deployment"
podLabels = map [ string ] string { "name" : nginxImageName }
By ( fmt . Sprintf ( "Creating deployment %q" , deploymentName ) )
d = newDeployment ( deploymentName , replicas , podLabels , nginxImageName , nginxImage , extensions . RollingUpdateDeploymentStrategyType , nil )
deployLater , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed creating the third deployment" )
// Wait for it to be updated to revision 1
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deployLater . Name , "1" , nginxImage )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "The third deployment failed to update to revision 1" )
// Update the second deployment's selector to make it overlap with the third deployment
By ( fmt . Sprintf ( "Updating deployment %q selector to make it overlap with existing one" , deployOverlapping . Name ) )
deployOverlapping , err = framework . UpdateDeploymentWithRetries ( c , ns , deployOverlapping . Name , func ( update * extensions . Deployment ) {
update . Spec . Selector = deployLater . Spec . Selector
update . Spec . Template . Labels = deployLater . Spec . Template . Labels
update . Spec . Template . Spec . Containers [ 0 ] . Image = redisImage
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Wait for overlapping annotation updated to both deployments
2016-10-17 14:26:32 +00:00
By ( "Waiting for the third deployment to have the overlapping annotation" )
2016-08-17 22:37:04 +00:00
err = framework . WaitForOverlappingAnnotationMatch ( c , ns , deployLater . Name , deployOverlapping . Name )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed to update the third deployment's overlapping annotation" )
2016-10-17 14:26:32 +00:00
err = framework . WaitForOverlappingAnnotationMatch ( c , ns , deployOverlapping . Name , "" )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "The deployment that holds the oldest selector shouldn't have the overlapping annotation" )
2016-08-17 22:37:04 +00:00
// The second deployment shouldn't be synced
By ( "Checking the second deployment is not synced" )
Expect ( deployOverlapping . Annotations [ deploymentutil . RevisionAnnotation ] ) . To ( Equal ( "1" ) )
// Update the second deployment's selector to make it not overlap with the third deployment
By ( fmt . Sprintf ( "Updating deployment %q selector to make it not overlap with existing one" , deployOverlapping . Name ) )
deployOverlapping , err = framework . UpdateDeploymentWithRetries ( c , ns , deployOverlapping . Name , func ( update * extensions . Deployment ) {
update . Spec . Selector = deploy . Spec . Selector
update . Spec . Template . Labels = deploy . Spec . Template . Labels
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Wait for the second deployment to be synced
By ( "Checking the second deployment is now synced" )
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deployOverlapping . Name , "2" , redisImage )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "The second deployment failed to update to revision 2" )
}
2016-09-15 15:58:19 +00:00
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 := "nginx"
nonExistentImage := "nginx:not-there"
thirty := int32 ( 30 )
d := newDeployment ( deploymentName , replicas , podLabels , nginxImageName , nonExistentImage , extensions . RecreateDeploymentStrategyType , nil )
d . Spec . ProgressDeadlineSeconds = & thirty
framework . Logf ( "Creating deployment %q with progressDeadlineSeconds set to %ds and a non-existent image" , deploymentName , thirty )
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
framework . Logf ( "Waiting for deployment %q to be observed by the controller" , deploymentName )
Expect ( framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation ) ) . NotTo ( HaveOccurred ( ) )
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 to be observed by the controller" , deploymentName )
Expect ( framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation ) ) . NotTo ( HaveOccurred ( ) )
framework . Logf ( "Waiting for deployment %q status" , deploymentName )
2016-11-10 15:07:51 +00:00
Expect ( framework . WaitForDeploymentStatusValid ( c , deployment ) ) . NotTo ( HaveOccurred ( ) )
2016-09-15 15:58:19 +00:00
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 ) {
switch r := rand . Float32 ( ) ; {
case r < 0.3 :
framework . Logf ( "%02d: scaling up" , i )
2016-11-18 20:55:17 +00:00
* ( d . Spec . Replicas ) ++
2016-09-15 15:58:19 +00:00
case r < 0.6 :
2016-11-18 20:55:17 +00:00
if * ( d . Spec . Replicas ) > 1 {
2016-09-15 15:58:19 +00:00
framework . Logf ( "%02d: scaling down" , i )
2016-11-18 20:55:17 +00:00
* ( d . Spec . Replicas ) --
2016-09-15 15:58:19 +00:00
}
}
}
func testIterativeDeployments ( f * framework . Framework ) {
ns := f . Namespace . Name
c := f . ClientSet
podLabels := map [ string ] string { "name" : nginxImageName }
replicas := int32 ( 6 )
zero := int64 ( 0 )
two := int32 ( 2 )
// Create a nginx deployment.
deploymentName := "nginx"
thirty := int32 ( 30 )
d := newDeployment ( deploymentName , replicas , podLabels , nginxImageName , nginxImage , extensions . RollingUpdateDeploymentStrategyType , nil )
d . Spec . ProgressDeadlineSeconds = & thirty
d . Spec . RevisionHistoryLimit = & two
d . Spec . Template . Spec . TerminationGracePeriodSeconds = & zero
framework . Logf ( "Creating deployment %q" , deploymentName )
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
iterations := 20
for i := 0 ; i < iterations ; i ++ {
if r := rand . Float32 ( ) ; r < 0.6 {
time . Sleep ( time . Duration ( float32 ( i ) * r * float32 ( time . Second ) ) )
}
switch n := rand . Float32 ( ) ; {
case n < 0.2 :
// trigger a new deployment
framework . Logf ( "%02d: triggering a new rollout for deployment %q" , i , deployment . Name )
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , deployment . Name , func ( update * extensions . Deployment ) {
2016-11-18 20:55:17 +00:00
newEnv := v1 . EnvVar { Name : "A" , Value : fmt . Sprintf ( "%d" , i ) }
2016-09-15 15:58:19 +00:00
update . Spec . Template . Spec . Containers [ 0 ] . Env = append ( update . Spec . Template . Spec . Containers [ 0 ] . Env , newEnv )
randomScale ( update , i )
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
case n < 0.4 :
// rollback to the previous version
framework . Logf ( "%02d: rolling back a rollout for deployment %q" , i , deployment . Name )
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , deployment . Name , func ( update * extensions . Deployment ) {
rollbackTo := & extensions . RollbackConfig { Revision : 0 }
update . Spec . RollbackTo = rollbackTo
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
case n < 0.6 :
// just scaling
framework . Logf ( "%02d: scaling deployment %q" , i , deployment . Name )
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , deployment . Name , func ( update * extensions . Deployment ) {
randomScale ( update , i )
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
case n < 0.8 :
// toggling the deployment
if deployment . Spec . Paused {
framework . Logf ( "%02d: pausing deployment %q" , i , deployment . Name )
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , deployment . Name , func ( update * extensions . Deployment ) {
update . Spec . Paused = true
randomScale ( update , i )
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
} else {
framework . Logf ( "%02d: resuming deployment %q" , i , deployment . Name )
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , deployment . Name , func ( update * extensions . Deployment ) {
update . Spec . Paused = false
randomScale ( update , i )
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
default :
// arbitrarily delete deployment pods
framework . Logf ( "%02d: arbitrarily deleting one or more deployment pods for deployment %q" , i , deployment . Name )
2016-12-03 18:57:26 +00:00
selector , err := metav1 . LabelSelectorAsSelector ( deployment . Spec . Selector )
2016-09-15 15:58:19 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-11-18 20:55:17 +00:00
opts := v1 . ListOptions { LabelSelector : selector . String ( ) }
2016-09-15 15:58:19 +00:00
podList , err := c . Core ( ) . Pods ( ns ) . List ( opts )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
if len ( podList . Items ) == 0 {
framework . Logf ( "%02d: no deployment pods to delete" , i )
continue
}
for p := range podList . Items {
if rand . Float32 ( ) < 0.5 {
continue
}
name := podList . Items [ p ] . Name
framework . Logf ( "%02d: deleting deployment pod %q" , i , name )
2016-11-06 12:30:47 +00:00
err := c . Core ( ) . Pods ( ns ) . Delete ( name , nil )
if err != nil && ! errors . IsNotFound ( err ) {
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
2016-09-15 15:58:19 +00:00
}
}
}
// unpause the deployment if we end up pausing it
2016-12-07 14:40:26 +00:00
deployment , err = c . Extensions ( ) . Deployments ( ns ) . Get ( deployment . Name , metav1 . GetOptions { } )
2016-09-15 15:58:19 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
if deployment . Spec . Paused {
deployment , err = framework . UpdateDeploymentWithRetries ( c , ns , deployment . Name , func ( update * extensions . Deployment ) {
update . Spec . Paused = false
} )
}
framework . Logf ( "Waiting for deployment %q to be observed by the controller" , deploymentName )
Expect ( framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation ) ) . NotTo ( HaveOccurred ( ) )
framework . Logf ( "Waiting for deployment %q status" , deploymentName )
Expect ( framework . WaitForDeploymentStatusValid ( 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 ( ) )
}
2016-11-18 20:55:17 +00:00
func replicaSetHasDesiredReplicas ( rsClient extensionsclient . ReplicaSetsGetter , replicaSet * extensions . ReplicaSet ) wait . ConditionFunc {
desiredGeneration := replicaSet . Generation
return func ( ) ( bool , error ) {
2016-12-07 14:40:26 +00:00
rs , err := rsClient . ReplicaSets ( replicaSet . Namespace ) . Get ( replicaSet . Name , metav1 . GetOptions { } )
2016-11-18 20:55:17 +00:00
if err != nil {
return false , err
}
return rs . Status . ObservedGeneration >= desiredGeneration && rs . Status . Replicas == * ( rs . Spec . Replicas ) , nil
}
}