diff --git a/apps/provisioning/pkg/repository/test_test.go b/apps/provisioning/pkg/repository/test_test.go index 5b7c8c6b815..0a35c024ca4 100644 --- a/apps/provisioning/pkg/repository/test_test.go +++ b/apps/provisioning/pkg/repository/test_test.go @@ -26,6 +26,9 @@ func TestValidateRepository(t *testing.T) { 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", }, @@ -232,6 +235,28 @@ func TestValidateRepository(t *testing.T) { 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") + }, + }, } for _, tt := range tests { diff --git a/pkg/tests/apis/provisioning/repository_test.go b/pkg/tests/apis/provisioning/repository_test.go index b48c7d82add..8d3e7daa089 100644 --- a/pkg/tests/apis/provisioning/repository_test.go +++ b/pkg/tests/apis/provisioning/repository_test.go @@ -18,6 +18,7 @@ import ( "k8s.io/apimachinery/pkg/types" provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + "github.com/grafana/grafana/apps/provisioning/pkg/repository" "github.com/grafana/grafana/pkg/apimachinery/utils" "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/tests/apis" @@ -162,6 +163,58 @@ func TestIntegrationProvisioning_CreatingAndGetting(t *testing.T) { }) } +func TestIntegrationProvisioning_RepositoryValidation(t *testing.T) { + testutil.SkipIntegrationTestInShortMode(t) + + helper := runGrafana(t) + ctx := context.Background() + + for _, testCase := range []struct { + name string + repo *unstructured.Unstructured + expectedErr string + }{ + { + name: "should succeed with valid local repository", + repo: func() *unstructured.Unstructured { + return helper.RenderObject(t, "testdata/local-readonly.json.tmpl", map[string]any{ + "Name": "valid-repo", + "SyncEnabled": true, + }) + }(), + }, + { + name: "should error if mutually exclusive finalizers are set", + repo: func() *unstructured.Unstructured { + localTmp := helper.RenderObject(t, "testdata/local-readonly.json.tmpl", map[string]any{ + "Name": "repo-with-invalid-finalizers", + "SyncEnabled": true, + }) + + // Setting finalizers to trigger a failure + localTmp.SetFinalizers([]string{ + repository.CleanFinalizer, + repository.ReleaseOrphanResourcesFinalizer, + repository.RemoveOrphanResourcesFinalizer, + }) + + return localTmp + }(), + expectedErr: "cannot have both remove and release orphan resources finalizers", + }, + } { + t.Run(testCase.name, func(t *testing.T) { + _, err := helper.Repositories.Resource.Create(ctx, testCase.repo, metav1.CreateOptions{}) + if testCase.expectedErr == "" { + assert.NoError(t, err) + } else { + assert.Error(t, err) + assert.ErrorContains(t, err, testCase.expectedErr) + } + }) + } +} + func TestIntegrationProvisioning_FailInvalidSchema(t *testing.T) { testutil.SkipIntegrationTestInShortMode(t)