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 .
* /
2017-07-20 10:22:11 +00:00
package apps
2015-09-24 18:16:17 +00:00
import (
2015-09-29 23:55:06 +00:00
"fmt"
2016-09-15 15:58:19 +00:00
"math/rand"
2016-01-21 10:12:58 +00:00
"time"
2015-10-26 23:20:43 +00:00
2017-04-21 17:49:30 +00:00
"github.com/davecgh/go-spew/spew"
2016-05-10 21:44:45 +00:00
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
2017-04-21 17:49:30 +00:00
2017-06-22 18:24:23 +00:00
"k8s.io/api/core/v1"
extensions "k8s.io/api/extensions/v1beta1"
2017-01-13 17:48:50 +00:00
"k8s.io/apimachinery/pkg/api/errors"
2017-01-11 14:09:48 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
2017-03-13 22:29:27 +00:00
"k8s.io/apimachinery/pkg/types"
2017-01-27 20:42:17 +00:00
"k8s.io/apimachinery/pkg/util/intstr"
2017-01-11 14:09:48 +00:00
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/watch"
2017-06-23 20:56:37 +00:00
clientset "k8s.io/client-go/kubernetes"
extensionsclient "k8s.io/client-go/kubernetes/typed/extensions/v1beta1"
2016-11-18 20:55:17 +00:00
extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions"
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"
2017-06-29 08:39:26 +00:00
utilpointer "k8s.io/kubernetes/pkg/util/pointer"
2016-04-07 17:21:31 +00:00
"k8s.io/kubernetes/test/e2e/framework"
2016-11-07 17:23:09 +00:00
testutil "k8s.io/kubernetes/test/utils"
2015-09-24 18:16:17 +00:00
)
2016-03-06 01:40:59 +00:00
const (
2017-03-13 22:29:27 +00:00
dRetryPeriod = 2 * time . Second
dRetryTimeout = 5 * time . Minute
2016-03-06 01:40:59 +00:00
)
2017-04-24 18:14:21 +00:00
var (
nilRs * extensions . ReplicaSet
)
2017-07-12 18:35:57 +00:00
var _ = SIGDescribe ( "Deployment" , func ( ) {
2016-11-07 17:23:09 +00:00
var ns string
var c clientset . Interface
AfterEach ( func ( ) {
failureTrap ( c , ns )
} )
2016-04-07 17:21:31 +00:00
f := framework . NewDefaultFramework ( "deployment" )
2015-09-24 18:16:17 +00:00
2016-11-07 17:23:09 +00:00
BeforeEach ( func ( ) {
c = f . ClientSet
ns = f . Namespace . Name
} )
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 )
} )
2017-04-02 17:00:59 +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 ( "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-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 )
} )
2017-02-27 18:08:59 +00:00
It ( "lack of progress should be reported in the deployment status" , func ( ) {
2016-09-15 15:58:19 +00:00
testFailedDeployment ( f )
} )
It ( "iterative rollouts should eventually progress" , func ( ) {
testIterativeDeployments ( f )
} )
2017-03-13 22:29:27 +00:00
It ( "test Deployment ReplicaSet orphaning and adoption regarding controllerRef" , func ( ) {
testDeploymentsControllerRef ( 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-11-07 17:23:09 +00:00
func failureTrap ( c clientset . Interface , ns string ) {
deployments , err := c . Extensions ( ) . Deployments ( ns ) . List ( metav1 . ListOptions { LabelSelector : labels . Everything ( ) . String ( ) } )
if err != nil {
framework . Logf ( "Could not list Deployments in namespace %q: %v" , ns , err )
return
}
for i := range deployments . Items {
d := deployments . Items [ i ]
framework . Logf ( spew . Sprintf ( "Deployment %q:\n%+v\n" , d . Name , d ) )
2017-07-21 10:46:24 +00:00
_ , allOldRSs , newRS , err := deploymentutil . GetAllReplicaSets ( & d , c . ExtensionsV1beta1 ( ) )
2016-11-07 17:23:09 +00:00
if err != nil {
framework . Logf ( "Could not list ReplicaSets for Deployment %q: %v" , d . Name , err )
return
}
testutil . LogReplicaSetsOfDeployment ( & d , allOldRSs , newRS , framework . Logf )
rsList := allOldRSs
if newRS != nil {
rsList = append ( rsList , newRS )
}
testutil . LogPodsOfDeployment ( c , & d , rsList , framework . Logf )
}
2017-06-15 10:09:43 +00:00
// We need print all the ReplicaSets if there are no Deployment object created
if len ( deployments . Items ) != 0 {
return
}
framework . Logf ( "Log out all the ReplicaSets if there is no deployment created" )
rss , err := c . ExtensionsV1beta1 ( ) . ReplicaSets ( ns ) . List ( metav1 . ListOptions { LabelSelector : labels . Everything ( ) . String ( ) } )
if err != nil {
framework . Logf ( "Could not list ReplicaSets in namespace %q: %v" , ns , err )
return
}
for _ , rs := range rss . Items {
framework . Logf ( spew . Sprintf ( "ReplicaSet %q:\n%+v\n" , rs . Name , rs ) )
selector , err := metav1 . LabelSelectorAsSelector ( rs . Spec . Selector )
if err != nil {
framework . Logf ( "failed to get selector of ReplicaSet %s: %v" , rs . Name , err )
}
options := metav1 . ListOptions { LabelSelector : selector . String ( ) }
podList , err := c . Core ( ) . Pods ( rs . Namespace ) . List ( options )
for _ , pod := range podList . Items {
framework . Logf ( spew . Sprintf ( "pod: %q:\n%+v\n" , pod . Name , pod ) )
}
}
2016-11-07 17:23:09 +00:00
}
2017-03-29 17:12:59 +00:00
func intOrStrP ( num int ) * intstr . IntOrString {
intstr := intstr . FromInt ( num )
return & intstr
}
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
2017-07-21 11:52:39 +00:00
newRS , err := deploymentutil . GetNewReplicaSet ( deployment , c . ExtensionsV1beta1 ( ) )
2016-01-15 02:04:05 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-04-24 18:14:21 +00:00
Expect ( newRS ) . NotTo ( Equal ( nilRs ) )
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 stopDeployment ( c clientset . Interface , internalClient internalclientset . Interface , ns , deploymentName 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
2017-01-24 15:38:21 +00:00
err = reaper . Stop ( ns , deployment . Name , timeout , metav1 . NewDeleteOptions ( 0 ) )
2015-12-02 15:09:01 +00:00
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 ( ) )
2017-01-22 03:36:02 +00:00
options := metav1 . ListOptions { LabelSelector : selector . String ( ) }
2015-12-02 15:09:01 +00:00
rss , err := c . Extensions ( ) . ReplicaSets ( ns ) . List ( options )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-03-04 01:00:30 +00:00
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-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
2017-03-04 01:00:30 +00:00
if len ( pods . Items ) == 0 {
2015-12-02 15:09:01 +00:00
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-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"
2017-05-25 09:18:42 +00:00
podLabels := map [ string ] string { "name" : NginxImageName }
2016-10-07 10:16:34 +00:00
replicas := int32 ( 1 )
framework . Logf ( "Creating simple deployment %s" , deploymentName )
2017-05-25 09:18:42 +00:00
d := framework . NewDeployment ( deploymentName , replicas , podLabels , NginxImageName , NginxImage , extensions . RollingUpdateDeploymentStrategyType )
2017-05-16 22:30:29 +00:00
d . Annotations = map [ string ] string { "test" : "should-copy-to-replica-set" , v1 . LastAppliedConfigAnnotation : "should-not-copy-to-replica-set" }
2016-10-07 10:16:34 +00:00
deploy , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Wait for it to be updated to revision 1
2017-05-25 09:18:42 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "1" , NginxImage )
2016-10-07 10:16:34 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-04-24 18:14:21 +00:00
err = framework . WaitForDeploymentStatusValid ( c , deploy )
2016-10-07 10:16:34 +00:00
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 ( ) )
2017-07-21 11:52:39 +00:00
newRS , err := deploymentutil . GetNewReplicaSet ( deployment , c . ExtensionsV1beta1 ( ) )
2016-10-07 10:16:34 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-04-24 18:14:21 +00:00
Expect ( newRS ) . NotTo ( Equal ( nilRs ) )
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" ,
2017-05-25 09:18:42 +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"
2017-02-03 18:38:42 +00:00
replicas := int32 ( 1 )
2016-12-09 16:16:00 +00:00
rsRevision := "3546343826724305832"
annotations := make ( map [ string ] string )
annotations [ deploymentutil . RevisionAnnotation ] = rsRevision
2017-05-25 09:18:42 +00:00
rs := newRS ( rsName , replicas , rsPodLabels , NginxImageName , NginxImage )
2016-12-09 16:16:00 +00:00
rs . Annotations = annotations
2017-04-24 18:14:21 +00:00
framework . Logf ( "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.
2017-02-03 18:38:42 +00:00
err = framework . VerifyPodsRunning ( c , ns , "sample-pod" , false , replicas )
2017-04-24 18:14:21 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) , "error in waiting for pods to come up: %s" , err )
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-update-deployment"
2017-04-24 18:14:21 +00:00
framework . Logf ( "Creating deployment %q" , deploymentName )
2017-05-25 09:18:42 +00:00
d := framework . NewDeployment ( deploymentName , replicas , deploymentPodLabels , RedisImageName , RedisImage , extensions . RollingUpdateDeploymentStrategyType )
2017-02-01 18:40:55 +00:00
deploy , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
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.
2017-04-24 18:14:21 +00:00
framework . Logf ( "Ensuring deployment %q gets the next revision from the one the adopted replica set %q has" , deploy . Name , rs . Name )
2017-05-25 09:18:42 +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
2017-04-24 18:14:21 +00:00
framework . Logf ( "Ensuring status for deployment %q is the expected" , deploy . Name )
err = framework . WaitForDeploymentStatusValid ( 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)
2017-04-24 18:14:21 +00:00
framework . Logf ( "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 ( ) )
2017-07-21 11:52:39 +00:00
_ , allOldRSs , err := deploymentutil . GetOldReplicaSets ( deployment , c . ExtensionsV1beta1 ( ) )
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"
2017-04-24 18:14:21 +00:00
framework . Logf ( "Creating deployment %q" , deploymentName )
2017-05-25 09:18:42 +00:00
d := framework . NewDeployment ( deploymentName , int32 ( 1 ) , map [ string ] string { "name" : "sample-pod-3" } , RedisImageName , RedisImage , extensions . RecreateDeploymentStrategyType )
2017-02-01 18:40:55 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
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
2017-04-24 18:14:21 +00:00
framework . Logf ( "Waiting deployment %q to be updated to revision 1" , deploymentName )
2017-05-25 09:18:42 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploymentName , "1" , RedisImage )
2016-03-01 01:56:40 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-04-24 18:14:21 +00:00
framework . Logf ( "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.
2017-04-24 18:14:21 +00:00
framework . Logf ( "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 ) {
2017-05-25 09:18:42 +00:00
update . Spec . Template . Spec . Containers [ 0 ] . Name = NginxImageName
update . Spec . Template . Spec . Containers [ 0 ] . Image = NginxImage
2016-11-10 12:30:44 +00:00
} )
2016-01-13 03:27:26 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2016-11-10 12:30:44 +00:00
2017-04-24 18:14:21 +00:00
framework . Logf ( "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" ,
2017-05-25 09:18:42 +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 )
2017-06-29 08:39:26 +00:00
revisionHistoryLimit := utilpointer . Int32Ptr ( 0 )
2017-05-25 09:18:42 +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.
2017-03-29 17:12:59 +00:00
err = framework . VerifyPodsRunning ( c , ns , "cleanup-pod" , false , replicas )
2017-04-24 18:14:21 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) , "error in waiting for pods to come up: %v" , err )
2016-01-28 06:13:07 +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-cleanup-deployment"
2017-04-24 18:14:21 +00:00
framework . Logf ( "Creating deployment %s" , deploymentName )
2016-03-11 18:34:13 +00:00
2017-01-22 03:36:02 +00:00
pods , err := c . Core ( ) . Pods ( ns ) . List ( metav1 . ListOptions { LabelSelector : labels . Everything ( ) . String ( ) } )
2017-04-24 18:14:21 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed to query for pods: %v" , err )
2017-01-22 03:36:02 +00:00
options := metav1 . ListOptions {
2016-03-11 18:34:13 +00:00
ResourceVersion : pods . ListMeta . ResourceVersion ,
}
stopCh := make ( chan struct { } )
2017-03-29 17:12:59 +00:00
defer close ( stopCh )
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 {
2017-04-24 18:14:21 +00:00
framework . Failf ( "Expect event Object to be a pod" )
2016-03-11 18:34:13 +00:00
}
2017-05-25 09:18:42 +00:00
if pod . Spec . Containers [ 0 ] . Name != RedisImageName {
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
}
}
} ( )
2017-05-25 09:18:42 +00:00
d := framework . NewDeployment ( deploymentName , replicas , deploymentPodLabels , RedisImageName , RedisImage , extensions . RollingUpdateDeploymentStrategyType )
2017-02-01 18:40:55 +00:00
d . Spec . RevisionHistoryLimit = revisionHistoryLimit
_ , err = c . Extensions ( ) . Deployments ( ns ) . Create ( d )
2016-01-28 06:13:07 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-02-08 22:18:13 +00:00
By ( fmt . Sprintf ( "Waiting for deployment %s history to be cleaned up" , deploymentName ) )
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 ( ) )
}
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 ,
2017-05-25 09:18:42 +00:00
"pod" : NginxImageName ,
2015-12-01 23:55:13 +00:00
}
2016-02-29 19:03:43 +00:00
rsName := "test-rollover-controller"
2017-03-29 17:12:59 +00:00
rsReplicas := int32 ( 1 )
2017-05-25 09:18:42 +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.
2017-02-03 00:58:13 +00:00
err = framework . VerifyPodsRunning ( c , ns , podName , false , rsReplicas )
2017-04-24 18:14:21 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) , "error in waiting for pods to come up: %v" , err )
2015-12-01 23:55:13 +00:00
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"
2017-03-29 17:12:59 +00:00
deploymentReplicas := int32 ( 1 )
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 )
2017-02-01 18:40:55 +00:00
newDeployment := framework . NewDeployment ( deploymentName , deploymentReplicas , deploymentPodLabels , deploymentImageName , deploymentImage , deploymentStrategyType )
2015-12-01 23:55:13 +00:00
newDeployment . Spec . Strategy . RollingUpdate = & extensions . RollingUpdateDeployment {
2017-03-29 17:12:59 +00:00
MaxUnavailable : intOrStrP ( 0 ) ,
MaxSurge : intOrStrP ( 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
2017-03-29 17:12:59 +00:00
err = framework . WaitForDeploymentUpdatedReplicasLTE ( c , ns , deploymentName , deploymentReplicas , 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
2017-03-29 17:12:59 +00:00
framework . Logf ( "Ensure that both replica sets have 1 created replica" )
oldRS , err := c . Extensions ( ) . ReplicaSets ( ns ) . Get ( rsName , metav1 . GetOptions { } )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
ensureReplicas ( oldRS , int32 ( 1 ) )
newRS , err = c . Extensions ( ) . ReplicaSets ( ns ) . Get ( newRS . Name , metav1 . GetOptions { } )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
ensureReplicas ( newRS , int32 ( 1 ) )
// The deployment is stuck, update it to rollover the above 2 ReplicaSets and bring up redis pods.
framework . Logf ( "Rollover old replica sets for deployment %q with new image update" , deploymentName )
2017-05-25 09:18:42 +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 ( ) )
2017-03-29 17:12:59 +00:00
framework . Logf ( "Ensure that both old replica sets have no replicas" )
oldRS , err = c . Extensions ( ) . ReplicaSets ( ns ) . Get ( rsName , metav1 . GetOptions { } )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
ensureReplicas ( oldRS , int32 ( 0 ) )
// Not really the new replica set anymore but we GET by name so that's fine.
newRS , err = c . Extensions ( ) . ReplicaSets ( ns ) . Get ( newRS . Name , metav1 . GetOptions { } )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
ensureReplicas ( newRS , int32 ( 0 ) )
2015-12-01 23:55:13 +00:00
}
2016-01-21 10:12:58 +00:00
2017-03-29 17:12:59 +00:00
func ensureReplicas ( rs * extensions . ReplicaSet , replicas int32 ) {
Expect ( * rs . Spec . Replicas ) . Should ( Equal ( replicas ) )
Expect ( rs . Status . Replicas ) . Should ( Equal ( replicas ) )
}
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),
2017-10-12 23:36:13 +00:00
// and then rollback to last revision (which is revision 4 that comes from revision 2).
// Then rollback the deployment to revision 10 (doesn't exist in history) should fail.
// Finally, rollback current deployment (revision 4) to revision 4 should be no-op.
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.
2017-05-25 09:18:42 +00:00
deploymentName , deploymentImageName := "test-rollback-deployment" , NginxImageName
2016-04-27 04:35:14 +00:00
deploymentReplicas := int32 ( 1 )
2017-05-25 09:18:42 +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 )
2017-02-01 18:40:55 +00:00
d := framework . NewDeployment ( deploymentName , deploymentReplicas , deploymentPodLabels , deploymentImageName , deploymentImage , deploymentStrategyType )
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 ( ) )
2017-04-24 18:14:21 +00:00
err = framework . WaitForDeploymentStatusValid ( 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.
2017-05-25 09:18:42 +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 ( ) )
2017-10-12 23:36:13 +00:00
// 5. Update the deploymentRollback to rollback to revision 10
// Since there's no revision 10 in history, it should stay as revision 4
revision = 10
framework . Logf ( "rolling back deployment %s to revision %d" , deploymentName , revision )
rollback = newDeploymentRollback ( deploymentName , nil , revision )
err = c . Extensions ( ) . Deployments ( ns ) . Rollback ( rollback )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Wait for the deployment to start rolling back
err = framework . WaitForDeploymentRollbackCleared ( c , ns , deploymentName )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// TODO: report RollbackRevisionNotFound in deployment status and check it here
// The pod template shouldn't change since there's no revision 10
// Check if it's still revision 4 and still has the old pod template
checkDeploymentRevision ( c , ns , deploymentName , "4" , updatedDeploymentImageName , updatedDeploymentImage )
// 6. Update the deploymentRollback to rollback to revision 4
// Since it's already revision 4, it should be no-op
revision = 4
framework . Logf ( "rolling back deployment %s to revision %d" , deploymentName , revision )
rollback = newDeploymentRollback ( deploymentName , nil , revision )
err = c . Extensions ( ) . Deployments ( ns ) . Rollback ( rollback )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// Wait for the deployment to start rolling back
err = framework . WaitForDeploymentRollbackCleared ( c , ns , deploymentName )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
// TODO: report RollbackTemplateUnchanged in deployment status and check it here
// The pod template shouldn't change since it's already revision 4
// Check if it's still revision 4 and still has the old pod template
checkDeploymentRevision ( c , ns , deploymentName , "4" , updatedDeploymentImageName , updatedDeploymentImage )
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 ,
2017-05-25 09:18:42 +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 )
2017-05-25 09:18:42 +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.
2017-05-25 09:18:42 +00:00
deploymentName , deploymentImageName := "test-rollback-no-revision-deployment" , NginxImageName
2016-04-27 04:35:14 +00:00
deploymentReplicas := int32 ( 1 )
2017-05-25 09:18:42 +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 )
2017-02-01 18:40:55 +00:00
d := framework . NewDeployment ( deploymentName , deploymentReplicas , deploymentPodLabels , deploymentImageName , deploymentImage , deploymentStrategyType )
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 ( ) )
2017-04-24 18:14:21 +00:00
err = framework . WaitForDeploymentStatusValid ( 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.
2017-05-25 09:18:42 +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 ( ) )
2016-01-15 02:04:05 +00:00
}
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"
2017-03-29 17:12:59 +00:00
replicas := int32 ( 1 )
2017-05-25 09:18:42 +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.
2017-03-29 17:12:59 +00:00
err = framework . VerifyPodsRunning ( c , ns , podName , false , replicas )
2017-04-24 18:14:21 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) , "error in waiting for pods to come up: %v" , err )
2016-02-11 18:57:42 +00:00
// 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 )
2017-02-01 18:40:55 +00:00
deploy , err := c . Extensions ( ) . Deployments ( ns ) . Create ( framework . NewDeployment ( deploymentName , replicas , podLabels , podName , image , extensions . RollingUpdateDeploymentStrategyType ) )
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
2017-04-24 18:14:21 +00:00
err = framework . WaitForDeploymentStatusValid ( 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 ( ) )
2017-07-21 10:46:24 +00:00
oldRSs , allOldRSs , newRS , err := deploymentutil . GetAllReplicaSets ( deployment , c . ExtensionsV1beta1 ( ) )
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 ( ) )
2017-01-22 03:36:02 +00:00
options := metav1 . 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
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
2017-05-25 09:18:42 +00:00
podLabels := map [ string ] string { "name" : NginxImageName }
2016-06-29 10:55:39 +00:00
replicas := int32 ( 10 )
// Create a nginx deployment.
deploymentName := "nginx"
2017-05-25 09:18:42 +00:00
d := framework . NewDeployment ( deploymentName , replicas , podLabels , NginxImageName , NginxImage , extensions . RollingUpdateDeploymentStrategyType )
2016-06-29 10:55:39 +00:00
d . Spec . Strategy . RollingUpdate = new ( extensions . RollingUpdateDeployment )
2017-03-29 17:12:59 +00:00
d . Spec . Strategy . RollingUpdate . MaxSurge = intOrStrP ( 3 )
d . Spec . Strategy . RollingUpdate . MaxUnavailable = intOrStrP ( 2 )
2016-06-29 10:55:39 +00:00
2017-04-24 18:14:21 +00:00
framework . Logf ( "Creating deployment %q" , deploymentName )
2016-11-06 12:48:31 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
2016-06-29 10:55:39 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-04-24 18:14:21 +00:00
framework . Logf ( "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.
2017-04-24 18:14:21 +00:00
framework . Logf ( "Waiting for all required pods to come up" )
2017-05-25 09:18:42 +00:00
err = framework . VerifyPodsRunning ( f . ClientSet , ns , NginxImageName , false , * ( deployment . Spec . Replicas ) )
2017-04-24 18:14:21 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) , "error in waiting for pods to come up: %v" , err )
framework . Logf ( "Waiting for deployment %q to complete" , deployment . Name )
2016-11-06 12:48:31 +00:00
Expect ( framework . WaitForDeploymentStatusValid ( c , deployment ) ) . NotTo ( HaveOccurred ( ) )
2016-06-29 10:55:39 +00:00
2017-07-21 11:52:39 +00:00
first , err := deploymentutil . GetNewReplicaSet ( deployment , c . ExtensionsV1beta1 ( ) )
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.
2017-04-24 18:14:21 +00:00
framework . Logf ( "Updating deployment %q with a non-existent image" , deploymentName )
2016-06-29 10:55:39 +00:00
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 ( ) )
2017-04-24 18:14:21 +00:00
framework . Logf ( "Waiting for observed generation %d" , deployment . Generation )
2016-06-29 10:55:39 +00:00
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
2017-04-24 18:14:21 +00:00
framework . Logf ( "Checking that the replica sets for %q are synced" , deploymentName )
2017-07-21 11:52:39 +00:00
second , err := deploymentutil . GetNewReplicaSet ( deployment , c . ExtensionsV1beta1 ( ) )
2016-06-29 10:55:39 +00:00
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
2017-04-24 18:14:21 +00:00
framework . Logf ( "Updating the size (up) and template at the same time for deployment %q" , deploymentName )
2016-06-29 10:55:39 +00:00
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
2017-05-25 09:18:42 +00:00
update . Spec . Template . Spec . Containers [ 0 ] . Image = NautilusImage
2016-06-29 10:55:39 +00:00
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-04-24 18:14:21 +00:00
framework . Logf ( "Waiting for deployment status to sync (current available: %d, minimum available: %d)" , deployment . Status . AvailableReplicas , deploymentutil . MinAvailable ( deployment ) )
2016-10-30 14:11:40 +00:00
Expect ( framework . WaitForDeploymentStatusValid ( c , deployment ) ) . NotTo ( HaveOccurred ( ) )
2017-07-21 10:46:24 +00:00
oldRSs , _ , rs , err := deploymentutil . GetAllReplicaSets ( deployment , c . ExtensionsV1beta1 ( ) )
2016-06-29 10:55:39 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
for _ , rs := range append ( oldRSs , rs ) {
2017-04-24 18:14:21 +00:00
framework . Logf ( "Ensuring replica set %q has the correct desiredReplicas annotation" , rs . Name )
2016-06-29 10:55:39 +00:00
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.
2017-04-24 18:14:21 +00:00
framework . Logf ( "Updating deployment %q with a non-existent image" , deploymentName )
2016-06-29 10:55:39 +00:00
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 ( ) )
2017-04-24 18:14:21 +00:00
framework . Logf ( "Waiting for observed generation %d" , deployment . Generation )
2016-06-29 10:55:39 +00:00
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
2017-04-24 18:14:21 +00:00
framework . Logf ( "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 ( ) )
2017-07-21 11:52:39 +00:00
newRs , err := deploymentutil . GetNewReplicaSet ( deployment , c . ExtensionsV1beta1 ( ) )
2016-06-29 10:55:39 +00:00
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
2017-04-24 18:14:21 +00:00
framework . Logf ( "Updating the size (down) and template at the same time for deployment %q" , deploymentName )
2016-06-29 10:55:39 +00:00
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
2017-05-25 09:18:42 +00:00
update . Spec . Template . Spec . Containers [ 0 ] . Image = KittenImage
2016-06-29 10:55:39 +00:00
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
err = framework . WaitForObservedDeployment ( c , ns , deploymentName , deployment . Generation )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-04-24 18:14:21 +00:00
framework . Logf ( "Waiting for deployment status to sync (current available: %d, minimum available: %d)" , deployment . Status . AvailableReplicas , deploymentutil . MinAvailable ( deployment ) )
2016-10-30 14:11:40 +00:00
Expect ( framework . WaitForDeploymentStatusValid ( c , deployment ) ) . NotTo ( HaveOccurred ( ) )
2017-07-21 10:46:24 +00:00
oldRSs , _ , rs , err = deploymentutil . GetAllReplicaSets ( deployment , c . ExtensionsV1beta1 ( ) )
2016-06-29 10:55:39 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
for _ , rs := range append ( oldRSs , rs ) {
2017-04-24 18:14:21 +00:00
framework . Logf ( "Ensuring replica set %q has the correct desiredReplicas annotation" , rs . Name )
2016-06-29 10:55:39 +00:00
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-08-17 22:37:04 +00:00
2017-03-04 01:00:30 +00:00
// Create first deployment.
2016-08-17 22:37:04 +00:00
deploymentName := "first-deployment"
2017-05-25 09:18:42 +00:00
podLabels := map [ string ] string { "name" : RedisImageName }
2016-08-17 22:37:04 +00:00
replicas := int32 ( 1 )
2017-04-24 18:14:21 +00:00
framework . Logf ( "Creating deployment %q" , deploymentName )
2017-05-25 09:18:42 +00:00
d := framework . NewDeployment ( deploymentName , replicas , podLabels , RedisImageName , RedisImage , extensions . RollingUpdateDeploymentStrategyType )
2016-08-17 22:37:04 +00:00
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
2017-05-25 09:18:42 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deploy . Name , "1" , RedisImage )
2016-08-17 22:37:04 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) , "The first deployment failed to update to revision 1" )
2017-03-04 01:00:30 +00:00
// Create second deployment with overlapping selector.
2016-08-17 22:37:04 +00:00
deploymentName = "second-deployment"
2017-04-24 18:14:21 +00:00
framework . Logf ( "Creating deployment %q with overlapping selector" , deploymentName )
2016-11-02 21:43:23 +00:00
podLabels [ "other-label" ] = "random-label"
2017-05-25 09:18:42 +00:00
d = framework . NewDeployment ( deploymentName , replicas , podLabels , NginxImageName , NginxImage , extensions . RollingUpdateDeploymentStrategyType )
2016-08-17 22:37:04 +00:00
deployOverlapping , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed creating the second deployment" )
// Wait for it to be updated to revision 1
2017-05-25 09:18:42 +00:00
err = framework . WaitForDeploymentRevisionAndImage ( c , ns , deployOverlapping . Name , "1" , NginxImage )
2016-08-17 22:37:04 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) , "The second deployment failed to update to revision 1" )
2017-03-04 01:00:30 +00:00
// Both deployments should proceed independently.
2017-04-24 18:14:21 +00:00
framework . Logf ( "Checking each deployment creates its own replica set" )
2017-03-04 01:00:30 +00:00
options := metav1 . ListOptions { }
rsList , err := c . Extensions ( ) . ReplicaSets ( ns ) . List ( options )
2016-08-17 22:37:04 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) , "Failed listing all replica sets in namespace %s" , ns )
2017-03-04 01:00:30 +00:00
Expect ( rsList . Items ) . To ( HaveLen ( 2 ) )
2016-08-17 22:37:04 +00:00
}
2016-09-15 15:58:19 +00:00
func testFailedDeployment ( f * framework . Framework ) {
ns := f . Namespace . Name
c := f . ClientSet
2017-05-25 09:18:42 +00:00
podLabels := map [ string ] string { "name" : NginxImageName }
2016-09-15 15:58:19 +00:00
replicas := int32 ( 1 )
// Create a nginx deployment.
2017-02-07 21:17:37 +00:00
deploymentName := "progress-check"
2016-09-15 15:58:19 +00:00
nonExistentImage := "nginx:not-there"
2017-02-02 13:41:11 +00:00
ten := int32 ( 10 )
2017-05-25 09:18:42 +00:00
d := framework . NewDeployment ( deploymentName , replicas , podLabels , NginxImageName , nonExistentImage , extensions . RecreateDeploymentStrategyType )
2017-02-02 13:41:11 +00:00
d . Spec . ProgressDeadlineSeconds = & ten
2016-09-15 15:58:19 +00:00
2017-02-02 13:41:11 +00:00
framework . Logf ( "Creating deployment %q with progressDeadlineSeconds set to %ds and a non-existent image" , deploymentName , ten )
2016-09-15 15:58:19 +00:00
deployment , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-02-02 13:41:11 +00:00
framework . Logf ( "Waiting for deployment %q new replica set to come up" , deploymentName )
2017-03-29 17:12:59 +00:00
Expect ( framework . WaitForDeploymentUpdatedReplicasLTE ( c , ns , deploymentName , replicas , deployment . Generation ) )
2016-09-15 15:58:19 +00:00
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 ) {
2017-05-25 09:18:42 +00:00
update . Spec . Template . Spec . Containers [ 0 ] . Image = NginxImage
2016-09-15 15:58:19 +00:00
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-02-02 13:41:11 +00:00
framework . Logf ( "Waiting for deployment %q new replica set to come up" , deploymentName )
2017-03-29 17:12:59 +00:00
Expect ( framework . WaitForDeploymentUpdatedReplicasLTE ( c , ns , deploymentName , replicas , deployment . Generation ) )
2016-09-15 15:58:19 +00:00
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
2017-05-25 09:18:42 +00:00
podLabels := map [ string ] string { "name" : NginxImageName }
2016-09-15 15:58:19 +00:00
replicas := int32 ( 6 )
zero := int64 ( 0 )
two := int32 ( 2 )
// Create a nginx deployment.
deploymentName := "nginx"
thirty := int32 ( 30 )
2017-05-25 09:18:42 +00:00
d := framework . NewDeployment ( deploymentName , replicas , podLabels , NginxImageName , NginxImage , extensions . RollingUpdateDeploymentStrategyType )
2016-09-15 15:58:19 +00:00
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 ( ) )
2017-01-22 03:36:02 +00:00
opts := metav1 . 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
}
}
2017-03-13 22:29:27 +00:00
func testDeploymentsControllerRef ( f * framework . Framework ) {
ns := f . Namespace . Name
c := f . ClientSet
deploymentName := "test-orphan-deployment"
2017-04-24 18:14:21 +00:00
framework . Logf ( "Creating Deployment %q" , deploymentName )
2017-05-25 09:18:42 +00:00
podLabels := map [ string ] string { "name" : NginxImageName }
2017-03-13 22:29:27 +00:00
replicas := int32 ( 1 )
2017-05-25 09:18:42 +00:00
d := framework . NewDeployment ( deploymentName , replicas , podLabels , NginxImageName , NginxImage , extensions . RollingUpdateDeploymentStrategyType )
2017-03-13 22:29:27 +00:00
deploy , err := c . Extensions ( ) . Deployments ( ns ) . Create ( d )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-04-24 18:14:21 +00:00
err = framework . WaitForDeploymentStatusValid ( c , deploy )
2017-03-13 22:29:27 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-04-24 18:14:21 +00:00
framework . Logf ( "Checking its ReplicaSet has the right controllerRef" )
2017-03-13 22:29:27 +00:00
err = checkDeploymentReplicaSetsControllerRef ( c , ns , deploy . UID , podLabels )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-04-24 18:14:21 +00:00
framework . Logf ( "Deleting Deployment %q and orphaning its ReplicaSets" , deploymentName )
2017-03-13 22:29:27 +00:00
err = orphanDeploymentReplicaSets ( c , deploy )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
By ( "Wait for the ReplicaSet to be orphaned" )
err = wait . Poll ( dRetryPeriod , dRetryTimeout , waitDeploymentReplicaSetsOrphaned ( c , ns , podLabels ) )
Expect ( err ) . NotTo ( HaveOccurred ( ) , "error waiting for Deployment ReplicaSet to be orphaned" )
deploymentName = "test-adopt-deployment"
2017-04-24 18:14:21 +00:00
framework . Logf ( "Creating Deployment %q to adopt the ReplicaSet" , deploymentName )
2017-05-25 09:18:42 +00:00
d = framework . NewDeployment ( deploymentName , replicas , podLabels , NginxImageName , NginxImage , extensions . RollingUpdateDeploymentStrategyType )
2017-03-13 22:29:27 +00:00
deploy , err = c . Extensions ( ) . Deployments ( ns ) . Create ( d )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-04-24 18:14:21 +00:00
err = framework . WaitForDeploymentStatusValid ( c , deploy )
2017-03-13 22:29:27 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2017-04-24 18:14:21 +00:00
framework . Logf ( "Waiting for the ReplicaSet to have the right controllerRef" )
2017-03-13 22:29:27 +00:00
err = checkDeploymentReplicaSetsControllerRef ( c , ns , deploy . UID , podLabels )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
}
func waitDeploymentReplicaSetsControllerRef ( c clientset . Interface , ns string , uid types . UID , label map [ string ] string ) func ( ) ( bool , error ) {
return func ( ) ( bool , error ) {
err := checkDeploymentReplicaSetsControllerRef ( c , ns , uid , label )
if err != nil {
return false , nil
}
return true , nil
}
}
func checkDeploymentReplicaSetsControllerRef ( c clientset . Interface , ns string , uid types . UID , label map [ string ] string ) error {
rsList := listDeploymentReplicaSets ( c , ns , label )
for _ , rs := range rsList . Items {
// This rs is adopted only when its controller ref is update
2017-08-02 09:41:33 +00:00
if controllerRef := metav1 . GetControllerOf ( & rs ) ; controllerRef == nil || controllerRef . UID != uid {
2017-03-13 22:29:27 +00:00
return fmt . Errorf ( "ReplicaSet %s has unexpected controllerRef %v" , rs . Name , controllerRef )
}
}
return nil
}
func waitDeploymentReplicaSetsOrphaned ( c clientset . Interface , ns string , label map [ string ] string ) func ( ) ( bool , error ) {
return func ( ) ( bool , error ) {
rsList := listDeploymentReplicaSets ( c , ns , label )
for _ , rs := range rsList . Items {
// This rs is orphaned only when controller ref is cleared
2017-08-02 09:41:33 +00:00
if controllerRef := metav1 . GetControllerOf ( & rs ) ; controllerRef != nil {
2017-03-13 22:29:27 +00:00
return false , nil
}
}
return true , nil
}
}
func listDeploymentReplicaSets ( c clientset . Interface , ns string , label map [ string ] string ) * extensions . ReplicaSetList {
selector := labels . Set ( label ) . AsSelector ( )
options := metav1 . ListOptions { LabelSelector : selector . String ( ) }
rsList , err := c . Extensions ( ) . ReplicaSets ( ns ) . List ( options )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
Expect ( len ( rsList . Items ) ) . To ( BeNumerically ( ">" , 0 ) )
return rsList
}
func orphanDeploymentReplicaSets ( c clientset . Interface , d * extensions . Deployment ) error {
trueVar := true
deleteOptions := & metav1 . DeleteOptions { OrphanDependents : & trueVar }
deleteOptions . Preconditions = metav1 . NewUIDPreconditions ( string ( d . UID ) )
return c . Extensions ( ) . Deployments ( d . Namespace ) . Delete ( d . Name , deleteOptions )
}