2017-07-31 22:43:20 +00:00
/ *
Copyright 2017 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 .
* /
package apimachinery
import (
2017-09-20 21:58:49 +00:00
"crypto/rand"
2017-07-31 22:43:20 +00:00
"encoding/json"
2017-09-20 21:58:49 +00:00
"fmt"
"math/big"
2017-07-31 22:43:20 +00:00
"strings"
"time"
2018-03-20 17:06:17 +00:00
apps "k8s.io/api/apps/v1"
2017-07-31 22:43:20 +00:00
"k8s.io/api/core/v1"
rbacv1beta1 "k8s.io/api/rbac/v1beta1"
apierrs "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
unstructuredv1 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/wait"
2017-08-21 22:45:51 +00:00
"k8s.io/apiserver/pkg/authentication/user"
2017-07-31 22:43:20 +00:00
"k8s.io/client-go/discovery"
2017-11-11 08:03:48 +00:00
clientset "k8s.io/client-go/kubernetes"
2017-07-31 22:43:20 +00:00
apiregistrationv1beta1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1"
2017-11-11 08:03:48 +00:00
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
2017-07-31 22:43:20 +00:00
rbacapi "k8s.io/kubernetes/pkg/apis/rbac"
2017-08-21 22:45:51 +00:00
utilversion "k8s.io/kubernetes/pkg/util/version"
2017-07-31 22:43:20 +00:00
"k8s.io/kubernetes/test/e2e/framework"
2017-12-01 19:01:47 +00:00
imageutils "k8s.io/kubernetes/test/utils/image"
2017-07-31 22:43:20 +00:00
samplev1alpha1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1"
. "github.com/onsi/ginkgo"
)
2017-08-21 22:45:51 +00:00
var serverAggregatorVersion = utilversion . MustParseSemantic ( "v1.7.0" )
2017-07-31 22:43:20 +00:00
var _ = SIGDescribe ( "Aggregator" , func ( ) {
2017-11-11 08:03:48 +00:00
var ns string
var c clientset . Interface
var aggrclient * aggregatorclient . Clientset
2017-12-20 18:50:03 +00:00
// BeforeEachs run in LIFO order, AfterEachs run in FIFO order.
// We want cleanTest to happen before the namespace cleanup AfterEach
// inserted by NewDefaultFramework, so we put this AfterEach in front
// of NewDefaultFramework.
AfterEach ( func ( ) {
cleanTest ( c , aggrclient , ns )
} )
2017-07-31 22:43:20 +00:00
f := framework . NewDefaultFramework ( "aggregator" )
2017-11-11 08:03:48 +00:00
2017-12-20 18:50:03 +00:00
// We want namespace initialization BeforeEach inserted by
// NewDefaultFramework to happen before this, so we put this BeforeEach
// after NewDefaultFramework.
2017-11-11 08:03:48 +00:00
BeforeEach ( func ( ) {
c = f . ClientSet
ns = f . Namespace . Name
aggrclient = f . AggregatorClient
2017-07-31 22:43:20 +00:00
} )
It ( "Should be able to support the 1.7 Sample API Server using the current Aggregator" , func ( ) {
// Make sure the relevant provider supports Agggregator
2017-08-21 22:45:51 +00:00
framework . SkipUnlessServerVersionGTE ( serverAggregatorVersion , f . ClientSet . Discovery ( ) )
2017-07-31 22:43:20 +00:00
framework . SkipUnlessProviderIs ( "gce" , "gke" )
// Testing a 1.7 version of the sample-apiserver
2017-12-01 19:01:47 +00:00
TestSampleAPIServer ( f , imageutils . GetE2EImage ( imageutils . APIServer ) )
2017-07-31 22:43:20 +00:00
} )
} )
2017-11-11 08:03:48 +00:00
func cleanTest ( client clientset . Interface , aggrclient * aggregatorclient . Clientset , namespace string ) {
2017-09-04 21:31:17 +00:00
// delete the APIService first to avoid causing discovery errors
_ = aggrclient . ApiregistrationV1beta1 ( ) . APIServices ( ) . Delete ( "v1alpha1.wardle.k8s.io" , nil )
2018-03-20 17:06:17 +00:00
_ = client . AppsV1 ( ) . Deployments ( namespace ) . Delete ( "sample-apiserver" , nil )
2017-07-31 22:43:20 +00:00
_ = client . CoreV1 ( ) . Secrets ( namespace ) . Delete ( "sample-apiserver-secret" , nil )
_ = client . CoreV1 ( ) . Services ( namespace ) . Delete ( "sample-api" , nil )
_ = client . CoreV1 ( ) . ServiceAccounts ( namespace ) . Delete ( "sample-apiserver" , nil )
_ = client . RbacV1beta1 ( ) . RoleBindings ( "kube-system" ) . Delete ( "wardler-auth-reader" , nil )
_ = client . RbacV1beta1 ( ) . ClusterRoles ( ) . Delete ( "wardler" , nil )
2017-10-05 02:09:19 +00:00
_ = client . RbacV1beta1 ( ) . ClusterRoleBindings ( ) . Delete ( "wardler:" + namespace + ":anonymous" , nil )
2017-07-31 22:43:20 +00:00
}
// A basic test if the sample-apiserver code from 1.7 and compiled against 1.7
// will work on the current Aggregator/API-Server.
2017-10-05 02:09:19 +00:00
func TestSampleAPIServer ( f * framework . Framework , image string ) {
2017-07-31 22:43:20 +00:00
By ( "Registering the sample API server." )
client := f . ClientSet
2017-09-20 21:58:49 +00:00
restClient := client . Discovery ( ) . RESTClient ( )
2017-07-31 22:43:20 +00:00
iclient := f . InternalClientset
aggrclient := f . AggregatorClient
2017-10-05 02:09:19 +00:00
namespace := f . Namespace . Name
2017-10-13 21:37:37 +00:00
context := setupServerCert ( namespace , "sample-api" )
2017-07-31 22:43:20 +00:00
if framework . ProviderIs ( "gke" ) {
// kubectl create clusterrolebinding user-cluster-admin-binding --clusterrole=cluster-admin --user=user@domain.com
2017-08-21 22:45:51 +00:00
authenticated := rbacv1beta1 . Subject { Kind : rbacv1beta1 . GroupKind , Name : user . AllAuthenticated }
2017-10-05 02:09:19 +00:00
framework . BindClusterRole ( client . RbacV1beta1 ( ) , "cluster-admin" , namespace , authenticated )
2017-07-31 22:43:20 +00:00
}
// kubectl create -f namespace.yaml
2017-10-05 02:09:19 +00:00
// NOTE: aggregated apis should generally be set up in there own namespace. As the test framework is setting up a new namespace, we are just using that.
2017-07-31 22:43:20 +00:00
// kubectl create -f secret.yaml
secretName := "sample-apiserver-secret"
secret := & v1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : secretName ,
} ,
Type : v1 . SecretTypeOpaque ,
Data : map [ string ] [ ] byte {
2017-10-13 21:37:37 +00:00
"tls.crt" : context . cert ,
"tls.key" : context . key ,
2017-07-31 22:43:20 +00:00
} ,
}
2017-10-05 02:09:19 +00:00
_ , err := client . CoreV1 ( ) . Secrets ( namespace ) . Create ( secret )
2017-07-31 22:43:20 +00:00
framework . ExpectNoError ( err , "creating secret %q in namespace %q" , secretName , namespace )
// kubectl create -f deploy.yaml
deploymentName := "sample-apiserver-deployment"
2018-03-14 20:51:39 +00:00
etcdImage := "quay.io/coreos/etcd:v3.2.18"
2017-07-31 22:43:20 +00:00
podLabels := map [ string ] string { "app" : "sample-apiserver" , "apiserver" : "true" }
replicas := int32 ( 1 )
zero := int64 ( 0 )
mounts := [ ] v1 . VolumeMount {
{
Name : "apiserver-certs" ,
ReadOnly : true ,
MountPath : "/apiserver.local.config/certificates" ,
} ,
}
volumes := [ ] v1 . Volume {
{
Name : "apiserver-certs" ,
VolumeSource : v1 . VolumeSource {
Secret : & v1 . SecretVolumeSource { SecretName : secretName } ,
} ,
} ,
}
containers := [ ] v1 . Container {
{
Name : "sample-apiserver" ,
VolumeMounts : mounts ,
Args : [ ] string {
"--etcd-servers=http://localhost:2379" ,
"--tls-cert-file=/apiserver.local.config/certificates/tls.crt" ,
"--tls-private-key-file=/apiserver.local.config/certificates/tls.key" ,
"--audit-log-path=-" ,
"--audit-log-maxage=0" ,
"--audit-log-maxbackup=0" ,
} ,
Image : image ,
} ,
{
Name : "etcd" ,
Image : etcdImage ,
} ,
}
2018-03-20 17:06:17 +00:00
d := & apps . Deployment {
2017-07-31 22:43:20 +00:00
ObjectMeta : metav1 . ObjectMeta {
2018-05-11 18:09:56 +00:00
Name : deploymentName ,
Labels : podLabels ,
2017-07-31 22:43:20 +00:00
} ,
2018-03-20 17:06:17 +00:00
Spec : apps . DeploymentSpec {
2017-07-31 22:43:20 +00:00
Replicas : & replicas ,
2018-05-11 18:09:56 +00:00
Selector : & metav1 . LabelSelector {
MatchLabels : podLabels ,
} ,
2018-03-20 17:06:17 +00:00
Strategy : apps . DeploymentStrategy {
Type : apps . RollingUpdateDeploymentStrategyType ,
2017-07-31 22:43:20 +00:00
} ,
Template : v1 . PodTemplateSpec {
ObjectMeta : metav1 . ObjectMeta {
Labels : podLabels ,
} ,
Spec : v1 . PodSpec {
TerminationGracePeriodSeconds : & zero ,
Containers : containers ,
Volumes : volumes ,
} ,
} ,
} ,
}
2018-03-20 17:06:17 +00:00
deployment , err := client . AppsV1 ( ) . Deployments ( namespace ) . Create ( d )
2017-07-31 22:43:20 +00:00
framework . ExpectNoError ( err , "creating deployment %s in namespace %s" , deploymentName , namespace )
err = framework . WaitForDeploymentRevisionAndImage ( client , namespace , deploymentName , "1" , image )
framework . ExpectNoError ( err , "waiting for the deployment of image %s in %s in %s to complete" , image , deploymentName , namespace )
err = framework . WaitForDeploymentRevisionAndImage ( client , namespace , deploymentName , "1" , etcdImage )
framework . ExpectNoError ( err , "waiting for the deployment of image %s in %s to complete" , etcdImage , deploymentName , namespace )
// kubectl create -f service.yaml
serviceLabels := map [ string ] string { "apiserver" : "true" }
service := & v1 . Service {
ObjectMeta : metav1 . ObjectMeta {
Namespace : namespace ,
Name : "sample-api" ,
Labels : map [ string ] string { "test" : "aggregator" } ,
} ,
Spec : v1 . ServiceSpec {
Selector : serviceLabels ,
Ports : [ ] v1 . ServicePort {
{
Protocol : "TCP" ,
Port : 443 ,
TargetPort : intstr . FromInt ( 443 ) ,
} ,
} ,
} ,
}
_ , err = client . CoreV1 ( ) . Services ( namespace ) . Create ( service )
framework . ExpectNoError ( err , "creating service %s in namespace %s" , "sample-apiserver" , namespace )
// kubectl create -f serviceAccount.yaml
sa := & v1 . ServiceAccount { ObjectMeta : metav1 . ObjectMeta { Name : "sample-apiserver" } }
_ , err = client . CoreV1 ( ) . ServiceAccounts ( namespace ) . Create ( sa )
framework . ExpectNoError ( err , "creating service account %s in namespace %s" , "sample-apiserver" , namespace )
// kubectl create -f authDelegator.yaml
_ , err = client . RbacV1beta1 ( ) . ClusterRoleBindings ( ) . Create ( & rbacv1beta1 . ClusterRoleBinding {
ObjectMeta : metav1 . ObjectMeta {
Name : "wardler:" + namespace + ":anonymous" ,
} ,
RoleRef : rbacv1beta1 . RoleRef {
APIGroup : "rbac.authorization.k8s.io" ,
Kind : "ClusterRole" ,
Name : "wardler" ,
} ,
Subjects : [ ] rbacv1beta1 . Subject {
{
APIGroup : "rbac.authorization.k8s.io" ,
Kind : "User" ,
Name : namespace + ":anonymous" ,
} ,
} ,
} )
framework . ExpectNoError ( err , "creating cluster role binding %s" , "wardler:" + namespace + ":anonymous" )
// kubectl create -f role.yaml
resourceRule , err := rbacapi . NewRule ( "create" , "delete" , "deletecollection" , "get" , "list" , "patch" , "update" , "watch" ) . Groups ( "wardle.k8s.io" ) . Resources ( "flunders" ) . Rule ( )
framework . ExpectNoError ( err , "creating cluster resource rule" )
urlRule , err := rbacapi . NewRule ( "get" ) . URLs ( "*" ) . Rule ( )
framework . ExpectNoError ( err , "creating cluster url rule" )
2017-08-21 22:45:51 +00:00
err = wait . Poll ( 100 * time . Millisecond , 30 * time . Second , func ( ) ( bool , error ) {
roleLabels := map [ string ] string { "kubernetes.io/bootstrapping" : "wardle-default" }
role := rbacapi . ClusterRole {
ObjectMeta : metav1 . ObjectMeta {
Name : "wardler" ,
Labels : roleLabels ,
} ,
Rules : [ ] rbacapi . PolicyRule { resourceRule , urlRule } ,
}
_ , err = iclient . Rbac ( ) . ClusterRoles ( ) . Create ( & role )
if err != nil {
return false , nil
}
return true , nil
} )
framework . ExpectNoError ( err , "creating cluster role wardler - may not have permissions" )
2017-07-31 22:43:20 +00:00
// kubectl create -f auth-reader.yaml
_ , err = client . RbacV1beta1 ( ) . RoleBindings ( "kube-system" ) . Create ( & rbacv1beta1 . RoleBinding {
ObjectMeta : metav1 . ObjectMeta {
Name : "wardler-auth-reader" ,
Annotations : map [ string ] string {
rbacv1beta1 . AutoUpdateAnnotationKey : "true" ,
} ,
} ,
RoleRef : rbacv1beta1 . RoleRef {
APIGroup : "" ,
Kind : "Role" ,
Name : "extension-apiserver-authentication-reader" ,
} ,
Subjects : [ ] rbacv1beta1 . Subject {
{
Kind : "ServiceAccount" ,
Name : "default" , // "sample-apiserver",
Namespace : namespace ,
} ,
} ,
} )
framework . ExpectNoError ( err , "creating role binding %s:sample-apiserver to access configMap" , namespace )
2018-01-23 15:01:41 +00:00
// Wait for the extension apiserver to be up and healthy
// kubectl get deployments -n <aggregated-api-namespace> && status == Running
// NOTE: aggregated apis should generally be set up in there own namespace (<aggregated-api-namespace>). As the test framework
// is setting up a new namespace, we are just using that.
err = framework . WaitForDeploymentComplete ( client , deployment )
framework . ExpectNoError ( err , "deploying extension apiserver in namespace %s" , namespace )
2017-07-31 22:43:20 +00:00
// kubectl create -f apiservice.yaml
_ , err = aggrclient . ApiregistrationV1beta1 ( ) . APIServices ( ) . Create ( & apiregistrationv1beta1 . APIService {
ObjectMeta : metav1 . ObjectMeta { Name : "v1alpha1.wardle.k8s.io" } ,
Spec : apiregistrationv1beta1 . APIServiceSpec {
Service : & apiregistrationv1beta1 . ServiceReference {
Namespace : namespace ,
Name : "sample-api" ,
} ,
Group : "wardle.k8s.io" ,
Version : "v1alpha1" ,
2017-10-13 21:37:37 +00:00
CABundle : context . signingCert ,
2017-07-31 22:43:20 +00:00
GroupPriorityMinimum : 2000 ,
VersionPriority : 200 ,
} ,
} )
framework . ExpectNoError ( err , "creating apiservice %s with namespace %s" , "v1alpha1.wardle.k8s.io" , namespace )
2018-06-01 00:13:00 +00:00
var (
currentAPIService * apiregistrationv1beta1 . APIService
currentPods * v1 . PodList
)
2018-06-11 21:43:23 +00:00
err = pollTimed ( 100 * time . Millisecond , 60 * time . Second , func ( ) ( bool , error ) {
2018-06-01 00:13:00 +00:00
currentAPIService , _ = aggrclient . ApiregistrationV1beta1 ( ) . APIServices ( ) . Get ( "v1alpha1.wardle.k8s.io" , metav1 . GetOptions { } )
currentPods , _ = client . CoreV1 ( ) . Pods ( namespace ) . List ( metav1 . ListOptions { } )
2017-09-20 21:58:49 +00:00
request := restClient . Get ( ) . AbsPath ( "/apis/wardle.k8s.io/v1alpha1/namespaces/default/flunders" )
2017-07-31 22:43:20 +00:00
request . SetHeader ( "Accept" , "application/json" )
_ , err := request . DoRaw ( )
if err != nil {
status , ok := err . ( * apierrs . StatusError )
if ! ok {
return false , err
}
2018-01-21 02:25:03 +00:00
if status . Status ( ) . Code == 503 {
return false , nil
}
2017-07-31 22:43:20 +00:00
if status . Status ( ) . Code == 404 && strings . HasPrefix ( err . Error ( ) , "the server could not find the requested resource" ) {
return false , nil
}
return false , err
}
return true , nil
2018-06-11 21:43:23 +00:00
} , "Waited %s for the sample-apiserver to be ready to handle requests." )
2018-06-01 00:13:00 +00:00
if err != nil {
currentAPIServiceJSON , _ := json . Marshal ( currentAPIService )
framework . Logf ( "current APIService: %s" , string ( currentAPIServiceJSON ) )
currentPodsJSON , _ := json . Marshal ( currentPods )
framework . Logf ( "current pods: %s" , string ( currentPodsJSON ) )
if currentPods != nil {
for _ , pod := range currentPods . Items {
for _ , container := range pod . Spec . Containers {
logs , err := framework . GetPodLogs ( client , namespace , pod . Name , container . Name )
framework . Logf ( "logs of %s/%s (error: %v): %s" , pod . Name , container . Name , err , logs )
}
}
}
}
2017-07-31 22:43:20 +00:00
framework . ExpectNoError ( err , "gave up waiting for apiservice wardle to come up successfully" )
2017-09-20 21:58:49 +00:00
flunderName := generateFlunderName ( "rest-flunder" )
2017-07-31 22:43:20 +00:00
// kubectl create -f flunders-1.yaml -v 9
// curl -k -v -XPOST https://localhost/apis/wardle.k8s.io/v1alpha1/namespaces/default/flunders
// Request Body: {"apiVersion":"wardle.k8s.io/v1alpha1","kind":"Flunder","metadata":{"labels":{"sample-label":"true"},"name":"test-flunder","namespace":"default"}}
2017-09-20 21:58:49 +00:00
flunder := ` { "apiVersion":"wardle.k8s.io/v1alpha1","kind":"Flunder","metadata": { "labels": { "sample-label":"true"},"name":" ` + flunderName + ` ","namespace":"default"}} `
result := restClient . Post ( ) . AbsPath ( "/apis/wardle.k8s.io/v1alpha1/namespaces/default/flunders" ) . Body ( [ ] byte ( flunder ) ) . Do ( )
2017-07-31 22:43:20 +00:00
framework . ExpectNoError ( result . Error ( ) , "creating a new flunders resource" )
var statusCode int
result . StatusCode ( & statusCode )
if statusCode != 201 {
framework . Failf ( "Flunders client creation response was status %d, not 201" , statusCode )
}
2017-09-20 21:58:49 +00:00
pods , err := client . CoreV1 ( ) . Pods ( namespace ) . List ( metav1 . ListOptions { } )
framework . ExpectNoError ( result . Error ( ) , "getting pods for flunders service" )
2017-07-31 22:43:20 +00:00
// kubectl get flunders -v 9
// curl -k -v -XGET https://localhost/apis/wardle.k8s.io/v1alpha1/namespaces/default/flunders
2017-09-20 21:58:49 +00:00
contents , err := restClient . Get ( ) . AbsPath ( "/apis/wardle.k8s.io/v1alpha1/namespaces/default/flunders" ) . SetHeader ( "Accept" , "application/json" ) . DoRaw ( )
2017-07-31 22:43:20 +00:00
framework . ExpectNoError ( err , "attempting to get a newly created flunders resource" )
var flundersList samplev1alpha1 . FlunderList
err = json . Unmarshal ( contents , & flundersList )
2017-09-20 21:58:49 +00:00
validateErrorWithDebugInfo ( f , err , pods , "Error in unmarshalling %T response from server %s" , contents , "/apis/wardle.k8s.io/v1alpha1" )
2017-07-31 22:43:20 +00:00
if len ( flundersList . Items ) != 1 {
framework . Failf ( "failed to get back the correct flunders list %v" , flundersList )
}
// kubectl delete flunder test-flunder -v 9
// curl -k -v -XDELETE https://35.193.112.40/apis/wardle.k8s.io/v1alpha1/namespaces/default/flunders/test-flunder
2017-09-20 21:58:49 +00:00
_ , err = restClient . Delete ( ) . AbsPath ( "/apis/wardle.k8s.io/v1alpha1/namespaces/default/flunders/" + flunderName ) . DoRaw ( )
validateErrorWithDebugInfo ( f , err , pods , "attempting to delete a newly created flunders(%v) resource" , flundersList . Items )
2017-07-31 22:43:20 +00:00
// kubectl get flunders -v 9
// curl -k -v -XGET https://localhost/apis/wardle.k8s.io/v1alpha1/namespaces/default/flunders
2017-09-20 21:58:49 +00:00
contents , err = restClient . Get ( ) . AbsPath ( "/apis/wardle.k8s.io/v1alpha1/namespaces/default/flunders" ) . SetHeader ( "Accept" , "application/json" ) . DoRaw ( )
2017-07-31 22:43:20 +00:00
framework . ExpectNoError ( err , "confirming delete of a newly created flunders resource" )
err = json . Unmarshal ( contents , & flundersList )
2017-09-20 21:58:49 +00:00
validateErrorWithDebugInfo ( f , err , pods , "Error in unmarshalling %T response from server %s" , contents , "/apis/wardle.k8s.io/v1alpha1" )
2017-07-31 22:43:20 +00:00
if len ( flundersList . Items ) != 0 {
framework . Failf ( "failed to get back the correct deleted flunders list %v" , flundersList )
}
2017-09-20 21:58:49 +00:00
flunderName = generateFlunderName ( "dynamic-flunder" )
2017-07-31 22:43:20 +00:00
// Rerun the Create/List/Delete tests using the Dynamic client.
2018-05-09 22:00:33 +00:00
resources , discoveryErr := client . Discovery ( ) . ServerPreferredNamespacedResources ( )
2017-07-31 22:43:20 +00:00
groupVersionResources , err := discovery . GroupVersionResources ( resources )
framework . ExpectNoError ( err , "getting group version resources for dynamic client" )
gvr := schema . GroupVersionResource { Group : "wardle.k8s.io" , Version : "v1alpha1" , Resource : "flunders" }
_ , ok := groupVersionResources [ gvr ]
if ! ok {
2018-05-09 22:00:33 +00:00
framework . Failf ( "could not find group version resource for dynamic client and wardle/flunders (discovery error: %v, discovery results: %#v)" , discoveryErr , groupVersionResources )
2017-07-31 22:43:20 +00:00
}
2018-04-27 15:29:05 +00:00
dynamicClient := f . DynamicClient . Resource ( gvr ) . Namespace ( namespace )
2017-07-31 22:43:20 +00:00
// kubectl create -f flunders-1.yaml
// Request Body: {"apiVersion":"wardle.k8s.io/v1alpha1","kind":"Flunder","metadata":{"labels":{"sample-label":"true"},"name":"test-flunder","namespace":"default"}}
testFlunder := samplev1alpha1 . Flunder {
TypeMeta : metav1 . TypeMeta {
Kind : "Flunder" ,
APIVersion : "wardle.k8s.io/v1alpha1" ,
} ,
2017-09-20 21:58:49 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : flunderName } ,
2017-07-31 22:43:20 +00:00
Spec : samplev1alpha1 . FlunderSpec { } ,
}
jsonFlunder , err := json . Marshal ( testFlunder )
framework . ExpectNoError ( err , "marshalling test-flunder for create using dynamic client" )
unstruct := & unstructuredv1 . Unstructured { }
err = unstruct . UnmarshalJSON ( jsonFlunder )
framework . ExpectNoError ( err , "unmarshalling test-flunder as unstructured for create using dynamic client" )
2018-04-26 08:53:07 +00:00
unstruct , err = dynamicClient . Create ( unstruct )
2017-07-31 22:43:20 +00:00
framework . ExpectNoError ( err , "listing flunders using dynamic client" )
// kubectl get flunders
2018-04-26 08:53:07 +00:00
unstructuredList , err := dynamicClient . List ( metav1 . ListOptions { } )
2017-07-31 22:43:20 +00:00
framework . ExpectNoError ( err , "listing flunders using dynamic client" )
if len ( unstructuredList . Items ) != 1 {
framework . Failf ( "failed to get back the correct flunders list %v from the dynamic client" , unstructuredList )
}
// kubectl delete flunder test-flunder
2018-04-26 08:53:07 +00:00
err = dynamicClient . Delete ( flunderName , & metav1 . DeleteOptions { } )
2017-09-20 21:58:49 +00:00
validateErrorWithDebugInfo ( f , err , pods , "deleting flunders(%v) using dynamic client" , unstructuredList . Items )
2017-07-31 22:43:20 +00:00
// kubectl get flunders
2018-04-26 08:53:07 +00:00
unstructuredList , err = dynamicClient . List ( metav1 . ListOptions { } )
2017-07-31 22:43:20 +00:00
framework . ExpectNoError ( err , "listing flunders using dynamic client" )
if len ( unstructuredList . Items ) != 0 {
framework . Failf ( "failed to get back the correct deleted flunders list %v from the dynamic client" , unstructuredList )
}
2017-11-11 08:03:48 +00:00
cleanTest ( client , aggrclient , namespace )
2017-07-31 22:43:20 +00:00
}
2017-09-20 21:58:49 +00:00
2018-06-11 21:43:23 +00:00
// pollTimed will call Poll but time how long Poll actually took.
// It will then framework.logf the msg with the duration of the Poll.
// It is assumed that msg will contain one %s for the elapsed time.
func pollTimed ( interval , timeout time . Duration , condition wait . ConditionFunc , msg string ) error {
defer func ( start time . Time , msg string ) {
elapsed := time . Since ( start )
framework . Logf ( msg , elapsed )
} ( time . Now ( ) , msg )
return wait . Poll ( interval , timeout , condition )
}
2017-09-20 21:58:49 +00:00
func validateErrorWithDebugInfo ( f * framework . Framework , err error , pods * v1 . PodList , msg string , fields ... interface { } ) {
if err != nil {
2017-10-05 02:09:19 +00:00
namespace := f . Namespace . Name
2017-09-20 21:58:49 +00:00
msg := fmt . Sprintf ( msg , fields ... )
msg += fmt . Sprintf ( " but received unexpected error:\n%v" , err )
client := f . ClientSet
ep , err := client . CoreV1 ( ) . Endpoints ( namespace ) . Get ( "sample-api" , metav1 . GetOptions { } )
if err == nil {
msg += fmt . Sprintf ( "\nFound endpoints for sample-api:\n%v" , ep )
}
pds , err := client . CoreV1 ( ) . Pods ( namespace ) . List ( metav1 . ListOptions { } )
if err == nil {
2017-10-05 02:09:19 +00:00
msg += fmt . Sprintf ( "\nFound pods in %s:\n%v" , namespace , pds )
msg += fmt . Sprintf ( "\nOriginal pods in %s:\n%v" , namespace , pods )
2017-09-20 21:58:49 +00:00
}
framework . Failf ( msg )
}
}
func generateFlunderName ( base string ) string {
id , err := rand . Int ( rand . Reader , big . NewInt ( 2147483647 ) )
if err != nil {
return base
}
return fmt . Sprintf ( "%s-%d" , base , id )
}