2016-06-17 04:07:39 +00:00
/ *
2016-06-03 00:25:58 +00:00
Copyright 2016 The Kubernetes Authors .
2016-06-17 04:07:39 +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-01-11 13:23:31 +00:00
package e2e_federation
2016-06-17 04:07:39 +00:00
import (
"fmt"
2016-07-29 08:01:41 +00:00
"time"
2017-01-27 20:42:17 +00:00
"k8s.io/apimachinery/pkg/util/intstr"
2016-06-17 04:07:39 +00:00
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/util/wait"
2017-01-19 18:27:59 +00:00
restclient "k8s.io/client-go/rest"
2017-01-20 18:06:17 +00:00
"k8s.io/client-go/tools/clientcmd"
2017-01-18 14:57:11 +00:00
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
2016-08-10 20:43:57 +00:00
federationapi "k8s.io/kubernetes/federation/apis/federation/v1beta1"
2016-12-14 17:57:24 +00:00
fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
2016-07-29 08:01:41 +00:00
"k8s.io/kubernetes/pkg/api"
2016-08-10 20:43:57 +00:00
"k8s.io/kubernetes/pkg/api/v1"
2016-12-14 01:18:17 +00:00
kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
2017-01-11 13:23:31 +00:00
"k8s.io/kubernetes/test/e2e/common"
2016-06-17 04:07:39 +00:00
"k8s.io/kubernetes/test/e2e/framework"
2017-01-11 13:23:31 +00:00
fedframework "k8s.io/kubernetes/test/e2e_federation/framework"
2016-07-29 08:01:41 +00:00
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var (
KubeAPIQPS float32 = 20.0
KubeAPIBurst = 30
DefaultFederationName = "federation"
UserAgentName = "federation-e2e"
// We use this to decide how long to wait for our DNS probes to succeed.
DNSTTL = 180 * time . Second // TODO: make k8s.io/kubernetes/federation/pkg/federation-controller/service.minDnsTtl exported, and import it here.
2017-02-22 01:39:26 +00:00
// FederatedSvcNodePort is the node port on which the federated
// service shards are exposed in the underlying cluster.
FederatedSvcNodePort = int32 ( 32256 )
2016-06-17 04:07:39 +00:00
)
2017-01-11 13:23:31 +00:00
var FederationSuite common . Suite
2017-02-13 22:58:49 +00:00
// cluster keeps track of the assorted objects and state related to each cluster
// in the federation
2016-07-29 08:01:41 +00:00
type cluster struct {
name string
2016-09-02 18:57:44 +00:00
* kubeclientset . Clientset
2016-07-29 08:01:41 +00:00
namespaceCreated bool // Did we need to create a new namespace in this cluster? If so, we should delete it.
backendPod * v1 . Pod // The backend pod, if one's been created.
}
2017-01-11 13:23:31 +00:00
func createClusterObjectOrFail ( f * fedframework . Framework , context * fedframework . E2EContext ) {
2016-06-17 04:07:39 +00:00
framework . Logf ( "Creating cluster object: %s (%s, secret: %s)" , context . Name , context . Cluster . Cluster . Server , context . Name )
cluster := federationapi . Cluster {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-06-17 04:07:39 +00:00
Name : context . Name ,
} ,
Spec : federationapi . ClusterSpec {
ServerAddressByClientCIDRs : [ ] federationapi . ServerAddressByClientCIDR {
{
ClientCIDR : "0.0.0.0/0" ,
ServerAddress : context . Cluster . Cluster . Server ,
} ,
} ,
2016-08-10 20:43:57 +00:00
SecretRef : & v1 . LocalObjectReference {
2016-06-17 04:07:39 +00:00
// Note: Name must correlate with federation build script secret name,
// which currently matches the cluster name.
// See federation/cluster/common.sh:132
Name : context . Name ,
} ,
} ,
}
2017-01-11 13:23:31 +00:00
_ , err := f . FederationClientset . Federation ( ) . Clusters ( ) . Create ( & cluster )
2016-06-17 04:07:39 +00:00
framework . ExpectNoError ( err , fmt . Sprintf ( "creating cluster: %+v" , err ) )
framework . Logf ( "Successfully created cluster object: %s (%s, secret: %s)" , context . Name , context . Cluster . Cluster . Server , context . Name )
}
2017-01-11 13:23:31 +00:00
func clusterIsReadyOrFail ( f * fedframework . Framework , context * fedframework . E2EContext ) {
c , err := f . FederationClientset . Federation ( ) . Clusters ( ) . Get ( context . Name , metav1 . GetOptions { } )
2016-06-17 04:07:39 +00:00
framework . ExpectNoError ( err , fmt . Sprintf ( "get cluster: %+v" , err ) )
if c . ObjectMeta . Name != context . Name {
framework . Failf ( "cluster name does not match input context: actual=%+v, expected=%+v" , c , context )
}
2017-01-11 13:23:31 +00:00
err = isReady ( context . Name , f . FederationClientset )
2016-06-17 04:07:39 +00:00
framework . ExpectNoError ( err , fmt . Sprintf ( "unexpected error in verifying if cluster %s is ready: %+v" , context . Name , err ) )
framework . Logf ( "Cluster %s is Ready" , context . Name )
}
2016-07-29 08:01:41 +00:00
2017-02-03 10:06:28 +00:00
// waitForAllRegisteredClusters waits for all clusters defined in e2e context to be created
2016-08-18 01:49:08 +00:00
// return ClusterList until the listed cluster items equals clusterCount
2017-02-03 10:06:28 +00:00
func waitForAllRegisteredClusters ( f * fedframework . Framework , clusterCount int ) * federationapi . ClusterList {
2016-07-29 08:01:41 +00:00
var clusterList * federationapi . ClusterList
if err := wait . PollImmediate ( framework . Poll , FederatedServiceTimeout , func ( ) ( bool , error ) {
var err error
2017-01-22 03:36:02 +00:00
clusterList , err = f . FederationClientset . Federation ( ) . Clusters ( ) . List ( metav1 . ListOptions { } )
2016-07-29 08:01:41 +00:00
if err != nil {
return false , err
}
2016-08-18 01:49:08 +00:00
framework . Logf ( "%d clusters registered, waiting for %d" , len ( clusterList . Items ) , clusterCount )
if len ( clusterList . Items ) == clusterCount {
2016-07-29 08:01:41 +00:00
return true , nil
}
return false , nil
} ) ; err != nil {
framework . Failf ( "Failed to list registered clusters: %+v" , err )
}
return clusterList
}
2016-09-02 18:57:44 +00:00
func createClientsetForCluster ( c federationapi . Cluster , i int , userAgentName string ) * kubeclientset . Clientset {
2016-07-29 08:01:41 +00:00
kubecfg , err := clientcmd . LoadFromFile ( framework . TestContext . KubeConfig )
framework . ExpectNoError ( err , "error loading KubeConfig: %v" , err )
cfgOverride := & clientcmd . ConfigOverrides {
ClusterInfo : clientcmdapi . Cluster {
Server : c . Spec . ServerAddressByClientCIDRs [ 0 ] . ServerAddress ,
} ,
}
ccfg := clientcmd . NewNonInteractiveClientConfig ( * kubecfg , c . Name , cfgOverride , clientcmd . NewDefaultClientConfigLoadingRules ( ) )
cfg , err := ccfg . ClientConfig ( )
framework . ExpectNoError ( err , "Error creating client config in cluster #%d (%q)" , i , c . Name )
cfg . QPS = KubeAPIQPS
cfg . Burst = KubeAPIBurst
2016-09-02 18:57:44 +00:00
return kubeclientset . NewForConfigOrDie ( restclient . AddUserAgent ( cfg , userAgentName ) )
2016-07-29 08:01:41 +00:00
}
2016-08-22 17:48:43 +00:00
// Creates the federation namespace in all underlying clusters.
2017-01-11 13:23:31 +00:00
func createNamespaceInClusters ( clusters map [ string ] * cluster , f * fedframework . Framework ) {
2016-08-22 17:48:43 +00:00
nsName := f . FederationNamespace . Name
2016-07-29 08:01:41 +00:00
for name , c := range clusters {
2016-08-22 17:48:43 +00:00
// The e2e Framework created the required namespace in federation control plane, but we need to create it in all the others, if it doesn't yet exist.
// TODO(nikhiljindal): remove this once we have the namespace controller working as expected.
2016-12-07 14:40:26 +00:00
if _ , err := c . Clientset . Core ( ) . Namespaces ( ) . Get ( nsName , metav1 . GetOptions { } ) ; errors . IsNotFound ( err ) {
2016-07-29 08:01:41 +00:00
ns := & v1 . Namespace {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-08-22 17:48:43 +00:00
Name : nsName ,
2016-07-29 08:01:41 +00:00
} ,
}
_ , err := c . Clientset . Core ( ) . Namespaces ( ) . Create ( ns )
if err == nil {
c . namespaceCreated = true
}
2016-08-22 17:48:43 +00:00
framework . ExpectNoError ( err , "Couldn't create the namespace %s in cluster %q" , nsName , name )
framework . Logf ( "Namespace %s created in cluster %q" , nsName , name )
2016-07-29 08:01:41 +00:00
} else if err != nil {
2016-08-22 17:48:43 +00:00
framework . Logf ( "Couldn't create the namespace %s in cluster %q: %v" , nsName , name , err )
2016-07-29 08:01:41 +00:00
}
}
}
2016-08-22 17:48:43 +00:00
// Unregisters the given clusters from federation control plane.
// Also deletes the federation namespace from each cluster.
2017-01-11 13:23:31 +00:00
func unregisterClusters ( clusters map [ string ] * cluster , f * fedframework . Framework ) {
2016-08-22 17:48:43 +00:00
nsName := f . FederationNamespace . Name
2016-07-29 08:01:41 +00:00
for name , c := range clusters {
if c . namespaceCreated {
2016-12-07 14:40:26 +00:00
if _ , err := c . Clientset . Core ( ) . Namespaces ( ) . Get ( nsName , metav1 . GetOptions { } ) ; ! errors . IsNotFound ( err ) {
2017-01-24 15:38:21 +00:00
err := c . Clientset . Core ( ) . Namespaces ( ) . Delete ( nsName , & metav1 . DeleteOptions { } )
2016-08-22 17:48:43 +00:00
framework . ExpectNoError ( err , "Couldn't delete the namespace %s in cluster %q: %v" , nsName , name , err )
2016-07-29 08:01:41 +00:00
}
2016-08-22 17:48:43 +00:00
framework . Logf ( "Namespace %s deleted in cluster %q" , nsName , name )
2016-07-29 08:01:41 +00:00
}
}
// Delete the registered clusters in the federation API server.
2017-01-22 03:36:02 +00:00
clusterList , err := f . FederationClientset . Federation ( ) . Clusters ( ) . List ( metav1 . ListOptions { } )
2016-07-29 08:01:41 +00:00
framework . ExpectNoError ( err , "Error listing clusters" )
for _ , cluster := range clusterList . Items {
2017-01-24 15:38:21 +00:00
err := f . FederationClientset . Federation ( ) . Clusters ( ) . Delete ( cluster . Name , & metav1 . DeleteOptions { } )
2016-07-29 08:01:41 +00:00
framework . ExpectNoError ( err , "Error deleting cluster %q" , cluster . Name )
}
}
// can not be moved to util, as By and Expect must be put in Ginkgo test unit
2017-02-03 10:06:28 +00:00
func getRegisteredClusters ( userAgentName string , f * fedframework . Framework ) ( map [ string ] * cluster , string ) {
clusters := make ( map [ string ] * cluster )
2016-07-29 08:01:41 +00:00
contexts := f . GetUnderlyingFederatedContexts ( )
By ( "Obtaining a list of all the clusters" )
2017-02-03 10:06:28 +00:00
clusterList := waitForAllRegisteredClusters ( f , len ( contexts ) )
2016-07-29 08:01:41 +00:00
framework . Logf ( "Checking that %d clusters are Ready" , len ( contexts ) )
for _ , context := range contexts {
clusterIsReadyOrFail ( f , & context )
}
framework . Logf ( "%d clusters are Ready" , len ( contexts ) )
primaryClusterName := clusterList . Items [ 0 ] . Name
By ( fmt . Sprintf ( "Labeling %q as the first cluster" , primaryClusterName ) )
for i , c := range clusterList . Items {
framework . Logf ( "Creating a clientset for the cluster %s" , c . Name )
Expect ( framework . TestContext . KubeConfig ) . ToNot ( Equal ( "" ) , "KubeConfig must be specified to load clusters' client config" )
clusters [ c . Name ] = & cluster { c . Name , createClientsetForCluster ( c , i , userAgentName ) , false , nil }
}
2017-02-03 10:06:28 +00:00
return clusters , primaryClusterName
2016-07-29 08:01:41 +00:00
}
2017-02-13 22:58:49 +00:00
// waitForServiceOrFail waits until a service is either present or absent in the cluster specified by clientset.
// If the condition is not met within timout, it fails the calling test.
2016-09-02 18:57:44 +00:00
func waitForServiceOrFail ( clientset * kubeclientset . Clientset , namespace string , service * v1 . Service , present bool , timeout time . Duration ) {
2016-07-29 08:01:41 +00:00
By ( fmt . Sprintf ( "Fetching a federated service shard of service %q in namespace %q from cluster" , service . Name , namespace ) )
err := wait . PollImmediate ( framework . Poll , timeout , func ( ) ( bool , error ) {
2016-12-07 14:40:26 +00:00
clusterService , err := clientset . Services ( namespace ) . Get ( service . Name , metav1 . GetOptions { } )
2016-07-29 08:01:41 +00:00
if ( ! present ) && errors . IsNotFound ( err ) { // We want it gone, and it's gone.
By ( fmt . Sprintf ( "Success: shard of federated service %q in namespace %q in cluster is absent" , service . Name , namespace ) )
return true , nil // Success
}
if present && err == nil { // We want it present, and the Get succeeded, so we're all good.
2017-02-14 07:20:42 +00:00
if equivalent ( * clusterService , * service ) {
By ( fmt . Sprintf ( "Success: shard of federated service %q in namespace %q in cluster is present" , service . Name , namespace ) )
return true , nil // Success
}
return false , nil
2016-07-29 08:01:41 +00:00
}
By ( fmt . Sprintf ( "Service %q in namespace %q in cluster. Found: %v, waiting for Found: %v, trying again in %s (err=%v)" , service . Name , namespace , clusterService != nil && err == nil , present , framework . Poll , err ) )
return false , nil
} )
framework . ExpectNoError ( err , "Failed to verify service %q in namespace %q in cluster: Present=%v" , service . Name , namespace , present )
}
2017-02-13 22:58:49 +00:00
// waitForServiceShardsOrFail waits for the service to appear in all clusters
2016-07-29 08:01:41 +00:00
func waitForServiceShardsOrFail ( namespace string , service * v1 . Service , clusters map [ string ] * cluster ) {
framework . Logf ( "Waiting for service %q in %d clusters" , service . Name , len ( clusters ) )
for _ , c := range clusters {
waitForServiceOrFail ( c . Clientset , namespace , service , true , FederatedServiceTimeout )
}
}
2016-09-02 18:57:44 +00:00
func createService ( clientset * fedclientset . Clientset , namespace , name string ) ( * v1 . Service , error ) {
2016-07-29 08:01:41 +00:00
if clientset == nil || len ( namespace ) == 0 {
return nil , fmt . Errorf ( "Internal error: invalid parameters passed to createService: clientset: %v, namespace: %v" , clientset , namespace )
}
By ( fmt . Sprintf ( "Creating federated service %q in namespace %q" , name , namespace ) )
service := & v1 . Service {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-08-22 17:48:43 +00:00
Name : name ,
Namespace : namespace ,
2016-07-29 08:01:41 +00:00
} ,
Spec : v1 . ServiceSpec {
Selector : FederatedServiceLabels ,
Type : "LoadBalancer" ,
Ports : [ ] v1 . ServicePort {
{
Name : "http" ,
2016-10-21 05:30:46 +00:00
Protocol : v1 . ProtocolTCP ,
2016-07-29 08:01:41 +00:00
Port : 80 ,
TargetPort : intstr . FromInt ( 8080 ) ,
2017-02-22 01:39:26 +00:00
NodePort : FederatedSvcNodePort ,
2016-07-29 08:01:41 +00:00
} ,
} ,
2016-10-21 05:30:46 +00:00
SessionAffinity : v1 . ServiceAffinityNone ,
2016-07-29 08:01:41 +00:00
} ,
}
By ( fmt . Sprintf ( "Trying to create service %q in namespace %q" , service . Name , namespace ) )
return clientset . Services ( namespace ) . Create ( service )
}
2016-09-02 18:57:44 +00:00
func createServiceOrFail ( clientset * fedclientset . Clientset , namespace , name string ) * v1 . Service {
2016-07-29 08:01:41 +00:00
service , err := createService ( clientset , namespace , name )
framework . ExpectNoError ( err , "Creating service %q in namespace %q" , service . Name , namespace )
By ( fmt . Sprintf ( "Successfully created federated service %q in namespace %q" , name , namespace ) )
return service
}
2016-12-17 00:06:06 +00:00
func deleteServiceOrFail ( clientset * fedclientset . Clientset , namespace string , serviceName string , orphanDependents * bool ) {
2016-07-29 08:01:41 +00:00
if clientset == nil || len ( namespace ) == 0 || len ( serviceName ) == 0 {
Fail ( fmt . Sprintf ( "Internal error: invalid parameters passed to deleteServiceOrFail: clientset: %v, namespace: %v, service: %v" , clientset , namespace , serviceName ) )
}
2017-02-22 01:39:26 +00:00
framework . Logf ( "Deleting service %q in namespace %v" , serviceName , namespace )
2017-01-24 15:38:21 +00:00
err := clientset . Services ( namespace ) . Delete ( serviceName , & metav1 . DeleteOptions { OrphanDependents : orphanDependents } )
2016-07-29 08:01:41 +00:00
framework . ExpectNoError ( err , "Error deleting service %q from namespace %q" , serviceName , namespace )
2016-12-17 00:06:06 +00:00
// Wait for the service to be deleted.
2017-02-22 01:39:26 +00:00
err = wait . Poll ( 5 * time . Second , 10 * wait . ForeverTestTimeout , func ( ) ( bool , error ) {
2016-12-17 00:06:06 +00:00
_ , err := clientset . Core ( ) . Services ( namespace ) . Get ( serviceName , metav1 . GetOptions { } )
if err != nil && errors . IsNotFound ( err ) {
return true , nil
}
return false , err
} )
if err != nil {
framework . Failf ( "Error in deleting service %s: %v" , serviceName , err )
}
2016-07-29 08:01:41 +00:00
}
2016-09-09 21:07:42 +00:00
func cleanupServiceShardsAndProviderResources ( namespace string , service * v1 . Service , clusters map [ string ] * cluster ) {
framework . Logf ( "Deleting service %q in %d clusters" , service . Name , len ( clusters ) )
for name , c := range clusters {
2016-09-22 20:01:45 +00:00
var cSvc * v1 . Service
err := wait . PollImmediate ( framework . Poll , FederatedServiceTimeout , func ( ) ( bool , error ) {
var err error
2016-12-07 14:40:26 +00:00
cSvc , err = c . Clientset . Services ( namespace ) . Get ( service . Name , metav1 . GetOptions { } )
2016-09-22 20:01:45 +00:00
if err != nil && ! errors . IsNotFound ( err ) {
// Get failed with an error, try again.
framework . Logf ( "Failed to find service %q in namespace %q, in cluster %q: %v. Trying again in %s" , service . Name , namespace , name , err , framework . Poll )
return false , nil
2016-09-30 18:54:39 +00:00
} else if errors . IsNotFound ( err ) {
cSvc = nil
By ( fmt . Sprintf ( "Service %q in namespace %q in cluster %q not found" , service . Name , namespace , name ) )
2016-09-30 22:13:02 +00:00
return true , err
2016-09-22 20:01:45 +00:00
}
By ( fmt . Sprintf ( "Service %q in namespace %q in cluster %q found" , service . Name , namespace , name ) )
2016-09-30 22:13:02 +00:00
return true , err
2016-09-22 20:01:45 +00:00
} )
if err != nil || cSvc == nil {
By ( fmt . Sprintf ( "Failed to find service %q in namespace %q, in cluster %q in %s" , service . Name , namespace , name , FederatedServiceTimeout ) )
2016-09-30 18:54:39 +00:00
continue
2016-09-22 20:01:45 +00:00
}
err = cleanupServiceShard ( c . Clientset , name , namespace , cSvc , FederatedServiceTimeout )
2016-09-09 21:07:42 +00:00
if err != nil {
framework . Logf ( "Failed to delete service %q in namespace %q, in cluster %q: %v" , service . Name , namespace , name , err )
}
2016-09-22 20:01:45 +00:00
err = cleanupServiceShardLoadBalancer ( name , cSvc , FederatedServiceTimeout )
2016-09-09 21:07:42 +00:00
if err != nil {
framework . Logf ( "Failed to delete cloud provider resources for service %q in namespace %q, in cluster %q" , service . Name , namespace , name )
}
}
}
2016-09-02 18:57:44 +00:00
func cleanupServiceShard ( clientset * kubeclientset . Clientset , clusterName , namespace string , service * v1 . Service , timeout time . Duration ) error {
2016-09-09 21:07:42 +00:00
err := wait . PollImmediate ( framework . Poll , timeout , func ( ) ( bool , error ) {
2017-01-24 15:38:21 +00:00
err := clientset . Services ( namespace ) . Delete ( service . Name , & metav1 . DeleteOptions { } )
2016-09-09 21:07:42 +00:00
if err != nil && ! errors . IsNotFound ( err ) {
// Deletion failed with an error, try again.
framework . Logf ( "Failed to delete service %q in namespace %q, in cluster %q" , service . Name , namespace , clusterName )
return false , nil
}
By ( fmt . Sprintf ( "Service %q in namespace %q in cluster %q deleted" , service . Name , namespace , clusterName ) )
return true , nil
} )
return err
}
func cleanupServiceShardLoadBalancer ( clusterName string , service * v1 . Service , timeout time . Duration ) error {
provider := framework . TestContext . CloudConfig . Provider
if provider == nil {
return fmt . Errorf ( "cloud provider undefined" )
}
2016-11-18 20:55:17 +00:00
internalSvc := & v1 . Service { }
2016-09-09 21:07:42 +00:00
err := api . Scheme . Convert ( service , internalSvc , nil )
if err != nil {
return fmt . Errorf ( "failed to convert versioned service object to internal type: %v" , err )
}
err = wait . PollImmediate ( framework . Poll , timeout , func ( ) ( bool , error ) {
lbi , supported := provider . LoadBalancer ( )
if ! supported {
return false , fmt . Errorf ( "%q doesn't support load balancers" , provider . ProviderName ( ) )
}
err := lbi . EnsureLoadBalancerDeleted ( clusterName , internalSvc )
if err != nil {
// Deletion failed with an error, try again.
framework . Logf ( "Failed to delete cloud provider resources for service %q in namespace %q, in cluster %q" , service . Name , service . Namespace , clusterName )
return false , nil
}
By ( fmt . Sprintf ( "Cloud provider resources for Service %q in namespace %q in cluster %q deleted" , service . Name , service . Namespace , clusterName ) )
return true , nil
} )
return err
}
2017-01-11 13:23:31 +00:00
func podExitCodeDetector ( f * fedframework . Framework , name , namespace string , code int32 ) func ( ) error {
2016-07-29 08:01:41 +00:00
// If we ever get any container logs, stash them here.
logs := ""
logerr := func ( err error ) error {
if err == nil {
return nil
}
if logs == "" {
return err
}
return fmt . Errorf ( "%s (%v)" , logs , err )
}
return func ( ) error {
2016-12-07 14:40:26 +00:00
pod , err := f . ClientSet . Core ( ) . Pods ( namespace ) . Get ( name , metav1 . GetOptions { } )
2016-07-29 08:01:41 +00:00
if err != nil {
return logerr ( err )
}
if len ( pod . Status . ContainerStatuses ) < 1 {
return logerr ( fmt . Errorf ( "no container statuses" ) )
}
// Best effort attempt to grab pod logs for debugging
2016-10-18 13:00:38 +00:00
logs , err = framework . GetPodLogs ( f . ClientSet , namespace , name , pod . Spec . Containers [ 0 ] . Name )
2016-07-29 08:01:41 +00:00
if err != nil {
framework . Logf ( "Cannot fetch pod logs: %v" , err )
}
status := pod . Status . ContainerStatuses [ 0 ]
if status . State . Terminated == nil {
return logerr ( fmt . Errorf ( "container is not in terminated state" ) )
}
if status . State . Terminated . ExitCode == code {
return nil
}
return logerr ( fmt . Errorf ( "exited %d" , status . State . Terminated . ExitCode ) )
}
}
2017-01-11 13:23:31 +00:00
func discoverService ( f * fedframework . Framework , name string , exists bool , podName string ) {
2016-07-29 08:01:41 +00:00
command := [ ] string { "sh" , "-c" , fmt . Sprintf ( "until nslookup '%s'; do sleep 10; done" , name ) }
By ( fmt . Sprintf ( "Looking up %q" , name ) )
2016-11-18 20:55:17 +00:00
pod := & v1 . Pod {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-07-29 08:01:41 +00:00
Name : podName ,
} ,
2016-11-18 20:55:17 +00:00
Spec : v1 . PodSpec {
Containers : [ ] v1 . Container {
2016-07-29 08:01:41 +00:00
{
Name : "federated-service-discovery-container" ,
Image : "gcr.io/google_containers/busybox:1.24" ,
Command : command ,
} ,
} ,
2016-11-18 20:55:17 +00:00
RestartPolicy : v1 . RestartPolicyOnFailure ,
2016-07-29 08:01:41 +00:00
} ,
}
2016-08-22 17:48:43 +00:00
nsName := f . FederationNamespace . Name
By ( fmt . Sprintf ( "Creating pod %q in namespace %q" , pod . Name , nsName ) )
2016-10-18 13:00:38 +00:00
_ , err := f . ClientSet . Core ( ) . Pods ( nsName ) . Create ( pod )
2016-07-29 08:01:41 +00:00
framework . ExpectNoError ( err , "Trying to create pod to run %q" , command )
2016-08-22 17:48:43 +00:00
By ( fmt . Sprintf ( "Successfully created pod %q in namespace %q" , pod . Name , nsName ) )
2016-07-29 08:01:41 +00:00
defer func ( ) {
2016-08-22 17:48:43 +00:00
By ( fmt . Sprintf ( "Deleting pod %q from namespace %q" , podName , nsName ) )
2017-01-24 15:38:21 +00:00
err := f . ClientSet . Core ( ) . Pods ( nsName ) . Delete ( podName , metav1 . NewDeleteOptions ( 0 ) )
2016-08-22 17:48:43 +00:00
framework . ExpectNoError ( err , "Deleting pod %q from namespace %q" , podName , nsName )
By ( fmt . Sprintf ( "Deleted pod %q from namespace %q" , podName , nsName ) )
2016-07-29 08:01:41 +00:00
} ( )
if exists {
// TODO(mml): Eventually check the IP address is correct, too.
2016-08-22 17:48:43 +00:00
Eventually ( podExitCodeDetector ( f , podName , nsName , 0 ) , 3 * DNSTTL , time . Second * 2 ) .
2016-07-29 08:01:41 +00:00
Should ( BeNil ( ) , "%q should exit 0, but it never did" , command )
} else {
2016-08-22 17:48:43 +00:00
Eventually ( podExitCodeDetector ( f , podName , nsName , 0 ) , 3 * DNSTTL , time . Second * 2 ) .
2016-07-29 08:01:41 +00:00
ShouldNot ( BeNil ( ) , "%q should eventually not exit 0, but it always did" , command )
}
}
2017-02-13 22:58:49 +00:00
// createBackendPodsOrFail creates one pod in each cluster, and returns the created pods (in the same order as clusterClientSets).
// If creation of any pod fails, the test fails (possibly with a partially created set of pods). No retries are attempted.
2016-07-29 08:01:41 +00:00
func createBackendPodsOrFail ( clusters map [ string ] * cluster , namespace string , name string ) {
pod := & v1 . Pod {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-07-29 08:01:41 +00:00
Name : name ,
// Namespace: namespace,
Labels : FederatedServiceLabels ,
} ,
Spec : v1 . PodSpec {
Containers : [ ] v1 . Container {
{
Name : name ,
Image : "gcr.io/google_containers/echoserver:1.4" ,
} ,
} ,
RestartPolicy : v1 . RestartPolicyAlways ,
} ,
}
for name , c := range clusters {
By ( fmt . Sprintf ( "Creating pod %q in namespace %q in cluster %q" , pod . Name , namespace , name ) )
createdPod , err := c . Clientset . Core ( ) . Pods ( namespace ) . Create ( pod )
framework . ExpectNoError ( err , "Creating pod %q in namespace %q in cluster %q" , name , namespace , name )
By ( fmt . Sprintf ( "Successfully created pod %q in namespace %q in cluster %q: %v" , pod . Name , namespace , name , * createdPod ) )
c . backendPod = createdPod
}
}
2017-02-13 22:58:49 +00:00
// deleteOneBackendPodOrFail deletes exactly one backend pod which must not be nil
// The test fails if there are any errors.
2016-07-29 08:01:41 +00:00
func deleteOneBackendPodOrFail ( c * cluster ) {
pod := c . backendPod
Expect ( pod ) . ToNot ( BeNil ( ) )
2017-01-24 15:38:21 +00:00
err := c . Clientset . Core ( ) . Pods ( pod . Namespace ) . Delete ( pod . Name , metav1 . NewDeleteOptions ( 0 ) )
2016-07-29 08:01:41 +00:00
if errors . IsNotFound ( err ) {
By ( fmt . Sprintf ( "Pod %q in namespace %q in cluster %q does not exist. No need to delete it." , pod . Name , pod . Namespace , c . name ) )
} else {
framework . ExpectNoError ( err , "Deleting pod %q in namespace %q from cluster %q" , pod . Name , pod . Namespace , c . name )
}
By ( fmt . Sprintf ( "Backend pod %q in namespace %q in cluster %q deleted or does not exist" , pod . Name , pod . Namespace , c . name ) )
}
2017-02-13 22:58:49 +00:00
// deleteBackendPodsOrFail deletes one pod from each cluster that has one.
// If deletion of any pod fails, the test fails (possibly with a partially deleted set of pods). No retries are attempted.
2016-07-29 08:01:41 +00:00
func deleteBackendPodsOrFail ( clusters map [ string ] * cluster , namespace string ) {
for name , c := range clusters {
if c . backendPod != nil {
deleteOneBackendPodOrFail ( c )
c . backendPod = nil
} else {
By ( fmt . Sprintf ( "No backend pod to delete for cluster %q" , name ) )
}
}
}
2017-02-11 01:12:07 +00:00
// waitForReplicatSetToBeDeletedOrFail waits for the named ReplicaSet in namespace to be deleted.
// If the deletion fails, the enclosing test fails.
func waitForReplicaSetToBeDeletedOrFail ( clientset * fedclientset . Clientset , namespace string , replicaSet string ) {
err := wait . Poll ( 5 * time . Second , wait . ForeverTestTimeout , func ( ) ( bool , error ) {
_ , err := clientset . Extensions ( ) . ReplicaSets ( namespace ) . Get ( replicaSet , metav1 . GetOptions { } )
if err != nil && errors . IsNotFound ( err ) {
return true , nil
}
return false , err
} )
if err != nil {
framework . Failf ( "Error in deleting replica set %s: %v" , replicaSet , err )
}
}