314 lines
9.4 KiB
Go
314 lines
9.4 KiB
Go
package repository
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
|
|
|
provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1"
|
|
)
|
|
|
|
func TestValidateRepository(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
repository *MockRepository
|
|
expectedErrs int
|
|
validateError func(t *testing.T, errors field.ErrorList)
|
|
}{
|
|
{
|
|
name: "valid repository",
|
|
repository: func() *MockRepository {
|
|
m := NewMockRepository(t)
|
|
m.On("Config").Return(&provisioning.Repository{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Finalizers: []string{CleanFinalizer, RemoveOrphanResourcesFinalizer},
|
|
},
|
|
Spec: provisioning.RepositorySpec{
|
|
Title: "Test Repo",
|
|
},
|
|
})
|
|
m.On("Validate").Return(field.ErrorList{})
|
|
return m
|
|
}(),
|
|
expectedErrs: 0,
|
|
},
|
|
{
|
|
name: "missing title",
|
|
repository: func() *MockRepository {
|
|
m := NewMockRepository(t)
|
|
m.On("Config").Return(&provisioning.Repository{
|
|
Spec: provisioning.RepositorySpec{},
|
|
})
|
|
m.On("Validate").Return(field.ErrorList{})
|
|
return m
|
|
}(),
|
|
expectedErrs: 1,
|
|
validateError: func(t *testing.T, errors field.ErrorList) {
|
|
require.Contains(t, errors.ToAggregate().Error(), "spec.title: Required value")
|
|
},
|
|
},
|
|
{
|
|
name: "sync enabled without target",
|
|
repository: func() *MockRepository {
|
|
m := NewMockRepository(t)
|
|
m.On("Config").Return(&provisioning.Repository{
|
|
Spec: provisioning.RepositorySpec{
|
|
Title: "Test Repo",
|
|
Sync: provisioning.SyncOptions{
|
|
Enabled: true,
|
|
IntervalSeconds: 10,
|
|
},
|
|
},
|
|
})
|
|
m.On("Validate").Return(field.ErrorList{})
|
|
return m
|
|
}(),
|
|
expectedErrs: 1,
|
|
validateError: func(t *testing.T, errors field.ErrorList) {
|
|
require.Contains(t, errors.ToAggregate().Error(), "spec.sync.target: Required value")
|
|
},
|
|
},
|
|
{
|
|
name: "sync interval too low",
|
|
repository: func() *MockRepository {
|
|
m := NewMockRepository(t)
|
|
m.On("Config").Return(&provisioning.Repository{
|
|
Spec: provisioning.RepositorySpec{
|
|
Title: "Test Repo",
|
|
Sync: provisioning.SyncOptions{
|
|
Enabled: true,
|
|
Target: provisioning.SyncTargetTypeFolder,
|
|
IntervalSeconds: 5,
|
|
},
|
|
},
|
|
})
|
|
m.On("Validate").Return(field.ErrorList{})
|
|
return m
|
|
}(),
|
|
expectedErrs: 1,
|
|
validateError: func(t *testing.T, errors field.ErrorList) {
|
|
require.Contains(t, errors.ToAggregate().Error(), "spec.sync.intervalSeconds: Invalid value")
|
|
},
|
|
},
|
|
{
|
|
name: "reserved name",
|
|
repository: func() *MockRepository {
|
|
m := NewMockRepository(t)
|
|
m.On("Config").Return(&provisioning.Repository{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "sql",
|
|
},
|
|
Spec: provisioning.RepositorySpec{
|
|
Title: "Test Repo",
|
|
},
|
|
})
|
|
m.On("Validate").Return(field.ErrorList{})
|
|
return m
|
|
}(),
|
|
expectedErrs: 1,
|
|
validateError: func(t *testing.T, errors field.ErrorList) {
|
|
require.Contains(t, errors.ToAggregate().Error(), "metadata.name: Invalid value")
|
|
},
|
|
},
|
|
{
|
|
name: "mismatched local config",
|
|
repository: func() *MockRepository {
|
|
m := NewMockRepository(t)
|
|
m.On("Config").Return(&provisioning.Repository{
|
|
Spec: provisioning.RepositorySpec{
|
|
Title: "Test Repo",
|
|
Type: provisioning.GitHubRepositoryType,
|
|
Local: &provisioning.LocalRepositoryConfig{},
|
|
},
|
|
})
|
|
m.On("Validate").Return(field.ErrorList{})
|
|
return m
|
|
}(),
|
|
expectedErrs: 1,
|
|
validateError: func(t *testing.T, errors field.ErrorList) {
|
|
require.Contains(t, errors.ToAggregate().Error(), "spec.local: Invalid value")
|
|
},
|
|
},
|
|
{
|
|
name: "mismatched github config",
|
|
repository: func() *MockRepository {
|
|
m := NewMockRepository(t)
|
|
m.On("Config").Return(&provisioning.Repository{
|
|
Spec: provisioning.RepositorySpec{
|
|
Title: "Test Repo",
|
|
Type: provisioning.LocalRepositoryType,
|
|
GitHub: &provisioning.GitHubRepositoryConfig{},
|
|
},
|
|
})
|
|
m.On("Validate").Return(field.ErrorList{})
|
|
return m
|
|
}(),
|
|
expectedErrs: 1,
|
|
validateError: func(t *testing.T, errors field.ErrorList) {
|
|
require.Contains(t, errors.ToAggregate().Error(), "spec.github: Invalid value")
|
|
},
|
|
},
|
|
{
|
|
name: "github enabled when image rendering is not allowed",
|
|
repository: func() *MockRepository {
|
|
m := NewMockRepository(t)
|
|
m.On("Config").Return(&provisioning.Repository{
|
|
Spec: provisioning.RepositorySpec{
|
|
Title: "Test Repo",
|
|
Type: provisioning.GitHubRepositoryType,
|
|
GitHub: &provisioning.GitHubRepositoryConfig{
|
|
GenerateDashboardPreviews: true,
|
|
},
|
|
},
|
|
})
|
|
m.On("Validate").Return(field.ErrorList{})
|
|
return m
|
|
}(),
|
|
expectedErrs: 1,
|
|
validateError: func(t *testing.T, errors field.ErrorList) {
|
|
require.Contains(t, errors.ToAggregate().Error(), "spec.generateDashboardPreviews: Invalid value")
|
|
},
|
|
},
|
|
{
|
|
name: "mismatched git config",
|
|
repository: func() *MockRepository {
|
|
m := NewMockRepository(t)
|
|
m.On("Config").Return(&provisioning.Repository{
|
|
Spec: provisioning.RepositorySpec{
|
|
Title: "Test Repo",
|
|
Type: provisioning.LocalRepositoryType,
|
|
Git: &provisioning.GitRepositoryConfig{},
|
|
},
|
|
})
|
|
m.On("Validate").Return(field.ErrorList{})
|
|
return m
|
|
}(),
|
|
expectedErrs: 1,
|
|
validateError: func(t *testing.T, errors field.ErrorList) {
|
|
require.Contains(t, errors.ToAggregate().Error(), "spec.git: Invalid value")
|
|
},
|
|
},
|
|
{
|
|
name: "multiple validation errors",
|
|
repository: func() *MockRepository {
|
|
m := NewMockRepository(t)
|
|
m.On("Config").Return(&provisioning.Repository{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "sql",
|
|
},
|
|
Spec: provisioning.RepositorySpec{
|
|
Sync: provisioning.SyncOptions{
|
|
Enabled: true,
|
|
IntervalSeconds: 5,
|
|
Target: provisioning.SyncTargetTypeInstance,
|
|
},
|
|
},
|
|
})
|
|
m.On("Validate").Return(field.ErrorList{})
|
|
return m
|
|
}(),
|
|
expectedErrs: 4,
|
|
// 1. missing title
|
|
// 2. sync target missing
|
|
// 3. reserved name
|
|
// 4. sync target not supported
|
|
},
|
|
{
|
|
name: "branch workflow for non-github repository",
|
|
repository: func() *MockRepository {
|
|
m := NewMockRepository(t)
|
|
m.On("Config").Return(&provisioning.Repository{
|
|
Spec: provisioning.RepositorySpec{
|
|
Title: "Test Repo",
|
|
Type: provisioning.LocalRepositoryType,
|
|
Workflows: []provisioning.Workflow{provisioning.BranchWorkflow},
|
|
},
|
|
})
|
|
m.On("Validate").Return(field.ErrorList{})
|
|
return m
|
|
}(),
|
|
expectedErrs: 1,
|
|
validateError: func(t *testing.T, errors field.ErrorList) {
|
|
require.Contains(t, errors.ToAggregate().Error(), "spec.workflow: Invalid value: \"branch\": branch is only supported on git repositories")
|
|
},
|
|
},
|
|
{
|
|
name: "invalid workflow in the list",
|
|
repository: func() *MockRepository {
|
|
m := NewMockRepository(t)
|
|
m.On("Config").Return(&provisioning.Repository{
|
|
Spec: provisioning.RepositorySpec{
|
|
Title: "Test Repo",
|
|
Type: provisioning.GitHubRepositoryType,
|
|
Workflows: []provisioning.Workflow{provisioning.WriteWorkflow, "invalid"},
|
|
},
|
|
})
|
|
m.On("Validate").Return(field.ErrorList{})
|
|
return m
|
|
}(),
|
|
expectedErrs: 1,
|
|
validateError: func(t *testing.T, errors field.ErrorList) {
|
|
require.Contains(t, errors.ToAggregate().Error(), "spec.workflow: Invalid value: \"invalid\": invalid workflow")
|
|
},
|
|
},
|
|
{
|
|
name: "mutual exclusive finalizers are set together",
|
|
repository: func() *MockRepository {
|
|
m := NewMockRepository(t)
|
|
m.On("Config").Return(&provisioning.Repository{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Finalizers: []string{RemoveOrphanResourcesFinalizer, ReleaseOrphanResourcesFinalizer},
|
|
},
|
|
Spec: provisioning.RepositorySpec{
|
|
Title: "Test Repo",
|
|
Type: provisioning.GitHubRepositoryType,
|
|
Workflows: []provisioning.Workflow{provisioning.WriteWorkflow},
|
|
},
|
|
})
|
|
m.On("Validate").Return(field.ErrorList{})
|
|
return m
|
|
}(),
|
|
expectedErrs: 1,
|
|
validateError: func(t *testing.T, errors field.ErrorList) {
|
|
require.Contains(t, errors.ToAggregate().Error(), "cannot have both remove and release orphan resources finalizers")
|
|
},
|
|
},
|
|
{
|
|
name: "invalid finalizer in the list",
|
|
repository: func() *MockRepository {
|
|
m := NewMockRepository(t)
|
|
m.On("Config").Return(&provisioning.Repository{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Finalizers: []string{CleanFinalizer, "invalid-finalizer", RemoveOrphanResourcesFinalizer},
|
|
},
|
|
Spec: provisioning.RepositorySpec{
|
|
Title: "Test Repo",
|
|
Type: provisioning.GitHubRepositoryType,
|
|
Workflows: []provisioning.Workflow{provisioning.WriteWorkflow},
|
|
},
|
|
})
|
|
m.On("Validate").Return(field.ErrorList{})
|
|
return m
|
|
}(),
|
|
expectedErrs: 1,
|
|
validateError: func(t *testing.T, errors field.ErrorList) {
|
|
require.Contains(t, errors.ToAggregate().Error(), "unknown finalizer: invalid-finalizer")
|
|
},
|
|
},
|
|
}
|
|
|
|
validator := NewValidator(10*time.Second, []provisioning.SyncTargetType{provisioning.SyncTargetTypeFolder}, false)
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
errors := validator.ValidateRepository(tt.repository)
|
|
require.Len(t, errors, tt.expectedErrs)
|
|
if tt.validateError != nil {
|
|
tt.validateError(t, errors)
|
|
}
|
|
})
|
|
}
|
|
}
|