diff --git a/test/integration/auth/BUILD b/test/integration/auth/BUILD index ccd4ec402c4..897557a21a9 100644 --- a/test/integration/auth/BUILD +++ b/test/integration/auth/BUILD @@ -58,6 +58,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/group:go_default_library", diff --git a/test/integration/auth/node_test.go b/test/integration/auth/node_test.go index 32a699b12c4..1199ad9cbb1 100644 --- a/test/integration/auth/node_test.go +++ b/test/integration/auth/node_test.go @@ -20,8 +20,6 @@ import ( "fmt" "net/http" "net/http/httptest" - "path/filepath" - "runtime" "testing" "time" @@ -29,6 +27,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/authentication/request/bearertoken" "k8s.io/apiserver/pkg/authentication/token/tokenfile" "k8s.io/apiserver/pkg/authentication/user" @@ -149,125 +148,159 @@ func TestNodeAuthorizer(t *testing.T) { t.Fatal(err) } - getSecret := func(client clientset.Interface) error { - _, err := client.Core().Secrets("ns").Get("mysecret", metav1.GetOptions{}) - return err + getSecret := func(client clientset.Interface) func() error { + return func() error { + _, err := client.Core().Secrets("ns").Get("mysecret", metav1.GetOptions{}) + return err + } } - getPVSecret := func(client clientset.Interface) error { - _, err := client.Core().Secrets("ns").Get("mypvsecret", metav1.GetOptions{}) - return err + getPVSecret := func(client clientset.Interface) func() error { + return func() error { + _, err := client.Core().Secrets("ns").Get("mypvsecret", metav1.GetOptions{}) + return err + } } - getConfigMap := func(client clientset.Interface) error { - _, err := client.Core().ConfigMaps("ns").Get("myconfigmap", metav1.GetOptions{}) - return err + getConfigMap := func(client clientset.Interface) func() error { + return func() error { + _, err := client.Core().ConfigMaps("ns").Get("myconfigmap", metav1.GetOptions{}) + return err + } } - getPVC := func(client clientset.Interface) error { - _, err := client.Core().PersistentVolumeClaims("ns").Get("mypvc", metav1.GetOptions{}) - return err + getPVC := func(client clientset.Interface) func() error { + return func() error { + _, err := client.Core().PersistentVolumeClaims("ns").Get("mypvc", metav1.GetOptions{}) + return err + } } - getPV := func(client clientset.Interface) error { - _, err := client.Core().PersistentVolumes().Get("mypv", metav1.GetOptions{}) - return err + getPV := func(client clientset.Interface) func() error { + return func() error { + _, err := client.Core().PersistentVolumes().Get("mypv", metav1.GetOptions{}) + return err + } } - createNode2NormalPod := func(client clientset.Interface) error { - _, err := client.Core().Pods("ns").Create(&api.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "node2normalpod"}, - Spec: api.PodSpec{ - NodeName: "node2", - Containers: []api.Container{{Name: "image", Image: "busybox"}}, - Volumes: []api.Volume{ - {Name: "secret", VolumeSource: api.VolumeSource{Secret: &api.SecretVolumeSource{SecretName: "mysecret"}}}, - {Name: "cm", VolumeSource: api.VolumeSource{ConfigMap: &api.ConfigMapVolumeSource{LocalObjectReference: api.LocalObjectReference{Name: "myconfigmap"}}}}, - {Name: "pvc", VolumeSource: api.VolumeSource{PersistentVolumeClaim: &api.PersistentVolumeClaimVolumeSource{ClaimName: "mypvc"}}}, + createNode2NormalPod := func(client clientset.Interface) func() error { + return func() error { + _, err := client.Core().Pods("ns").Create(&api.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "node2normalpod"}, + Spec: api.PodSpec{ + NodeName: "node2", + Containers: []api.Container{{Name: "image", Image: "busybox"}}, + Volumes: []api.Volume{ + {Name: "secret", VolumeSource: api.VolumeSource{Secret: &api.SecretVolumeSource{SecretName: "mysecret"}}}, + {Name: "cm", VolumeSource: api.VolumeSource{ConfigMap: &api.ConfigMapVolumeSource{LocalObjectReference: api.LocalObjectReference{Name: "myconfigmap"}}}}, + {Name: "pvc", VolumeSource: api.VolumeSource{PersistentVolumeClaim: &api.PersistentVolumeClaimVolumeSource{ClaimName: "mypvc"}}}, + }, }, - }, - }) - return err + }) + return err + } } - updateNode2NormalPodStatus := func(client clientset.Interface) error { - startTime := metav1.NewTime(time.Now()) - _, err := client.Core().Pods("ns").UpdateStatus(&api.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "node2normalpod"}, - Status: api.PodStatus{StartTime: &startTime}, - }) - return err + updateNode2NormalPodStatus := func(client clientset.Interface) func() error { + return func() error { + startTime := metav1.NewTime(time.Now()) + _, err := client.Core().Pods("ns").UpdateStatus(&api.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "node2normalpod"}, + Status: api.PodStatus{StartTime: &startTime}, + }) + return err + } } - deleteNode2NormalPod := func(client clientset.Interface) error { - zero := int64(0) - return client.Core().Pods("ns").Delete("node2normalpod", &metav1.DeleteOptions{GracePeriodSeconds: &zero}) + deleteNode2NormalPod := func(client clientset.Interface) func() error { + return func() error { + zero := int64(0) + return client.Core().Pods("ns").Delete("node2normalpod", &metav1.DeleteOptions{GracePeriodSeconds: &zero}) + } } - createNode2MirrorPod := func(client clientset.Interface) error { - _, err := client.Core().Pods("ns").Create(&api.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node2mirrorpod", - Annotations: map[string]string{api.MirrorPodAnnotationKey: "true"}, - }, - Spec: api.PodSpec{ - NodeName: "node2", - Containers: []api.Container{{Name: "image", Image: "busybox"}}, - }, - }) - return err + createNode2MirrorPod := func(client clientset.Interface) func() error { + return func() error { + _, err := client.Core().Pods("ns").Create(&api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node2mirrorpod", + Annotations: map[string]string{api.MirrorPodAnnotationKey: "true"}, + }, + Spec: api.PodSpec{ + NodeName: "node2", + Containers: []api.Container{{Name: "image", Image: "busybox"}}, + }, + }) + return err + } } - deleteNode2MirrorPod := func(client clientset.Interface) error { - zero := int64(0) - return client.Core().Pods("ns").Delete("node2mirrorpod", &metav1.DeleteOptions{GracePeriodSeconds: &zero}) + deleteNode2MirrorPod := func(client clientset.Interface) func() error { + return func() error { + zero := int64(0) + return client.Core().Pods("ns").Delete("node2mirrorpod", &metav1.DeleteOptions{GracePeriodSeconds: &zero}) + } } - createNode2 := func(client clientset.Interface) error { - _, err := client.Core().Nodes().Create(&api.Node{ObjectMeta: metav1.ObjectMeta{Name: "node2"}}) - return err + createNode2 := func(client clientset.Interface) func() error { + return func() error { + _, err := client.Core().Nodes().Create(&api.Node{ObjectMeta: metav1.ObjectMeta{Name: "node2"}}) + return err + } } - updateNode2Status := func(client clientset.Interface) error { - _, err := client.Core().Nodes().UpdateStatus(&api.Node{ - ObjectMeta: metav1.ObjectMeta{Name: "node2"}, - Status: api.NodeStatus{}, - }) - return err + updateNode2Status := func(client clientset.Interface) func() error { + return func() error { + _, err := client.Core().Nodes().UpdateStatus(&api.Node{ + ObjectMeta: metav1.ObjectMeta{Name: "node2"}, + Status: api.NodeStatus{}, + }) + return err + } } - deleteNode2 := func(client clientset.Interface) error { - return client.Core().Nodes().Delete("node2", nil) + deleteNode2 := func(client clientset.Interface) func() error { + return func() error { + return client.Core().Nodes().Delete("node2", nil) + } } - createNode2NormalPodEviction := func(client clientset.Interface) error { - return client.Policy().Evictions("ns").Evict(&policy.Eviction{ - TypeMeta: metav1.TypeMeta{ - APIVersion: "policy/v1beta1", - Kind: "Eviction", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "node2normalpod", - Namespace: "ns", - }, - }) + createNode2NormalPodEviction := func(client clientset.Interface) func() error { + return func() error { + return client.Policy().Evictions("ns").Evict(&policy.Eviction{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "policy/v1beta1", + Kind: "Eviction", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "node2normalpod", + Namespace: "ns", + }, + }) + } } - createNode2MirrorPodEviction := func(client clientset.Interface) error { - return client.Policy().Evictions("ns").Evict(&policy.Eviction{ - TypeMeta: metav1.TypeMeta{ - APIVersion: "policy/v1beta1", - Kind: "Eviction", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "node2mirrorpod", - Namespace: "ns", - }, - }) + createNode2MirrorPodEviction := func(client clientset.Interface) func() error { + return func() error { + return client.Policy().Evictions("ns").Evict(&policy.Eviction{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "policy/v1beta1", + Kind: "Eviction", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "node2mirrorpod", + Namespace: "ns", + }, + }) + } } capacity := 50 - updatePVCCapacity := func(client clientset.Interface) error { - capacity++ - statusString := fmt.Sprintf("{\"status\": {\"capacity\": {\"storage\": \"%dG\"}}}", capacity) - patchBytes := []byte(statusString) - _, err := client.Core().PersistentVolumeClaims("ns").Patch("mypvc", types.StrategicMergePatchType, patchBytes, "status") - return err + updatePVCCapacity := func(client clientset.Interface) func() error { + return func() error { + capacity++ + statusString := fmt.Sprintf("{\"status\": {\"capacity\": {\"storage\": \"%dG\"}}}", capacity) + patchBytes := []byte(statusString) + _, err := client.Core().PersistentVolumeClaims("ns").Patch("mypvc", types.StrategicMergePatchType, patchBytes, "status") + return err + } } - updatePVCPhase := func(client clientset.Interface) error { - patchBytes := []byte(`{"status":{"phase": "Bound"}}`) - _, err := client.Core().PersistentVolumeClaims("ns").Patch("mypvc", types.StrategicMergePatchType, patchBytes, "status") - return err + updatePVCPhase := func(client clientset.Interface) func() error { + return func() error { + patchBytes := []byte(`{"status":{"phase": "Bound"}}`) + _, err := client.Core().PersistentVolumeClaims("ns").Patch("mypvc", types.StrategicMergePatchType, patchBytes, "status") + return err + } } nodeanonClient := clientsetForToken(tokenNodeUnknown, clientConfig) @@ -386,23 +419,37 @@ func TestNodeAuthorizer(t *testing.T) { expectForbidden(t, updatePVCPhase(node2Client)) } -func expectForbidden(t *testing.T, err error) { - if !errors.IsForbidden(err) { - _, file, line, _ := runtime.Caller(1) - t.Errorf("%s:%d: Expected forbidden error, got %v", filepath.Base(file), line, err) +// expect executes a function a set number of times until it either returns the +// expected error or executes too many times. It returns if the retries timed +// out and the last error returned by the method. +func expect(f func() error, wantErr func(error) bool) (timeout bool, lastErr error) { + err := wait.PollImmediate(time.Second, 30*time.Second, func() (bool, error) { + lastErr = f() + if wantErr(lastErr) { + return true, nil + } + return false, nil + }) + return err == nil, lastErr +} + +func expectForbidden(t *testing.T, f func() error) { + t.Helper() + if ok, err := expect(f, errors.IsForbidden); !ok { + t.Errorf("Expected forbidden error, got %v", err) } } -func expectNotFound(t *testing.T, err error) { - if !errors.IsNotFound(err) { - _, file, line, _ := runtime.Caller(1) - t.Errorf("%s:%d: Expected notfound error, got %v", filepath.Base(file), line, err) +func expectNotFound(t *testing.T, f func() error) { + t.Helper() + if ok, err := expect(f, errors.IsNotFound); !ok { + t.Errorf("Expected notfound error, got %v", err) } } -func expectAllowed(t *testing.T, err error) { - if err != nil { - _, file, line, _ := runtime.Caller(1) - t.Errorf("%s:%d: Expected no error, got %v", filepath.Base(file), line, err) +func expectAllowed(t *testing.T, f func() error) { + t.Helper() + if ok, err := expect(f, func(e error) bool { return e == nil }); !ok { + t.Errorf("Expected no error, got %v", err) } }