Merge pull request #47252 from sttts/sttts-crd-initializers

Automatic merge from submit-queue (batch tested with PRs 43443, 46193, 49071, 47252)

custom-resources: add initializer test
This commit is contained in:
Kubernetes Submit Queue 2017-07-25 21:52:52 -07:00 committed by GitHub
commit 06e3a00a14
3 changed files with 159 additions and 0 deletions

View File

@ -14,12 +14,15 @@ go_test(
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library",
"//vendor/k8s.io/api/apps/v1beta1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/networking/v1:go_default_library",
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
"//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//vendor/k8s.io/client-go/dynamic:go_default_library",

View File

@ -17,16 +17,20 @@ limitations under the License.
package testing
import (
"encoding/json"
"fmt"
"testing"
"time"
admissionregistrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1"
appsv1beta1 "k8s.io/api/apps/v1beta1"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/dynamic"
@ -149,6 +153,11 @@ func TestCRD(t *testing.T) {
config, tearDown := StartTestServerOrDie(t)
defer tearDown()
kubeclient, err := kubernetes.NewForConfig(config)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
apiextensionsclient, err := apiextensionsclientset.NewForConfig(config)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
@ -193,6 +202,152 @@ func TestCRD(t *testing.T) {
if err != nil {
t.Errorf("Failed to list foos.cr.bar.com instances: %v", err)
}
t.Logf("Creating InitializerConfiguration")
_, err = kubeclient.AdmissionregistrationV1alpha1().InitializerConfigurations().Create(&admissionregistrationv1alpha1.InitializerConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: "foos.cr.bar.com",
},
Initializers: []admissionregistrationv1alpha1.Initializer{
{
Name: "cr.bar.com",
Rules: []admissionregistrationv1alpha1.Rule{
{
APIGroups: []string{"cr.bar.com"},
APIVersions: []string{"*"},
Resources: []string{"*"},
},
},
},
},
})
if err != nil {
t.Fatalf("Failed to create InitializerConfiguration: %v", err)
}
// TODO DO NOT MERGE THIS
time.Sleep(5 * time.Second)
t.Logf("Creating Foo instance")
foo := &Foo{
TypeMeta: metav1.TypeMeta{
APIVersion: "cr.bar.com/v1",
Kind: "Foo",
},
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
}
unstructuredFoo, err := unstructuredFoo(foo)
if err != nil {
t.Fatalf("Unable to create Foo: %v", err)
}
createErr := make(chan error, 1)
go func() {
_, err = barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Create(unstructuredFoo)
t.Logf("Foo instance create returned: %v", err)
if err != nil {
createErr <- err
}
}()
err = wait.PollImmediate(100*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) {
select {
case createErr := <-createErr:
return true, createErr
default:
}
t.Logf("Checking that Foo instance is visible with IncludeUninitialized=true")
_, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Get(foo.ObjectMeta.Name, metav1.GetOptions{
IncludeUninitialized: true,
})
switch {
case err == nil:
return true, nil
case errors.IsNotFound(err):
return false, nil
default:
return false, err
}
})
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
t.Logf("Removing initializer from Foo instance")
success := false
for i := 0; i < 10; i++ {
// would love to replace the following with a patch, but removing strings from the intitializer array
// is not what JSON (Merge) patch authors had in mind.
fooUnstructured, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Get(foo.ObjectMeta.Name, metav1.GetOptions{
IncludeUninitialized: true,
})
if err != nil {
t.Fatalf("Error getting Foo instance: %v", err)
}
bs, _ := fooUnstructured.MarshalJSON()
t.Logf("Got Foo instance: %v", string(bs))
foo := Foo{}
if err := json.Unmarshal(bs, &foo); err != nil {
t.Fatalf("Error parsing Foo instance: %v", err)
}
// remove initialize
if foo.ObjectMeta.Initializers == nil {
t.Fatalf("Expected initializers to be set in Foo instance")
}
found := false
for i := range foo.ObjectMeta.Initializers.Pending {
if foo.ObjectMeta.Initializers.Pending[i].Name == "cr.bar.com" {
foo.ObjectMeta.Initializers.Pending = append(foo.ObjectMeta.Initializers.Pending[:i], foo.ObjectMeta.Initializers.Pending[i+1:]...)
found = true
break
}
}
if !found {
t.Fatalf("Expected cr.bar.com as initializer on Foo instance")
}
if len(foo.ObjectMeta.Initializers.Pending) == 0 && foo.ObjectMeta.Initializers.Result == nil {
foo.ObjectMeta.Initializers = nil
}
bs, err = json.Marshal(&foo)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
fooUnstructured.UnmarshalJSON(bs)
_, err = barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Update(fooUnstructured)
if err != nil && !errors.IsConflict(err) {
t.Fatalf("Failed to update Foo instance: %v", err)
} else if err == nil {
success = true
break
}
}
if !success {
t.Fatalf("Failed to remove initializer from Foo object")
}
t.Logf("Checking that Foo instance is visible after removing the initializer")
if _, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Get(foo.ObjectMeta.Name, metav1.GetOptions{}); err != nil {
t.Errorf("Unexpected error: %v", err)
}
}
type Foo struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
}
func unstructuredFoo(foo *Foo) (*unstructured.Unstructured, error) {
bs, err := json.Marshal(foo)
if err != nil {
return nil, err
}
ret := &unstructured.Unstructured{}
if err = ret.UnmarshalJSON(bs); err != nil {
return nil, err
}
return ret, nil
}
func waitForEstablishedCRD(client apiextensionsclientset.Interface, name string) error {

View File

@ -79,6 +79,7 @@ func StartTestServer(t *testing.T) (result *restclient.Config, tearDownForCaller
s.Etcd.StorageConfig = *storageConfig
s.Etcd.DefaultStorageMediaType = "application/json"
s.Admission.PluginNames = strings.Split("Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds", ",")
s.APIEnablement.RuntimeConfig.Set("api/all=true")
t.Logf("Starting kube-apiserver...")
runErrCh := make(chan error, 1)