mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
219 lines
6.0 KiB
Go
219 lines
6.0 KiB
Go
package plugin
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
admissionv1 "k8s.io/api/admission/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
|
|
"github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1"
|
|
"github.com/grafana/grafana/pkg/aggregator/apiserver/plugin/fakes"
|
|
)
|
|
|
|
func TestAdmissionMutation(t *testing.T) {
|
|
dps := v0alpha1.DataPlaneService{
|
|
Spec: v0alpha1.DataPlaneServiceSpec{
|
|
PluginID: "testds",
|
|
Group: "testds.example.com",
|
|
Version: "v1",
|
|
Services: []v0alpha1.Service{
|
|
{
|
|
Type: v0alpha1.AdmissionControlServiceType,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
pluginContext := backend.PluginContext{
|
|
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
|
|
ID: 1,
|
|
},
|
|
}
|
|
contextProvider := &fakes.FakePluginContextProvider{
|
|
PluginContext: pluginContext,
|
|
}
|
|
|
|
admissionReview := &admissionv1.AdmissionReview{
|
|
TypeMeta: metav1.TypeMeta{
|
|
Kind: "AdmissionReview",
|
|
APIVersion: admissionv1.SchemeGroupVersion.String(),
|
|
},
|
|
Request: &admissionv1.AdmissionRequest{
|
|
UID: "1234",
|
|
Operation: admissionv1.Update,
|
|
Kind: metav1.GroupVersionKind{
|
|
Group: "example.k8s.io",
|
|
Version: "v1",
|
|
Kind: "Pod",
|
|
},
|
|
Object: runtime.RawExtension{
|
|
Raw: []byte(`{"foo":"bar"}`),
|
|
},
|
|
OldObject: runtime.RawExtension{
|
|
Raw: []byte(`{"bar":"foo"}`),
|
|
},
|
|
},
|
|
}
|
|
|
|
pluginRes := &backend.MutationResponse{
|
|
Allowed: true,
|
|
ObjectBytes: []byte(`{"foo": "foo"}`),
|
|
}
|
|
|
|
jsonAdmissionReview, err := json.Marshal(admissionReview)
|
|
require.NoError(t, err)
|
|
|
|
pc := &fakes.FakePluginClient{
|
|
MutateAdmissionFunc: newFakeMutateAdmissionHandler(pluginRes, nil),
|
|
}
|
|
|
|
delegate := fakes.NewFakeHTTPHandler(http.StatusNotFound, []byte(`Not Found`))
|
|
handler := NewPluginHandler(pc, dps, contextProvider, delegate)
|
|
|
|
t.Run("should return mutation response", func(t *testing.T) {
|
|
req, err := http.NewRequest("POST", "/apis/testds.example.com/v1/admission/mutate", bytes.NewBuffer(jsonAdmissionReview))
|
|
assert.NoError(t, err)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
rr := httptest.NewRecorder()
|
|
handler.ServeHTTP(rr, req)
|
|
|
|
assert.Equal(t, http.StatusOK, rr.Code)
|
|
pt := admissionv1.PatchTypeJSONPatch
|
|
expectedRes := &admissionv1.AdmissionReview{
|
|
TypeMeta: metav1.TypeMeta{
|
|
Kind: "AdmissionReview",
|
|
APIVersion: admissionv1.SchemeGroupVersion.String(),
|
|
},
|
|
Response: &admissionv1.AdmissionResponse{
|
|
UID: admissionReview.Request.UID,
|
|
Allowed: true,
|
|
Patch: []byte(`[{"op":"replace","path":"/foo","value":"foo"}]`),
|
|
PatchType: &pt,
|
|
},
|
|
}
|
|
actualRes := &admissionv1.AdmissionReview{}
|
|
assert.NoError(t, json.NewDecoder(rr.Body).Decode(actualRes))
|
|
require.Equal(t, expectedRes, actualRes)
|
|
})
|
|
}
|
|
|
|
func TestAdmissionValidation(t *testing.T) {
|
|
dps := v0alpha1.DataPlaneService{
|
|
Spec: v0alpha1.DataPlaneServiceSpec{
|
|
PluginID: "testds",
|
|
Group: "testds.example.com",
|
|
Version: "v1",
|
|
Services: []v0alpha1.Service{
|
|
{
|
|
Type: v0alpha1.AdmissionControlServiceType,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
pluginContext := backend.PluginContext{
|
|
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
|
|
ID: 1,
|
|
},
|
|
}
|
|
contextProvider := &fakes.FakePluginContextProvider{
|
|
PluginContext: pluginContext,
|
|
}
|
|
|
|
admissionReview := &admissionv1.AdmissionReview{
|
|
TypeMeta: metav1.TypeMeta{
|
|
Kind: "AdmissionReview",
|
|
APIVersion: admissionv1.SchemeGroupVersion.String(),
|
|
},
|
|
Request: &admissionv1.AdmissionRequest{
|
|
UID: "1234",
|
|
Operation: admissionv1.Update,
|
|
Kind: metav1.GroupVersionKind{
|
|
Group: "example.k8s.io",
|
|
Version: "v1",
|
|
Kind: "Pod",
|
|
},
|
|
Object: runtime.RawExtension{
|
|
Raw: []byte(`{"foo":"bar"}`),
|
|
},
|
|
OldObject: runtime.RawExtension{
|
|
Raw: []byte(`{"bar":"foo"}`),
|
|
},
|
|
},
|
|
}
|
|
|
|
pluginRes := &backend.ValidationResponse{
|
|
Allowed: false,
|
|
Result: &backend.StatusResult{
|
|
Status: "Failure",
|
|
Message: "message",
|
|
Reason: "NotFound",
|
|
Code: 404,
|
|
},
|
|
Warnings: []string{"warning 1", "warning 2"},
|
|
}
|
|
|
|
jsonAdmissionReview, err := json.Marshal(admissionReview)
|
|
require.NoError(t, err)
|
|
|
|
pc := &fakes.FakePluginClient{
|
|
ValidateAdmissionFunc: newFakeValidateAdmissionHandler(pluginRes, nil),
|
|
}
|
|
|
|
delegate := fakes.NewFakeHTTPHandler(http.StatusNotFound, []byte(`Not Found`))
|
|
handler := NewPluginHandler(pc, dps, contextProvider, delegate)
|
|
|
|
t.Run("should return validation response", func(t *testing.T) {
|
|
req, err := http.NewRequest("POST", "/apis/testds.example.com/v1/admission/validate", bytes.NewBuffer(jsonAdmissionReview))
|
|
assert.NoError(t, err)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
rr := httptest.NewRecorder()
|
|
handler.ServeHTTP(rr, req)
|
|
|
|
assert.Equal(t, http.StatusOK, rr.Code)
|
|
expectedRes := &admissionv1.AdmissionReview{
|
|
TypeMeta: metav1.TypeMeta{
|
|
Kind: "AdmissionReview",
|
|
APIVersion: admissionv1.SchemeGroupVersion.String(),
|
|
},
|
|
Response: &admissionv1.AdmissionResponse{
|
|
UID: admissionReview.Request.UID,
|
|
Allowed: false,
|
|
Result: &metav1.Status{
|
|
Status: metav1.StatusFailure,
|
|
Message: "message",
|
|
Reason: metav1.StatusReasonNotFound,
|
|
Code: 404,
|
|
},
|
|
Warnings: pluginRes.Warnings,
|
|
},
|
|
}
|
|
actualRes := &admissionv1.AdmissionReview{}
|
|
assert.NoError(t, json.NewDecoder(rr.Body).Decode(actualRes))
|
|
require.Equal(t, expectedRes, actualRes)
|
|
})
|
|
}
|
|
|
|
func newFakeMutateAdmissionHandler(response *backend.MutationResponse, err error) backend.MutateAdmissionFunc {
|
|
return func(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
|
return response, err
|
|
}
|
|
}
|
|
|
|
func newFakeValidateAdmissionHandler(response *backend.ValidationResponse, err error) backend.ValidateAdmissionFunc {
|
|
return func(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
|
return response, err
|
|
}
|
|
}
|