mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
	
	
		
			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) | ||
|  | 	}) | ||
|  | } |