* [git-sync] add sync job & phase metrics * refactoring sync jobs for clarity and ease of instrumentation * make gofmt
191 lines
7.2 KiB
Go
191 lines
7.2 KiB
Go
package sync
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
|
|
provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1"
|
|
"github.com/grafana/grafana/apps/provisioning/pkg/repository"
|
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
|
"github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs"
|
|
"github.com/grafana/grafana/pkg/registry/apis/provisioning/resources"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
mock "github.com/stretchr/testify/mock"
|
|
"github.com/stretchr/testify/require"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
)
|
|
|
|
type mockReaderWriter struct {
|
|
*repository.MockRepository
|
|
*repository.MockVersioned
|
|
}
|
|
|
|
// FIXME: understand how the MockRepository was generated as it seems
|
|
// stale and it's causing collisions for the embedded
|
|
func (m *mockReaderWriter) History(ctx context.Context, path, ref string) ([]provisioning.HistoryItem, error) {
|
|
return m.MockVersioned.History(ctx, path, ref)
|
|
}
|
|
|
|
func (m *mockReaderWriter) LatestRef(ctx context.Context) (string, error) {
|
|
return m.MockVersioned.LatestRef(ctx)
|
|
}
|
|
|
|
func (m *mockReaderWriter) CompareFiles(ctx context.Context, base, ref string) ([]repository.VersionedFileChange, error) {
|
|
return m.MockVersioned.CompareFiles(ctx, base, ref)
|
|
}
|
|
|
|
func (m *mockReaderWriter) Move(ctx context.Context, oldPath, newPath, ref, message string) error {
|
|
args := m.MockRepository.Called(ctx, oldPath, newPath, ref, message)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func TestSyncer_Sync(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
options provisioning.SyncJobOptions
|
|
setupMocks func(*mockReaderWriter, *resources.MockRepositoryResources, *resources.MockResourceClients, *jobs.MockJobProgressRecorder, *MockCompareFn, *MockFullSyncFn, *MockIncrementalSyncFn)
|
|
expectedRef string
|
|
expectedError string
|
|
expectedMessages []string
|
|
expectedFinalMsg string
|
|
}{
|
|
{
|
|
name: "successful full sync",
|
|
options: provisioning.SyncJobOptions{
|
|
Incremental: false,
|
|
},
|
|
setupMocks: func(repo *mockReaderWriter, repoResources *resources.MockRepositoryResources, clients *resources.MockResourceClients, progress *jobs.MockJobProgressRecorder, compareFn *MockCompareFn, fullSyncFn *MockFullSyncFn, incrementalSyncFn *MockIncrementalSyncFn) {
|
|
repo.MockRepository.On("Config").Return(&provisioning.Repository{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-repo",
|
|
},
|
|
Spec: provisioning.RepositorySpec{
|
|
Title: "Test Repo",
|
|
},
|
|
})
|
|
repo.MockVersioned.On("LatestRef", mock.Anything).Return("new-ref", nil)
|
|
|
|
progress.On("SetMessage", mock.Anything, "full sync").Return()
|
|
fullSyncFn.EXPECT().Execute(mock.Anything, mock.Anything, mock.Anything, mock.Anything, "new-ref", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
|
},
|
|
expectedMessages: []string{"full sync"},
|
|
},
|
|
{
|
|
name: "successful incremental sync",
|
|
options: provisioning.SyncJobOptions{
|
|
Incremental: true,
|
|
},
|
|
setupMocks: func(repo *mockReaderWriter, repoResources *resources.MockRepositoryResources, clients *resources.MockResourceClients, progress *jobs.MockJobProgressRecorder, compareFn *MockCompareFn, fullSyncFn *MockFullSyncFn, incrementalSyncFn *MockIncrementalSyncFn) {
|
|
repo.MockRepository.On("Config").Return(&provisioning.Repository{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-repo",
|
|
},
|
|
Status: provisioning.RepositoryStatus{
|
|
Sync: provisioning.SyncStatus{
|
|
LastRef: "old-ref",
|
|
},
|
|
},
|
|
})
|
|
repo.MockVersioned.On("LatestRef", mock.Anything).Return("new-ref", nil)
|
|
progress.On("SetMessage", mock.Anything, "incremental sync").Return()
|
|
incrementalSyncFn.EXPECT().Execute(mock.Anything, mock.Anything, "old-ref", "new-ref", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
|
},
|
|
expectedRef: "new-ref",
|
|
expectedMessages: []string{"incremental sync"},
|
|
},
|
|
{
|
|
name: "latest ref error",
|
|
options: provisioning.SyncJobOptions{
|
|
Incremental: true,
|
|
},
|
|
setupMocks: func(repo *mockReaderWriter, repoResources *resources.MockRepositoryResources, clients *resources.MockResourceClients, progress *jobs.MockJobProgressRecorder, compareFn *MockCompareFn, fullSyncFn *MockFullSyncFn, incrementalSyncFn *MockIncrementalSyncFn) {
|
|
repo.MockRepository.On("Config").Return(&provisioning.Repository{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-repo",
|
|
},
|
|
Status: provisioning.RepositoryStatus{
|
|
Sync: provisioning.SyncStatus{
|
|
LastRef: "old-ref",
|
|
},
|
|
},
|
|
})
|
|
repo.MockVersioned.On("LatestRef", mock.Anything).Return("", fmt.Errorf("failed to get latest ref"))
|
|
},
|
|
expectedError: "get latest ref: failed to get latest ref",
|
|
},
|
|
{
|
|
name: "incremental sync error",
|
|
options: provisioning.SyncJobOptions{
|
|
Incremental: true,
|
|
},
|
|
setupMocks: func(repo *mockReaderWriter, repoResources *resources.MockRepositoryResources, clients *resources.MockResourceClients, progress *jobs.MockJobProgressRecorder, compareFn *MockCompareFn, fullSyncFn *MockFullSyncFn, incrementalSyncFn *MockIncrementalSyncFn) {
|
|
repo.MockRepository.On("Config").Return(&provisioning.Repository{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-repo",
|
|
},
|
|
Status: provisioning.RepositoryStatus{
|
|
Sync: provisioning.SyncStatus{
|
|
LastRef: "old-ref",
|
|
},
|
|
},
|
|
})
|
|
repo.MockVersioned.On("LatestRef", mock.Anything).Return("new-ref", nil)
|
|
progress.On("SetMessage", mock.Anything, "incremental sync").Return()
|
|
incrementalSyncFn.On("Execute", mock.Anything, mock.Anything, "old-ref", "new-ref", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(fmt.Errorf("incremental sync failed"))
|
|
},
|
|
expectedRef: "new-ref",
|
|
expectedMessages: []string{"incremental sync"},
|
|
expectedError: "incremental sync failed",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
repoResources := resources.NewMockRepositoryResources(t)
|
|
clients := resources.NewMockResourceClients(t)
|
|
progress := jobs.NewMockJobProgressRecorder(t)
|
|
compareFn := NewMockCompareFn(t)
|
|
fullSyncFn := NewMockFullSyncFn(t)
|
|
incrementalSyncFn := NewMockIncrementalSyncFn(t)
|
|
|
|
repo := &mockReaderWriter{
|
|
MockRepository: repository.NewMockRepository(t),
|
|
MockVersioned: repository.NewMockVersioned(t),
|
|
}
|
|
|
|
tt.setupMocks(repo, repoResources, clients, progress, compareFn, fullSyncFn, incrementalSyncFn)
|
|
|
|
syncer := NewSyncer(
|
|
compareFn.Execute,
|
|
fullSyncFn.Execute,
|
|
incrementalSyncFn.Execute,
|
|
tracing.NewNoopTracerService(),
|
|
10,
|
|
jobs.RegisterJobMetrics(prometheus.NewPedanticRegistry()),
|
|
)
|
|
|
|
ref, err := syncer.Sync(context.Background(), repo, tt.options, repoResources, clients, progress)
|
|
if tt.expectedError != "" {
|
|
require.EqualError(t, err, tt.expectedError)
|
|
} else {
|
|
require.NoError(t, err)
|
|
if tt.expectedRef != "" {
|
|
require.Equal(t, tt.expectedRef, ref)
|
|
}
|
|
}
|
|
|
|
// Verify expected messages were set
|
|
if len(tt.expectedMessages) > 0 {
|
|
for _, msg := range tt.expectedMessages {
|
|
progress.AssertCalled(t, "SetMessage", mock.Anything, msg)
|
|
}
|
|
}
|
|
|
|
if tt.expectedFinalMsg != "" {
|
|
progress.AssertCalled(t, "SetFinalMessage", mock.Anything, tt.expectedFinalMsg)
|
|
}
|
|
})
|
|
}
|
|
}
|