2016-07-29 08:01:41 +00:00
/ *
Copyright 2016 The Kubernetes Authors .
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-07-29 08:01:41 +00:00
import (
2017-02-22 01:39:26 +00:00
"crypto/tls"
2016-07-29 08:01:41 +00:00
"fmt"
2016-08-24 07:51:03 +00:00
"net/http"
2016-07-29 08:01:41 +00:00
"os"
"reflect"
"strconv"
2016-11-10 01:50:25 +00:00
"strings"
2016-07-29 08:01:41 +00:00
"time"
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"
2017-01-27 20:42:17 +00:00
"k8s.io/apimachinery/pkg/util/intstr"
2017-02-22 01:39:26 +00:00
utilnet "k8s.io/apimachinery/pkg/util/net"
2017-01-11 14:09:48 +00:00
"k8s.io/apimachinery/pkg/util/wait"
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/v1"
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
2016-12-14 01:18:17 +00:00
kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
2017-02-22 01:39:26 +00:00
2016-07-29 08:01:41 +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"
)
const (
2016-08-29 02:49:09 +00:00
MaxRetriesOnFederatedApiserver = 3
2017-03-24 23:23:27 +00:00
FederatedIngressTimeout = 15 * time . Minute
2017-03-13 23:47:33 +00:00
FederatedIngressDeleteTimeout = 2 * time . Minute
2016-07-29 08:01:41 +00:00
FederatedIngressName = "federated-ingress"
FederatedIngressServiceName = "federated-ingress-service"
2017-02-22 01:39:26 +00:00
FederatedIngressTLSSecretName = "federated-ingress-tls-secret"
2016-07-29 08:01:41 +00:00
FederatedIngressServicePodName = "federated-ingress-service-test-pod"
2017-02-22 01:39:26 +00:00
FederatedIngressHost = "test-f8n.k8s.io."
// TLS Certificate and Key for the ingress resource
// Generated using:
// $ openssl req -nodes -x509 -newkey rsa:2048 -keyout fedingtestkey.pem -out fedingtestcrt.pem -days 2485
// 2485 days is an arbitrary large number chosen below int32 seconds.
FederatedIngressTLSCrt = ` -- -- - BEGIN CERTIFICATE -- -- -
MIIDaTCCAlGgAwIBAgIJANwsCbwxm9pyMA0GCSqGSIb3DQEBCwUAMEoxCzAJBgNV
BAYTAlVTMRMwEQYDVQQIDApTb21lLVN0YXRlMQswCQYDVQQKDAJOQTEZMBcGA1UE
AwwQdGVzdC1mOG4uazhzLmlvLjAgFw0xNjEyMTYwNjA1NDRaGA8yMDg1MDEwMzA2
MDU0NFowSjELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUtU3RhdGUxCzAJBgNV
BAoMAk5BMRkwFwYDVQQDDBB0ZXN0LWY4bi5rOHMuaW8uMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEAmsHYnLhqSeO1Q6SEjaiPiLUQV8tyGfttwNQiOT5u
ULz6ZWYA40m / 1 hhla9KH9sJZ515Iq + jTtiVH0rUjryT96SjxitLCAZlxVwQ63B50
aZF2T2OPSzvrmN + J6VGcRIq0N8fUeyp2WTIEdWlpQ7DTmDNArQqFSIvJndkLow3d
hec7O + PErnvZQQC9zqa23rGndDzlgDJ4HJGAQNm3uYVh5WHv + wziP67T / 82 bEGgO
A6EdDPWzpYxzAA1wsqz9lX5jitlbKdI56698fPR2KRelySf7OXVvZCS4 / ED1lF4k
b7fQgtBhAWe1BkuAMUl7vdRjMps7nkxmBSuxBkVQ7sb5AwIDAQABo1AwTjAdBgNV
HQ4EFgQUjf53O / W / iE2mxuJkNjZGUfjJ9RUwHwYDVR0jBBgwFoAUjf53O / W / iE2m
xuJkNjZGUfjJ9RUwDAYDVR0TBAUwAwEB / zANBgkqhkiG9w0BAQsFAAOCAQEABE7B
bAiORDBA3qE5lh6JCs / lEfz93E / gOhD9oDnm9SRND4kjy7qeGxk4Wzsd / Vr + R2mi
EZ40d4MA / mCCPnYsNQoEXMFc8IvwAbzkhh2gqTNgG0 / Ks0A1mIPQNpvUcSetS4IV
732 DvB3nSnFtlzf6afw + V1Vf5ydRNuM / c9GEOOHSz + rs + 9 M364d + wNaFD64M72ol
iDMAdtcrhOqkQi0lUING904jlJcyYM5oVNCCtme4F8nkIX9bxP / 9 Ea6VhDGPeJiX
tVwZuudkoEbrFlEYbyLrbVeVa9oTf4Jn66iz49 / + th + bUtEoTt9gk9Cul5TFgfzx
EscdahceC7afheq6zg ==
-- -- - END CERTIFICATE -- -- - `
FederatedIngressTLSKey = ` -- -- - BEGIN PRIVATE KEY -- -- -
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCawdicuGpJ47VD
pISNqI + ItRBXy3IZ + 23 A1CI5Pm5QvPplZgDjSb / WGGVr0of2wlnnXkir6NO2JUfS
tSOvJP3pKPGK0sIBmXFXBDrcHnRpkXZPY49LO + uY34npUZxEirQ3x9R7KnZZMgR1
aWlDsNOYM0CtCoVIi8md2QujDd2F5zs748Sue9lBAL3Oprbesad0POWAMngckYBA
2 be5hWHlYe / 7 DOI / rtP / zZsQaA4DoR0M9bOljHMADXCyrP2VfmOK2Vsp0jnrr3x8
9 HYpF6XJJ / s5dW9kJLj8QPWUXiRvt9CC0GEBZ7UGS4AxSXu91GMymzueTGYFK7EG
RVDuxvkDAgMBAAECggEAYrXGPqB6W0r88XpceibL9rzXAcjorJ3s8ZPdiHnDz4fa
hxa69j6yOBMzjcSpqMFqquM + ozhM4d + BomqbqjmEI1ZUSuIHkRGYc5JlIMXkJvn7
ZsPwQGKl8cqTotjFPgrizLmPVEhPWLFImsNzuxNsw6XdWQJe5VkUbrRkccqEQ8Wt
xwq / SlRercIMnRVLOOESq8EyjOY4yDgOdIifq9K9xiI8W6nMiPs0X5AcIJoTMbCe
cX0zUqW317awDWWP8u2GswwDDm4qPeWnXOrDkDx8Eo0dWJbmxw9su0XrM6KMvEMe
2 a / Fy / enr5Cc6 / jgsh3gO5sa8dJ1Cu + wexcoEbez8QKBgQDMXlXJu / C7djke94s3
vGxati7AGO95bBQHW + cPuN4l0rfPZ8YuUAWD4csW4BOlUPAOukreD / SKdanigR3N
FqVPeI8rXd5kzy8 / lPIOGuSkkVEpKsAJ7prFbSUVKjVPYQk2dsOEeR0r7pr2FxC9
SBhVS / LgmPYh ++ iny9D0aU23hQKBgQDB2t55OE + 00 vgoauUc10LEY + J6tiwXuNm7
43 JtrH5ET4N + TJ2BOUl5f88TY / 3 QuTu6vYwlxjyn + LFuWQNhShX6lFMjt5zqPTdw
ZPDA + 9 B6a45cV3YjXjRsYidpWj0D2lJgy0DbucC4f3eIhNGyFUbAQB9npKDzOeUh
7 Z + p / Grg5wKBgGUnVCLzySWgUImJUPkXZDJJ9j3SmcVpv0gdLvLTN / FUqPIZlTgb
F3 + 9 ZL4 / zrmGpCtF / gSHtSxLLPkVm2CFkvEQ5Rw76 / XNrr8zw9NDcGQcISXVKRRB
a43IhhBBwf02NE8m3YNWRyAVi9G + fOSTKKgfXWnZjAoqG2 / iK9ytum / ZAoGAYlP8
KIxxkYy5Jvchg4GEck0f4ZJpxxaSCoWR0yN9YHTcg8Gk2pkONbyocnNzmN17 + HqQ
jdCBj8nLZedsmXqUr2dwzFskEoQ + jJoGrDyOQKoxqZELcWElQhx / VSbacAvbYRF3
snwDzxGItgx4uNWl73oW8 + FDalvhZ1Y6eGR6ad0CgYEAtlNa92Fbvd3r9O2mdyWe
D2SXNMi45 + wsNafX2sdkyb + qNN6qZXC9ylUl9h0zdky88JNgtAOgxIaRIdEZajnD
/ Zq17sTNtgpm53x16gOAgD8M + / wmBZxA + / IKfFCubuV77MbQoPfcjT5wBMRnFQnY
Ks7c + dzaRlgDKZ6v / L / 8i ZU =
-- -- - END PRIVATE KEY -- -- - `
2016-07-29 08:01:41 +00:00
)
2017-01-11 13:23:31 +00:00
const (
// timeout on a single http request.
reqTimeout = 10 * time . Second
)
2016-08-29 02:49:09 +00:00
var _ = framework . KubeDescribe ( "Federated ingresses [Feature:Federation]" , func ( ) {
2017-01-11 13:23:31 +00:00
f := fedframework . NewDefaultFederatedFramework ( "federated-ingress" )
2016-07-29 08:01:41 +00:00
// Create/delete ingress api objects
// Validate federation apiserver, does not rely on underlying clusters or federation ingress controller.
2017-01-31 23:09:07 +00:00
Describe ( "Federated Ingresses [NoCluster]" , func ( ) {
2016-07-29 08:01:41 +00:00
AfterEach ( func ( ) {
nsName := f . FederationNamespace . Name
2016-11-10 01:50:25 +00:00
// Delete all ingresses.
2017-01-11 13:23:31 +00:00
deleteAllIngressesOrFail ( f . FederationClientset , nsName )
2016-07-29 08:01:41 +00:00
} )
It ( "should be created and deleted successfully" , func ( ) {
2017-01-11 13:23:31 +00:00
fedframework . SkipUnlessFederated ( f . ClientSet )
2016-10-12 22:12:54 +00:00
framework . SkipUnlessProviderIs ( "gce" , "gke" ) // TODO: Federated ingress is not yet supported on non-GCP platforms.
2016-07-29 08:01:41 +00:00
nsName := f . FederationNamespace . Name
2017-02-22 01:39:26 +00:00
ingress := createIngressOrFail ( f . FederationClientset , nsName , FederatedIngressServiceName , FederatedIngressTLSSecretName )
2016-07-29 08:01:41 +00:00
By ( fmt . Sprintf ( "Creation of ingress %q in namespace %q succeeded. Deleting ingress." , ingress . Name , nsName ) )
// Cleanup
2017-01-24 15:38:21 +00:00
err := f . FederationClientset . Extensions ( ) . Ingresses ( nsName ) . Delete ( ingress . Name , & metav1 . DeleteOptions { } )
2016-07-29 08:01:41 +00:00
framework . ExpectNoError ( err , "Error deleting ingress %q in namespace %q" , ingress . Name , ingress . Namespace )
By ( fmt . Sprintf ( "Deletion of ingress %q in namespace %q succeeded." , ingress . Name , nsName ) )
} )
} )
// e2e cases for federation ingress controller
2016-08-24 07:51:03 +00:00
var _ = Describe ( "Federated Ingresses" , func ( ) {
2016-07-29 08:01:41 +00:00
var (
2017-03-22 05:28:59 +00:00
clusters fedframework . ClusterMap // All clusters, keyed by cluster name
2016-07-29 08:01:41 +00:00
primaryClusterName , federationName , ns string
2016-08-24 07:51:03 +00:00
jig * federationTestJig
2017-02-22 01:39:26 +00:00
service * v1 . Service
secret * v1 . Secret
2016-07-29 08:01:41 +00:00
)
// register clusters in federation apiserver
BeforeEach ( func ( ) {
2017-01-11 13:23:31 +00:00
fedframework . SkipUnlessFederated ( f . ClientSet )
2016-10-12 22:12:54 +00:00
framework . SkipUnlessProviderIs ( "gce" , "gke" ) // TODO: Federated ingress is not yet supported on non-GCP platforms.
2016-07-29 08:01:41 +00:00
if federationName = os . Getenv ( "FEDERATION_NAME" ) ; federationName == "" {
federationName = DefaultFederationName
}
2017-01-11 13:23:31 +00:00
jig = newFederationTestJig ( f . FederationClientset )
2017-03-22 05:28:59 +00:00
clusters , primaryClusterName = f . GetRegisteredClusters ( )
2016-09-06 08:05:09 +00:00
ns = f . FederationNamespace . Name
2017-02-22 01:39:26 +00:00
// create backend service
service = createServiceOrFail ( f . FederationClientset , ns , FederatedIngressServiceName )
// create the TLS secret
secret = createTLSSecretOrFail ( f . FederationClientset , ns , FederatedIngressTLSSecretName )
// wait for services objects sync
waitForServiceShardsOrFail ( ns , service , clusters )
// wait for TLS secret sync
waitForSecretShardsOrFail ( ns , secret , clusters )
2016-07-29 08:01:41 +00:00
} )
AfterEach ( func ( ) {
2016-11-10 01:50:25 +00:00
// Delete all ingresses.
2017-03-20 21:35:37 +00:00
deleteAllIngressesOrFail ( f . FederationClientset , ns )
2017-02-22 01:39:26 +00:00
if secret != nil {
2017-03-13 23:47:33 +00:00
By ( "Deleting secret" )
2017-02-22 01:39:26 +00:00
orphanDependents := false
deleteSecretOrFail ( f . FederationClientset , ns , secret . Name , & orphanDependents )
secret = nil
} else {
By ( "No secret to delete. Secret is nil" )
}
if service != nil {
2017-03-13 23:47:33 +00:00
By ( "Deleting service" )
2017-02-22 01:39:26 +00:00
deleteServiceOrFail ( f . FederationClientset , ns , service . Name , nil )
2017-03-13 23:47:33 +00:00
By ( "Cleanup service shards and provider resources" )
2017-02-22 01:39:26 +00:00
cleanupServiceShardsAndProviderResources ( ns , service , clusters )
service = nil
} else {
By ( "No service to delete. Service is nil" )
}
2016-07-29 08:01:41 +00:00
} )
It ( "should create and update matching ingresses in underlying clusters" , func ( ) {
2017-02-22 01:39:26 +00:00
ingress := createIngressOrFail ( f . FederationClientset , ns , FederatedIngressServiceName , FederatedIngressTLSSecretName )
2016-07-29 08:01:41 +00:00
// wait for ingress shards being created
2016-09-06 08:05:09 +00:00
waitForIngressShardsOrFail ( ns , ingress , clusters )
2017-01-11 13:23:31 +00:00
ingress = updateIngressOrFail ( f . FederationClientset , ns )
2016-09-06 08:05:09 +00:00
waitForIngressShardsUpdatedOrFail ( ns , ingress , clusters )
2016-07-29 08:01:41 +00:00
} )
2016-11-10 01:50:25 +00:00
It ( "should be deleted from underlying clusters when OrphanDependents is false" , func ( ) {
2017-01-11 13:23:31 +00:00
fedframework . SkipUnlessFederated ( f . ClientSet )
2016-11-10 01:50:25 +00:00
orphanDependents := false
2017-03-20 21:35:37 +00:00
verifyCascadingDeletionForIngress ( f . FederationClientset , clusters , & orphanDependents , ns )
2016-11-10 01:50:25 +00:00
By ( fmt . Sprintf ( "Verified that ingresses were deleted from underlying clusters" ) )
} )
It ( "should not be deleted from underlying clusters when OrphanDependents is true" , func ( ) {
2017-01-11 13:23:31 +00:00
fedframework . SkipUnlessFederated ( f . ClientSet )
2016-11-10 01:50:25 +00:00
orphanDependents := true
2017-03-20 21:35:37 +00:00
verifyCascadingDeletionForIngress ( f . FederationClientset , clusters , & orphanDependents , ns )
2016-11-10 01:50:25 +00:00
By ( fmt . Sprintf ( "Verified that ingresses were not deleted from underlying clusters" ) )
} )
It ( "should not be deleted from underlying clusters when OrphanDependents is nil" , func ( ) {
2017-01-11 13:23:31 +00:00
fedframework . SkipUnlessFederated ( f . ClientSet )
2017-03-20 21:35:37 +00:00
verifyCascadingDeletionForIngress ( f . FederationClientset , clusters , nil , ns )
2016-11-10 01:50:25 +00:00
By ( fmt . Sprintf ( "Verified that ingresses were not deleted from underlying clusters" ) )
} )
2016-07-29 08:01:41 +00:00
var _ = Describe ( "Ingress connectivity and DNS" , func ( ) {
BeforeEach ( func ( ) {
2017-01-11 13:23:31 +00:00
fedframework . SkipUnlessFederated ( f . ClientSet )
2016-07-29 08:01:41 +00:00
// create backend pod
2016-09-06 08:05:09 +00:00
createBackendPodsOrFail ( clusters , ns , FederatedIngressServicePodName )
2016-07-29 08:01:41 +00:00
// create ingress object
2017-02-22 01:39:26 +00:00
jig . ing = createIngressOrFail ( f . FederationClientset , ns , service . Name , FederatedIngressTLSSecretName )
2016-07-29 08:01:41 +00:00
// wait for ingress objects sync
2016-09-06 08:05:09 +00:00
waitForIngressShardsOrFail ( ns , jig . ing , clusters )
2017-03-13 23:47:33 +00:00
By ( fmt . Sprintf ( "Ingress created as %v" , jig . ing . Name ) )
2016-07-29 08:01:41 +00:00
} )
AfterEach ( func ( ) {
2016-09-06 08:05:09 +00:00
deleteBackendPodsOrFail ( clusters , ns )
2016-07-29 08:01:41 +00:00
if jig . ing != nil {
2017-03-13 23:47:33 +00:00
By ( fmt . Sprintf ( "Deleting ingress %v on all clusters" , jig . ing . Name ) )
2017-03-20 21:35:37 +00:00
orphanDependents := false
deleteIngressOrFail ( f . FederationClientset , ns , jig . ing . Name , & orphanDependents )
2016-07-29 08:01:41 +00:00
jig . ing = nil
} else {
By ( "No ingress to delete. Ingress is nil" )
}
} )
2016-09-13 00:34:55 +00:00
PIt ( "should be able to discover a federated ingress service via DNS" , func ( ) {
2016-07-29 08:01:41 +00:00
// we are about the ingress name
svcDNSNames := [ ] string {
2016-09-06 08:05:09 +00:00
fmt . Sprintf ( "%s.%s" , FederatedIngressServiceName , ns ) ,
fmt . Sprintf ( "%s.%s.svc.cluster.local." , FederatedIngressServiceName , ns ) ,
2016-07-29 08:01:41 +00:00
// TODO these two entries are not set yet
2016-09-06 08:05:09 +00:00
//fmt.Sprintf("%s.%s.%s", FederatedIngressServiceName, ns, federationName),
//fmt.Sprintf("%s.%s.%s.svc.cluster.local.", FederatedIngressServiceName, ns, federationName),
2016-07-29 08:01:41 +00:00
}
// check dns records in underlying cluster
for i , DNSName := range svcDNSNames {
discoverService ( f , DNSName , true , "federated-ingress-e2e-discovery-pod-" + strconv . Itoa ( i ) )
}
// TODO check dns record in global dns server
2016-09-13 00:34:55 +00:00
} )
2016-09-21 07:09:13 +00:00
2017-03-24 23:23:27 +00:00
PIt ( "should be able to connect to a federated ingress via its load balancer" , func ( ) {
2017-03-13 23:47:33 +00:00
By ( fmt . Sprintf ( "Waiting for Federated Ingress on %v" , jig . ing . Name ) )
2016-07-29 08:01:41 +00:00
// check the traffic on federation ingress
jig . waitForFederatedIngress ( )
} )
} )
} )
} )
2016-11-10 01:50:25 +00:00
// Deletes all Ingresses in the given namespace name.
func deleteAllIngressesOrFail ( clientset * fedclientset . Clientset , nsName string ) {
orphanDependents := false
2017-01-24 15:38:21 +00:00
err := clientset . Extensions ( ) . Ingresses ( nsName ) . DeleteCollection ( & metav1 . DeleteOptions { OrphanDependents : & orphanDependents } , metav1 . ListOptions { } )
2016-11-10 01:50:25 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) , fmt . Sprintf ( "Error in deleting ingresses in namespace: %s" , nsName ) )
}
2017-02-13 22:58:49 +00:00
// equivalent returns true if the two ingress spec are equivalent.
2016-07-29 08:01:41 +00:00
func equivalentIngress ( federatedIngress , clusterIngress v1beta1 . Ingress ) bool {
return reflect . DeepEqual ( clusterIngress . Spec , federatedIngress . Spec )
}
2016-11-10 01:50:25 +00:00
// verifyCascadingDeletionForIngress verifies that ingresses are deleted from
// underlying clusters when orphan dependents is false and they are not deleted
// when orphan dependents is true.
2017-03-22 05:28:59 +00:00
func verifyCascadingDeletionForIngress ( clientset * fedclientset . Clientset , clusters fedframework . ClusterMap , orphanDependents * bool , nsName string ) {
2017-02-22 01:39:26 +00:00
ingress := createIngressOrFail ( clientset , nsName , FederatedIngressServiceName , FederatedIngressTLSSecretName )
2016-11-10 01:50:25 +00:00
ingressName := ingress . Name
// Check subclusters if the ingress was created there.
By ( fmt . Sprintf ( "Waiting for ingress %s to be created in all underlying clusters" , ingressName ) )
waitForIngressShardsOrFail ( nsName , ingress , clusters )
By ( fmt . Sprintf ( "Deleting ingress %s" , ingressName ) )
deleteIngressOrFail ( clientset , nsName , ingressName , orphanDependents )
By ( fmt . Sprintf ( "Verifying ingresses %s in underlying clusters" , ingressName ) )
errMessages := [ ] string { }
// ingress should be present in underlying clusters unless orphanDependents is false.
shouldExist := orphanDependents == nil || * orphanDependents == true
for clusterName , clusterClientset := range clusters {
2016-12-07 14:40:26 +00:00
_ , err := clusterClientset . Extensions ( ) . Ingresses ( nsName ) . Get ( ingressName , metav1 . GetOptions { } )
2016-11-10 01:50:25 +00:00
if shouldExist && errors . IsNotFound ( err ) {
errMessages = append ( errMessages , fmt . Sprintf ( "unexpected NotFound error for ingress %s in cluster %s, expected ingress to exist" , ingressName , clusterName ) )
} else if ! shouldExist && ! errors . IsNotFound ( err ) {
errMessages = append ( errMessages , fmt . Sprintf ( "expected NotFound error for ingress %s in cluster %s, got error: %v" , ingressName , clusterName , err ) )
}
}
if len ( errMessages ) != 0 {
framework . Failf ( "%s" , strings . Join ( errMessages , "; " ) )
}
}
2017-02-13 22:58:49 +00:00
// waitForIngressOrFail waits until a ingress 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 waitForIngressOrFail ( clientset * kubeclientset . Clientset , namespace string , ingress * v1beta1 . Ingress , present bool , timeout time . Duration ) {
2016-07-29 08:01:41 +00:00
By ( fmt . Sprintf ( "Fetching a federated ingress shard of ingress %q in namespace %q from cluster" , ingress . Name , namespace ) )
var clusterIngress * v1beta1 . Ingress
err := wait . PollImmediate ( framework . Poll , timeout , func ( ) ( bool , error ) {
2016-12-07 14:40:26 +00:00
clusterIngress , err := clientset . Ingresses ( namespace ) . Get ( ingress . 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 ingress %q in namespace %q in cluster is absent" , ingress . Name , namespace ) )
return true , nil // Success
}
if present && err == nil { // We want it present, and the Get succeeded, so we're all good.
By ( fmt . Sprintf ( "Success: shard of federated ingress %q in namespace %q in cluster is present" , ingress . Name , namespace ) )
return true , nil // Success
}
By ( fmt . Sprintf ( "Ingress %q in namespace %q in cluster. Found: %v, waiting for Found: %v, trying again in %s (err=%v)" , ingress . Name , namespace , clusterIngress != nil && err == nil , present , framework . Poll , err ) )
return false , nil
} )
framework . ExpectNoError ( err , "Failed to verify ingress %q in namespace %q in cluster: Present=%v" , ingress . Name , namespace , present )
if present && clusterIngress != nil {
Expect ( equivalentIngress ( * clusterIngress , * ingress ) )
}
}
2017-02-13 22:58:49 +00:00
// waitForIngressShardsOrFail waits for the ingress to appear in all clusters
2017-03-22 05:28:59 +00:00
func waitForIngressShardsOrFail ( namespace string , ingress * v1beta1 . Ingress , clusters fedframework . ClusterMap ) {
2016-07-29 08:01:41 +00:00
framework . Logf ( "Waiting for ingress %q in %d clusters" , ingress . Name , len ( clusters ) )
for _ , c := range clusters {
waitForIngressOrFail ( c . Clientset , namespace , ingress , true , FederatedIngressTimeout )
}
}
2017-02-13 22:58:49 +00:00
// waitForIngressShardsUpdatedOrFail waits for the ingress to be updated in all clusters
2017-03-22 05:28:59 +00:00
func waitForIngressShardsUpdatedOrFail ( namespace string , ingress * v1beta1 . Ingress , clusters fedframework . ClusterMap ) {
2016-07-29 08:01:41 +00:00
framework . Logf ( "Waiting for ingress %q in %d clusters" , ingress . Name , len ( clusters ) )
for _ , c := range clusters {
waitForIngressUpdateOrFail ( c . Clientset , namespace , ingress , FederatedIngressTimeout )
}
}
2017-02-13 22:58:49 +00:00
// waitForIngressUpdateOrFail waits until a ingress is updated in the specified cluster with same spec of federated ingress.
// If the condition is not met within timeout, it fails the calling test.
2016-09-02 18:57:44 +00:00
func waitForIngressUpdateOrFail ( clientset * kubeclientset . Clientset , namespace string , ingress * v1beta1 . Ingress , timeout time . Duration ) {
2016-07-29 08:01:41 +00:00
By ( fmt . Sprintf ( "Fetching a federated ingress shard of ingress %q in namespace %q from cluster" , ingress . Name , namespace ) )
err := wait . PollImmediate ( framework . Poll , timeout , func ( ) ( bool , error ) {
2016-12-07 14:40:26 +00:00
clusterIngress , err := clientset . Ingresses ( namespace ) . Get ( ingress . Name , metav1 . GetOptions { } )
2016-07-29 08:01:41 +00:00
if err == nil { // We want it present, and the Get succeeded, so we're all good.
if equivalentIngress ( * clusterIngress , * ingress ) {
By ( fmt . Sprintf ( "Success: shard of federated ingress %q in namespace %q in cluster is updated" , ingress . Name , namespace ) )
return true , nil
}
By ( fmt . Sprintf ( "Ingress %q in namespace %q in cluster, waiting for service being updated, trying again in %s (err=%v)" , ingress . Name , namespace , framework . Poll , err ) )
return false , nil
}
By ( fmt . Sprintf ( "Ingress %q in namespace %q in cluster, waiting for service being updated, trying again in %s (err=%v)" , ingress . Name , namespace , framework . Poll , err ) )
return false , nil
} )
framework . ExpectNoError ( err , "Failed to verify ingress %q in namespace %q in cluster" , ingress . Name , namespace )
}
2017-02-13 22:58:49 +00:00
// waitForIngressShardsGoneOrFail waits for the ingress to disappear in all clusters
2017-03-22 05:28:59 +00:00
func waitForIngressShardsGoneOrFail ( namespace string , ingress * v1beta1 . Ingress , clusters fedframework . ClusterMap ) {
2016-07-29 08:01:41 +00:00
framework . Logf ( "Waiting for ingress %q in %d clusters" , ingress . Name , len ( clusters ) )
for _ , c := range clusters {
waitForIngressOrFail ( c . Clientset , namespace , ingress , false , FederatedIngressTimeout )
}
}
2016-11-10 01:50:25 +00:00
func deleteIngressOrFail ( clientset * fedclientset . Clientset , namespace string , ingressName string , orphanDependents * bool ) {
2016-07-29 08:01:41 +00:00
if clientset == nil || len ( namespace ) == 0 || len ( ingressName ) == 0 {
Fail ( fmt . Sprintf ( "Internal error: invalid parameters passed to deleteIngressOrFail: clientset: %v, namespace: %v, ingress: %v" , clientset , namespace , ingressName ) )
}
2017-01-24 15:38:21 +00:00
err := clientset . Ingresses ( namespace ) . Delete ( ingressName , & metav1 . DeleteOptions { OrphanDependents : orphanDependents } )
2016-07-29 08:01:41 +00:00
framework . ExpectNoError ( err , "Error deleting ingress %q from namespace %q" , ingressName , namespace )
2016-11-10 01:50:25 +00:00
// Wait for the ingress to be deleted.
2017-03-13 23:47:33 +00:00
err = wait . Poll ( framework . Poll , FederatedIngressDeleteTimeout , func ( ) ( bool , error ) {
2016-12-07 14:40:26 +00:00
_ , err := clientset . Extensions ( ) . Ingresses ( namespace ) . Get ( ingressName , metav1 . GetOptions { } )
2016-11-10 01:50:25 +00:00
if err != nil && errors . IsNotFound ( err ) {
return true , nil
}
return false , err
} )
if err != nil {
framework . Failf ( "Error in deleting ingress %s: %v" , ingressName , err )
}
2016-07-29 08:01:41 +00:00
}
2016-10-12 22:12:54 +00:00
// TODO: quinton: This is largely a cut 'n paste of the above. Yuck! Refactor as soon as we have a common interface implmented by both fedclientset.Clientset and kubeclientset.Clientset
func deleteClusterIngressOrFail ( clusterName string , clientset * kubeclientset . Clientset , namespace string , ingressName string ) {
if clientset == nil || len ( namespace ) == 0 || len ( ingressName ) == 0 {
Fail ( fmt . Sprintf ( "Internal error: invalid parameters passed to deleteClusterIngressOrFail: cluster: %q, clientset: %v, namespace: %v, ingress: %v" , clusterName , clientset , namespace , ingressName ) )
}
2017-01-24 15:38:21 +00:00
err := clientset . Ingresses ( namespace ) . Delete ( ingressName , metav1 . NewDeleteOptions ( 0 ) )
2016-10-12 22:12:54 +00:00
framework . ExpectNoError ( err , "Error deleting cluster ingress %q/%q from cluster %q" , namespace , ingressName , clusterName )
}
2017-02-22 01:39:26 +00:00
func createIngressOrFail ( clientset * fedclientset . Clientset , namespace , serviceName , secretName string ) * v1beta1 . Ingress {
2016-07-29 08:01:41 +00:00
if clientset == nil || len ( namespace ) == 0 {
Fail ( fmt . Sprintf ( "Internal error: invalid parameters passed to createIngressOrFail: clientset: %v, namespace: %v" , clientset , namespace ) )
}
By ( fmt . Sprintf ( "Creating federated ingress %q in namespace %q" , FederatedIngressName , namespace ) )
ingress := & v1beta1 . Ingress {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-07-29 08:01:41 +00:00
Name : FederatedIngressName ,
} ,
Spec : v1beta1 . IngressSpec {
Backend : & v1beta1 . IngressBackend {
2017-02-22 01:39:26 +00:00
ServiceName : serviceName ,
2016-07-29 08:01:41 +00:00
ServicePort : intstr . FromInt ( 80 ) ,
} ,
2017-02-22 01:39:26 +00:00
TLS : [ ] v1beta1 . IngressTLS {
{
SecretName : secretName ,
} ,
} ,
2016-07-29 08:01:41 +00:00
} ,
}
2016-10-03 22:59:30 +00:00
newIng , err := clientset . Extensions ( ) . Ingresses ( namespace ) . Create ( ingress )
2016-07-29 08:01:41 +00:00
framework . ExpectNoError ( err , "Creating ingress %q in namespace %q" , ingress . Name , namespace )
By ( fmt . Sprintf ( "Successfully created federated ingress %q in namespace %q" , FederatedIngressName , namespace ) )
2016-10-03 22:59:30 +00:00
return newIng
2016-07-29 08:01:41 +00:00
}
2016-09-02 18:57:44 +00:00
func updateIngressOrFail ( clientset * fedclientset . Clientset , namespace string ) ( newIng * v1beta1 . Ingress ) {
2016-07-29 08:01:41 +00:00
var err error
if clientset == nil || len ( namespace ) == 0 {
Fail ( fmt . Sprintf ( "Internal error: invalid parameters passed to createIngressOrFail: clientset: %v, namespace: %v" , clientset , namespace ) )
}
ingress := & v1beta1 . Ingress {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-07-29 08:01:41 +00:00
Name : FederatedIngressName ,
} ,
Spec : v1beta1 . IngressSpec {
Backend : & v1beta1 . IngressBackend {
ServiceName : "updated-testingress-service" ,
ServicePort : intstr . FromInt ( 80 ) ,
} ,
} ,
}
2016-09-07 07:53:46 +00:00
err = waitForFederatedIngressExists ( clientset , namespace , FederatedIngressName , FederatedIngressTimeout )
if err != nil {
framework . Failf ( "failed to get ingress %q: %v" , FederatedIngressName , err )
}
for i := 0 ; i < MaxRetriesOnFederatedApiserver ; i ++ {
2016-07-29 08:01:41 +00:00
newIng , err = clientset . Extensions ( ) . Ingresses ( namespace ) . Update ( ingress )
if err == nil {
2017-01-11 13:23:31 +00:00
framework . DescribeIng ( namespace )
2016-09-07 07:53:46 +00:00
return newIng
2016-07-29 08:01:41 +00:00
}
if ! errors . IsConflict ( err ) && ! errors . IsServerTimeout ( err ) {
framework . Failf ( "failed to update ingress %q: %v" , FederatedIngressName , err )
}
}
framework . Failf ( "too many retries updating ingress %q" , FederatedIngressName )
2016-09-07 07:53:46 +00:00
return nil
2016-07-29 08:01:41 +00:00
}
func ( j * federationTestJig ) waitForFederatedIngress ( ) {
// Wait for the loadbalancer IP.
2016-12-29 23:35:47 +00:00
address , err := waitForFederatedIngressAddress ( j . client , j . ing . Namespace , j . ing . Name , framework . LoadBalancerPollTimeout )
2016-07-29 08:01:41 +00:00
if err != nil {
2016-12-29 23:35:47 +00:00
framework . Failf ( "Ingress failed to acquire an IP address within %v" , framework . LoadBalancerPollTimeout )
2016-07-29 08:01:41 +00:00
}
j . address = address
framework . Logf ( "Found address %v for ingress %v" , j . address , j . ing . Name )
2017-02-22 01:39:26 +00:00
client := & http . Client {
// This is mostly `http.DefaultTransport` except for the
// `TLSClientConfig`.
Transport : utilnet . SetTransportDefaults ( & http . Transport {
TLSClientConfig : & tls . Config {
InsecureSkipVerify : true ,
} ,
} ) ,
Timeout : reqTimeout ,
}
// Verify that simple GET works.
route := fmt . Sprintf ( "https://%v" , address )
framework . Logf ( "Testing route %v with simple GET" , route )
framework . ExpectNoError ( framework . PollURL ( route , FederatedIngressHost , framework . LoadBalancerPollTimeout , framework . LoadBalancerPollInterval , client , false ) )
}
func createTLSSecretOrFail ( clientset * fedclientset . Clientset , namespace , secretName string ) * v1 . Secret {
if clientset == nil || len ( namespace ) == 0 {
framework . Logf ( "Internal error: invalid parameters passed to createTLSSecretOrFail: clientset: %v, namespace: %v" , clientset , namespace )
}
secret := & v1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : secretName ,
} ,
Type : v1 . SecretTypeOpaque ,
Data : map [ string ] [ ] byte {
"tls.crt" : [ ] byte ( FederatedIngressTLSCrt ) ,
"tls.key" : [ ] byte ( FederatedIngressTLSKey ) ,
} ,
2016-07-29 08:01:41 +00:00
}
2017-02-22 01:39:26 +00:00
By ( fmt . Sprintf ( "Creating federated secret %q in namespace %q" , secretName , namespace ) )
newSecret , err := clientset . Core ( ) . Secrets ( namespace ) . Create ( secret )
framework . ExpectNoError ( err , "creating secret %q in namespace %q" , secret . Name , namespace )
return newSecret
2016-07-29 08:01:41 +00:00
}
type federationTestJig struct {
// TODO add TLS check later
rootCAs map [ string ] [ ] byte
address string
ing * v1beta1 . Ingress
2016-09-02 18:57:44 +00:00
client * fedclientset . Clientset
2016-07-29 08:01:41 +00:00
}
2016-09-02 18:57:44 +00:00
func newFederationTestJig ( c * fedclientset . Clientset ) * federationTestJig {
2016-07-29 08:01:41 +00:00
return & federationTestJig { client : c , rootCAs : map [ string ] [ ] byte { } }
}
// WaitForFederatedIngressAddress waits for the Ingress to acquire an address.
2016-09-02 18:57:44 +00:00
func waitForFederatedIngressAddress ( c * fedclientset . Clientset , ns , ingName string , timeout time . Duration ) ( string , error ) {
2016-07-29 08:01:41 +00:00
var address string
err := wait . PollImmediate ( 10 * time . Second , timeout , func ( ) ( bool , error ) {
ipOrNameList , err := getFederatedIngressAddress ( c , ns , ingName )
if err != nil || len ( ipOrNameList ) == 0 {
framework . Logf ( "Waiting for Ingress %v to acquire IP, error %v" , ingName , err )
return false , nil
}
address = ipOrNameList [ 0 ]
return true , nil
} )
return address , err
}
2016-09-07 07:53:46 +00:00
// waitForFederatedIngressExists waits for the Ingress object exists.
2016-09-02 18:57:44 +00:00
func waitForFederatedIngressExists ( c * fedclientset . Clientset , ns , ingName string , timeout time . Duration ) error {
2016-09-07 07:53:46 +00:00
err := wait . PollImmediate ( 10 * time . Second , timeout , func ( ) ( bool , error ) {
2016-12-07 14:40:26 +00:00
_ , err := c . Extensions ( ) . Ingresses ( ns ) . Get ( ingName , metav1 . GetOptions { } )
2016-09-07 07:53:46 +00:00
if err != nil {
framework . Logf ( "Waiting for Ingress %v, error %v" , ingName , err )
return false , nil
}
return true , nil
} )
return err
}
2016-07-29 08:01:41 +00:00
// getFederatedIngressAddress returns the ips/hostnames associated with the Ingress.
2016-09-02 18:57:44 +00:00
func getFederatedIngressAddress ( client * fedclientset . Clientset , ns , name string ) ( [ ] string , error ) {
2016-12-07 14:40:26 +00:00
ing , err := client . Extensions ( ) . Ingresses ( ns ) . Get ( name , metav1 . GetOptions { } )
2016-07-29 08:01:41 +00:00
if err != nil {
return nil , err
}
addresses := [ ] string { }
for _ , a := range ing . Status . LoadBalancer . Ingress {
if a . IP != "" {
addresses = append ( addresses , a . IP )
}
if a . Hostname != "" {
addresses = append ( addresses , a . Hostname )
}
}
return addresses , nil
}