mirror of https://github.com/grafana/grafana
K8s: Add validation support to builder (#95502)
parent
e0163c93c2
commit
5533b30135
@ -0,0 +1,43 @@ |
||||
package builder |
||||
|
||||
import ( |
||||
"context" |
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/schema" |
||||
"k8s.io/apiserver/pkg/admission" |
||||
) |
||||
|
||||
const PluginName = "GrafanaAdmission" |
||||
|
||||
type builderAdmission struct { |
||||
validators map[schema.GroupVersion]APIGroupValidation |
||||
} |
||||
|
||||
var _ admission.ValidationInterface = (*builderAdmission)(nil) |
||||
|
||||
func (b *builderAdmission) Validate(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) (err error) { |
||||
if v, ok := b.validators[a.GetResource().GroupVersion()]; ok { |
||||
return v.Validate(ctx, a, o) |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func (b *builderAdmission) Handles(operation admission.Operation) bool { |
||||
return true |
||||
} |
||||
|
||||
func NewAdmissionFromBuilders(builders []APIGroupBuilder) *builderAdmission { |
||||
validators := make(map[schema.GroupVersion]APIGroupValidation) |
||||
for _, builder := range builders { |
||||
if v, ok := builder.(APIGroupValidation); ok { |
||||
validators[builder.GetGroupVersion()] = v |
||||
} |
||||
} |
||||
return NewAdmission(validators) |
||||
} |
||||
|
||||
func NewAdmission(validators map[schema.GroupVersion]APIGroupValidation) *builderAdmission { |
||||
return &builderAdmission{ |
||||
validators: validators, |
||||
} |
||||
} |
@ -0,0 +1,85 @@ |
||||
package builder_test |
||||
|
||||
import ( |
||||
"context" |
||||
"errors" |
||||
"testing" |
||||
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/builder" |
||||
"github.com/stretchr/testify/require" |
||||
"k8s.io/apimachinery/pkg/runtime/schema" |
||||
"k8s.io/apiserver/pkg/admission" |
||||
) |
||||
|
||||
func TestBuilderAdmission_Validate(t *testing.T) { |
||||
gvk := schema.GroupVersionKind{ |
||||
Group: "testGroup", |
||||
Version: "v1", |
||||
Kind: "testKind", |
||||
} |
||||
gvr := gvk.GroupVersion().WithResource("testkinds") |
||||
defaultAttributes := admission.NewAttributesRecord(nil, nil, gvk, "", "", gvr, "", admission.Create, nil, false, nil) |
||||
tests := []struct { |
||||
name string |
||||
validators map[schema.GroupVersion]builder.APIGroupValidation |
||||
attributes admission.Attributes |
||||
wantErr bool |
||||
}{ |
||||
{ |
||||
name: "validator exists - forbidden", |
||||
validators: map[schema.GroupVersion]builder.APIGroupValidation{ |
||||
{Group: "testGroup", Version: "v1"}: &mockValidator{ |
||||
validateFunc: func(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error { |
||||
return admission.NewForbidden(a, errors.New("test error")) |
||||
}, |
||||
}, |
||||
}, |
||||
attributes: defaultAttributes, |
||||
wantErr: true, |
||||
}, |
||||
{ |
||||
name: "validator exists - allowed", |
||||
validators: map[schema.GroupVersion]builder.APIGroupValidation{ |
||||
{Group: "testGroup", Version: "v1"}: &mockValidator{ |
||||
validateFunc: func(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error { |
||||
return nil |
||||
}, |
||||
}, |
||||
}, |
||||
attributes: defaultAttributes, |
||||
wantErr: false, |
||||
}, |
||||
{ |
||||
name: "validator does not exist", |
||||
validators: map[schema.GroupVersion]builder.APIGroupValidation{ |
||||
{Group: "testGroup", Version: "v1"}: &mockValidator{ |
||||
validateFunc: func(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error { |
||||
return nil |
||||
}, |
||||
}, |
||||
}, |
||||
attributes: defaultAttributes, |
||||
wantErr: false, |
||||
}, |
||||
} |
||||
|
||||
for _, tt := range tests { |
||||
t.Run(tt.name, func(t *testing.T) { |
||||
b := builder.NewAdmission(tt.validators) |
||||
err := b.Validate(context.Background(), tt.attributes, nil) |
||||
if tt.wantErr { |
||||
require.Error(t, err) |
||||
} else { |
||||
require.NoError(t, err) |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
|
||||
type mockValidator struct { |
||||
validateFunc func(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error |
||||
} |
||||
|
||||
func (m *mockValidator) Validate(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error { |
||||
return m.validateFunc(ctx, a, o) |
||||
} |
Loading…
Reference in new issue