grafana/pkg/registry/apis/dashboard/restore_test.go

127 lines
3.4 KiB
Go

package dashboard
import (
"bytes"
"context"
"fmt"
"net/http"
"net/http/httptest"
"strconv"
"testing"
"github.com/grafana/grafana/pkg/storage/unified/resource"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/endpoints/request"
)
type mockResourceClient struct {
mock.Mock
resource.ResourceClient
}
func (m *mockResourceClient) Restore(ctx context.Context, req *resource.RestoreRequest, opts ...grpc.CallOption) (*resource.RestoreResponse, error) {
args := m.Called(ctx, req)
return args.Get(0).(*resource.RestoreResponse), args.Error(1)
}
func (m *mockResourceClient) Read(ctx context.Context, req *resource.ReadRequest, opts ...grpc.CallOption) (*resource.ReadResponse, error) {
args := m.Called(ctx, req)
return args.Get(0).(*resource.ReadResponse), args.Error(1)
}
type mockResponder struct {
mock.Mock
}
func (m *mockResponder) Object(statusCode int, obj runtime.Object) {
m.Called(statusCode, obj)
}
func (m *mockResponder) Error(err error) {
m.Called(err)
}
func TestRestore(t *testing.T) {
gr := schema.GroupResource{
Group: "group",
Resource: "resource",
}
ctx := context.Background()
mockResponder := &mockResponder{}
mockClient := &mockResourceClient{}
r := &restoreREST{
unified: mockClient,
gr: gr,
}
t.Run("no namespace in context", func(t *testing.T) {
_, err := r.Connect(ctx, "test-uid", nil, mockResponder)
assert.Error(t, err)
})
ctx = request.WithNamespace(context.Background(), "default")
t.Run("invalid resourceVersion", func(t *testing.T) {
req := httptest.NewRequest("POST", "/restore", bytes.NewReader([]byte(`{"resourceVersion":0}`)))
w := httptest.NewRecorder()
expectedError := fmt.Errorf("resource version required")
mockResponder.On("Error", mock.MatchedBy(func(err error) bool {
return err.Error() == expectedError.Error()
}))
handler, err := r.Connect(ctx, "test-uid", nil, mockResponder)
assert.NoError(t, err)
handler.ServeHTTP(w, req)
mockResponder.AssertExpectations(t)
})
t.Run("happy path", func(t *testing.T) {
req := httptest.NewRequest("POST", "/restore", bytes.NewReader([]byte(`{"resourceVersion":123}`)))
w := httptest.NewRecorder()
restoreReq := &resource.RestoreRequest{
ResourceVersion: 123,
Key: &resource.ResourceKey{
Namespace: "default",
Group: "group",
Resource: "resource",
Name: "uid",
},
}
expectedObject := &metav1.PartialObjectMetadata{
ObjectMeta: metav1.ObjectMeta{
Name: "uid",
Namespace: "default",
ResourceVersion: strconv.FormatInt(123, 10),
},
}
mockClient.On("Restore", ctx, restoreReq).Return(&resource.RestoreResponse{
ResourceVersion: 123,
}, nil).Once()
mockResponder.On("Object", http.StatusOK, mock.MatchedBy(func(obj interface{}) bool {
metadata, ok := obj.(*metav1.PartialObjectMetadata)
return ok &&
metadata.ObjectMeta.Name == "uid" &&
metadata.ObjectMeta.Namespace == "default" &&
metadata.ObjectMeta.ResourceVersion == "123"
})).Return(expectedObject)
handler, err := r.Connect(ctx, "uid", nil, mockResponder)
assert.NoError(t, err)
handler.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
mockClient.AssertExpectations(t)
mockResponder.AssertExpectations(t)
})
}