From c28036efa5fcafdbd9d10014c9197bef42d05eaf Mon Sep 17 00:00:00 2001 From: yue9944882 <291271447@qq.com> Date: Mon, 21 Sep 2020 15:43:01 +0800 Subject: [PATCH] e2e cases for apf --- .../k8s.io/api/flowcontrol/v1alpha1/types.go | 6 + .../server/filters/priority-and-fairness.go | 9 +- test/e2e/apimachinery/BUILD | 2 + test/e2e/apimachinery/flowcontrol.go | 137 ++++++++++++++++++ 4 files changed, 147 insertions(+), 7 deletions(-) create mode 100644 test/e2e/apimachinery/flowcontrol.go diff --git a/staging/src/k8s.io/api/flowcontrol/v1alpha1/types.go b/staging/src/k8s.io/api/flowcontrol/v1alpha1/types.go index a67c6dd0275..b1bb5879614 100644 --- a/staging/src/k8s.io/api/flowcontrol/v1alpha1/types.go +++ b/staging/src/k8s.io/api/flowcontrol/v1alpha1/types.go @@ -51,6 +51,12 @@ const ( FlowSchemaMaxMatchingPrecedence int32 = 10000 ) +// Constants for apiserver response headers. +const ( + ResponseHeaderMatchedPriorityLevelConfigurationUID = "X-Kubernetes-PF-PriorityLevel-UID" + ResponseHeaderMatchedFlowSchemaUID = "X-Kubernetes-PF-FlowSchema-UID" +) + // +genclient // +genclient:nonNamespaced // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/staging/src/k8s.io/apiserver/pkg/server/filters/priority-and-fairness.go b/staging/src/k8s.io/apiserver/pkg/server/filters/priority-and-fairness.go index 7d1be83f14d..acf39454114 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/filters/priority-and-fairness.go +++ b/staging/src/k8s.io/apiserver/pkg/server/filters/priority-and-fairness.go @@ -35,11 +35,6 @@ type priorityAndFairnessKeyType int const priorityAndFairnessKey priorityAndFairnessKeyType = iota -const ( - responseHeaderMatchedPriorityLevelConfigurationUID = "X-Kubernetes-PF-PriorityLevel-UID" - responseHeaderMatchedFlowSchemaUID = "X-Kubernetes-PF-FlowSchema-UID" -) - // PriorityAndFairnessClassification identifies the results of // classification for API Priority and Fairness type PriorityAndFairnessClassification struct { @@ -131,8 +126,8 @@ func WithPriorityAndFairness( served = true innerCtx := context.WithValue(ctx, priorityAndFairnessKey, classification) innerReq := r.Clone(innerCtx) - w.Header().Set(responseHeaderMatchedPriorityLevelConfigurationUID, string(classification.PriorityLevelUID)) - w.Header().Set(responseHeaderMatchedFlowSchemaUID, string(classification.FlowSchemaUID)) + w.Header().Set(fcv1a1.ResponseHeaderMatchedPriorityLevelConfigurationUID, string(classification.PriorityLevelUID)) + w.Header().Set(fcv1a1.ResponseHeaderMatchedFlowSchemaUID, string(classification.FlowSchemaUID)) handler.ServeHTTP(w, innerReq) } digest := utilflowcontrol.RequestDigest{RequestInfo: requestInfo, User: user} diff --git a/test/e2e/apimachinery/BUILD b/test/e2e/apimachinery/BUILD index 31d7e02a218..b43da348371 100644 --- a/test/e2e/apimachinery/BUILD +++ b/test/e2e/apimachinery/BUILD @@ -18,6 +18,7 @@ go_library( "discovery.go", "etcd_failure.go", "events.go", + "flowcontrol.go", "framework.go", "garbage_collector.go", "generated_clientset.go", @@ -41,6 +42,7 @@ go_library( "//staging/src/k8s.io/api/batch/v1:go_default_library", "//staging/src/k8s.io/api/batch/v1beta1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", + "//staging/src/k8s.io/api/flowcontrol/v1alpha1:go_default_library", "//staging/src/k8s.io/api/rbac/v1:go_default_library", "//staging/src/k8s.io/api/scheduling/v1:go_default_library", "//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", diff --git a/test/e2e/apimachinery/flowcontrol.go b/test/e2e/apimachinery/flowcontrol.go new file mode 100644 index 00000000000..a0b9a7b2aa4 --- /dev/null +++ b/test/e2e/apimachinery/flowcontrol.go @@ -0,0 +1,137 @@ +/* +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. +*/ + +package apimachinery + +import ( + "context" + "net/http" + + "github.com/onsi/ginkgo" + "k8s.io/client-go/rest" + + flowcontrolv1alpha1 "k8s.io/api/flowcontrol/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/test/e2e/framework" +) + +var _ = SIGDescribe("[Feature:APIPriorityAndFairness] response header should present", func() { + f := framework.NewDefaultFramework("flowschemas") + + ginkgo.It("should ensure that requests can be classified by testing flow-schemas/priority-levels", func() { + testingFlowSchemaName := "e2e-testing-flowschema" + testingPriorityLevelName := "e2e-testing-prioritylevel" + matchingUsername := "noxu" + nonMatchingUsername := "foo" + + ginkgo.By("creating a testing prioritylevel") + createdPriorityLevel, err := f.ClientSet.FlowcontrolV1alpha1().PriorityLevelConfigurations().Create( + context.TODO(), + &flowcontrolv1alpha1.PriorityLevelConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: testingPriorityLevelName, + }, + Spec: flowcontrolv1alpha1.PriorityLevelConfigurationSpec{ + Type: flowcontrolv1alpha1.PriorityLevelEnablementLimited, + Limited: &flowcontrolv1alpha1.LimitedPriorityLevelConfiguration{ + AssuredConcurrencyShares: 1, // will have at minimum 1 concurrency share + LimitResponse: flowcontrolv1alpha1.LimitResponse{ + Type: flowcontrolv1alpha1.LimitResponseTypeReject, + }, + }, + }, + }, + metav1.CreateOptions{}) + framework.ExpectNoError(err) + + defer func() { + // clean-ups + err := f.ClientSet.FlowcontrolV1alpha1().PriorityLevelConfigurations().Delete(context.TODO(), testingPriorityLevelName, metav1.DeleteOptions{}) + framework.ExpectNoError(err) + err = f.ClientSet.FlowcontrolV1alpha1().FlowSchemas().Delete(context.TODO(), testingFlowSchemaName, metav1.DeleteOptions{}) + framework.ExpectNoError(err) + }() + + ginkgo.By("creating a testing flowschema") + createdFlowSchema, err := f.ClientSet.FlowcontrolV1alpha1().FlowSchemas().Create( + context.TODO(), + &flowcontrolv1alpha1.FlowSchema{ + ObjectMeta: metav1.ObjectMeta{ + Name: testingFlowSchemaName, + }, + Spec: flowcontrolv1alpha1.FlowSchemaSpec{ + MatchingPrecedence: 1000, // a rather higher precedence to ensure it make effect + PriorityLevelConfiguration: flowcontrolv1alpha1.PriorityLevelConfigurationReference{ + Name: testingPriorityLevelName, + }, + DistinguisherMethod: &flowcontrolv1alpha1.FlowDistinguisherMethod{ + Type: flowcontrolv1alpha1.FlowDistinguisherMethodByUserType, + }, + Rules: []flowcontrolv1alpha1.PolicyRulesWithSubjects{ + { + Subjects: []flowcontrolv1alpha1.Subject{ + { + Kind: flowcontrolv1alpha1.SubjectKindUser, + User: &flowcontrolv1alpha1.UserSubject{ + Name: matchingUsername, + }, + }, + }, + NonResourceRules: []flowcontrolv1alpha1.NonResourcePolicyRule{ + { + Verbs: []string{flowcontrolv1alpha1.VerbAll}, + NonResourceURLs: []string{flowcontrolv1alpha1.NonResourceAll}, + }, + }, + }, + }, + }, + }, + metav1.CreateOptions{}) + framework.ExpectNoError(err) + + ginkgo.By("response headers should contain flow-schema/priority-level uid") + + if !testResponseHeaderMatches(f, matchingUsername, string(createdPriorityLevel.UID), string(createdFlowSchema.UID)) { + framework.Failf("matching user doesnt received UID for the testing priority-level and flow-schema") + } + if testResponseHeaderMatches(f, nonMatchingUsername, string(createdPriorityLevel.UID), string(createdPriorityLevel.UID)) { + framework.Failf("non-matching user unexpectedly received UID for the testing priority-level and flow-schema") + } + }) + +}) + +func testResponseHeaderMatches(f *framework.Framework, impersonatingUser, plUID, fsUID string) bool { + config := rest.CopyConfig(f.ClientConfig()) + config.Impersonate.UserName = impersonatingUser + roundTripper, err := rest.TransportFor(config) + framework.ExpectNoError(err) + + req, err := http.NewRequest(http.MethodGet, f.ClientSet.CoreV1().RESTClient().Get().AbsPath("version").URL().String(), nil) + framework.ExpectNoError(err) + + response, err := roundTripper.RoundTrip(req) + framework.ExpectNoError(err) + + if response.Header.Get(flowcontrolv1alpha1.ResponseHeaderMatchedFlowSchemaUID) != fsUID { + return false + } + if response.Header.Get(flowcontrolv1alpha1.ResponseHeaderMatchedPriorityLevelConfigurationUID) != plUID { + return false + } + return true +}