Minor cleanup to use t.Run() in test/integration

This commit is contained in:
Wojciech Tyczyński 2022-05-02 20:28:09 +02:00
parent f0791b5014
commit 04b77f02ee
5 changed files with 211 additions and 206 deletions

View File

@ -115,67 +115,68 @@ func TestBootstrapTokenAuth(t *testing.T) {
}, },
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
authenticator := group.NewAuthenticatedGroupAdder(bearertoken.New(bootstrap.NewTokenAuthenticator(bootstrapSecrets{test.secret})))
// Set up an API server
controlPlaneConfig := framework.NewIntegrationTestControlPlaneConfig()
controlPlaneConfig.GenericConfig.Authentication.Authenticator = authenticator
_, s, closeFn := framework.RunAnAPIServer(controlPlaneConfig)
defer closeFn()
authenticator := group.NewAuthenticatedGroupAdder(bearertoken.New(bootstrap.NewTokenAuthenticator(bootstrapSecrets{test.secret}))) ns := framework.CreateTestingNamespace("auth-bootstrap-token", s, t)
// Set up an API server defer framework.DeleteTestingNamespace(ns, s, t)
controlPlaneConfig := framework.NewIntegrationTestControlPlaneConfig()
controlPlaneConfig.GenericConfig.Authentication.Authenticator = authenticator
_, s, closeFn := framework.RunAnAPIServer(controlPlaneConfig)
defer closeFn()
ns := framework.CreateTestingNamespace("auth-bootstrap-token", s, t) previousResourceVersion := make(map[string]float64)
defer framework.DeleteTestingNamespace(ns, s, t) transport := http.DefaultTransport
previousResourceVersion := make(map[string]float64) token := validTokenID + "." + validSecret
transport := http.DefaultTransport var bodyStr string
if test.request.body != "" {
token := validTokenID + "." + validSecret sub := ""
var bodyStr string if test.request.verb == "PUT" {
if test.request.body != "" { // For update operations, insert previous resource version
sub := "" if resVersion := previousResourceVersion[getPreviousResourceVersionKey(test.request.URL, "")]; resVersion != 0 {
if test.request.verb == "PUT" { sub += fmt.Sprintf(",\r\n\"resourceVersion\": \"%v\"", resVersion)
// For update operations, insert previous resource version }
if resVersion := previousResourceVersion[getPreviousResourceVersionKey(test.request.URL, "")]; resVersion != 0 { sub += fmt.Sprintf(",\r\n\"namespace\": %q", ns.Name)
sub += fmt.Sprintf(",\r\n\"resourceVersion\": \"%v\"", resVersion)
} }
sub += fmt.Sprintf(",\r\n\"namespace\": %q", ns.Name) bodyStr = fmt.Sprintf(test.request.body, sub)
} }
bodyStr = fmt.Sprintf(test.request.body, sub) test.request.body = bodyStr
} bodyBytes := bytes.NewReader([]byte(bodyStr))
test.request.body = bodyStr req, err := http.NewRequest(test.request.verb, s.URL+test.request.URL, bodyBytes)
bodyBytes := bytes.NewReader([]byte(bodyStr))
req, err := http.NewRequest(test.request.verb, s.URL+test.request.URL, bodyBytes)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
if test.request.verb == "PATCH" {
req.Header.Set("Content-Type", "application/merge-patch+json")
}
func() {
resp, err := transport.RoundTrip(req)
if err != nil { if err != nil {
t.Logf("case %v", test.name)
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
defer resp.Body.Close() req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
b, _ := io.ReadAll(resp.Body) if test.request.verb == "PATCH" {
if _, ok := test.request.statusCodes[resp.StatusCode]; !ok { req.Header.Set("Content-Type", "application/merge-patch+json")
t.Logf("case %v", test.name)
t.Errorf("Expected status one of %v, but got %v", test.request.statusCodes, resp.StatusCode)
t.Errorf("Body: %v", string(b))
} else {
if test.request.verb == "POST" {
// For successful create operations, extract resourceVersion
id, currentResourceVersion, err := parseResourceVersion(b)
if err == nil {
key := getPreviousResourceVersionKey(test.request.URL, id)
previousResourceVersion[key] = currentResourceVersion
}
}
} }
}() func() {
resp, err := transport.RoundTrip(req)
if err != nil {
t.Logf("case %v", test.name)
t.Fatalf("unexpected error: %v", err)
}
defer resp.Body.Close()
b, _ := io.ReadAll(resp.Body)
if _, ok := test.request.statusCodes[resp.StatusCode]; !ok {
t.Logf("case %v", test.name)
t.Errorf("Expected status one of %v, but got %v", test.request.statusCodes, resp.StatusCode)
t.Errorf("Body: %v", string(b))
} else {
if test.request.verb == "POST" {
// For successful create operations, extract resourceVersion
id, currentResourceVersion, err := parseResourceVersion(b)
if err == nil {
key := getPreviousResourceVersionKey(test.request.URL, id)
previousResourceVersion[key] = currentResourceVersion
}
}
}
}()
})
} }
} }

View File

@ -518,124 +518,126 @@ func TestRBAC(t *testing.T) {
} }
for i, tc := range tests { for i, tc := range tests {
// Create an API Server. t.Run(fmt.Sprintf("case-%d", i), func(t *testing.T) {
controlPlaneConfig := framework.NewIntegrationTestControlPlaneConfig() // Create an API Server.
controlPlaneConfig.GenericConfig.Authorization.Authorizer = newRBACAuthorizer(t, controlPlaneConfig) controlPlaneConfig := framework.NewIntegrationTestControlPlaneConfig()
controlPlaneConfig.GenericConfig.Authentication.Authenticator = group.NewAuthenticatedGroupAdder(bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{ controlPlaneConfig.GenericConfig.Authorization.Authorizer = newRBACAuthorizer(t, controlPlaneConfig)
superUser: {Name: "admin", Groups: []string{"system:masters"}}, controlPlaneConfig.GenericConfig.Authentication.Authenticator = group.NewAuthenticatedGroupAdder(bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{
"any-rolebinding-writer": {Name: "any-rolebinding-writer"}, superUser: {Name: "admin", Groups: []string{"system:masters"}},
"any-rolebinding-writer-namespace": {Name: "any-rolebinding-writer-namespace"}, "any-rolebinding-writer": {Name: "any-rolebinding-writer"},
"bob": {Name: "bob"}, "any-rolebinding-writer-namespace": {Name: "any-rolebinding-writer-namespace"},
"job-writer": {Name: "job-writer"}, "bob": {Name: "bob"},
"job-writer-namespace": {Name: "job-writer-namespace"}, "job-writer": {Name: "job-writer"},
"nonescalating-rolebinding-writer": {Name: "nonescalating-rolebinding-writer"}, "job-writer-namespace": {Name: "job-writer-namespace"},
"pod-reader": {Name: "pod-reader"}, "nonescalating-rolebinding-writer": {Name: "nonescalating-rolebinding-writer"},
"limitrange-updater": {Name: "limitrange-updater"}, "pod-reader": {Name: "pod-reader"},
"limitrange-patcher": {Name: "limitrange-patcher"}, "limitrange-updater": {Name: "limitrange-updater"},
"user-with-no-permissions": {Name: "user-with-no-permissions"}, "limitrange-patcher": {Name: "limitrange-patcher"},
}))) "user-with-no-permissions": {Name: "user-with-no-permissions"},
controlPlaneConfig.GenericConfig.OpenAPIConfig = framework.DefaultOpenAPIConfig() })))
_, s, closeFn := framework.RunAnAPIServer(controlPlaneConfig) controlPlaneConfig.GenericConfig.OpenAPIConfig = framework.DefaultOpenAPIConfig()
defer closeFn() _, s, closeFn := framework.RunAnAPIServer(controlPlaneConfig)
defer closeFn()
clientConfig := &restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs}} clientConfig := &restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs}}
// Bootstrap the API Server with the test case's initial roles. // Bootstrap the API Server with the test case's initial roles.
superuserClient, _ := clientsetForToken(superUser, clientConfig) superuserClient, _ := clientsetForToken(superUser, clientConfig)
if err := tc.bootstrapRoles.bootstrap(superuserClient); err != nil { if err := tc.bootstrapRoles.bootstrap(superuserClient); err != nil {
t.Errorf("case %d: failed to apply initial roles: %v", i, err) t.Errorf("case %d: failed to apply initial roles: %v", i, err)
continue return
} }
previousResourceVersion := make(map[string]float64) previousResourceVersion := make(map[string]float64)
for j, r := range tc.requests { for j, r := range tc.requests {
path := "/" path := "/"
if r.apiGroup == "" { if r.apiGroup == "" {
path = gopath.Join(path, "api/v1") path = gopath.Join(path, "api/v1")
} else { } else {
path = gopath.Join(path, "apis", r.apiGroup, "v1") path = gopath.Join(path, "apis", r.apiGroup, "v1")
} }
if r.namespace != "" { if r.namespace != "" {
path = gopath.Join(path, "namespaces", r.namespace) path = gopath.Join(path, "namespaces", r.namespace)
} }
if r.resource != "" { if r.resource != "" {
path = gopath.Join(path, r.resource) path = gopath.Join(path, r.resource)
} }
if r.name != "" { if r.name != "" {
path = gopath.Join(path, r.name) path = gopath.Join(path, r.name)
} }
var body io.Reader var body io.Reader
if r.body != "" { if r.body != "" {
sub := "" sub := ""
if r.verb == "PUT" { if r.verb == "PUT" {
// For update operations, insert previous resource version // For update operations, insert previous resource version
if resVersion := previousResourceVersion[getPreviousResourceVersionKey(path, "")]; resVersion != 0 { if resVersion := previousResourceVersion[getPreviousResourceVersionKey(path, "")]; resVersion != 0 {
sub += fmt.Sprintf(",\"resourceVersion\": \"%v\"", resVersion) sub += fmt.Sprintf(",\"resourceVersion\": \"%v\"", resVersion)
}
} }
body = strings.NewReader(fmt.Sprintf(r.body, sub))
} }
body = strings.NewReader(fmt.Sprintf(r.body, sub))
}
req, err := http.NewRequest(r.verb, s.URL+path, body) req, err := http.NewRequest(r.verb, s.URL+path, body)
if r.verb == "PATCH" { if r.verb == "PATCH" {
// For patch operations, use the apply content type // For patch operations, use the apply content type
req.Header.Add("Content-Type", string(types.ApplyPatchType)) req.Header.Add("Content-Type", string(types.ApplyPatchType))
q := req.URL.Query() q := req.URL.Query()
q.Add("fieldManager", "rbac_test") q.Add("fieldManager", "rbac_test")
req.URL.RawQuery = q.Encode() req.URL.RawQuery = q.Encode()
} }
if err != nil {
t.Fatalf("failed to create request: %v", err)
}
func() {
reqDump, err := httputil.DumpRequest(req, true)
if err != nil { if err != nil {
t.Fatalf("failed to dump request: %v", err) t.Fatalf("failed to create request: %v", err)
return
} }
resp, err := clientForToken(r.token).Do(req) func() {
if err != nil { reqDump, err := httputil.DumpRequest(req, true)
t.Errorf("case %d, req %d: failed to make request: %v", i, j, err) if err != nil {
return t.Fatalf("failed to dump request: %v", err)
} return
defer resp.Body.Close()
respDump, err := httputil.DumpResponse(resp, true)
if err != nil {
t.Fatalf("failed to dump response: %v", err)
return
}
if resp.StatusCode != r.expectedStatus {
// When debugging is on, dump the entire request and response. Very helpful for
// debugging malformed test cases.
//
// To turn on debugging, use the '-args' flag.
//
// go test -v -tags integration -run RBAC -args -v 10
//
klog.V(8).Infof("case %d, req %d: %s\n%s\n", i, j, reqDump, respDump)
t.Errorf("case %d, req %d: %s expected %q got %q", i, j, r, statusCode(r.expectedStatus), statusCode(resp.StatusCode))
}
b, _ := io.ReadAll(resp.Body)
if r.verb == "POST" && (resp.StatusCode/100) == 2 {
// For successful create operations, extract resourceVersion
id, currentResourceVersion, err := parseResourceVersion(b)
if err == nil {
key := getPreviousResourceVersionKey(path, id)
previousResourceVersion[key] = currentResourceVersion
} else {
t.Logf("error in trying to extract resource version: %s", err)
} }
}
}() resp, err := clientForToken(r.token).Do(req)
} if err != nil {
t.Errorf("case %d, req %d: failed to make request: %v", i, j, err)
return
}
defer resp.Body.Close()
respDump, err := httputil.DumpResponse(resp, true)
if err != nil {
t.Fatalf("failed to dump response: %v", err)
return
}
if resp.StatusCode != r.expectedStatus {
// When debugging is on, dump the entire request and response. Very helpful for
// debugging malformed test cases.
//
// To turn on debugging, use the '-args' flag.
//
// go test -v -tags integration -run RBAC -args -v 10
//
klog.V(8).Infof("case %d, req %d: %s\n%s\n", i, j, reqDump, respDump)
t.Errorf("case %d, req %d: %s expected %q got %q", i, j, r, statusCode(r.expectedStatus), statusCode(resp.StatusCode))
}
b, _ := io.ReadAll(resp.Body)
if r.verb == "POST" && (resp.StatusCode/100) == 2 {
// For successful create operations, extract resourceVersion
id, currentResourceVersion, err := parseResourceVersion(b)
if err == nil {
key := getPreviousResourceVersionKey(path, id)
previousResourceVersion[key] = currentResourceVersion
} else {
t.Logf("error in trying to extract resource version: %s", err)
}
}
}()
}
})
} }
} }

View File

@ -422,7 +422,7 @@ func TestAdoption(t *testing.T) {
}, },
} }
for i, tc := range testCases { for i, tc := range testCases {
func() { t.Run(tc.name, func(t *testing.T) {
s, closeFn, rm, informers, clientSet := rmSetup(t) s, closeFn, rm, informers, clientSet := rmSetup(t)
defer closeFn() defer closeFn()
ns := framework.CreateTestingNamespace(fmt.Sprintf("rs-adoption-%d", i), s, t) ns := framework.CreateTestingNamespace(fmt.Sprintf("rs-adoption-%d", i), s, t)
@ -461,7 +461,7 @@ func TestAdoption(t *testing.T) {
}); err != nil { }); err != nil {
t.Fatalf("test %q failed: %v", tc.name, err) t.Fatalf("test %q failed: %v", tc.name, err)
} }
}() })
} }
} }

View File

@ -410,7 +410,7 @@ func TestAdoption(t *testing.T) {
}, },
} }
for i, tc := range testCases { for i, tc := range testCases {
func() { t.Run(tc.name, func(t *testing.T) {
s, closeFn, rm, informers, clientSet := rmSetup(t) s, closeFn, rm, informers, clientSet := rmSetup(t)
defer closeFn() defer closeFn()
ns := framework.CreateTestingNamespace(fmt.Sprintf("rc-adoption-%d", i), s, t) ns := framework.CreateTestingNamespace(fmt.Sprintf("rc-adoption-%d", i), s, t)
@ -449,7 +449,7 @@ func TestAdoption(t *testing.T) {
}); err != nil { }); err != nil {
t.Fatalf("test %q failed: %v", tc.name, err) t.Fatalf("test %q failed: %v", tc.name, err)
} }
}() })
} }
} }

View File

@ -262,53 +262,55 @@ func TestStatefulSetAvailable(t *testing.T) {
}, },
} }
for _, test := range tests { for _, test := range tests {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.StatefulSetMinReadySeconds, test.enabled)() t.Run(test.name, func(t *testing.T) {
s, closeFn, rm, informers, c := scSetup(t) defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.StatefulSetMinReadySeconds, test.enabled)()
defer closeFn() s, closeFn, rm, informers, c := scSetup(t)
ns := framework.CreateTestingNamespace("test-available-pods", s, t) defer closeFn()
defer framework.DeleteTestingNamespace(ns, s, t) ns := framework.CreateTestingNamespace("test-available-pods", s, t)
stopCh := runControllerAndInformers(rm, informers) defer framework.DeleteTestingNamespace(ns, s, t)
defer close(stopCh) stopCh := runControllerAndInformers(rm, informers)
defer close(stopCh)
labelMap := labelMap() labelMap := labelMap()
sts := newSTS("sts", ns.Name, 4) sts := newSTS("sts", ns.Name, 4)
sts.Spec.MinReadySeconds = int32(3600) sts.Spec.MinReadySeconds = int32(3600)
stss, _ := createSTSsPods(t, c, []*appsv1.StatefulSet{sts}, []*v1.Pod{}) stss, _ := createSTSsPods(t, c, []*appsv1.StatefulSet{sts}, []*v1.Pod{})
sts = stss[0] sts = stss[0]
waitSTSStable(t, c, sts) waitSTSStable(t, c, sts)
// Verify STS creates 4 pods // Verify STS creates 4 pods
podClient := c.CoreV1().Pods(ns.Name) podClient := c.CoreV1().Pods(ns.Name)
pods := getPods(t, podClient, labelMap) pods := getPods(t, podClient, labelMap)
if len(pods.Items) != 4 { if len(pods.Items) != 4 {
t.Fatalf("len(pods) = %d, want 4", len(pods.Items)) t.Fatalf("len(pods) = %d, want 4", len(pods.Items))
}
// Separate 3 pods into their own list
firstPodList := &v1.PodList{Items: pods.Items[:1]}
secondPodList := &v1.PodList{Items: pods.Items[1:2]}
thirdPodList := &v1.PodList{Items: pods.Items[2:]}
// First pod: Running, but not Ready
// by setting the Ready condition to false with LastTransitionTime to be now
setPodsReadyCondition(t, c, firstPodList, v1.ConditionFalse, time.Now())
// Second pod: Running and Ready, but not Available
// by setting LastTransitionTime to now
setPodsReadyCondition(t, c, secondPodList, v1.ConditionTrue, time.Now())
// Third pod: Running, Ready, and Available
// by setting LastTransitionTime to more than 3600 seconds ago
setPodsReadyCondition(t, c, thirdPodList, v1.ConditionTrue, time.Now().Add(-120*time.Minute))
stsClient := c.AppsV1().StatefulSets(ns.Name)
if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
newSts, err := stsClient.Get(context.TODO(), sts.Name, metav1.GetOptions{})
if err != nil {
return false, err
} }
// Verify 4 pods exist, 3 pods are Ready, and 2 pods are Available
return newSts.Status.Replicas == test.totalReplicas && newSts.Status.ReadyReplicas == test.readyReplicas && newSts.Status.AvailableReplicas == test.activeReplicas, nil // Separate 3 pods into their own list
}); err != nil { firstPodList := &v1.PodList{Items: pods.Items[:1]}
t.Fatalf("Failed to verify number of Replicas, ReadyReplicas and AvailableReplicas of rs %s to be as expected: %v", sts.Name, err) secondPodList := &v1.PodList{Items: pods.Items[1:2]}
} thirdPodList := &v1.PodList{Items: pods.Items[2:]}
// First pod: Running, but not Ready
// by setting the Ready condition to false with LastTransitionTime to be now
setPodsReadyCondition(t, c, firstPodList, v1.ConditionFalse, time.Now())
// Second pod: Running and Ready, but not Available
// by setting LastTransitionTime to now
setPodsReadyCondition(t, c, secondPodList, v1.ConditionTrue, time.Now())
// Third pod: Running, Ready, and Available
// by setting LastTransitionTime to more than 3600 seconds ago
setPodsReadyCondition(t, c, thirdPodList, v1.ConditionTrue, time.Now().Add(-120*time.Minute))
stsClient := c.AppsV1().StatefulSets(ns.Name)
if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
newSts, err := stsClient.Get(context.TODO(), sts.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
// Verify 4 pods exist, 3 pods are Ready, and 2 pods are Available
return newSts.Status.Replicas == test.totalReplicas && newSts.Status.ReadyReplicas == test.readyReplicas && newSts.Status.AvailableReplicas == test.activeReplicas, nil
}); err != nil {
t.Fatalf("Failed to verify number of Replicas, ReadyReplicas and AvailableReplicas of rs %s to be as expected: %v", sts.Name, err)
}
})
} }
} }