Plumb context to admission Admit/Validate
Kubernetes-commit: 61774cd7176cae0c0324d23ab20e6c6b3038153f
This commit is contained in:
parent
aab7154c4f
commit
0c706a033c
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package admission
|
package admission
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
auditinternal "k8s.io/apiserver/pkg/apis/audit"
|
auditinternal "k8s.io/apiserver/pkg/apis/audit"
|
||||||
|
|
@ -44,7 +45,7 @@ func WithAudit(i Interface, ae *auditinternal.Event) Interface {
|
||||||
return &auditHandler{i, ae}
|
return &auditHandler{i, ae}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler auditHandler) Admit(a Attributes, o ObjectInterfaces) error {
|
func (handler auditHandler) Admit(ctx context.Context, a Attributes, o ObjectInterfaces) error {
|
||||||
if !handler.Interface.Handles(a.GetOperation()) {
|
if !handler.Interface.Handles(a.GetOperation()) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -53,13 +54,13 @@ func (handler auditHandler) Admit(a Attributes, o ObjectInterfaces) error {
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
if mutator, ok := handler.Interface.(MutationInterface); ok {
|
if mutator, ok := handler.Interface.(MutationInterface); ok {
|
||||||
err = mutator.Admit(a, o)
|
err = mutator.Admit(ctx, a, o)
|
||||||
handler.logAnnotations(a)
|
handler.logAnnotations(a)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler auditHandler) Validate(a Attributes, o ObjectInterfaces) error {
|
func (handler auditHandler) Validate(ctx context.Context, a Attributes, o ObjectInterfaces) error {
|
||||||
if !handler.Interface.Handles(a.GetOperation()) {
|
if !handler.Interface.Handles(a.GetOperation()) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -68,7 +69,7 @@ func (handler auditHandler) Validate(a Attributes, o ObjectInterfaces) error {
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
if validator, ok := handler.Interface.(ValidationInterface); ok {
|
if validator, ok := handler.Interface.(ValidationInterface); ok {
|
||||||
err = validator.Validate(a, o)
|
err = validator.Validate(ctx, a, o)
|
||||||
handler.logAnnotations(a)
|
handler.logAnnotations(a)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package admission
|
package admission
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
|
@ -45,14 +46,14 @@ var _ Interface = &fakeHandler{}
|
||||||
var _ MutationInterface = &fakeHandler{}
|
var _ MutationInterface = &fakeHandler{}
|
||||||
var _ ValidationInterface = &fakeHandler{}
|
var _ ValidationInterface = &fakeHandler{}
|
||||||
|
|
||||||
func (h fakeHandler) Admit(a Attributes, o ObjectInterfaces) error {
|
func (h fakeHandler) Admit(ctx context.Context, a Attributes, o ObjectInterfaces) error {
|
||||||
for k, v := range h.admitAnnotations {
|
for k, v := range h.admitAnnotations {
|
||||||
a.AddAnnotation(k, v)
|
a.AddAnnotation(k, v)
|
||||||
}
|
}
|
||||||
return h.admit
|
return h.admit
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h fakeHandler) Validate(a Attributes, o ObjectInterfaces) error {
|
func (h fakeHandler) Validate(ctx context.Context, a Attributes, o ObjectInterfaces) error {
|
||||||
for k, v := range h.validateAnnotations {
|
for k, v := range h.validateAnnotations {
|
||||||
a.AddAnnotation(k, v)
|
a.AddAnnotation(k, v)
|
||||||
}
|
}
|
||||||
|
|
@ -149,13 +150,13 @@ func TestWithAudit(t *testing.T) {
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
auditMutator, ok := auditHandler.(MutationInterface)
|
auditMutator, ok := auditHandler.(MutationInterface)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
assert.Equal(t, mutator.Admit(a, nil), auditMutator.Admit(a, nil), tcName+": WithAudit decorator should not effect the return value")
|
assert.Equal(t, mutator.Admit(context.TODO(), a, nil), auditMutator.Admit(context.TODO(), a, nil), tcName+": WithAudit decorator should not effect the return value")
|
||||||
|
|
||||||
validator, ok := handler.(ValidationInterface)
|
validator, ok := handler.(ValidationInterface)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
auditValidator, ok := auditHandler.(ValidationInterface)
|
auditValidator, ok := auditHandler.(ValidationInterface)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
assert.Equal(t, validator.Validate(a, nil), auditValidator.Validate(a, nil), tcName+": WithAudit decorator should not effect the return value")
|
assert.Equal(t, validator.Validate(context.TODO(), a, nil), auditValidator.Validate(context.TODO(), a, nil), tcName+": WithAudit decorator should not effect the return value")
|
||||||
|
|
||||||
annotations := make(map[string]string, len(tc.admitAnnotations)+len(tc.validateAnnotations))
|
annotations := make(map[string]string, len(tc.admitAnnotations)+len(tc.validateAnnotations))
|
||||||
for k, v := range tc.admitAnnotations {
|
for k, v := range tc.admitAnnotations {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ limitations under the License.
|
||||||
|
|
||||||
package admission
|
package admission
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
// chainAdmissionHandler is an instance of admission.NamedHandler that performs admission control using
|
// chainAdmissionHandler is an instance of admission.NamedHandler that performs admission control using
|
||||||
// a chain of admission handlers
|
// a chain of admission handlers
|
||||||
type chainAdmissionHandler []Interface
|
type chainAdmissionHandler []Interface
|
||||||
|
|
@ -26,13 +28,13 @@ func NewChainHandler(handlers ...Interface) chainAdmissionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Admit performs an admission control check using a chain of handlers, and returns immediately on first error
|
// Admit performs an admission control check using a chain of handlers, and returns immediately on first error
|
||||||
func (admissionHandler chainAdmissionHandler) Admit(a Attributes, o ObjectInterfaces) error {
|
func (admissionHandler chainAdmissionHandler) Admit(ctx context.Context, a Attributes, o ObjectInterfaces) error {
|
||||||
for _, handler := range admissionHandler {
|
for _, handler := range admissionHandler {
|
||||||
if !handler.Handles(a.GetOperation()) {
|
if !handler.Handles(a.GetOperation()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if mutator, ok := handler.(MutationInterface); ok {
|
if mutator, ok := handler.(MutationInterface); ok {
|
||||||
err := mutator.Admit(a, o)
|
err := mutator.Admit(ctx, a, o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -42,13 +44,13 @@ func (admissionHandler chainAdmissionHandler) Admit(a Attributes, o ObjectInterf
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate performs an admission control check using a chain of handlers, and returns immediately on first error
|
// Validate performs an admission control check using a chain of handlers, and returns immediately on first error
|
||||||
func (admissionHandler chainAdmissionHandler) Validate(a Attributes, o ObjectInterfaces) error {
|
func (admissionHandler chainAdmissionHandler) Validate(ctx context.Context, a Attributes, o ObjectInterfaces) error {
|
||||||
for _, handler := range admissionHandler {
|
for _, handler := range admissionHandler {
|
||||||
if !handler.Handles(a.GetOperation()) {
|
if !handler.Handles(a.GetOperation()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if validator, ok := handler.(ValidationInterface); ok {
|
if validator, ok := handler.(ValidationInterface); ok {
|
||||||
err := validator.Validate(a, o)
|
err := validator.Validate(ctx, a, o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package admission
|
package admission
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
|
@ -32,7 +33,7 @@ type FakeHandler struct {
|
||||||
validate, validateCalled bool
|
validate, validateCalled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *FakeHandler) Admit(a Attributes, o ObjectInterfaces) (err error) {
|
func (h *FakeHandler) Admit(ctx context.Context, a Attributes, o ObjectInterfaces) (err error) {
|
||||||
h.admitCalled = true
|
h.admitCalled = true
|
||||||
if h.admit {
|
if h.admit {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -40,7 +41,7 @@ func (h *FakeHandler) Admit(a Attributes, o ObjectInterfaces) (err error) {
|
||||||
return fmt.Errorf("Don't admit")
|
return fmt.Errorf("Don't admit")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *FakeHandler) Validate(a Attributes, o ObjectInterfaces) (err error) {
|
func (h *FakeHandler) Validate(ctx context.Context, a Attributes, o ObjectInterfaces) (err error) {
|
||||||
h.validateCalled = true
|
h.validateCalled = true
|
||||||
if h.validate {
|
if h.validate {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -125,7 +126,7 @@ func TestAdmitAndValidate(t *testing.T) {
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Logf("testcase = %s", test.name)
|
t.Logf("testcase = %s", test.name)
|
||||||
// call admit and check that validate was not called at all
|
// call admit and check that validate was not called at all
|
||||||
err := test.chain.Admit(NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, test.options, false, nil), nil)
|
err := test.chain.Admit(context.TODO(), NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, test.options, false, nil), nil)
|
||||||
accepted := (err == nil)
|
accepted := (err == nil)
|
||||||
if accepted != test.accept {
|
if accepted != test.accept {
|
||||||
t.Errorf("unexpected result of admit call: %v", accepted)
|
t.Errorf("unexpected result of admit call: %v", accepted)
|
||||||
|
|
@ -146,7 +147,7 @@ func TestAdmitAndValidate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// call validate and check that admit was not called at all
|
// call validate and check that admit was not called at all
|
||||||
err = test.chain.Validate(NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, test.options, false, nil), nil)
|
err = test.chain.Validate(context.TODO(), NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, test.options, false, nil), nil)
|
||||||
accepted = (err == nil)
|
accepted = (err == nil)
|
||||||
if accepted != test.accept {
|
if accepted != test.accept {
|
||||||
t.Errorf("unexpected result of validate call: %v\n", accepted)
|
t.Errorf("unexpected result of validate call: %v\n", accepted)
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package initializer_test
|
package initializer_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -72,7 +73,7 @@ type WantExternalKubeInformerFactory struct {
|
||||||
func (self *WantExternalKubeInformerFactory) SetExternalKubeInformerFactory(sf informers.SharedInformerFactory) {
|
func (self *WantExternalKubeInformerFactory) SetExternalKubeInformerFactory(sf informers.SharedInformerFactory) {
|
||||||
self.sf = sf
|
self.sf = sf
|
||||||
}
|
}
|
||||||
func (self *WantExternalKubeInformerFactory) Admit(a admission.Attributes, o admission.ObjectInterfaces) error {
|
func (self *WantExternalKubeInformerFactory) Admit(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (self *WantExternalKubeInformerFactory) Handles(o admission.Operation) bool { return false }
|
func (self *WantExternalKubeInformerFactory) Handles(o admission.Operation) bool { return false }
|
||||||
|
|
@ -87,7 +88,7 @@ type WantExternalKubeClientSet struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WantExternalKubeClientSet) SetExternalKubeClientSet(cs kubernetes.Interface) { self.cs = cs }
|
func (self *WantExternalKubeClientSet) SetExternalKubeClientSet(cs kubernetes.Interface) { self.cs = cs }
|
||||||
func (self *WantExternalKubeClientSet) Admit(a admission.Attributes, o admission.ObjectInterfaces) error {
|
func (self *WantExternalKubeClientSet) Admit(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (self *WantExternalKubeClientSet) Handles(o admission.Operation) bool { return false }
|
func (self *WantExternalKubeClientSet) Handles(o admission.Operation) bool { return false }
|
||||||
|
|
@ -102,7 +103,7 @@ type WantAuthorizerAdmission struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WantAuthorizerAdmission) SetAuthorizer(a authorizer.Authorizer) { self.auth = a }
|
func (self *WantAuthorizerAdmission) SetAuthorizer(a authorizer.Authorizer) { self.auth = a }
|
||||||
func (self *WantAuthorizerAdmission) Admit(a admission.Attributes, o admission.ObjectInterfaces) error {
|
func (self *WantAuthorizerAdmission) Admit(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (self *WantAuthorizerAdmission) Handles(o admission.Operation) bool { return false }
|
func (self *WantAuthorizerAdmission) Handles(o admission.Operation) bool { return false }
|
||||||
|
|
@ -124,7 +125,7 @@ type clientCertWanter struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *clientCertWanter) SetClientCert(cert, key []byte) { s.gotCert, s.gotKey = cert, key }
|
func (s *clientCertWanter) SetClientCert(cert, key []byte) { s.gotCert, s.gotKey = cert, key }
|
||||||
func (s *clientCertWanter) Admit(a admission.Attributes, o admission.ObjectInterfaces) error {
|
func (s *clientCertWanter) Admit(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (s *clientCertWanter) Handles(o admission.Operation) bool { return false }
|
func (s *clientCertWanter) Handles(o admission.Operation) bool { return false }
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package admission
|
package admission
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
|
@ -120,8 +121,9 @@ type Interface interface {
|
||||||
type MutationInterface interface {
|
type MutationInterface interface {
|
||||||
Interface
|
Interface
|
||||||
|
|
||||||
// Admit makes an admission decision based on the request attributes
|
// Admit makes an admission decision based on the request attributes.
|
||||||
Admit(a Attributes, o ObjectInterfaces) (err error)
|
// Context is used only for timeout/deadline/cancellation and tracing information.
|
||||||
|
Admit(ctx context.Context, a Attributes, o ObjectInterfaces) (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidationInterface is an abstract, pluggable interface for Admission Control decisions.
|
// ValidationInterface is an abstract, pluggable interface for Admission Control decisions.
|
||||||
|
|
@ -129,7 +131,8 @@ type ValidationInterface interface {
|
||||||
Interface
|
Interface
|
||||||
|
|
||||||
// Validate makes an admission decision based on the request attributes. It is NOT allowed to mutate
|
// Validate makes an admission decision based on the request attributes. It is NOT allowed to mutate
|
||||||
Validate(a Attributes, o ObjectInterfaces) (err error)
|
// Context is used only for timeout/deadline/cancellation and tracing information.
|
||||||
|
Validate(ctx context.Context, a Attributes, o ObjectInterfaces) (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Operation is the type of resource operation being checked for admission control
|
// Operation is the type of resource operation being checked for admission control
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package metrics
|
package metrics
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -75,27 +76,27 @@ type pluginHandlerWithMetrics struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Admit performs a mutating admission control check and emit metrics.
|
// Admit performs a mutating admission control check and emit metrics.
|
||||||
func (p pluginHandlerWithMetrics) Admit(a admission.Attributes, o admission.ObjectInterfaces) error {
|
func (p pluginHandlerWithMetrics) Admit(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error {
|
||||||
mutatingHandler, ok := p.Interface.(admission.MutationInterface)
|
mutatingHandler, ok := p.Interface.(admission.MutationInterface)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
err := mutatingHandler.Admit(a, o)
|
err := mutatingHandler.Admit(ctx, a, o)
|
||||||
p.observer(time.Since(start), err != nil, a, stepAdmit, p.extraLabels...)
|
p.observer(time.Since(start), err != nil, a, stepAdmit, p.extraLabels...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate performs a non-mutating admission control check and emits metrics.
|
// Validate performs a non-mutating admission control check and emits metrics.
|
||||||
func (p pluginHandlerWithMetrics) Validate(a admission.Attributes, o admission.ObjectInterfaces) error {
|
func (p pluginHandlerWithMetrics) Validate(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error {
|
||||||
validatingHandler, ok := p.Interface.(admission.ValidationInterface)
|
validatingHandler, ok := p.Interface.(admission.ValidationInterface)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
err := validatingHandler.Validate(a, o)
|
err := validatingHandler.Validate(ctx, a, o)
|
||||||
p.observer(time.Since(start), err != nil, a, stepValidate, p.extraLabels...)
|
p.observer(time.Since(start), err != nil, a, stepValidate, p.extraLabels...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package metrics
|
package metrics
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -36,8 +37,8 @@ var (
|
||||||
func TestObserveAdmissionStep(t *testing.T) {
|
func TestObserveAdmissionStep(t *testing.T) {
|
||||||
Metrics.reset()
|
Metrics.reset()
|
||||||
handler := WithStepMetrics(&mutatingAndValidatingFakeHandler{admission.NewHandler(admission.Create), true, true})
|
handler := WithStepMetrics(&mutatingAndValidatingFakeHandler{admission.NewHandler(admission.Create), true, true})
|
||||||
handler.(admission.MutationInterface).Admit(attr, nil)
|
handler.(admission.MutationInterface).Admit(context.TODO(), attr, nil)
|
||||||
handler.(admission.ValidationInterface).Validate(attr, nil)
|
handler.(admission.ValidationInterface).Validate(context.TODO(), attr, nil)
|
||||||
wantLabels := map[string]string{
|
wantLabels := map[string]string{
|
||||||
"operation": string(admission.Create),
|
"operation": string(admission.Create),
|
||||||
"type": "admit",
|
"type": "admit",
|
||||||
|
|
@ -54,8 +55,8 @@ func TestObserveAdmissionStep(t *testing.T) {
|
||||||
func TestObserveAdmissionController(t *testing.T) {
|
func TestObserveAdmissionController(t *testing.T) {
|
||||||
Metrics.reset()
|
Metrics.reset()
|
||||||
handler := WithControllerMetrics(&mutatingAndValidatingFakeHandler{admission.NewHandler(admission.Create), true, true}, "a")
|
handler := WithControllerMetrics(&mutatingAndValidatingFakeHandler{admission.NewHandler(admission.Create), true, true}, "a")
|
||||||
handler.(admission.MutationInterface).Admit(attr, nil)
|
handler.(admission.MutationInterface).Admit(context.TODO(), attr, nil)
|
||||||
handler.(admission.ValidationInterface).Validate(attr, nil)
|
handler.(admission.ValidationInterface).Validate(context.TODO(), attr, nil)
|
||||||
wantLabels := map[string]string{
|
wantLabels := map[string]string{
|
||||||
"name": "a",
|
"name": "a",
|
||||||
"operation": string(admission.Create),
|
"operation": string(admission.Create),
|
||||||
|
|
@ -154,7 +155,7 @@ func TestWithMetrics(t *testing.T) {
|
||||||
h := WithMetrics(test.handler, Metrics.ObserveAdmissionController, test.name)
|
h := WithMetrics(test.handler, Metrics.ObserveAdmissionController, test.name)
|
||||||
|
|
||||||
// test mutation
|
// test mutation
|
||||||
err := h.(admission.MutationInterface).Admit(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, test.options, false, nil), nil)
|
err := h.(admission.MutationInterface).Admit(context.TODO(), admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, test.options, false, nil), nil)
|
||||||
if test.admit && err != nil {
|
if test.admit && err != nil {
|
||||||
t.Errorf("expected admit to succeed, but failed: %v", err)
|
t.Errorf("expected admit to succeed, but failed: %v", err)
|
||||||
continue
|
continue
|
||||||
|
|
@ -179,7 +180,7 @@ func TestWithMetrics(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// test validation
|
// test validation
|
||||||
err = h.(admission.ValidationInterface).Validate(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, test.options, false, nil), nil)
|
err = h.(admission.ValidationInterface).Validate(context.TODO(), admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, test.options, false, nil), nil)
|
||||||
if test.validate && err != nil {
|
if test.validate && err != nil {
|
||||||
t.Errorf("expected admit to succeed, but failed: %v", err)
|
t.Errorf("expected admit to succeed, but failed: %v", err)
|
||||||
continue
|
continue
|
||||||
|
|
@ -206,14 +207,14 @@ type mutatingAndValidatingFakeHandler struct {
|
||||||
validate bool
|
validate bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *mutatingAndValidatingFakeHandler) Admit(a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
func (h *mutatingAndValidatingFakeHandler) Admit(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
||||||
if h.admit {
|
if h.admit {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("don't admit")
|
return fmt.Errorf("don't admit")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *mutatingAndValidatingFakeHandler) Validate(a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
func (h *mutatingAndValidatingFakeHandler) Validate(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
||||||
if h.validate {
|
if h.validate {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +226,7 @@ type validatingFakeHandler struct {
|
||||||
validate bool
|
validate bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *validatingFakeHandler) Validate(a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
func (h *validatingFakeHandler) Validate(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
||||||
if h.validate {
|
if h.validate {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -237,7 +238,7 @@ type mutatingFakeHandler struct {
|
||||||
admit bool
|
admit bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *mutatingFakeHandler) Admit(a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
func (h *mutatingFakeHandler) Admit(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
||||||
if h.admit {
|
if h.admit {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,14 @@ limitations under the License.
|
||||||
package lifecycle
|
package lifecycle
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
|
@ -73,7 +74,7 @@ var _ = initializer.WantsExternalKubeInformerFactory(&Lifecycle{})
|
||||||
var _ = initializer.WantsExternalKubeClientSet(&Lifecycle{})
|
var _ = initializer.WantsExternalKubeClientSet(&Lifecycle{})
|
||||||
|
|
||||||
// Admit makes an admission decision based on the request attributes
|
// Admit makes an admission decision based on the request attributes
|
||||||
func (l *Lifecycle) Admit(a admission.Attributes, o admission.ObjectInterfaces) error {
|
func (l *Lifecycle) Admit(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error {
|
||||||
// prevent deletion of immortal namespaces
|
// prevent deletion of immortal namespaces
|
||||||
if a.GetOperation() == admission.Delete && a.GetKind().GroupKind() == v1.SchemeGroupVersion.WithKind("Namespace").GroupKind() && l.immortalNamespaces.Has(a.GetName()) {
|
if a.GetOperation() == admission.Delete && a.GetKind().GroupKind() == v1.SchemeGroupVersion.WithKind("Namespace").GroupKind() && l.immortalNamespaces.Has(a.GetName()) {
|
||||||
return errors.NewForbidden(a.GetResource().GroupResource(), a.GetName(), fmt.Errorf("this namespace may not be deleted"))
|
return errors.NewForbidden(a.GetResource().GroupResource(), a.GetName(), fmt.Errorf("this namespace may not be deleted"))
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package lifecycle
|
package lifecycle
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -104,7 +105,7 @@ func TestAccessReviewCheckOnMissingNamespace(t *testing.T) {
|
||||||
}
|
}
|
||||||
informerFactory.Start(wait.NeverStop)
|
informerFactory.Start(wait.NeverStop)
|
||||||
|
|
||||||
err = handler.Admit(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{Group: "authorization.k8s.io", Version: "v1", Kind: "LocalSubjectAccesReview"}, namespace, "", schema.GroupVersionResource{Group: "authorization.k8s.io", Version: "v1", Resource: "localsubjectaccessreviews"}, "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{Group: "authorization.k8s.io", Version: "v1", Kind: "LocalSubjectAccesReview"}, namespace, "", schema.GroupVersionResource{Group: "authorization.k8s.io", Version: "v1", Resource: "localsubjectaccessreviews"}, "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
@ -124,7 +125,7 @@ func TestAdmissionNamespaceDoesNotExist(t *testing.T) {
|
||||||
informerFactory.Start(wait.NeverStop)
|
informerFactory.Start(wait.NeverStop)
|
||||||
|
|
||||||
pod := newPod(namespace)
|
pod := newPod(namespace)
|
||||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
actions := ""
|
actions := ""
|
||||||
for _, action := range mockClient.Actions() {
|
for _, action := range mockClient.Actions() {
|
||||||
|
|
@ -134,19 +135,19 @@ func TestAdmissionNamespaceDoesNotExist(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify create operations in the namespace cause an error
|
// verify create operations in the namespace cause an error
|
||||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Expected error rejecting creates in a namespace when it is missing")
|
t.Errorf("Expected error rejecting creates in a namespace when it is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify update operations in the namespace cause an error
|
// verify update operations in the namespace cause an error
|
||||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Expected error rejecting updates in a namespace when it is missing")
|
t.Errorf("Expected error rejecting updates in a namespace when it is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify delete operations in the namespace can proceed
|
// verify delete operations in the namespace can proceed
|
||||||
err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error returned from admission handler: %v", err)
|
t.Errorf("Unexpected error returned from admission handler: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +167,7 @@ func TestAdmissionNamespaceActive(t *testing.T) {
|
||||||
informerFactory.Start(wait.NeverStop)
|
informerFactory.Start(wait.NeverStop)
|
||||||
|
|
||||||
pod := newPod(namespace)
|
pod := newPod(namespace)
|
||||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error returned from admission handler")
|
t.Errorf("unexpected error returned from admission handler")
|
||||||
}
|
}
|
||||||
|
|
@ -187,31 +188,31 @@ func TestAdmissionNamespaceTerminating(t *testing.T) {
|
||||||
|
|
||||||
pod := newPod(namespace)
|
pod := newPod(namespace)
|
||||||
// verify create operations in the namespace cause an error
|
// verify create operations in the namespace cause an error
|
||||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Expected error rejecting creates in a namespace when it is terminating")
|
t.Errorf("Expected error rejecting creates in a namespace when it is terminating")
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify update operations in the namespace can proceed
|
// verify update operations in the namespace can proceed
|
||||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error returned from admission handler: %v", err)
|
t.Errorf("Unexpected error returned from admission handler: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify delete operations in the namespace can proceed
|
// verify delete operations in the namespace can proceed
|
||||||
err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error returned from admission handler: %v", err)
|
t.Errorf("Unexpected error returned from admission handler: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify delete of namespace default can never proceed
|
// verify delete of namespace default can never proceed
|
||||||
err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Namespace").GroupKind().WithVersion("version"), "", metav1.NamespaceDefault, v1.Resource("namespaces").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Namespace").GroupKind().WithVersion("version"), "", metav1.NamespaceDefault, v1.Resource("namespaces").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Expected an error that this namespace can never be deleted")
|
t.Errorf("Expected an error that this namespace can never be deleted")
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify delete of namespace other than default can proceed
|
// verify delete of namespace other than default can proceed
|
||||||
err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Namespace").GroupKind().WithVersion("version"), "", "other", v1.Resource("namespaces").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Namespace").GroupKind().WithVersion("version"), "", "other", v1.Resource("namespaces").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Did not expect an error %v", err)
|
t.Errorf("Did not expect an error %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -238,7 +239,7 @@ func TestAdmissionNamespaceForceLiveLookup(t *testing.T) {
|
||||||
|
|
||||||
pod := newPod(namespace)
|
pod := newPod(namespace)
|
||||||
// verify create operations in the namespace is allowed
|
// verify create operations in the namespace is allowed
|
||||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error rejecting creates in an active namespace")
|
t.Errorf("Unexpected error rejecting creates in an active namespace")
|
||||||
}
|
}
|
||||||
|
|
@ -248,7 +249,7 @@ func TestAdmissionNamespaceForceLiveLookup(t *testing.T) {
|
||||||
getCalls = 0
|
getCalls = 0
|
||||||
|
|
||||||
// verify delete of namespace can proceed
|
// verify delete of namespace can proceed
|
||||||
err = handler.Admit(admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Namespace").GroupKind().WithVersion("version"), namespace, namespace, v1.Resource("namespaces").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(nil, nil, v1.SchemeGroupVersion.WithKind("Namespace").GroupKind().WithVersion("version"), namespace, namespace, v1.Resource("namespaces").WithVersion("version"), "", admission.Delete, &metav1.DeleteOptions{}, false, nil), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Expected namespace deletion to be allowed")
|
t.Errorf("Expected namespace deletion to be allowed")
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +262,7 @@ func TestAdmissionNamespaceForceLiveLookup(t *testing.T) {
|
||||||
phases[namespace] = v1.NamespaceTerminating
|
phases[namespace] = v1.NamespaceTerminating
|
||||||
|
|
||||||
// verify create operations in the namespace cause an error
|
// verify create operations in the namespace cause an error
|
||||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Expected error rejecting creates in a namespace right after deleting it")
|
t.Errorf("Expected error rejecting creates in a namespace right after deleting it")
|
||||||
}
|
}
|
||||||
|
|
@ -274,7 +275,7 @@ func TestAdmissionNamespaceForceLiveLookup(t *testing.T) {
|
||||||
fakeClock.Step(forceLiveLookupTTL)
|
fakeClock.Step(forceLiveLookupTTL)
|
||||||
|
|
||||||
// verify create operations in the namespace cause an error
|
// verify create operations in the namespace cause an error
|
||||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
err = handler.Admit(context.TODO(), admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Expected error rejecting creates in a namespace right after deleting it")
|
t.Errorf("Expected error rejecting creates in a namespace right after deleting it")
|
||||||
}
|
}
|
||||||
|
|
@ -287,7 +288,7 @@ func TestAdmissionNamespaceForceLiveLookup(t *testing.T) {
|
||||||
fakeClock.Step(time.Millisecond)
|
fakeClock.Step(time.Millisecond)
|
||||||
|
|
||||||
// verify create operations in the namespace don't force a live lookup after the timeout
|
// verify create operations in the namespace don't force a live lookup after the timeout
|
||||||
handler.Admit(admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
handler.Admit(context.TODO(), admission.NewAttributesRecord(&pod, nil, v1.SchemeGroupVersion.WithKind("Pod").GroupKind().WithVersion("version"), pod.Namespace, pod.Name, v1.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil), nil)
|
||||||
if getCalls != 0 {
|
if getCalls != 0 {
|
||||||
t.Errorf("Expected no live lookup of the namespace at t=forceLiveLookupTTL+1ms, got %d", getCalls)
|
t.Errorf("Expected no live lookup of the namespace at t=forceLiveLookupTTL+1ms, got %d", getCalls)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,7 @@ type attrWithResourceOverride struct {
|
||||||
func (a *attrWithResourceOverride) GetResource() schema.GroupVersionResource { return a.resource }
|
func (a *attrWithResourceOverride) GetResource() schema.GroupVersionResource { return a.resource }
|
||||||
|
|
||||||
// Dispatch is called by the downstream Validate or Admit methods.
|
// Dispatch is called by the downstream Validate or Admit methods.
|
||||||
func (a *Webhook) Dispatch(attr admission.Attributes, o admission.ObjectInterfaces) error {
|
func (a *Webhook) Dispatch(ctx context.Context, attr admission.Attributes, o admission.ObjectInterfaces) error {
|
||||||
if rules.IsWebhookConfigurationResource(attr) {
|
if rules.IsWebhookConfigurationResource(attr) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -219,8 +219,5 @@ func (a *Webhook) Dispatch(attr admission.Attributes, o admission.ObjectInterfac
|
||||||
return admission.NewForbidden(attr, fmt.Errorf("not yet ready to handle request"))
|
return admission.NewForbidden(attr, fmt.Errorf("not yet ready to handle request"))
|
||||||
}
|
}
|
||||||
hooks := a.hookSource.Webhooks()
|
hooks := a.hookSource.Webhooks()
|
||||||
// TODO: Figure out if adding one second timeout make sense here.
|
|
||||||
ctx := context.TODO()
|
|
||||||
|
|
||||||
return a.dispatcher.Dispatch(ctx, attr, o, hooks)
|
return a.dispatcher.Dispatch(ctx, attr, o, hooks)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package mutating
|
package mutating
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
|
|
@ -70,6 +71,6 @@ func (a *Plugin) ValidateInitialization() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Admit makes an admission decision based on the request attributes.
|
// Admit makes an admission decision based on the request attributes.
|
||||||
func (a *Plugin) Admit(attr admission.Attributes, o admission.ObjectInterfaces) error {
|
func (a *Plugin) Admit(ctx context.Context, attr admission.Attributes, o admission.ObjectInterfaces) error {
|
||||||
return a.Webhook.Dispatch(attr, o)
|
return a.Webhook.Dispatch(ctx, attr, o)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package mutating
|
package mutating
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
@ -80,7 +81,7 @@ func TestAdmit(t *testing.T) {
|
||||||
attr = webhooktesting.NewAttribute(ns, tt.AdditionalLabels, tt.IsDryRun)
|
attr = webhooktesting.NewAttribute(ns, tt.AdditionalLabels, tt.IsDryRun)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = wh.Admit(attr, objectInterfaces)
|
err = wh.Admit(context.TODO(), attr, objectInterfaces)
|
||||||
if tt.ExpectAllow != (err == nil) {
|
if tt.ExpectAllow != (err == nil) {
|
||||||
t.Errorf("expected allowed=%v, but got err=%v", tt.ExpectAllow, err)
|
t.Errorf("expected allowed=%v, but got err=%v", tt.ExpectAllow, err)
|
||||||
}
|
}
|
||||||
|
|
@ -163,7 +164,7 @@ func TestAdmitCachedClient(t *testing.T) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err = wh.Admit(webhooktesting.NewAttribute(ns, nil, false), objectInterfaces)
|
err = wh.Admit(context.TODO(), webhooktesting.NewAttribute(ns, nil, false), objectInterfaces)
|
||||||
if tt.ExpectAllow != (err == nil) {
|
if tt.ExpectAllow != (err == nil) {
|
||||||
t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err)
|
t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package validating
|
package validating
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
|
|
@ -61,6 +62,6 @@ func NewValidatingAdmissionWebhook(configFile io.Reader) (*Plugin, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate makes an admission decision based on the request attributes.
|
// Validate makes an admission decision based on the request attributes.
|
||||||
func (a *Plugin) Validate(attr admission.Attributes, o admission.ObjectInterfaces) error {
|
func (a *Plugin) Validate(ctx context.Context, attr admission.Attributes, o admission.ObjectInterfaces) error {
|
||||||
return a.Webhook.Dispatch(attr, o)
|
return a.Webhook.Dispatch(ctx, attr, o)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package validating
|
package validating
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -67,7 +68,7 @@ func TestValidate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
attr := webhooktesting.NewAttribute(ns, nil, tt.IsDryRun)
|
attr := webhooktesting.NewAttribute(ns, nil, tt.IsDryRun)
|
||||||
err = wh.Validate(attr, objectInterfaces)
|
err = wh.Validate(context.TODO(), attr, objectInterfaces)
|
||||||
if tt.ExpectAllow != (err == nil) {
|
if tt.ExpectAllow != (err == nil) {
|
||||||
t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err)
|
t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err)
|
||||||
}
|
}
|
||||||
|
|
@ -132,7 +133,7 @@ func TestValidateCachedClient(t *testing.T) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err = wh.Validate(webhooktesting.NewAttribute(ns, nil, false), objectInterfaces)
|
err = wh.Validate(context.TODO(), webhooktesting.NewAttribute(ns, nil, false), objectInterfaces)
|
||||||
if tt.ExpectAllow != (err == nil) {
|
if tt.ExpectAllow != (err == nil) {
|
||||||
t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err)
|
t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ limitations under the License.
|
||||||
|
|
||||||
package admission
|
package admission
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
// newReinvocationHandler creates a handler that wraps the provided admission chain and reinvokes it
|
// newReinvocationHandler creates a handler that wraps the provided admission chain and reinvokes it
|
||||||
// if needed according to re-invocation policy of the webhooks.
|
// if needed according to re-invocation policy of the webhooks.
|
||||||
func newReinvocationHandler(admissionChain Interface) Interface {
|
func newReinvocationHandler(admissionChain Interface) Interface {
|
||||||
|
|
@ -30,9 +32,9 @@ type reinvoker struct {
|
||||||
// admission chain if needed according to the reinvocation policy. Plugins are expected to check
|
// admission chain if needed according to the reinvocation policy. Plugins are expected to check
|
||||||
// the admission attributes' reinvocation context against their reinvocation policy to decide if
|
// the admission attributes' reinvocation context against their reinvocation policy to decide if
|
||||||
// they should re-run, and to update the reinvocation context if they perform any mutations.
|
// they should re-run, and to update the reinvocation context if they perform any mutations.
|
||||||
func (r *reinvoker) Admit(a Attributes, o ObjectInterfaces) error {
|
func (r *reinvoker) Admit(ctx context.Context, a Attributes, o ObjectInterfaces) error {
|
||||||
if mutator, ok := r.admissionChain.(MutationInterface); ok {
|
if mutator, ok := r.admissionChain.(MutationInterface); ok {
|
||||||
err := mutator.Admit(a, o)
|
err := mutator.Admit(ctx, a, o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -42,16 +44,16 @@ func (r *reinvoker) Admit(a Attributes, o ObjectInterfaces) error {
|
||||||
// Calling admit a second time will reinvoke all in-tree plugins
|
// Calling admit a second time will reinvoke all in-tree plugins
|
||||||
// as well as any webhook plugins that need to be reinvoked based on the
|
// as well as any webhook plugins that need to be reinvoked based on the
|
||||||
// reinvocation policy.
|
// reinvocation policy.
|
||||||
return mutator.Admit(a, o)
|
return mutator.Admit(ctx, a, o)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate performs an admission control check using the wrapped admission chain, and returns immediately on first error.
|
// Validate performs an admission control check using the wrapped admission chain, and returns immediately on first error.
|
||||||
func (r *reinvoker) Validate(a Attributes, o ObjectInterfaces) error {
|
func (r *reinvoker) Validate(ctx context.Context, a Attributes, o ObjectInterfaces) error {
|
||||||
if validator, ok := r.admissionChain.(ValidationInterface); ok {
|
if validator, ok := r.admissionChain.(ValidationInterface); ok {
|
||||||
return validator.Validate(a, o)
|
return validator.Validate(ctx, a, o)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package testing
|
package testing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
|
@ -40,11 +41,11 @@ type reinvoker struct {
|
||||||
|
|
||||||
// Admit reinvokes the admission handler and reports a test error if the admission handler performs
|
// Admit reinvokes the admission handler and reports a test error if the admission handler performs
|
||||||
// non-idempotent mutatations to the admission object.
|
// non-idempotent mutatations to the admission object.
|
||||||
func (r *reinvoker) Admit(a admission.Attributes, o admission.ObjectInterfaces) error {
|
func (r *reinvoker) Admit(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error {
|
||||||
r.t.Helper()
|
r.t.Helper()
|
||||||
outputs := []runtime.Object{}
|
outputs := []runtime.Object{}
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
err := r.admission.Admit(a, o)
|
err := r.admission.Admit(ctx, a, o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ import (
|
||||||
|
|
||||||
type alwaysMutatingDeny struct{}
|
type alwaysMutatingDeny struct{}
|
||||||
|
|
||||||
func (alwaysMutatingDeny) Admit(a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
func (alwaysMutatingDeny) Admit(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
||||||
return admission.NewForbidden(a, errors.New("Mutating admission control is denying all modifications"))
|
return admission.NewForbidden(a, errors.New("Mutating admission control is denying all modifications"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,7 +87,7 @@ func (alwaysMutatingDeny) Handles(operation admission.Operation) bool {
|
||||||
|
|
||||||
type alwaysValidatingDeny struct{}
|
type alwaysValidatingDeny struct{}
|
||||||
|
|
||||||
func (alwaysValidatingDeny) Validate(a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
func (alwaysValidatingDeny) Validate(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
||||||
return admission.NewForbidden(a, errors.New("Validating admission control is denying all modifications"))
|
return admission.NewForbidden(a, errors.New("Validating admission control is denying all modifications"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -448,7 +448,7 @@ func (storage *SimpleRESTStorage) Delete(ctx context.Context, id string, deleteV
|
||||||
if err := storage.errors["delete"]; err != nil {
|
if err := storage.errors["delete"]; err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
if err := deleteValidation(&storage.item); err != nil {
|
if err := deleteValidation(ctx, &storage.item); err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
var obj runtime.Object = &metav1.Status{Status: metav1.StatusSuccess}
|
var obj runtime.Object = &metav1.Status{Status: metav1.StatusSuccess}
|
||||||
|
|
@ -477,7 +477,7 @@ func (storage *SimpleRESTStorage) Create(ctx context.Context, obj runtime.Object
|
||||||
if storage.injectedFunction != nil {
|
if storage.injectedFunction != nil {
|
||||||
obj, err = storage.injectedFunction(obj)
|
obj, err = storage.injectedFunction(obj)
|
||||||
}
|
}
|
||||||
if err := createValidation(obj); err != nil {
|
if err := createValidation(ctx, obj); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return obj, err
|
return obj, err
|
||||||
|
|
@ -496,7 +496,7 @@ func (storage *SimpleRESTStorage) Update(ctx context.Context, name string, objIn
|
||||||
if storage.injectedFunction != nil {
|
if storage.injectedFunction != nil {
|
||||||
obj, err = storage.injectedFunction(obj)
|
obj, err = storage.injectedFunction(obj)
|
||||||
}
|
}
|
||||||
if err := updateValidation(&storage.item, obj); err != nil {
|
if err := updateValidation(ctx, &storage.item, obj); err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
return obj, false, err
|
return obj, false, err
|
||||||
|
|
@ -654,7 +654,7 @@ func (storage *NamedCreaterRESTStorage) Create(ctx context.Context, name string,
|
||||||
if storage.injectedFunction != nil {
|
if storage.injectedFunction != nil {
|
||||||
obj, err = storage.injectedFunction(obj)
|
obj, err = storage.injectedFunction(obj)
|
||||||
}
|
}
|
||||||
if err := createValidation(obj); err != nil {
|
if err := createValidation(ctx, obj); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return obj, err
|
return obj, err
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ func createHandler(r rest.NamedCreater, scope *RequestScope, admit admission.Int
|
||||||
userInfo, _ := request.UserFrom(ctx)
|
userInfo, _ := request.UserFrom(ctx)
|
||||||
admissionAttributes := admission.NewAttributesRecord(obj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, options, dryrun.IsDryRun(options.DryRun), userInfo)
|
admissionAttributes := admission.NewAttributesRecord(obj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, options, dryrun.IsDryRun(options.DryRun), userInfo)
|
||||||
if mutatingAdmission, ok := admit.(admission.MutationInterface); ok && mutatingAdmission.Handles(admission.Create) {
|
if mutatingAdmission, ok := admit.(admission.MutationInterface); ok && mutatingAdmission.Handles(admission.Create) {
|
||||||
err = mutatingAdmission.Admit(admissionAttributes, scope)
|
err = mutatingAdmission.Admit(ctx, admissionAttributes, scope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
scope.err(err, w, req)
|
scope.err(err, w, req)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -239,7 +239,7 @@ func PatchResource(r rest.Patcher, scope *RequestScope, admit admission.Interfac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type mutateObjectUpdateFunc func(obj, old runtime.Object) error
|
type mutateObjectUpdateFunc func(ctx context.Context, obj, old runtime.Object) error
|
||||||
|
|
||||||
// patcher breaks the process of patch application and retries into smaller
|
// patcher breaks the process of patch application and retries into smaller
|
||||||
// pieces of functionality.
|
// pieces of functionality.
|
||||||
|
|
@ -515,7 +515,7 @@ func (p *patcher) applyAdmission(ctx context.Context, patchedObject runtime.Obje
|
||||||
}
|
}
|
||||||
if p.admissionCheck != nil && p.admissionCheck.Handles(operation) {
|
if p.admissionCheck != nil && p.admissionCheck.Handles(operation) {
|
||||||
attributes := p.admissionAttributes(ctx, patchedObject, currentObject, operation, options)
|
attributes := p.admissionAttributes(ctx, patchedObject, currentObject, operation, options)
|
||||||
return patchedObject, p.admissionCheck.Admit(attributes, p.objectInterfaces)
|
return patchedObject, p.admissionCheck.Admit(ctx, attributes, p.objectInterfaces)
|
||||||
}
|
}
|
||||||
return patchedObject, nil
|
return patchedObject, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -163,14 +163,14 @@ func ConnectResource(connecter rest.Connecter, scope *RequestScope, admit admiss
|
||||||
userInfo, _ := request.UserFrom(ctx)
|
userInfo, _ := request.UserFrom(ctx)
|
||||||
// TODO: remove the mutating admission here as soon as we have ported all plugin that handle CONNECT
|
// TODO: remove the mutating admission here as soon as we have ported all plugin that handle CONNECT
|
||||||
if mutatingAdmission, ok := admit.(admission.MutationInterface); ok {
|
if mutatingAdmission, ok := admit.(admission.MutationInterface); ok {
|
||||||
err = mutatingAdmission.Admit(admission.NewAttributesRecord(opts, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, nil, false, userInfo), scope)
|
err = mutatingAdmission.Admit(ctx, admission.NewAttributesRecord(opts, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, nil, false, userInfo), scope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
scope.err(err, w, req)
|
scope.err(err, w, req)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if validatingAdmission, ok := admit.(admission.ValidationInterface); ok {
|
if validatingAdmission, ok := admit.(admission.ValidationInterface); ok {
|
||||||
err = validatingAdmission.Validate(admission.NewAttributesRecord(opts, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, nil, false, userInfo), scope)
|
err = validatingAdmission.Validate(ctx, admission.NewAttributesRecord(opts, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, nil, false, userInfo), scope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
scope.err(err, w, req)
|
scope.err(err, w, req)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -260,11 +260,11 @@ func (p *testPatcher) Update(ctx context.Context, name string, objInfo rest.Upda
|
||||||
}
|
}
|
||||||
|
|
||||||
if currentPod == nil {
|
if currentPod == nil {
|
||||||
if err := createValidation(currentPod); err != nil {
|
if err := createValidation(ctx, currentPod); err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := updateValidation(currentPod, inPod); err != nil {
|
if err := updateValidation(ctx, currentPod, inPod); err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -351,13 +351,13 @@ func (tc *patchTestCase) Run(t *testing.T) {
|
||||||
|
|
||||||
admissionMutation := tc.admissionMutation
|
admissionMutation := tc.admissionMutation
|
||||||
if admissionMutation == nil {
|
if admissionMutation == nil {
|
||||||
admissionMutation = func(updatedObject runtime.Object, currentObject runtime.Object) error {
|
admissionMutation = func(ctx context.Context, updatedObject runtime.Object, currentObject runtime.Object) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
admissionValidation := tc.admissionValidation
|
admissionValidation := tc.admissionValidation
|
||||||
if admissionValidation == nil {
|
if admissionValidation == nil {
|
||||||
admissionValidation = func(updatedObject runtime.Object, currentObject runtime.Object) error {
|
admissionValidation = func(ctx context.Context, updatedObject runtime.Object, currentObject runtime.Object) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -718,7 +718,7 @@ func TestPatchWithAdmissionRejection(t *testing.T) {
|
||||||
for _, test := range []Test{
|
for _, test := range []Test{
|
||||||
{
|
{
|
||||||
name: "TestPatchWithMutatingAdmissionRejection",
|
name: "TestPatchWithMutatingAdmissionRejection",
|
||||||
admissionMutation: func(updatedObject runtime.Object, currentObject runtime.Object) error {
|
admissionMutation: func(ctx context.Context, updatedObject runtime.Object, currentObject runtime.Object) error {
|
||||||
return errors.New("mutating admission failure")
|
return errors.New("mutating admission failure")
|
||||||
},
|
},
|
||||||
admissionValidation: rest.ValidateAllObjectUpdateFunc,
|
admissionValidation: rest.ValidateAllObjectUpdateFunc,
|
||||||
|
|
@ -727,17 +727,17 @@ func TestPatchWithAdmissionRejection(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "TestPatchWithValidatingAdmissionRejection",
|
name: "TestPatchWithValidatingAdmissionRejection",
|
||||||
admissionMutation: rest.ValidateAllObjectUpdateFunc,
|
admissionMutation: rest.ValidateAllObjectUpdateFunc,
|
||||||
admissionValidation: func(updatedObject runtime.Object, currentObject runtime.Object) error {
|
admissionValidation: func(ctx context.Context, updatedObject runtime.Object, currentObject runtime.Object) error {
|
||||||
return errors.New("validating admission failure")
|
return errors.New("validating admission failure")
|
||||||
},
|
},
|
||||||
expectedError: "validating admission failure",
|
expectedError: "validating admission failure",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "TestPatchWithBothAdmissionRejections",
|
name: "TestPatchWithBothAdmissionRejections",
|
||||||
admissionMutation: func(updatedObject runtime.Object, currentObject runtime.Object) error {
|
admissionMutation: func(ctx context.Context, updatedObject runtime.Object, currentObject runtime.Object) error {
|
||||||
return errors.New("mutating admission failure")
|
return errors.New("mutating admission failure")
|
||||||
},
|
},
|
||||||
admissionValidation: func(updatedObject runtime.Object, currentObject runtime.Object) error {
|
admissionValidation: func(ctx context.Context, updatedObject runtime.Object, currentObject runtime.Object) error {
|
||||||
return errors.New("validating admission failure")
|
return errors.New("validating admission failure")
|
||||||
},
|
},
|
||||||
expectedError: "mutating admission failure",
|
expectedError: "mutating admission failure",
|
||||||
|
|
@ -777,7 +777,7 @@ func TestPatchWithVersionConflictThenAdmissionFailure(t *testing.T) {
|
||||||
tc := &patchTestCase{
|
tc := &patchTestCase{
|
||||||
name: "TestPatchWithVersionConflictThenAdmissionFailure",
|
name: "TestPatchWithVersionConflictThenAdmissionFailure",
|
||||||
|
|
||||||
admissionMutation: func(updatedObject runtime.Object, currentObject runtime.Object) error {
|
admissionMutation: func(ctx context.Context, updatedObject runtime.Object, currentObject runtime.Object) error {
|
||||||
if seen {
|
if seen {
|
||||||
return errors.New("admission failure")
|
return errors.New("admission failure")
|
||||||
}
|
}
|
||||||
|
|
@ -951,8 +951,8 @@ func (f mutateObjectUpdateFunc) Handles(operation admission.Operation) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f mutateObjectUpdateFunc) Admit(a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
func (f mutateObjectUpdateFunc) Admit(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) (err error) {
|
||||||
return f(a.GetObject(), a.GetOldObject())
|
return f(ctx, a.GetObject(), a.GetOldObject())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransformDecodeErrorEnsuresBadRequestError(t *testing.T) {
|
func TestTransformDecodeErrorEnsuresBadRequestError(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -140,11 +140,11 @@ func UpdateResource(r rest.Updater, scope *RequestScope, admit admission.Interfa
|
||||||
return nil, fmt.Errorf("unexpected error when extracting UID from oldObj: %v", err.Error())
|
return nil, fmt.Errorf("unexpected error when extracting UID from oldObj: %v", err.Error())
|
||||||
} else if !isNotZeroObject {
|
} else if !isNotZeroObject {
|
||||||
if mutatingAdmission.Handles(admission.Create) {
|
if mutatingAdmission.Handles(admission.Create) {
|
||||||
return newObj, mutatingAdmission.Admit(admission.NewAttributesRecord(newObj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, updateToCreateOptions(options), dryrun.IsDryRun(options.DryRun), userInfo), scope)
|
return newObj, mutatingAdmission.Admit(ctx, admission.NewAttributesRecord(newObj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, updateToCreateOptions(options), dryrun.IsDryRun(options.DryRun), userInfo), scope)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if mutatingAdmission.Handles(admission.Update) {
|
if mutatingAdmission.Handles(admission.Update) {
|
||||||
return newObj, mutatingAdmission.Admit(admission.NewAttributesRecord(newObj, oldObj, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, options, dryrun.IsDryRun(options.DryRun), userInfo), scope)
|
return newObj, mutatingAdmission.Admit(ctx, admission.NewAttributesRecord(newObj, oldObj, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, options, dryrun.IsDryRun(options.DryRun), userInfo), scope)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newObj, nil
|
return newObj, nil
|
||||||
|
|
@ -205,7 +205,7 @@ func withAuthorization(validate rest.ValidateObjectFunc, a authorizer.Authorizer
|
||||||
var authorizerDecision authorizer.Decision
|
var authorizerDecision authorizer.Decision
|
||||||
var authorizerReason string
|
var authorizerReason string
|
||||||
var authorizerErr error
|
var authorizerErr error
|
||||||
return func(obj runtime.Object) error {
|
return func(ctx context.Context, obj runtime.Object) error {
|
||||||
if a == nil {
|
if a == nil {
|
||||||
return errors.NewInternalError(fmt.Errorf("no authorizer provided, unable to authorize a create on update"))
|
return errors.NewInternalError(fmt.Errorf("no authorizer provided, unable to authorize a create on update"))
|
||||||
}
|
}
|
||||||
|
|
@ -215,7 +215,7 @@ func withAuthorization(validate rest.ValidateObjectFunc, a authorizer.Authorizer
|
||||||
// an authorizer like RBAC could encounter evaluation errors and still allow the request, so authorizer decision is checked before error here.
|
// an authorizer like RBAC could encounter evaluation errors and still allow the request, so authorizer decision is checked before error here.
|
||||||
if authorizerDecision == authorizer.DecisionAllow {
|
if authorizerDecision == authorizer.DecisionAllow {
|
||||||
// Continue to validating admission
|
// Continue to validating admission
|
||||||
return validate(obj)
|
return validate(ctx, obj)
|
||||||
}
|
}
|
||||||
if authorizerErr != nil {
|
if authorizerErr != nil {
|
||||||
return errors.NewInternalError(authorizerErr)
|
return errors.NewInternalError(authorizerErr)
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ func (s *DryRunnableStorage) Delete(ctx context.Context, key string, out runtime
|
||||||
if err := preconditions.Check(key, out); err != nil {
|
if err := preconditions.Check(key, out); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return deleteValidation(out)
|
return deleteValidation(ctx, out)
|
||||||
}
|
}
|
||||||
return s.Storage.Delete(ctx, key, out, preconditions, deleteValidation)
|
return s.Storage.Delete(ctx, key, out, preconditions, deleteValidation)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -342,7 +342,7 @@ func (e *Store) Create(ctx context.Context, obj runtime.Object, createValidation
|
||||||
// at this point we have a fully formed object. It is time to call the validators that the apiserver
|
// at this point we have a fully formed object. It is time to call the validators that the apiserver
|
||||||
// handling chain wants to enforce.
|
// handling chain wants to enforce.
|
||||||
if createValidation != nil {
|
if createValidation != nil {
|
||||||
if err := createValidation(obj.DeepCopyObject()); err != nil {
|
if err := createValidation(ctx, obj.DeepCopyObject()); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -504,7 +504,7 @@ func (e *Store) Update(ctx context.Context, name string, objInfo rest.UpdatedObj
|
||||||
// at this point we have a fully formed object. It is time to call the validators that the apiserver
|
// at this point we have a fully formed object. It is time to call the validators that the apiserver
|
||||||
// handling chain wants to enforce.
|
// handling chain wants to enforce.
|
||||||
if createValidation != nil {
|
if createValidation != nil {
|
||||||
if err := createValidation(obj.DeepCopyObject()); err != nil {
|
if err := createValidation(ctx, obj.DeepCopyObject()); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -546,7 +546,7 @@ func (e *Store) Update(ctx context.Context, name string, objInfo rest.UpdatedObj
|
||||||
// at this point we have a fully formed object. It is time to call the validators that the apiserver
|
// at this point we have a fully formed object. It is time to call the validators that the apiserver
|
||||||
// handling chain wants to enforce.
|
// handling chain wants to enforce.
|
||||||
if updateValidation != nil {
|
if updateValidation != nil {
|
||||||
if err := updateValidation(obj.DeepCopyObject(), existing.DeepCopyObject()); err != nil {
|
if err := updateValidation(ctx, obj.DeepCopyObject(), existing.DeepCopyObject()); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -812,7 +812,7 @@ func (e *Store) updateForGracefulDeletionAndFinalizers(ctx context.Context, name
|
||||||
false, /* ignoreNotFound */
|
false, /* ignoreNotFound */
|
||||||
&preconditions,
|
&preconditions,
|
||||||
storage.SimpleUpdate(func(existing runtime.Object) (runtime.Object, error) {
|
storage.SimpleUpdate(func(existing runtime.Object) (runtime.Object, error) {
|
||||||
if err := deleteValidation(existing); err != nil {
|
if err := deleteValidation(ctx, existing); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
graceful, pendingGraceful, err := rest.BeforeDelete(e.DeleteStrategy, ctx, existing, options)
|
graceful, pendingGraceful, err := rest.BeforeDelete(e.DeleteStrategy, ctx, existing, options)
|
||||||
|
|
|
||||||
|
|
@ -1713,11 +1713,11 @@ func TestQualifiedResource(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func denyCreateValidation(obj runtime.Object) error {
|
func denyCreateValidation(ctx context.Context, obj runtime.Object) error {
|
||||||
return fmt.Errorf("admission denied")
|
return fmt.Errorf("admission denied")
|
||||||
}
|
}
|
||||||
|
|
||||||
func denyUpdateValidation(obj, old runtime.Object) error {
|
func denyUpdateValidation(ctx context.Context, obj, old runtime.Object) error {
|
||||||
return fmt.Errorf("admission denied")
|
return fmt.Errorf("admission denied")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1933,7 +1933,7 @@ func TestRetryDeleteValidation(t *testing.T) {
|
||||||
updated := make(chan struct{})
|
updated := make(chan struct{})
|
||||||
var readyOnce, updatedOnce sync.Once
|
var readyOnce, updatedOnce sync.Once
|
||||||
var called int
|
var called int
|
||||||
deleteValidation := func(runtime.Object) error {
|
deleteValidation := func(ctx context.Context, obj runtime.Object) error {
|
||||||
readyOnce.Do(func() {
|
readyOnce.Do(func() {
|
||||||
close(ready)
|
close(ready)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -160,9 +160,9 @@ type NamespaceScopedStrategy interface {
|
||||||
func AdmissionToValidateObjectFunc(admit admission.Interface, staticAttributes admission.Attributes, o admission.ObjectInterfaces) ValidateObjectFunc {
|
func AdmissionToValidateObjectFunc(admit admission.Interface, staticAttributes admission.Attributes, o admission.ObjectInterfaces) ValidateObjectFunc {
|
||||||
validatingAdmission, ok := admit.(admission.ValidationInterface)
|
validatingAdmission, ok := admit.(admission.ValidationInterface)
|
||||||
if !ok {
|
if !ok {
|
||||||
return func(obj runtime.Object) error { return nil }
|
return func(ctx context.Context, obj runtime.Object) error { return nil }
|
||||||
}
|
}
|
||||||
return func(obj runtime.Object) error {
|
return func(ctx context.Context, obj runtime.Object) error {
|
||||||
finalAttributes := admission.NewAttributesRecord(
|
finalAttributes := admission.NewAttributesRecord(
|
||||||
obj,
|
obj,
|
||||||
staticAttributes.GetOldObject(),
|
staticAttributes.GetOldObject(),
|
||||||
|
|
@ -179,6 +179,6 @@ func AdmissionToValidateObjectFunc(admit admission.Interface, staticAttributes a
|
||||||
if !validatingAdmission.Handles(finalAttributes.GetOperation()) {
|
if !validatingAdmission.Handles(finalAttributes.GetOperation()) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return validatingAdmission.Validate(finalAttributes, o)
|
return validatingAdmission.Validate(ctx, finalAttributes, o)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ func AdmissionToValidateObjectDeleteFunc(admit admission.Interface, staticAttrib
|
||||||
mutating := isMutatingAdmission && mutatingAdmission.Handles(staticAttributes.GetOperation())
|
mutating := isMutatingAdmission && mutatingAdmission.Handles(staticAttributes.GetOperation())
|
||||||
validating := isValidatingAdmission && validatingAdmission.Handles(staticAttributes.GetOperation())
|
validating := isValidatingAdmission && validatingAdmission.Handles(staticAttributes.GetOperation())
|
||||||
|
|
||||||
return func(old runtime.Object) error {
|
return func(ctx context.Context, old runtime.Object) error {
|
||||||
if !mutating && !validating {
|
if !mutating && !validating {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -169,12 +169,12 @@ func AdmissionToValidateObjectDeleteFunc(admit admission.Interface, staticAttrib
|
||||||
staticAttributes.GetUserInfo(),
|
staticAttributes.GetUserInfo(),
|
||||||
)
|
)
|
||||||
if mutating {
|
if mutating {
|
||||||
if err := mutatingAdmission.Admit(finalAttributes, objInterfaces); err != nil {
|
if err := mutatingAdmission.Admit(ctx, finalAttributes, objInterfaces); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if validating {
|
if validating {
|
||||||
if err := validatingAdmission.Validate(finalAttributes, objInterfaces); err != nil {
|
if err := validatingAdmission.Validate(ctx, finalAttributes, objInterfaces); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -210,20 +210,20 @@ type UpdatedObjectInfo interface {
|
||||||
// ValidateObjectFunc is a function to act on a given object. An error may be returned
|
// ValidateObjectFunc is a function to act on a given object. An error may be returned
|
||||||
// if the hook cannot be completed. An ObjectFunc may NOT transform the provided
|
// if the hook cannot be completed. An ObjectFunc may NOT transform the provided
|
||||||
// object.
|
// object.
|
||||||
type ValidateObjectFunc func(obj runtime.Object) error
|
type ValidateObjectFunc func(ctx context.Context, obj runtime.Object) error
|
||||||
|
|
||||||
// ValidateAllObjectFunc is a "admit everything" instance of ValidateObjectFunc.
|
// ValidateAllObjectFunc is a "admit everything" instance of ValidateObjectFunc.
|
||||||
func ValidateAllObjectFunc(obj runtime.Object) error {
|
func ValidateAllObjectFunc(ctx context.Context, obj runtime.Object) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateObjectUpdateFunc is a function to act on a given object and its predecessor.
|
// ValidateObjectUpdateFunc is a function to act on a given object and its predecessor.
|
||||||
// An error may be returned if the hook cannot be completed. An UpdateObjectFunc
|
// An error may be returned if the hook cannot be completed. An UpdateObjectFunc
|
||||||
// may NOT transform the provided object.
|
// may NOT transform the provided object.
|
||||||
type ValidateObjectUpdateFunc func(obj, old runtime.Object) error
|
type ValidateObjectUpdateFunc func(ctx context.Context, obj, old runtime.Object) error
|
||||||
|
|
||||||
// ValidateAllObjectUpdateFunc is a "admit everything" instance of ValidateObjectUpdateFunc.
|
// ValidateAllObjectUpdateFunc is a "admit everything" instance of ValidateObjectUpdateFunc.
|
||||||
func ValidateAllObjectUpdateFunc(obj, old runtime.Object) error {
|
func ValidateAllObjectUpdateFunc(ctx context.Context, obj, old runtime.Object) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -255,9 +255,9 @@ func (i *wrappedUpdatedObjectInfo) UpdatedObject(ctx context.Context, oldObj run
|
||||||
func AdmissionToValidateObjectUpdateFunc(admit admission.Interface, staticAttributes admission.Attributes, o admission.ObjectInterfaces) ValidateObjectUpdateFunc {
|
func AdmissionToValidateObjectUpdateFunc(admit admission.Interface, staticAttributes admission.Attributes, o admission.ObjectInterfaces) ValidateObjectUpdateFunc {
|
||||||
validatingAdmission, ok := admit.(admission.ValidationInterface)
|
validatingAdmission, ok := admit.(admission.ValidationInterface)
|
||||||
if !ok {
|
if !ok {
|
||||||
return func(obj, old runtime.Object) error { return nil }
|
return func(ctx context.Context, obj, old runtime.Object) error { return nil }
|
||||||
}
|
}
|
||||||
return func(obj, old runtime.Object) error {
|
return func(ctx context.Context, obj, old runtime.Object) error {
|
||||||
finalAttributes := admission.NewAttributesRecord(
|
finalAttributes := admission.NewAttributesRecord(
|
||||||
obj,
|
obj,
|
||||||
old,
|
old,
|
||||||
|
|
@ -274,6 +274,6 @@ func AdmissionToValidateObjectUpdateFunc(admit admission.Interface, staticAttrib
|
||||||
if !validatingAdmission.Handles(finalAttributes.GetOperation()) {
|
if !validatingAdmission.Handles(finalAttributes.GetOperation()) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return validatingAdmission.Validate(finalAttributes, o)
|
return validatingAdmission.Validate(ctx, finalAttributes, o)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,7 @@ func (s *store) conditionalDelete(ctx context.Context, key string, out runtime.O
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := validateDeletion(origState.obj); err != nil {
|
if err := validateDeletion(ctx, origState.obj); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
|
||||||
|
|
@ -95,10 +95,10 @@ type UpdateFunc func(input runtime.Object, res ResponseMeta) (output runtime.Obj
|
||||||
// ValidateObjectFunc is a function to act on a given object. An error may be returned
|
// ValidateObjectFunc is a function to act on a given object. An error may be returned
|
||||||
// if the hook cannot be completed. The function may NOT transform the provided
|
// if the hook cannot be completed. The function may NOT transform the provided
|
||||||
// object.
|
// object.
|
||||||
type ValidateObjectFunc func(obj runtime.Object) error
|
type ValidateObjectFunc func(ctx context.Context, obj runtime.Object) error
|
||||||
|
|
||||||
// ValidateAllObjectFunc is a "admit everything" instance of ValidateObjectFunc.
|
// ValidateAllObjectFunc is a "admit everything" instance of ValidateObjectFunc.
|
||||||
func ValidateAllObjectFunc(obj runtime.Object) error {
|
func ValidateAllObjectFunc(ctx context.Context, obj runtime.Object) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue