mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 04:06:03 +00:00
use existing validation code and decoding in fieldManager admission
This commit is contained in:
parent
da610d6667
commit
fc1841d72f
@ -21,7 +21,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/warning"
|
||||
)
|
||||
@ -65,7 +64,7 @@ func (admit *managedFieldsValidatingAdmissionController) Admit(ctx context.Conte
|
||||
return err
|
||||
}
|
||||
managedFieldsAfterAdmission := objectMeta.GetManagedFields()
|
||||
if err := validateManagedFields(managedFieldsAfterAdmission); err != nil {
|
||||
if err := ValidateManagedFields(managedFieldsAfterAdmission); err != nil {
|
||||
objectMeta.SetManagedFields(managedFieldsBeforeAdmission)
|
||||
warning.AddWarning(ctx, "",
|
||||
fmt.Sprintf(InvalidManagedFieldsAfterMutatingAdmissionWarningFormat,
|
||||
@ -82,21 +81,3 @@ func (admit *managedFieldsValidatingAdmissionController) Validate(ctx context.Co
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateManagedFields(managedFields []metav1.ManagedFieldsEntry) error {
|
||||
for i, managed := range managedFields {
|
||||
if len(managed.APIVersion) < 1 {
|
||||
return fmt.Errorf(".metadata.managedFields[%d]: missing apiVersion", i)
|
||||
}
|
||||
if len(managed.FieldsType) < 1 {
|
||||
return fmt.Errorf(".metadata.managedFields[%d]: missing fieldsType", i)
|
||||
}
|
||||
if len(managed.Manager) < 1 {
|
||||
return fmt.Errorf(".metadata.managedFields[%d]: missing manager", i)
|
||||
}
|
||||
if managed.FieldsV1 == nil {
|
||||
return fmt.Errorf(".metadata.managedFields[%d]: missing fieldsV1", i)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -0,0 +1,115 @@
|
||||
package fieldmanager_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
func TestAdmission(t *testing.T) {
|
||||
wrap := &mockAdmissionController{}
|
||||
ac := fieldmanager.NewManagedFieldsValidatingAdmissionController(wrap)
|
||||
|
||||
tests := []struct {
|
||||
beforeAdmission []metav1.ManagedFieldsEntry
|
||||
afterAdmission []metav1.ManagedFieldsEntry
|
||||
expected []metav1.ManagedFieldsEntry
|
||||
}{
|
||||
{
|
||||
beforeAdmission: []metav1.ManagedFieldsEntry{
|
||||
{
|
||||
Manager: "test",
|
||||
},
|
||||
},
|
||||
afterAdmission: []metav1.ManagedFieldsEntry{
|
||||
{
|
||||
Manager: "",
|
||||
},
|
||||
},
|
||||
expected: []metav1.ManagedFieldsEntry{
|
||||
{
|
||||
Manager: "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
beforeAdmission: []metav1.ManagedFieldsEntry{
|
||||
{
|
||||
APIVersion: "test",
|
||||
},
|
||||
},
|
||||
afterAdmission: []metav1.ManagedFieldsEntry{
|
||||
{
|
||||
APIVersion: "",
|
||||
},
|
||||
},
|
||||
expected: []metav1.ManagedFieldsEntry{
|
||||
{
|
||||
APIVersion: "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
beforeAdmission: []metav1.ManagedFieldsEntry{
|
||||
{
|
||||
FieldsType: "FieldsV1",
|
||||
},
|
||||
},
|
||||
afterAdmission: []metav1.ManagedFieldsEntry{
|
||||
{
|
||||
FieldsType: "test",
|
||||
},
|
||||
},
|
||||
expected: []metav1.ManagedFieldsEntry{
|
||||
{
|
||||
FieldsType: "FieldsV1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
obj := &unstructured.Unstructured{}
|
||||
obj.SetManagedFields(test.beforeAdmission)
|
||||
wrap.admit = replaceManagedFields(test.afterAdmission)
|
||||
|
||||
attrs := admission.NewAttributesRecord(obj, obj, api.Kind("ConfigMap").WithVersion("version"), "default", "", api.Resource("configmaps").WithVersion("version"), "", admission.Update, nil, false, nil)
|
||||
if err := ac.(admission.MutationInterface).Admit(context.TODO(), attrs, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(obj.GetManagedFields(), test.expected) {
|
||||
t.Fatalf("expected: \n%v\ngot:\n%v", test.expected, obj.GetManagedFields())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func replaceManagedFields(with []metav1.ManagedFieldsEntry) func(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error {
|
||||
return func(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error {
|
||||
objectMeta, err := meta.Accessor(a.GetObject())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
objectMeta.SetManagedFields(with)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type mockAdmissionController struct {
|
||||
admit func(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error
|
||||
}
|
||||
|
||||
func (c *mockAdmissionController) Handles(operation admission.Operation) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *mockAdmissionController) Admit(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error {
|
||||
return c.admit(ctx, a, o)
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package fieldmanager
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
v1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
// ValidateManagedFields by checking the integrity of every entry and trying to decode
|
||||
// them to the internal format
|
||||
func ValidateManagedFields(managedFields []metav1.ManagedFieldsEntry) error {
|
||||
validationErrs := v1validation.ValidateManagedFields(managedFields, field.NewPath("metadata").Child("managedFields"))
|
||||
if len(validationErrs) > 0 {
|
||||
return validationErrs.ToAggregate()
|
||||
}
|
||||
|
||||
if _, err := DecodeManagedFields(managedFields); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user