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-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-02-06 02:43:02 +00:00
"k8s.io/kubernetes/pkg/api/unversioned"
2015-10-09 22:04:41 +00:00
"k8s.io/kubernetes/pkg/apis/extensions"
2016-02-05 21:58:03 +00:00
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
2015-12-02 15:09:01 +00:00
client "k8s.io/kubernetes/pkg/client/unversioned"
2016-03-01 22:15:55 +00:00
adapter "k8s.io/kubernetes/pkg/client/unversioned/adapters/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
It ( "deployment should create new pods" , func ( ) {
testNewDeployment ( 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-29 03:08:19 +00:00
It ( "RollingUpdateDeployment should scale up and down in the right order" , func ( ) {
2015-09-29 23:55:06 +00:00
testRollingUpdateDeploymentEvents ( f )
2015-09-24 18:16:17 +00:00
} )
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-07-25 18:22:18 +00:00
// TODO: add tests that cover deployment.Spec.MinReadySeconds once we solved clock-skew issues
2015-09-24 18:16:17 +00:00
} )
2016-04-27 04:35:14 +00:00
func newRS ( rsName string , replicas int32 , rsPodLabels map [ string ] string , imageName string , image string ) * extensions . ReplicaSet {
2015-12-02 15:09:01 +00:00
zero := int64 ( 0 )
2016-01-20 00:40:18 +00:00
return & extensions . ReplicaSet {
2015-12-01 23:55:13 +00:00
ObjectMeta : api . ObjectMeta {
2016-01-20 00:40:18 +00:00
Name : rsName ,
2015-12-01 23:55:13 +00:00
} ,
2016-01-20 00:40:18 +00:00
Spec : extensions . ReplicaSetSpec {
2015-12-01 23:55:13 +00:00
Replicas : replicas ,
2016-02-06 02:43:02 +00:00
Selector : & unversioned . LabelSelector { MatchLabels : rsPodLabels } ,
2016-03-09 21:11:13 +00:00
Template : api . PodTemplateSpec {
2015-12-01 23:55:13 +00:00
ObjectMeta : api . ObjectMeta {
2016-01-20 00:40:18 +00:00
Labels : rsPodLabels ,
2015-12-01 23:55:13 +00:00
} ,
Spec : api . PodSpec {
2015-12-02 15:09:01 +00:00
TerminationGracePeriodSeconds : & zero ,
2015-12-01 23:55:13 +00:00
Containers : [ ] api . Container {
{
Name : imageName ,
Image : image ,
} ,
} ,
} ,
} ,
} ,
}
}
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 {
2015-09-24 18:16:17 +00:00
ObjectMeta : api . ObjectMeta {
Name : deploymentName ,
} ,
2015-10-09 22:49:10 +00:00
Spec : extensions . DeploymentSpec {
2016-01-13 03:27:26 +00:00
Replicas : replicas ,
2016-02-06 02:43:02 +00:00
Selector : & unversioned . 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 ,
2015-10-26 23:20:43 +00:00
Template : api . PodTemplateSpec {
2015-09-24 18:16:17 +00:00
ObjectMeta : api . ObjectMeta {
Labels : podLabels ,
} ,
Spec : api . PodSpec {
2015-12-02 15:09:01 +00:00
TerminationGracePeriodSeconds : & zero ,
2015-09-24 18:16:17 +00:00
Containers : [ ] api . Container {
{
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.
func checkDeploymentRevision ( c * clientset . Clientset , ns , deploymentName , revision , imageName , image string ) ( * extensions . Deployment , * extensions . ReplicaSet ) {
2016-01-15 05:00:58 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName )
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
}
2015-12-02 15:09:01 +00:00
func stopDeployment ( c * clientset . Clientset , oldC client . Interface , ns , deploymentName string ) {
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-04-15 22:20:41 +00:00
framework . Logf ( "Deleting deployment %s" , deploymentName )
2015-12-02 15:09:01 +00:00
reaper , err := kubectl . ReaperFor ( extensions . Kind ( "Deployment" ) , oldC )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
timeout := 1 * time . Minute
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 )
2015-12-02 15:09:01 +00:00
_ , err = c . Extensions ( ) . Deployments ( ns ) . Get ( deployment . Name )
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 )
2015-12-02 15:09:01 +00:00
selector , err := unversioned . LabelSelectorAsSelector ( deployment . Spec . Selector )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
options := api . ListOptions { LabelSelector : selector }
rss , err := c . Extensions ( ) . ReplicaSets ( ns ) . List ( options )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
Expect ( rss . Items ) . Should ( HaveLen ( 0 ) )
2016-04-15 22:20:41 +00:00
framework . Logf ( "Ensuring deployment %s's Pods were deleted" , deploymentName )
2016-02-23 22:16:08 +00:00
var pods * api . 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
}
if len ( pods . Items ) == 0 {
return true , nil
}
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-01-15 05:00:58 +00:00
// TODO: remove unversionedClient when the refactoring is done. Currently some
// functions like verifyPod still expects a unversioned#Client.
2016-03-01 22:15:55 +00:00
c := adapter . FromUnversionedClient ( f . Client )
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
defer stopDeployment ( c , f . Client , ns , deploymentName )
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-03-01 01:56:40 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName )
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-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-01-15 05:00:58 +00:00
// TODO: remove unversionedClient when the refactoring is done. Currently some
// functions like verifyPod still expects a unversioned#Client.
unversionedClient := f . Client
2016-03-01 22:15:55 +00:00
c := adapter . FromUnversionedClient ( unversionedClient )
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-03-06 01:40:59 +00:00
_ , err := c . Extensions ( ) . ReplicaSets ( ns ) . Create ( newRS ( rsName , replicas , rsPodLabels , nginxImageName , nginxImage ) )
2015-09-29 23:55:06 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Verify that the required pods have come up.
2016-04-07 17:21:31 +00:00
err = framework . VerifyPods ( unversionedClient , 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-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 , deploymentPodLabels , redisImageName , redisImage , extensions . RollingUpdateDeploymentStrategyType , nil ) )
2015-09-29 23:55:06 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-12-02 15:09:01 +00:00
defer stopDeployment ( c , f . Client , ns , deploymentName )
2015-09-29 23:55:06 +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" , redisImage )
2015-10-03 01:27:37 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-13 01:52:18 +00:00
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)
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName )
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 testRollingUpdateDeploymentEvents ( f * framework . Framework ) {
2015-09-29 23:55:06 +00:00
ns := f . Namespace . Name
2016-01-15 05:00:58 +00:00
// TODO: remove unversionedClient when the refactoring is done. Currently some
// functions like verifyPod still expects a unversioned#Client.
unversionedClient := f . Client
2016-03-01 22:15:55 +00:00
c := adapter . FromUnversionedClient ( unversionedClient )
2015-09-29 23:55:06 +00:00
// Create nginx pods.
2015-12-17 02:47:50 +00:00
deploymentPodLabels := map [ string ] string { "name" : "sample-pod-2" }
2016-01-20 00:40:18 +00:00
rsPodLabels := map [ string ] string {
2015-12-17 02:47:50 +00:00
"name" : "sample-pod-2" ,
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-scale-controller"
2016-04-27 04:35:14 +00:00
replicas := int32 ( 1 )
2016-01-13 01:52:18 +00:00
2016-01-20 00:40:18 +00:00
rsRevision := "3546343826724305832"
2016-01-13 01:52:18 +00:00
annotations := make ( map [ string ] string )
2016-01-20 00:40:18 +00:00
annotations [ deploymentutil . RevisionAnnotation ] = rsRevision
2016-03-06 01:40:59 +00:00
rs := newRS ( rsName , replicas , rsPodLabels , nginxImageName , nginxImage )
2016-01-20 00:40:18 +00:00
rs . Annotations = annotations
2016-01-13 01:52:18 +00:00
2016-01-20 00:40:18 +00:00
_ , err := c . Extensions ( ) . ReplicaSets ( ns ) . Create ( rs )
2015-09-24 18:16:17 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Verify that the required pods have come up.
2016-04-07 17:21:31 +00:00
err = framework . VerifyPods ( unversionedClient , ns , "sample-pod-2" , false , 1 )
2015-09-24 18:16:17 +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 ( ) )
2015-09-24 18:16:17 +00:00
}
2015-09-29 23:55:06 +00:00
// Create a deployment to delete nginx pods and instead bring up redis pods.
2016-02-29 19:03:43 +00:00
deploymentName := "test-rolling-scale-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 , deploymentPodLabels , redisImageName , redisImage , extensions . RollingUpdateDeploymentStrategyType , nil ) )
2015-09-24 18:16:17 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-12-02 15:09:01 +00:00
defer stopDeployment ( c , f . Client , ns , deploymentName )
2015-09-24 18:16:17 +00:00
2016-03-01 01:56:40 +00:00
// Wait for it to be updated to revision 3546343826724305833
2016-04-07 17:21:31 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "3546343826724305833" , redisImage )
2016-03-01 01:56:40 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-08-02 00:04:00 +00:00
err = framework . WaitForDeploymentStatus ( c , deploy )
2015-10-03 01:27:37 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-09-29 23:55:06 +00:00
// Verify that the pods were scaled up and down as expected. We use events to verify that.
2016-01-15 05:00:58 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName )
2015-09-24 18:16:17 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-04-07 17:21:31 +00:00
framework . WaitForEvents ( unversionedClient , ns , deployment , 2 )
2016-02-03 21:21:05 +00:00
events , err := c . Core ( ) . Events ( ns ) . Search ( deployment )
2015-09-29 23:55:06 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Logf ( "error in listing events: %s" , err )
2015-09-29 23:55:06 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
2016-01-20 00:40:18 +00:00
// There should be 2 events, one to scale up the new ReplicaSet and then to scale down
// the old ReplicaSet.
2015-09-29 23:55:06 +00:00
Expect ( len ( events . Items ) ) . Should ( Equal ( 2 ) )
2016-02-28 02:13:32 +00:00
newRS , err := deploymentutil . GetNewReplicaSet ( deployment , c )
2015-09-29 23:55:06 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-20 00:40:18 +00:00
Expect ( newRS ) . NotTo ( Equal ( nil ) )
Expect ( events . Items [ 0 ] . Message ) . Should ( Equal ( fmt . Sprintf ( "Scaled up replica set %s to 1" , newRS . Name ) ) )
Expect ( events . Items [ 1 ] . Message ) . Should ( Equal ( fmt . Sprintf ( "Scaled down replica set %s to 0" , rsName ) ) )
2015-09-24 18:16:17 +00:00
}
2015-12-01 23:55:13 +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-01-15 05:00:58 +00:00
// TODO: remove unversionedClient when the refactoring is done. Currently some
// functions like verifyPod still expects a unversioned#Client.
unversionedClient := f . Client
2016-03-01 22:15:55 +00:00
c := adapter . FromUnversionedClient ( unversionedClient )
2016-01-13 03:27:26 +00:00
// Create nginx pods.
deploymentPodLabels := map [ string ] string { "name" : "sample-pod-3" }
2016-01-20 00:40:18 +00:00
rsPodLabels := map [ string ] string {
2016-01-13 03:27:26 +00:00
"name" : "sample-pod-3" ,
2016-03-06 01:40:59 +00:00
"pod" : nginxImageName ,
2016-01-13 03:27:26 +00:00
}
2016-02-29 19:03:43 +00:00
rsName := "test-recreate-controller"
2016-04-27 04:35:14 +00:00
replicas := int32 ( 3 )
2016-03-06 01:40:59 +00:00
_ , err := c . Extensions ( ) . ReplicaSets ( ns ) . Create ( newRS ( rsName , replicas , rsPodLabels , nginxImageName , nginxImage ) )
2016-01-13 03:27:26 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Verify that the required pods have come up.
2016-04-07 17:21:31 +00:00
err = framework . VerifyPods ( unversionedClient , ns , "sample-pod-3" , false , 3 )
2016-01-13 03:27:26 +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-13 03:27:26 +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-recreate-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 , deploymentPodLabels , redisImageName , redisImage , extensions . RecreateDeploymentStrategyType , nil ) )
2016-01-13 03:27:26 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-12-02 15:09:01 +00:00
defer stopDeployment ( c , f . Client , ns , deploymentName )
2016-01-13 03:27:26 +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" , redisImage )
2016-03-01 01:56:40 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-08-02 00:04:00 +00:00
err = framework . WaitForDeploymentStatus ( c , deploy )
2016-01-13 03:27:26 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Verify that the pods were scaled up and down as expected. We use events to verify that.
2016-01-15 05:00:58 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName )
2016-01-13 03:27:26 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-04-07 17:21:31 +00:00
framework . WaitForEvents ( unversionedClient , ns , deployment , 2 )
2016-02-03 21:21:05 +00:00
events , err := c . Core ( ) . Events ( ns ) . Search ( deployment )
2016-01-13 03:27:26 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Logf ( "error in listing events: %s" , err )
2016-01-13 03:27:26 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
2016-01-20 00:40:18 +00:00
// There should be 2 events, one to scale up the new ReplicaSet and then to scale down the old ReplicaSet.
2016-01-13 03:27:26 +00:00
Expect ( len ( events . Items ) ) . Should ( Equal ( 2 ) )
2016-02-28 02:13:32 +00:00
newRS , err := deploymentutil . GetNewReplicaSet ( deployment , c )
2016-01-13 03:27:26 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-01-20 00:40:18 +00:00
Expect ( newRS ) . NotTo ( Equal ( nil ) )
Expect ( events . Items [ 0 ] . Message ) . Should ( Equal ( fmt . Sprintf ( "Scaled down replica set %s to 0" , rsName ) ) )
Expect ( events . Items [ 1 ] . Message ) . Should ( Equal ( fmt . Sprintf ( "Scaled up replica set %s to 3" , newRS . Name ) ) )
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-01-15 05:00:58 +00:00
unversionedClient := f . Client
2016-03-01 22:15:55 +00:00
c := adapter . FromUnversionedClient ( unversionedClient )
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-04-07 17:21:31 +00:00
err = framework . VerifyPods ( unversionedClient , 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
pods , err := c . Pods ( ns ) . List ( api . ListOptions { LabelSelector : labels . Everything ( ) } )
if err != nil {
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed to query for pods: %v" , err )
}
options := api . ListOptions {
ResourceVersion : pods . ListMeta . ResourceVersion ,
}
stopCh := make ( chan struct { } )
w , err := c . Pods ( ns ) . Watch ( options )
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
}
pod , ok := event . Object . ( * api . Pod )
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 ( ) )
2015-12-02 15:09:01 +00:00
defer stopDeployment ( c , f . Client , ns , deploymentName )
2016-01-28 06:13:07 +00:00
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-01-15 05:00:58 +00:00
// TODO: remove unversionedClient when the refactoring is done. Currently some
// functions like verifyPod still expects a unversioned#Client.
unversionedClient := f . Client
2016-03-01 22:15:55 +00:00
c := adapter . FromUnversionedClient ( unversionedClient )
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-04-07 17:21:31 +00:00
err = framework . VerifyPods ( unversionedClient , 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 ( ) )
}
// 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-04-07 17:21:31 +00:00
framework . Logf ( "Creating deployment %s" , 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-01-31 13:59:58 +00:00
MaxUnavailable : intstr . FromInt ( 1 ) ,
MaxSurge : intstr . FromInt ( 1 ) ,
2015-12-01 23:55:13 +00:00
}
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
defer stopDeployment ( c , f . Client , ns , deploymentName )
2016-04-15 22:20:41 +00:00
// Verify that the pods were scaled up and down as expected.
2016-01-15 05:00:58 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName )
2016-01-13 01:52:18 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
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-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.
Expect ( newRS . Spec . Replicas ) . Should ( BeNumerically ( "<" , deploymentReplicas ) )
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-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-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-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-01-15 05:00:58 +00:00
// TODO: remove unversionedClient when the refactoring is done. Currently some
// functions like verifyPod still expects a unversioned#Client.
unversionedClient := f . Client
2016-03-01 22:15:55 +00:00
c := adapter . FromUnversionedClient ( unversionedClient )
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-01-28 16:35:14 +00:00
tgps := int64 ( 20 )
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 ( ) )
2015-12-02 15:09:01 +00:00
defer stopDeployment ( c , f . Client , ns , deploymentName )
2016-01-21 10:12:58 +00:00
// Check that deployment is created fine.
2016-01-15 05:00:58 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName )
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-02-06 02:43:02 +00:00
selector , err := unversioned . LabelSelectorAsSelector ( deployment . Spec . Selector )
if err != nil {
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
opts := api . ListOptions { LabelSelector : selector }
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 )
newTGPS := int64 ( 40 )
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-01-15 05:00:58 +00:00
unversionedClient := f . Client
2016-03-01 22:15:55 +00:00
c := adapter . FromUnversionedClient ( unversionedClient )
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-03-17 22:39:05 +00:00
createAnnotation := map [ string ] string { "action" : "create" , "author" : "minion" }
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
defer stopDeployment ( c , f . Client , ns , deploymentName )
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-03-01 22:15:55 +00:00
c := adapter . FromUnversionedClient ( f . Client )
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
defer stopDeployment ( c , f . Client , ns , deploymentName )
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
rs , err = c . Extensions ( ) . ReplicaSets ( ns ) . Get ( rsName )
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
// TODO: remove unversionedClient when the refactoring is done. Currently some
// functions like verifyPod still expects a unversioned#Client.
unversionedClient := f . Client
2016-03-01 22:15:55 +00:00
c := adapter . FromUnversionedClient ( unversionedClient )
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-04-07 17:21:31 +00:00
err = framework . VerifyPods ( unversionedClient , 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
defer stopDeployment ( c , f . Client , ns , deploymentName )
// 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)
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName )
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
selector , err := unversioned . LabelSelectorAsSelector ( deployment . Spec . Selector )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
options := api . ListOptions { LabelSelector : selector }
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
c := adapter . FromUnversionedClient ( f . Client )
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 ( ) )
defer stopDeployment ( c , f . Client , ns , deploymentName )
// Check that deployment is created fine.
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName )
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 ) {
update . Spec . Replicas = newReplicas
} )
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 ( ) )
if rs . Spec . Replicas != newReplicas {
err = fmt . Errorf ( "Expected %d replicas for the new replica set, got %d" , newReplicas , rs . Spec . Replicas )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
}
2016-06-29 10:55:39 +00:00
func testScaledRolloutDeployment ( f * framework . Framework ) {
ns := f . Namespace . Name
c := adapter . FromUnversionedClient ( f . Client )
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 )
d . Spec . Strategy . RollingUpdate . MaxSurge = intstr . FromInt ( 3 )
d . Spec . Strategy . RollingUpdate . MaxUnavailable = intstr . FromInt ( 2 )
By ( fmt . Sprintf ( "Creating deployment %q" , deploymentName ) )
_ , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
defer stopDeployment ( c , f . Client , ns , deploymentName )
// Check that deployment is created fine.
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName )
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 ( ) )
deployment , err = c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
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" )
err = framework . VerifyPods ( f . Client , ns , nginxImageName , false , deployment . Spec . Replicas )
if err != nil {
framework . Logf ( "error in waiting for pods to come up: %s" , err )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
err = framework . WaitForDeploymentStatus ( c , deployment )
2016-06-29 10:55:39 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
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 ( ) )
deployment , err = c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName )
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 ( ) )
first , err = c . Extensions ( ) . ReplicaSets ( first . Namespace ) . Get ( first . Name )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
firstCond := client . ReplicaSetHasDesiredReplicas ( f . Client . Extensions ( ) , first )
wait . PollImmediate ( 10 * time . Millisecond , 1 * time . Minute , firstCond )
secondCond := client . ReplicaSetHasDesiredReplicas ( f . Client . Extensions ( ) , second )
wait . PollImmediate ( 10 * time . Millisecond , 1 * time . Minute , secondCond )
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 ) {
update . Spec . Replicas = newReplicas
update . Spec . Template . Spec . Containers [ 0 ] . Image = nautilusImage
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
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 )
if ! ok || desired == deployment . Spec . Replicas {
continue
}
err = fmt . Errorf ( "unexpected desiredReplicas annotation %d for replica set %q" , desired , rs . Name )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
2016-08-01 22:26:17 +00:00
By ( fmt . Sprintf ( "Waiting for deployment status to sync (current available: %d, minimum available: %d)" , deployment . Status . AvailableReplicas , deploymentutil . MinAvailable ( deployment ) ) )
2016-08-02 19:11:25 +00:00
err = framework . WaitForDeploymentStatusValid ( c , deployment )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
err = framework . WaitForDeploymentStatus ( c , deployment )
2016-06-29 10:55:39 +00:00
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 ( ) )
deployment , err = c . Extensions ( ) . Deployments ( ns ) . Get ( deploymentName )
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 ) )
oldRs , err := c . Extensions ( ) . ReplicaSets ( rs . Namespace ) . Get ( rs . Name )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
newRs , err := deploymentutil . GetNewReplicaSet ( deployment , c )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
oldCond := client . ReplicaSetHasDesiredReplicas ( f . Client . Extensions ( ) , oldRs )
wait . PollImmediate ( 10 * time . Millisecond , 1 * time . Minute , oldCond )
newCond := client . ReplicaSetHasDesiredReplicas ( f . Client . Extensions ( ) , newRs )
wait . PollImmediate ( 10 * time . Millisecond , 1 * time . Minute , newCond )
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 ) {
update . Spec . Replicas = newReplicas
update . Spec . Template . Spec . Containers [ 0 ] . Image = kittenImage
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
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 )
if ! ok || desired == deployment . Spec . Replicas {
continue
}
err = fmt . Errorf ( "unexpected desiredReplicas annotation %d for replica set %q" , desired , rs . Name )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
2016-08-01 22:26:17 +00:00
By ( fmt . Sprintf ( "Waiting for deployment status to sync (current available: %d, minimum available: %d)" , deployment . Status . AvailableReplicas , deploymentutil . MinAvailable ( deployment ) ) )
2016-08-02 19:11:25 +00:00
err = framework . WaitForDeploymentStatusValid ( c , deployment )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
err = framework . WaitForDeploymentStatus ( c , deployment )
2016-06-29 10:55:39 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
2016-08-17 22:37:04 +00:00
func testOverlappingDeployment ( f * framework . Framework ) {
ns := f . Namespace . Name
// TODO: remove unversionedClient when the refactoring is done. Currently some
// functions like verifyPod still expects a unversioned#Client.
c := adapter . FromUnversionedClient ( f . Client )
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 ) )
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" )
defer stopDeployment ( c , f . Client , ns , deployOverlapping . Name )
// Wait for overlapping annotation updated to both deployments
By ( "Waiting for both deployments to have overlapping annotations" )
err = framework . WaitForOverlappingAnnotationMatch ( c , ns , deploy . Name , deployOverlapping . Name )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed to update the first deployment's overlapping annotation" )
err = framework . WaitForOverlappingAnnotationMatch ( c , ns , deployOverlapping . Name , deploy . Name )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed to update the second deployment's overlapping annotation" )
// Only the first deployment is synced
By ( "Checking only the first overlapping deployment is synced" )
options := api . ListOptions { }
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" )
stopDeployment ( c , f . Client , ns , deploy . Name )
// 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" )
defer stopDeployment ( c , f . Client , ns , deployLater . Name )
// 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
By ( "Waiting for both deployments to have overlapping annotations" )
err = framework . WaitForOverlappingAnnotationMatch ( c , ns , deployOverlapping . Name , deployLater . Name )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed to update the second deployment's overlapping annotation" )
err = framework . WaitForOverlappingAnnotationMatch ( c , ns , deployLater . Name , deployOverlapping . Name )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed to update the third deployment's overlapping annotation" )
// 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" )
}