Merge pull request #133146 from liggitt/debug-flake
Add flake debugging for admission test Kubernetes-commit: 48f9786332eb99e4874df987abd804080286b9ea
This commit is contained in:
commit
26d1b81057
4
go.mod
4
go.mod
|
@ -48,9 +48,9 @@ require (
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0
|
gopkg.in/evanphx/json-patch.v4 v4.12.0
|
||||||
gopkg.in/go-jose/go-jose.v2 v2.6.3
|
gopkg.in/go-jose/go-jose.v2 v2.6.3
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||||
k8s.io/api v0.0.0-20250722204042-c68fbbed1649
|
k8s.io/api v0.0.0-20250724064529-b87ac725dbf9
|
||||||
k8s.io/apimachinery v0.0.0-20250723005633-58c4eb072ebf
|
k8s.io/apimachinery v0.0.0-20250723005633-58c4eb072ebf
|
||||||
k8s.io/client-go v0.0.0-20250723062849-06fcc8a0753e
|
k8s.io/client-go v0.0.0-20250724024901-5f1f878e5cd4
|
||||||
k8s.io/component-base v0.0.0-20250717172125-4e07767df717
|
k8s.io/component-base v0.0.0-20250717172125-4e07767df717
|
||||||
k8s.io/klog/v2 v2.130.1
|
k8s.io/klog/v2 v2.130.1
|
||||||
k8s.io/kms v0.0.0-20250716213631-bbefe5cb7a2e
|
k8s.io/kms v0.0.0-20250716213631-bbefe5cb7a2e
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -296,12 +296,12 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYs
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
k8s.io/api v0.0.0-20250722204042-c68fbbed1649 h1:HLNbFkZn1/O3wPdTUDOFXtPPQxM/h89c5whVWROHdX0=
|
k8s.io/api v0.0.0-20250724064529-b87ac725dbf9 h1:szZeh22FWBBbJjDCHrh8P35J6afaiuPOpaTsgaEyX4Q=
|
||||||
k8s.io/api v0.0.0-20250722204042-c68fbbed1649/go.mod h1:FvioxCEMxTNUCXlpYjmaOHhxfVFA8yAGncDC2nhYf7w=
|
k8s.io/api v0.0.0-20250724064529-b87ac725dbf9/go.mod h1:70o+sJgHYrO2nPMKeEsmpidpEUMobuxHMhjK/ud9+og=
|
||||||
k8s.io/apimachinery v0.0.0-20250723005633-58c4eb072ebf h1:R1l0xAevbhH2Bg0iJuabo8/i9m31D1ehh2ZJPFKh9bc=
|
k8s.io/apimachinery v0.0.0-20250723005633-58c4eb072ebf h1:R1l0xAevbhH2Bg0iJuabo8/i9m31D1ehh2ZJPFKh9bc=
|
||||||
k8s.io/apimachinery v0.0.0-20250723005633-58c4eb072ebf/go.mod h1:v1p1Jsze3IHLy5gU17yVqR2qLO7jgYeX6mw3HZy2AEU=
|
k8s.io/apimachinery v0.0.0-20250723005633-58c4eb072ebf/go.mod h1:v1p1Jsze3IHLy5gU17yVqR2qLO7jgYeX6mw3HZy2AEU=
|
||||||
k8s.io/client-go v0.0.0-20250723062849-06fcc8a0753e h1:lDD8O87D4jXxiua49rdGq2ZH5JBpM92y1OO7SXO81WA=
|
k8s.io/client-go v0.0.0-20250724024901-5f1f878e5cd4 h1:cUaPGCS7dfX5d85Q8ZJBD2rdK5C6tbWEtGFdBcH+bxo=
|
||||||
k8s.io/client-go v0.0.0-20250723062849-06fcc8a0753e/go.mod h1:o0hSfvIl7oJ/btIHtj8nT9SVN7Kmp4W0PEUfsPxLN3c=
|
k8s.io/client-go v0.0.0-20250724024901-5f1f878e5cd4/go.mod h1:kgDY5crqhNpktphA+cjWLcLLjrF5apg7TWTtaVyhUm8=
|
||||||
k8s.io/component-base v0.0.0-20250717172125-4e07767df717 h1:07oqkM0FzuGUw/bJw2rJubzccG7ShpGcTJ7SBDGp5Fc=
|
k8s.io/component-base v0.0.0-20250717172125-4e07767df717 h1:07oqkM0FzuGUw/bJw2rJubzccG7ShpGcTJ7SBDGp5Fc=
|
||||||
k8s.io/component-base v0.0.0-20250717172125-4e07767df717/go.mod h1:/ehREU84M2OxVgU8WfxuUIi4/c5XsT6rIsEGQfhgxEQ=
|
k8s.io/component-base v0.0.0-20250717172125-4e07767df717/go.mod h1:/ehREU84M2OxVgU8WfxuUIi4/c5XsT6rIsEGQfhgxEQ=
|
||||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||||
|
|
|
@ -49,6 +49,7 @@ func makeTestDispatcher(authorizer.Authorizer, *matching.Matcher, kubernetes.Int
|
||||||
|
|
||||||
func TestPolicySourceHasSyncedEmpty(t *testing.T) {
|
func TestPolicySourceHasSyncedEmpty(t *testing.T) {
|
||||||
testContext, testCancel, err := generic.NewPolicyTestContext(
|
testContext, testCancel, err := generic.NewPolicyTestContext(
|
||||||
|
t,
|
||||||
func(fp *FakePolicy) generic.PolicyAccessor { return fp },
|
func(fp *FakePolicy) generic.PolicyAccessor { return fp },
|
||||||
func(fb *FakeBinding) generic.BindingAccessor { return fb },
|
func(fb *FakeBinding) generic.BindingAccessor { return fb },
|
||||||
func(fp *FakePolicy) generic.Evaluator { return nil },
|
func(fp *FakePolicy) generic.Evaluator { return nil },
|
||||||
|
@ -81,6 +82,7 @@ func TestPolicySourceHasSyncedInitialList(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
testContext, testCancel, err := generic.NewPolicyTestContext(
|
testContext, testCancel, err := generic.NewPolicyTestContext(
|
||||||
|
t,
|
||||||
func(fp *FakePolicy) generic.PolicyAccessor { return fp },
|
func(fp *FakePolicy) generic.PolicyAccessor { return fp },
|
||||||
func(fb *FakeBinding) generic.BindingAccessor { return fb },
|
func(fb *FakeBinding) generic.BindingAccessor { return fb },
|
||||||
func(fp *FakePolicy) generic.Evaluator { return nil },
|
func(fp *FakePolicy) generic.Evaluator { return nil },
|
||||||
|
@ -150,6 +152,7 @@ func TestPolicySourceBindsToPolicies(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
testContext, testCancel, err := generic.NewPolicyTestContext(
|
testContext, testCancel, err := generic.NewPolicyTestContext(
|
||||||
|
t,
|
||||||
func(fp *FakePolicy) generic.PolicyAccessor { return fp },
|
func(fp *FakePolicy) generic.PolicyAccessor { return fp },
|
||||||
func(fb *FakeBinding) generic.BindingAccessor { return fb },
|
func(fb *FakeBinding) generic.BindingAccessor { return fb },
|
||||||
func(fp *FakePolicy) generic.Evaluator { return nil },
|
func(fp *FakePolicy) generic.Evaluator { return nil },
|
||||||
|
|
|
@ -47,9 +47,16 @@ import (
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Logger allows t.Testing and b.Testing to be passed to PolicyTestContext
|
||||||
|
type Logger interface {
|
||||||
|
Helper()
|
||||||
|
Logf(format string, args ...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
// PolicyTestContext is everything you need to unit test a policy plugin
|
// PolicyTestContext is everything you need to unit test a policy plugin
|
||||||
type PolicyTestContext[P runtime.Object, B runtime.Object, E Evaluator] struct {
|
type PolicyTestContext[P runtime.Object, B runtime.Object, E Evaluator] struct {
|
||||||
context.Context
|
context.Context
|
||||||
|
Logger Logger
|
||||||
Plugin *Plugin[PolicyHook[P, B, E]]
|
Plugin *Plugin[PolicyHook[P, B, E]]
|
||||||
Source Source[PolicyHook[P, B, E]]
|
Source Source[PolicyHook[P, B, E]]
|
||||||
Start func() error
|
Start func() error
|
||||||
|
@ -68,6 +75,7 @@ type PolicyTestContext[P runtime.Object, B runtime.Object, E Evaluator] struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPolicyTestContext[P, B runtime.Object, E Evaluator](
|
func NewPolicyTestContext[P, B runtime.Object, E Evaluator](
|
||||||
|
logger Logger,
|
||||||
newPolicyAccessor func(P) PolicyAccessor,
|
newPolicyAccessor func(P) PolicyAccessor,
|
||||||
newBindingAccessor func(B) BindingAccessor,
|
newBindingAccessor func(B) BindingAccessor,
|
||||||
compileFunc func(P) E,
|
compileFunc func(P) E,
|
||||||
|
@ -214,6 +222,7 @@ func NewPolicyTestContext[P, B runtime.Object, E Evaluator](
|
||||||
}
|
}
|
||||||
|
|
||||||
res := &PolicyTestContext[P, B, E]{
|
res := &PolicyTestContext[P, B, E]{
|
||||||
|
Logger: logger,
|
||||||
Context: testContext,
|
Context: testContext,
|
||||||
Plugin: plugin,
|
Plugin: plugin,
|
||||||
Source: source,
|
Source: source,
|
||||||
|
@ -279,7 +288,7 @@ func (p *PolicyTestContext[P, B, E]) update(wait bool, objects ...runtime.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
if wait {
|
if wait {
|
||||||
timeoutCtx, timeoutCancel := context.WithTimeout(p, 3*time.Second)
|
timeoutCtx, timeoutCancel := context.WithTimeout(p, 5*time.Second)
|
||||||
defer timeoutCancel()
|
defer timeoutCancel()
|
||||||
|
|
||||||
for _, object := range objects {
|
for _, object := range objects {
|
||||||
|
@ -383,12 +392,13 @@ func (p *PolicyTestContext[P, B, E]) WaitForReconcile(timeoutCtx context.Context
|
||||||
func (p *PolicyTestContext[P, B, E]) waitForDelete(ctx context.Context, objectGVK schema.GroupVersionKind, name types.NamespacedName) error {
|
func (p *PolicyTestContext[P, B, E]) waitForDelete(ctx context.Context, objectGVK schema.GroupVersionKind, name types.NamespacedName) error {
|
||||||
srce := p.Source.(*policySource[P, B, E])
|
srce := p.Source.(*policySource[P, B, E])
|
||||||
|
|
||||||
return wait.PollUntilContextCancel(ctx, 100*time.Millisecond, true, func(ctx context.Context) (done bool, err error) {
|
return wait.PollUntilContextCancel(ctx, 50*time.Millisecond, true, func(ctx context.Context) (done bool, err error) {
|
||||||
switch objectGVK {
|
switch objectGVK {
|
||||||
case p.policyGVK:
|
case p.policyGVK:
|
||||||
for _, hook := range p.Source.Hooks() {
|
for _, hook := range p.Source.Hooks() {
|
||||||
accessor := srce.newPolicyAccessor(hook.Policy)
|
accessor := srce.newPolicyAccessor(hook.Policy)
|
||||||
if accessor.GetName() == name.Name && accessor.GetNamespace() == name.Namespace {
|
if accessor.GetName() == name.Name && accessor.GetNamespace() == name.Namespace {
|
||||||
|
p.Logger.Logf("waiting for %s at %v", name.Name, time.Now())
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,6 +409,7 @@ func (p *PolicyTestContext[P, B, E]) waitForDelete(ctx context.Context, objectGV
|
||||||
for _, binding := range hook.Bindings {
|
for _, binding := range hook.Bindings {
|
||||||
accessor := srce.newBindingAccessor(binding)
|
accessor := srce.newBindingAccessor(binding)
|
||||||
if accessor.GetName() == name.Name && accessor.GetNamespace() == name.Namespace {
|
if accessor.GetName() == name.Name && accessor.GetNamespace() == name.Namespace {
|
||||||
|
p.Logger.Logf("waiting for %s at %v", name.Name, time.Now())
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -406,7 +417,7 @@ func (p *PolicyTestContext[P, B, E]) waitForDelete(ctx context.Context, objectGV
|
||||||
return true, nil
|
return true, nil
|
||||||
default:
|
default:
|
||||||
// Do nothing, params are visible immediately
|
// Do nothing, params are visible immediately
|
||||||
// Loop until one of the params is visible via get of the param informer
|
// Loop until the param is deleted from the param informer
|
||||||
informer, scope := p.Source.(*policySource[P, B, E]).getParamInformer(objectGVK)
|
informer, scope := p.Source.(*policySource[P, B, E]).getParamInformer(objectGVK)
|
||||||
if informer == nil {
|
if informer == nil {
|
||||||
return true, nil
|
return true, nil
|
||||||
|
@ -417,13 +428,15 @@ func (p *PolicyTestContext[P, B, E]) waitForDelete(ctx context.Context, objectGV
|
||||||
lister = informer.Lister().ByNamespace(name.Namespace)
|
lister = informer.Lister().ByNamespace(name.Namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = lister.Get(name.Name)
|
obj, err := lister.Get(name.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.IsNotFound(err) {
|
if errors.IsNotFound(err) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
p.Logger.Logf("error on %s: %v", name.Name, err)
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
p.Logger.Logf("waiting for %s to be gone at %v, got %#v", name.Name, time.Now(), obj)
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -482,9 +495,10 @@ func (p *PolicyTestContext[P, B, E]) DeleteAndWait(object ...runtime.Object) err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
timeoutCtx, timeoutCancel := context.WithTimeout(p, 3*time.Second)
|
timeoutCtx, timeoutCancel := context.WithTimeout(p, 5*time.Second)
|
||||||
defer timeoutCancel()
|
defer timeoutCancel()
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
for _, object := range object {
|
for _, object := range object {
|
||||||
accessor, err := meta.Accessor(object)
|
accessor, err := meta.Accessor(object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -502,6 +516,7 @@ func (p *PolicyTestContext[P, B, E]) DeleteAndWait(object ...runtime.Object) err
|
||||||
types.NamespacedName{Name: accessor.GetName(), Namespace: accessor.GetNamespace()}); err != nil {
|
types.NamespacedName{Name: accessor.GetName(), Namespace: accessor.GetNamespace()}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
p.Logger.Logf("after wait on %s: %v", accessor.GetName(), time.Since(start))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ func setupTest(
|
||||||
) *generic.PolicyTestContext[*mutating.Policy, *mutating.PolicyBinding, mutating.PolicyEvaluator] {
|
) *generic.PolicyTestContext[*mutating.Policy, *mutating.PolicyBinding, mutating.PolicyEvaluator] {
|
||||||
|
|
||||||
testContext, testCancel, err := generic.NewPolicyTestContext[*mutating.Policy, *mutating.PolicyBinding, mutating.PolicyEvaluator](
|
testContext, testCancel, err := generic.NewPolicyTestContext[*mutating.Policy, *mutating.PolicyBinding, mutating.PolicyEvaluator](
|
||||||
|
t,
|
||||||
mutating.NewMutatingAdmissionPolicyAccessor,
|
mutating.NewMutatingAdmissionPolicyAccessor,
|
||||||
mutating.NewMutatingAdmissionPolicyBindingAccessor,
|
mutating.NewMutatingAdmissionPolicyBindingAccessor,
|
||||||
compiler,
|
compiler,
|
||||||
|
|
|
@ -360,6 +360,7 @@ func setupTestCommon(
|
||||||
shouldStartInformers bool,
|
shouldStartInformers bool,
|
||||||
) *generic.PolicyTestContext[*validating.Policy, *validating.PolicyBinding, validating.Validator] {
|
) *generic.PolicyTestContext[*validating.Policy, *validating.PolicyBinding, validating.Validator] {
|
||||||
testContext, testContextCancel, err := generic.NewPolicyTestContext(
|
testContext, testContextCancel, err := generic.NewPolicyTestContext(
|
||||||
|
t,
|
||||||
validating.NewValidatingAdmissionPolicyAccessor,
|
validating.NewValidatingAdmissionPolicyAccessor,
|
||||||
validating.NewValidatingAdmissionPolicyBindingAccessor,
|
validating.NewValidatingAdmissionPolicyBindingAccessor,
|
||||||
func(p *validating.Policy) validating.Validator {
|
func(p *validating.Policy) validating.Validator {
|
||||||
|
|
Loading…
Reference in New Issue