mirror of
https://github.com/grafana/grafana.git
synced 2025-07-29 05:02:21 +08:00

* refactor: remove unused code in the function * test: add unit tests for admission handler * Revert "refactor: remove unused code in the function" This reverts commit b8f48dbdbff49a2860efe0257ba62378fc8227b2. * revert: added again due to incorrectly made test scenario * test: add unit tests for admission handler
248 lines
7.2 KiB
Go
248 lines
7.2 KiB
Go
package promlib
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"testing"
|
|
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
|
|
"github.com/grafana/grafana-plugin-sdk-go/genproto/pluginv2"
|
|
"github.com/stretchr/testify/assert"
|
|
"google.golang.org/protobuf/proto"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
)
|
|
|
|
func Test_ValidateAdmission(t *testing.T) {
|
|
t.Run("should return error when MutateAdmission fails and response is nil", func(t *testing.T) {
|
|
httpProvider := getMockProvider[*healthCheckSuccessRoundTripper]()
|
|
logger := backend.NewLoggerWith("logger", "test")
|
|
s := &Service{
|
|
im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, logger, mockExtendClientOpts)),
|
|
logger: logger,
|
|
}
|
|
|
|
req := &backend.AdmissionRequest{
|
|
Kind: backend.GroupVersionKind{
|
|
Group: "grafana-plugin-sdk-go",
|
|
Kind: "DataSourceInstanceSettings",
|
|
},
|
|
ObjectBytes: []byte(`{"foo":"bar"}`),
|
|
}
|
|
|
|
actual, err := s.ValidateAdmission(context.Background(), req)
|
|
assert.ErrorContains(t, err, "cannot parse invalid")
|
|
assert.Nil(t, actual)
|
|
})
|
|
|
|
t.Run("should return ValidationResponse when MutateAdmission succeeds", func(t *testing.T) {
|
|
httpProvider := getMockProvider[*healthCheckSuccessRoundTripper]()
|
|
logger := backend.NewLoggerWith("logger", "test")
|
|
s := &Service{
|
|
im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, logger, mockExtendClientOpts)),
|
|
logger: logger,
|
|
}
|
|
|
|
pb := &pluginv2.DataSourceInstanceSettings{
|
|
ApiVersion: "v0alpha1",
|
|
Url: "https://grafana.example.com/",
|
|
}
|
|
data, err := proto.Marshal(pb)
|
|
assert.NoError(t, err)
|
|
|
|
expected := &backend.ValidationResponse{
|
|
Allowed: true,
|
|
}
|
|
|
|
req := &backend.AdmissionRequest{
|
|
Kind: backend.GroupVersionKind{
|
|
Group: "grafana-plugin-sdk-go",
|
|
Kind: "DataSourceInstanceSettings",
|
|
},
|
|
ObjectBytes: data,
|
|
}
|
|
|
|
actual, err := s.ValidateAdmission(context.Background(), req)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, expected, actual)
|
|
})
|
|
}
|
|
|
|
func Test_MutateAdmission(t *testing.T) {
|
|
t.Run("should fail when Kind and Group do not match expected values", func(t *testing.T) {
|
|
httpProvider := getMockProvider[*healthCheckSuccessRoundTripper]()
|
|
logger := backend.NewLoggerWith("logger", "test")
|
|
s := &Service{
|
|
im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, logger, mockExtendClientOpts)),
|
|
logger: logger,
|
|
}
|
|
|
|
expected := getBadRequest("expected DataSourceInstanceSettings protobuf payload")
|
|
|
|
req := &backend.AdmissionRequest{
|
|
Kind: backend.GroupVersionKind{
|
|
Group: "example.k8s.io",
|
|
Kind: "Pod",
|
|
},
|
|
}
|
|
|
|
actual, err := s.MutateAdmission(context.Background(), req)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, expected, actual)
|
|
})
|
|
|
|
t.Run("should return an error when object bytes is nil", func(t *testing.T) {
|
|
httpProvider := getMockProvider[*healthCheckSuccessRoundTripper]()
|
|
logger := backend.NewLoggerWith("logger", "test")
|
|
s := &Service{
|
|
im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, logger, mockExtendClientOpts)),
|
|
logger: logger,
|
|
}
|
|
|
|
expected := getBadRequest("missing datasource settings")
|
|
|
|
req := &backend.AdmissionRequest{
|
|
Kind: backend.GroupVersionKind{
|
|
Group: "grafana-plugin-sdk-go",
|
|
Kind: "DataSourceInstanceSettings",
|
|
},
|
|
}
|
|
|
|
actual, err := s.MutateAdmission(context.Background(), req)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, expected, actual)
|
|
})
|
|
|
|
t.Run("should return an error when protobuf payload conversion fails", func(t *testing.T) {
|
|
httpProvider := getMockProvider[*healthCheckSuccessRoundTripper]()
|
|
logger := backend.NewLoggerWith("logger", "test")
|
|
s := &Service{
|
|
im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, logger, mockExtendClientOpts)),
|
|
logger: logger,
|
|
}
|
|
|
|
req := &backend.AdmissionRequest{
|
|
Kind: backend.GroupVersionKind{
|
|
Group: "grafana-plugin-sdk-go",
|
|
Kind: "DataSourceInstanceSettings",
|
|
},
|
|
ObjectBytes: []byte(`{"foo":"bar"}`),
|
|
}
|
|
|
|
actual, err := s.MutateAdmission(context.Background(), req)
|
|
assert.ErrorContains(t, err, "cannot parse invalid")
|
|
assert.Nil(t, actual)
|
|
})
|
|
|
|
t.Run("should return bad request error when settings APIVersion is invalid", func(t *testing.T) {
|
|
httpProvider := getMockProvider[*healthCheckSuccessRoundTripper]()
|
|
logger := backend.NewLoggerWith("logger", "test")
|
|
s := &Service{
|
|
im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, logger, mockExtendClientOpts)),
|
|
logger: logger,
|
|
}
|
|
|
|
pb := &pluginv2.DataSourceInstanceSettings{
|
|
ApiVersion: "v0alpha2",
|
|
}
|
|
data, err := proto.Marshal(pb)
|
|
assert.NoError(t, err)
|
|
|
|
expected := getBadRequest(fmt.Sprintf("expected apiVersion: v0alpha1, found: %s", pb.ApiVersion))
|
|
|
|
req := &backend.AdmissionRequest{
|
|
Kind: backend.GroupVersionKind{
|
|
Group: "grafana-plugin-sdk-go",
|
|
Kind: "DataSourceInstanceSettings",
|
|
},
|
|
ObjectBytes: data,
|
|
}
|
|
|
|
actual, err := s.MutateAdmission(context.Background(), req)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, expected, actual)
|
|
})
|
|
|
|
t.Run("should return bad request error when settings URL is invalid", func(t *testing.T) {
|
|
httpProvider := getMockProvider[*healthCheckSuccessRoundTripper]()
|
|
logger := backend.NewLoggerWith("logger", "test")
|
|
s := &Service{
|
|
im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, logger, mockExtendClientOpts)),
|
|
logger: logger,
|
|
}
|
|
|
|
pb := &pluginv2.DataSourceInstanceSettings{
|
|
ApiVersion: "v0alpha1",
|
|
}
|
|
data, err := proto.Marshal(pb)
|
|
assert.NoError(t, err)
|
|
|
|
expected := getBadRequest("missing URL value")
|
|
|
|
req := &backend.AdmissionRequest{
|
|
Kind: backend.GroupVersionKind{
|
|
Group: "grafana-plugin-sdk-go",
|
|
Kind: "DataSourceInstanceSettings",
|
|
},
|
|
ObjectBytes: data,
|
|
}
|
|
|
|
actual, err := s.MutateAdmission(context.Background(), req)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, expected, actual)
|
|
})
|
|
|
|
t.Run("should return successfully mutation response", func(t *testing.T) {
|
|
httpProvider := getMockProvider[*healthCheckSuccessRoundTripper]()
|
|
logger := backend.NewLoggerWith("logger", "test")
|
|
s := &Service{
|
|
im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, logger, mockExtendClientOpts)),
|
|
logger: logger,
|
|
}
|
|
|
|
pb := &pluginv2.DataSourceInstanceSettings{
|
|
ApiVersion: "v0alpha1",
|
|
Url: "https://grafana.example.com/",
|
|
}
|
|
data, err := proto.Marshal(pb)
|
|
assert.NoError(t, err)
|
|
|
|
expected := &backend.MutationResponse{
|
|
Allowed: true,
|
|
ObjectBytes: data,
|
|
}
|
|
|
|
req := &backend.AdmissionRequest{
|
|
Kind: backend.GroupVersionKind{
|
|
Group: "grafana-plugin-sdk-go",
|
|
Kind: "DataSourceInstanceSettings",
|
|
},
|
|
ObjectBytes: data,
|
|
}
|
|
|
|
actual, err := s.MutateAdmission(context.Background(), req)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, expected, actual)
|
|
})
|
|
}
|
|
|
|
func Test_getBadRequest(t *testing.T) {
|
|
t.Run("should get a successful bad request", func(t *testing.T) {
|
|
msg := "missing URL value"
|
|
|
|
expected := &backend.MutationResponse{
|
|
Allowed: false,
|
|
Result: &backend.StatusResult{
|
|
Status: "Failure",
|
|
Message: "missing URL value",
|
|
Reason: string(metav1.StatusReasonBadRequest),
|
|
Code: http.StatusBadRequest,
|
|
},
|
|
}
|
|
|
|
actual := getBadRequest(msg)
|
|
assert.Equal(t, expected, actual)
|
|
})
|
|
}
|