mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-07-17 20:00:07 +00:00
scheduling/workload: fix tests requiring RequestInfo for declarative validation
- Update resttest and genericregistrytest to support RequestInfo injection. - Inject RequestInfo in Workload storage and strategy tests to resolve context-related failures. - Refine validate.go log messages and error deduplication logic.
This commit is contained in:
@@ -23,7 +23,9 @@ import (
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
||||
genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing"
|
||||
etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing"
|
||||
"k8s.io/kubernetes/pkg/apis/scheduling"
|
||||
@@ -66,11 +68,19 @@ func validNewWorkload() *scheduling.Workload {
|
||||
}
|
||||
}
|
||||
|
||||
func newTester(t *testing.T, storage *genericregistry.Store) *genericregistrytest.Tester {
|
||||
return genericregistrytest.New(t, storage).SetRequestInfo(&genericapirequest.RequestInfo{
|
||||
APIGroup: "scheduling.k8s.io",
|
||||
APIVersion: "v1alpha1",
|
||||
Resource: "workloads",
|
||||
})
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.Store.DestroyFunc()
|
||||
test := genericregistrytest.New(t, storage.Store)
|
||||
test := newTester(t, storage.Store)
|
||||
test.TestCreate(
|
||||
validNewWorkload(),
|
||||
// invalid cases
|
||||
@@ -86,7 +96,7 @@ func TestUpdate(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.Store.DestroyFunc()
|
||||
test := genericregistrytest.New(t, storage.Store)
|
||||
test := newTester(t, storage.Store)
|
||||
test.TestUpdate(
|
||||
// valid
|
||||
validNewWorkload(),
|
||||
@@ -114,7 +124,7 @@ func TestDelete(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.Store.DestroyFunc()
|
||||
test := genericregistrytest.New(t, storage.Store)
|
||||
test := newTester(t, storage.Store)
|
||||
test.TestDelete(validNewWorkload())
|
||||
}
|
||||
|
||||
@@ -122,7 +132,7 @@ func TestGet(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.Store.DestroyFunc()
|
||||
test := genericregistrytest.New(t, storage.Store)
|
||||
test := newTester(t, storage.Store)
|
||||
test.TestGet(validNewWorkload())
|
||||
}
|
||||
|
||||
@@ -130,7 +140,7 @@ func TestList(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.Store.DestroyFunc()
|
||||
test := genericregistrytest.New(t, storage.Store)
|
||||
test := newTester(t, storage.Store)
|
||||
test.TestList(validNewWorkload())
|
||||
}
|
||||
|
||||
@@ -138,7 +148,7 @@ func TestWatch(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.Store.DestroyFunc()
|
||||
test := genericregistrytest.New(t, storage.Store)
|
||||
test := newTester(t, storage.Store)
|
||||
test.TestWatch(
|
||||
validNewWorkload(),
|
||||
// matching labels
|
||||
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package workload
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -52,9 +53,18 @@ func TestWorkloadStrategy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func ctxWithRequestInfo() context.Context {
|
||||
return genericapirequest.WithRequestInfo(genericapirequest.NewDefaultContext(), &genericapirequest.RequestInfo{
|
||||
APIGroup: "scheduling.k8s.io",
|
||||
APIVersion: "v1alpha1",
|
||||
Resource: "workloads",
|
||||
IsResourceRequest: true,
|
||||
})
|
||||
}
|
||||
|
||||
func TestPodSchedulingStrategyCreate(t *testing.T) {
|
||||
t.Run("simple", func(t *testing.T) {
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
ctx := ctxWithRequestInfo()
|
||||
workload := workload.DeepCopy()
|
||||
|
||||
Strategy.PrepareForCreate(ctx, workload)
|
||||
@@ -65,7 +75,7 @@ func TestPodSchedulingStrategyCreate(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("failed validation", func(t *testing.T) {
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
ctx := ctxWithRequestInfo()
|
||||
workload := workload.DeepCopy()
|
||||
workload.Spec.PodGroups[0].Policy.Gang.MinCount = -1
|
||||
|
||||
@@ -79,7 +89,7 @@ func TestPodSchedulingStrategyCreate(t *testing.T) {
|
||||
|
||||
func TestPodSchedulingStrategyUpdate(t *testing.T) {
|
||||
t.Run("no changes", func(t *testing.T) {
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
ctx := ctxWithRequestInfo()
|
||||
workload := workload.DeepCopy()
|
||||
newWorkload := workload.DeepCopy()
|
||||
newWorkload.ResourceVersion = "4"
|
||||
@@ -92,7 +102,7 @@ func TestPodSchedulingStrategyUpdate(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("name update", func(t *testing.T) {
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
ctx := ctxWithRequestInfo()
|
||||
workload := workload.DeepCopy()
|
||||
newWorkload := workload.DeepCopy()
|
||||
newWorkload.Name += "bar"
|
||||
@@ -106,7 +116,7 @@ func TestPodSchedulingStrategyUpdate(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("spec update", func(t *testing.T) {
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
ctx := ctxWithRequestInfo()
|
||||
workload := workload.DeepCopy()
|
||||
newWorkload := workload.DeepCopy()
|
||||
newWorkload.Spec.ControllerRef = &scheduling.TypedLocalObjectReference{
|
||||
@@ -123,7 +133,7 @@ func TestPodSchedulingStrategyUpdate(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("invalid spec update", func(t *testing.T) {
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
ctx := ctxWithRequestInfo()
|
||||
workload := workload.DeepCopy()
|
||||
newWorkload := workload.DeepCopy()
|
||||
newWorkload.Spec.PodGroups[0].Policy.Gang.MinCount = 4
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
"k8s.io/apiserver/pkg/registry/rest/resttest"
|
||||
@@ -80,6 +81,11 @@ func (t *Tester) ReturnDeletedObject() *Tester {
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *Tester) SetRequestInfo(requestInfo *genericapirequest.RequestInfo) *Tester {
|
||||
t.tester.SetRequestInfo(requestInfo)
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *Tester) TestCreate(valid runtime.Object, invalid ...runtime.Object) {
|
||||
t.tester.TestCreate(
|
||||
valid,
|
||||
|
||||
@@ -53,6 +53,7 @@ type Tester struct {
|
||||
returnDeletedObject bool
|
||||
namer func(int) string
|
||||
userInfo user.Info
|
||||
requestInfo *genericapirequest.RequestInfo
|
||||
}
|
||||
|
||||
func New(t *testing.T, storage rest.Storage) *Tester {
|
||||
@@ -94,6 +95,12 @@ func (t *Tester) ReturnDeletedObject() *Tester {
|
||||
return t
|
||||
}
|
||||
|
||||
// SetRequestInfo sets the RequestInfo that should be present in the context when the
|
||||
// storage operation is called.
|
||||
func (t *Tester) SetRequestInfo(requestInfo *genericapirequest.RequestInfo) {
|
||||
t.requestInfo = requestInfo
|
||||
}
|
||||
|
||||
// TestNamespace returns the namespace that will be used when creating contexts.
|
||||
// Returns NamespaceNone for cluster-scoped objects.
|
||||
func (t *Tester) TestNamespace() string {
|
||||
@@ -117,6 +124,9 @@ func (t *Tester) TestContext() context.Context {
|
||||
if t.userInfo != nil {
|
||||
ctx = genericapirequest.WithUser(ctx, t.userInfo)
|
||||
}
|
||||
if t.requestInfo != nil {
|
||||
ctx = genericapirequest.WithRequestInfo(ctx, t.requestInfo)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
@@ -415,6 +425,9 @@ func (t *Tester) testCreateHasMetadata(valid runtime.Object) {
|
||||
func (t *Tester) testCreateIgnoresContextNamespace(valid runtime.Object, opts metav1.CreateOptions) {
|
||||
// Ignore non-empty namespace in context
|
||||
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), "not-default2")
|
||||
if t.requestInfo != nil {
|
||||
ctx = genericapirequest.WithRequestInfo(ctx, t.requestInfo)
|
||||
}
|
||||
|
||||
// Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted
|
||||
created, err := t.storage.(rest.Creater).Create(ctx, valid.DeepCopyObject(), rest.ValidateAllObjectFunc, &opts)
|
||||
@@ -434,6 +447,9 @@ func (t *Tester) testCreateIgnoresMismatchedNamespace(valid runtime.Object, opts
|
||||
// Ignore non-empty namespace in object meta
|
||||
objectMeta.SetNamespace("not-default")
|
||||
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), "not-default2")
|
||||
if t.requestInfo != nil {
|
||||
ctx = genericapirequest.WithRequestInfo(ctx, t.requestInfo)
|
||||
}
|
||||
|
||||
// Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted
|
||||
created, err := t.storage.(rest.Creater).Create(ctx, valid.DeepCopyObject(), rest.ValidateAllObjectFunc, &opts)
|
||||
@@ -1179,6 +1195,9 @@ func (t *Tester) testGetDifferentNamespace(obj runtime.Object) {
|
||||
objMeta.SetName(t.namer(5))
|
||||
|
||||
ctx1 := genericapirequest.WithNamespace(genericapirequest.NewContext(), "bar3")
|
||||
if t.requestInfo != nil {
|
||||
ctx1 = genericapirequest.WithRequestInfo(ctx1, t.requestInfo)
|
||||
}
|
||||
objMeta.SetNamespace(genericapirequest.NamespaceValue(ctx1))
|
||||
_, err := t.storage.(rest.Creater).Create(ctx1, obj, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
@@ -1186,6 +1205,9 @@ func (t *Tester) testGetDifferentNamespace(obj runtime.Object) {
|
||||
}
|
||||
|
||||
ctx2 := genericapirequest.WithNamespace(genericapirequest.NewContext(), "bar4")
|
||||
if t.requestInfo != nil {
|
||||
ctx2 = genericapirequest.WithRequestInfo(ctx2, t.requestInfo)
|
||||
}
|
||||
objMeta.SetNamespace(genericapirequest.NamespaceValue(ctx2))
|
||||
_, err = t.storage.(rest.Creater).Create(ctx2, obj, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
@@ -1240,7 +1262,13 @@ func (t *Tester) testGetFound(obj runtime.Object) {
|
||||
|
||||
func (t *Tester) testGetMimatchedNamespace(obj runtime.Object) {
|
||||
ctx1 := genericapirequest.WithNamespace(genericapirequest.NewContext(), "bar1")
|
||||
if t.requestInfo != nil {
|
||||
ctx1 = genericapirequest.WithRequestInfo(ctx1, t.requestInfo)
|
||||
}
|
||||
ctx2 := genericapirequest.WithNamespace(genericapirequest.NewContext(), "bar2")
|
||||
if t.requestInfo != nil {
|
||||
ctx2 = genericapirequest.WithRequestInfo(ctx2, t.requestInfo)
|
||||
}
|
||||
objMeta := t.getObjectMetaOrFail(obj)
|
||||
objMeta.SetName(t.namer(4))
|
||||
objMeta.SetNamespace(genericapirequest.NamespaceValue(ctx1))
|
||||
|
||||
Reference in New Issue
Block a user