Provisioning: use kind consistently for provisioning stats (#111977)
This commit is contained in:
@@ -221,9 +221,9 @@ func (in JobStatus) ToSyncStatus(jobId string) SyncStatus {
|
||||
}
|
||||
|
||||
type JobResourceSummary struct {
|
||||
Group string `json:"group,omitempty"`
|
||||
Resource string `json:"resource,omitempty"`
|
||||
Total int64 `json:"total,omitempty"` // the count (if known)
|
||||
Group string `json:"group,omitempty"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Total int64 `json:"total,omitempty"` // the count (if known)
|
||||
|
||||
Create int64 `json:"create,omitempty"`
|
||||
Update int64 `json:"update,omitempty"`
|
||||
|
||||
@@ -846,7 +846,7 @@ func schema_pkg_apis_provisioning_v0alpha1_JobResourceSummary(ref common.Referen
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"resource": {
|
||||
"kind": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
|
||||
+14
-14
@@ -7,16 +7,16 @@ package v0alpha1
|
||||
// JobResourceSummaryApplyConfiguration represents a declarative configuration of the JobResourceSummary type for use
|
||||
// with apply.
|
||||
type JobResourceSummaryApplyConfiguration struct {
|
||||
Group *string `json:"group,omitempty"`
|
||||
Resource *string `json:"resource,omitempty"`
|
||||
Total *int64 `json:"total,omitempty"`
|
||||
Create *int64 `json:"create,omitempty"`
|
||||
Update *int64 `json:"update,omitempty"`
|
||||
Delete *int64 `json:"delete,omitempty"`
|
||||
Write *int64 `json:"write,omitempty"`
|
||||
Error *int64 `json:"error,omitempty"`
|
||||
Noop *int64 `json:"noop,omitempty"`
|
||||
Errors []string `json:"errors,omitempty"`
|
||||
Group *string `json:"group,omitempty"`
|
||||
Kind *string `json:"kind,omitempty"`
|
||||
Total *int64 `json:"total,omitempty"`
|
||||
Create *int64 `json:"create,omitempty"`
|
||||
Update *int64 `json:"update,omitempty"`
|
||||
Delete *int64 `json:"delete,omitempty"`
|
||||
Write *int64 `json:"write,omitempty"`
|
||||
Error *int64 `json:"error,omitempty"`
|
||||
Noop *int64 `json:"noop,omitempty"`
|
||||
Errors []string `json:"errors,omitempty"`
|
||||
}
|
||||
|
||||
// JobResourceSummaryApplyConfiguration constructs a declarative configuration of the JobResourceSummary type for use with
|
||||
@@ -33,11 +33,11 @@ func (b *JobResourceSummaryApplyConfiguration) WithGroup(value string) *JobResou
|
||||
return b
|
||||
}
|
||||
|
||||
// WithResource sets the Resource field in the declarative configuration to the given value
|
||||
// WithKind sets the Kind field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Resource field is set to the value of the last call.
|
||||
func (b *JobResourceSummaryApplyConfiguration) WithResource(value string) *JobResourceSummaryApplyConfiguration {
|
||||
b.Resource = &value
|
||||
// If called multiple times, the Kind field is set to the value of the last call.
|
||||
func (b *JobResourceSummaryApplyConfiguration) WithKind(value string) *JobResourceSummaryApplyConfiguration {
|
||||
b.Kind = &value
|
||||
return b
|
||||
}
|
||||
|
||||
|
||||
@@ -45,11 +45,11 @@ func ExportFolders(ctx context.Context, repoName string, options provisioning.Ex
|
||||
progress.SetMessage(ctx, "write folders to repository")
|
||||
err := repositoryResources.EnsureFolderTreeExists(ctx, options.Branch, options.Path, tree, func(folder resources.Folder, created bool, err error) error {
|
||||
result := jobs.JobResourceResult{
|
||||
Action: repository.FileActionCreated,
|
||||
Name: folder.ID,
|
||||
Resource: resources.FolderResource.Resource,
|
||||
Group: resources.FolderResource.Group,
|
||||
Path: folder.Path,
|
||||
Action: repository.FileActionCreated,
|
||||
Name: folder.ID,
|
||||
Group: resources.FolderResource.Group,
|
||||
Kind: resources.FolderKind.Kind,
|
||||
Path: folder.Path,
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -98,10 +98,10 @@ func exportResource(ctx context.Context,
|
||||
return resources.ForEach(ctx, client, func(item *unstructured.Unstructured) (err error) {
|
||||
gvk := item.GroupVersionKind()
|
||||
result := jobs.JobResourceResult{
|
||||
Name: item.GetName(),
|
||||
Resource: resource,
|
||||
Group: gvk.Group,
|
||||
Action: repository.FileActionCreated,
|
||||
Name: item.GetName(),
|
||||
Group: gvk.Group,
|
||||
Kind: gvk.Kind,
|
||||
Action: repository.FileActionCreated,
|
||||
}
|
||||
|
||||
// Check if resource is already managed by a repository
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/loki"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -17,6 +16,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/loki"
|
||||
)
|
||||
|
||||
func TestLokiJobHistory_WriteJob(t *testing.T) {
|
||||
@@ -86,16 +86,16 @@ func TestLokiJobHistory_WriteJob(t *testing.T) {
|
||||
Errors: []string{"warning: deprecated field used"},
|
||||
Progress: 100.0,
|
||||
Summary: []*provisioning.JobResourceSummary{{
|
||||
Group: "dashboard.grafana.app",
|
||||
Resource: "dashboards",
|
||||
Total: 10,
|
||||
Create: 3,
|
||||
Update: 5,
|
||||
Delete: 1,
|
||||
Write: 8,
|
||||
Error: 1,
|
||||
Noop: 0,
|
||||
Errors: []string{"failed to process dashboard-x"},
|
||||
Group: "dashboard.grafana.app",
|
||||
Kind: "Dashboard",
|
||||
Total: 10,
|
||||
Create: 3,
|
||||
Update: 5,
|
||||
Delete: 1,
|
||||
Write: 8,
|
||||
Error: 1,
|
||||
Noop: 0,
|
||||
Errors: []string{"failed to process dashboard-x"},
|
||||
}},
|
||||
},
|
||||
}
|
||||
@@ -178,7 +178,7 @@ func TestLokiJobHistory_WriteJob(t *testing.T) {
|
||||
require.Len(t, deserializedJob.Status.Summary, 1)
|
||||
summary := deserializedJob.Status.Summary[0]
|
||||
assert.Equal(t, "dashboard.grafana.app", summary.Group)
|
||||
assert.Equal(t, "dashboards", summary.Resource)
|
||||
assert.Equal(t, "Dashboard", summary.Kind)
|
||||
assert.Equal(t, int64(10), summary.Total)
|
||||
assert.Equal(t, int64(3), summary.Create)
|
||||
assert.Equal(t, int64(5), summary.Update)
|
||||
|
||||
@@ -4,12 +4,13 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/repository"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/provisioning/resources"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
//go:generate mockery --name NamespaceCleaner --structname MockNamespaceCleaner --inpackage --filename mock_namespace_cleaner.go --with-expecter
|
||||
@@ -40,10 +41,10 @@ func (c *namespaceCleaner) Clean(ctx context.Context, namespace string, progress
|
||||
|
||||
if err = resources.ForEach(ctx, client, func(item *unstructured.Unstructured) error {
|
||||
result := jobs.JobResourceResult{
|
||||
Name: item.GetName(),
|
||||
Resource: item.GetKind(),
|
||||
Group: item.GroupVersionKind().Group,
|
||||
Action: repository.FileActionDeleted,
|
||||
Name: item.GetName(),
|
||||
Kind: item.GetKind(),
|
||||
Group: item.GroupVersionKind().Group,
|
||||
Action: repository.FileActionDeleted,
|
||||
}
|
||||
|
||||
// Skip provisioned resources - only delete unprovisioned (unmanaged) resources
|
||||
@@ -63,7 +64,7 @@ func (c *namespaceCleaner) Clean(ctx context.Context, namespace string, progress
|
||||
}
|
||||
|
||||
if err := client.Delete(ctx, item.GetName(), metav1.DeleteOptions{}); err != nil {
|
||||
result.Error = fmt.Errorf("deleting resource %s/%s %s: %w", result.Group, result.Resource, result.Name, err)
|
||||
result.Error = fmt.Errorf("deleting resource %s/%s %s: %w", result.Group, result.Kind, result.Name, err)
|
||||
progress.Record(ctx, result)
|
||||
return fmt.Errorf("delete resource: %w", err)
|
||||
}
|
||||
|
||||
@@ -204,11 +204,11 @@ func (r *legacyResourceResourceMigrator) Write(ctx context.Context, key *resourc
|
||||
}
|
||||
|
||||
result := jobs.JobResourceResult{
|
||||
Name: parsed.Meta.GetName(),
|
||||
Resource: r.kind.Resource,
|
||||
Group: r.kind.Group,
|
||||
Action: repository.FileActionCreated,
|
||||
Path: fileName,
|
||||
Name: parsed.Meta.GetName(),
|
||||
Group: r.kind.Group,
|
||||
Kind: parsed.GVK.Kind,
|
||||
Action: repository.FileActionCreated,
|
||||
Path: fileName,
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -667,7 +667,7 @@ func TestLegacyResourceResourceMigrator_Write(t *testing.T) {
|
||||
return result.Action == repository.FileActionCreated &&
|
||||
result.Name == "test" &&
|
||||
result.Error == nil &&
|
||||
result.Resource == "tests" &&
|
||||
result.Kind == "" && // empty kind
|
||||
result.Group == "test.grafana.app" &&
|
||||
result.Path == "test/path"
|
||||
})).Return()
|
||||
|
||||
@@ -35,12 +35,12 @@ func maybeNotifyProgress(threshold time.Duration, fn ProgressFn) ProgressFn {
|
||||
|
||||
// FIXME: ProgressRecorder should be initialized in the queue
|
||||
type JobResourceResult struct {
|
||||
Name string
|
||||
Resource string
|
||||
Group string
|
||||
Path string
|
||||
Action repository.FileAction
|
||||
Error error
|
||||
Name string
|
||||
Group string
|
||||
Kind string
|
||||
Path string
|
||||
Action repository.FileAction
|
||||
Error error
|
||||
}
|
||||
|
||||
type jobProgressRecorder struct {
|
||||
@@ -73,7 +73,7 @@ func (r *jobProgressRecorder) Record(ctx context.Context, result JobResourceResu
|
||||
r.mu.Lock()
|
||||
r.resultCount++
|
||||
|
||||
logger := logging.FromContext(ctx).With("path", result.Path, "resource", result.Resource, "group", result.Group, "action", result.Action, "name", result.Name)
|
||||
logger := logging.FromContext(ctx).With("path", result.Path, "group", result.Group, "kind", result.Kind, "action", result.Action, "name", result.Name)
|
||||
if result.Error != nil {
|
||||
logger.Error("job resource operation failed", "err", result.Error)
|
||||
if len(r.errors) < 20 {
|
||||
@@ -173,12 +173,12 @@ func (r *jobProgressRecorder) summary() []*provisioning.JobResourceSummary {
|
||||
|
||||
func (r *jobProgressRecorder) updateSummary(result JobResourceResult) {
|
||||
// Note: This method is called from Record() which already holds the lock
|
||||
key := result.Resource + ":" + result.Group
|
||||
key := result.Group + ":" + result.Kind
|
||||
summary, exists := r.summaries[key]
|
||||
if !exists {
|
||||
summary = &provisioning.JobResourceSummary{
|
||||
Resource: result.Resource,
|
||||
Group: result.Group,
|
||||
Group: result.Group,
|
||||
Kind: result.Kind,
|
||||
}
|
||||
r.summaries[key] = summary
|
||||
}
|
||||
|
||||
@@ -4,15 +4,16 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/repository"
|
||||
"github.com/grafana/grafana/apps/provisioning/pkg/safepath"
|
||||
"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"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
func FullSync(
|
||||
@@ -92,9 +93,7 @@ func applyChanges(ctx context.Context, changes []ResourceFileChange, clients res
|
||||
deleteSpan.End()
|
||||
continue
|
||||
}
|
||||
|
||||
result.Name = change.Existing.Name
|
||||
result.Resource = change.Existing.Resource
|
||||
result.Group = change.Existing.Group
|
||||
|
||||
versionlessGVR := schema.GroupVersionResource{
|
||||
@@ -103,15 +102,17 @@ func applyChanges(ctx context.Context, changes []ResourceFileChange, clients res
|
||||
}
|
||||
|
||||
// TODO: should we use the clients or the resource manager instead?
|
||||
client, _, err := clients.ForResource(deleteCtx, versionlessGVR)
|
||||
client, gvk, err := clients.ForResource(deleteCtx, versionlessGVR)
|
||||
if err != nil {
|
||||
result.Kind = versionlessGVR.Resource // could not find a kind
|
||||
result.Error = fmt.Errorf("get client for deleted object: %w", err)
|
||||
progress.Record(deleteCtx, result)
|
||||
continue
|
||||
}
|
||||
result.Kind = gvk.Kind
|
||||
|
||||
if err := client.Delete(deleteCtx, change.Existing.Name, metav1.DeleteOptions{}); err != nil {
|
||||
result.Error = fmt.Errorf("deleting resource %s/%s %s: %w", change.Existing.Group, change.Existing.Resource, change.Existing.Name, err)
|
||||
result.Error = fmt.Errorf("deleting resource %s/%s %s: %w", change.Existing.Group, gvk.Kind, change.Existing.Name, err)
|
||||
}
|
||||
progress.Record(deleteCtx, result)
|
||||
deleteSpan.End()
|
||||
@@ -122,10 +123,10 @@ func applyChanges(ctx context.Context, changes []ResourceFileChange, clients res
|
||||
if safepath.IsDir(change.Path) {
|
||||
ensureFolderCtx, ensureFolderSpan := tracer.Start(ctx, "provisioning.sync.full.apply_changes.ensure_folder_exists")
|
||||
result := jobs.JobResourceResult{
|
||||
Path: change.Path,
|
||||
Action: change.Action,
|
||||
Resource: resources.FolderResource.Resource,
|
||||
Group: resources.FolderResource.Group,
|
||||
Path: change.Path,
|
||||
Action: change.Action,
|
||||
Group: resources.FolderKind.Group,
|
||||
Kind: resources.FolderKind.Kind,
|
||||
}
|
||||
|
||||
folder, err := repositoryResources.EnsureFolderPathExist(ensureFolderCtx, change.Path)
|
||||
@@ -147,11 +148,11 @@ func applyChanges(ctx context.Context, changes []ResourceFileChange, clients res
|
||||
writeCtx, writeSpan := tracer.Start(ctx, "provisioning.sync.full.apply_changes.write_resource_from_file")
|
||||
name, gvk, err := repositoryResources.WriteResourceFromFile(writeCtx, change.Path, "")
|
||||
result := jobs.JobResourceResult{
|
||||
Path: change.Path,
|
||||
Action: change.Action,
|
||||
Name: name,
|
||||
Resource: gvk.Kind,
|
||||
Group: gvk.Group,
|
||||
Path: change.Path,
|
||||
Action: change.Action,
|
||||
Name: name,
|
||||
Group: gvk.Group,
|
||||
Kind: gvk.Kind,
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -6,11 +6,6 @@ import (
|
||||
"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/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -18,6 +13,12 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
dynamicfake "k8s.io/client-go/dynamic/fake"
|
||||
k8testing "k8s.io/client-go/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"
|
||||
)
|
||||
|
||||
func TestFullSync_ContextCancelled(t *testing.T) {
|
||||
@@ -209,11 +210,11 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
Return("test-dashboard", schema.GroupVersionKind{Kind: "Dashboard", Group: "dashboards"}, nil)
|
||||
|
||||
progress.On("Record", mock.Anything, jobs.JobResourceResult{
|
||||
Action: repository.FileActionCreated,
|
||||
Path: "dashboards/one.json",
|
||||
Name: "test-dashboard",
|
||||
Resource: "Dashboard",
|
||||
Group: "dashboards",
|
||||
Action: repository.FileActionCreated,
|
||||
Path: "dashboards/one.json",
|
||||
Name: "test-dashboard",
|
||||
Kind: "Dashboard",
|
||||
Group: "dashboards",
|
||||
}).Return()
|
||||
},
|
||||
expectedError: "too many errors",
|
||||
@@ -234,11 +235,11 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
Return("test-dashboard", schema.GroupVersionKind{Kind: "Dashboard", Group: "dashboards"}, nil)
|
||||
|
||||
progress.On("Record", mock.Anything, jobs.JobResourceResult{
|
||||
Action: repository.FileActionCreated,
|
||||
Path: "dashboards/test.json",
|
||||
Name: "test-dashboard",
|
||||
Resource: "Dashboard",
|
||||
Group: "dashboards",
|
||||
Action: repository.FileActionCreated,
|
||||
Path: "dashboards/test.json",
|
||||
Name: "test-dashboard",
|
||||
Kind: "Dashboard",
|
||||
Group: "dashboards",
|
||||
}).Return()
|
||||
},
|
||||
},
|
||||
@@ -261,7 +262,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
return result.Action == repository.FileActionCreated &&
|
||||
result.Path == "dashboards/test.json" &&
|
||||
result.Name == "test-dashboard" &&
|
||||
result.Resource == "Dashboard" &&
|
||||
result.Kind == "Dashboard" &&
|
||||
result.Group == "dashboards" &&
|
||||
result.Error != nil &&
|
||||
result.Error.Error() == "writing resource from file dashboards/test.json: write error"
|
||||
@@ -284,11 +285,11 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
Return("test-dashboard", schema.GroupVersionKind{Kind: "Dashboard", Group: "dashboards"}, nil)
|
||||
|
||||
progress.On("Record", mock.Anything, jobs.JobResourceResult{
|
||||
Action: repository.FileActionUpdated,
|
||||
Path: "dashboards/test.json",
|
||||
Name: "test-dashboard",
|
||||
Resource: "Dashboard",
|
||||
Group: "dashboards",
|
||||
Action: repository.FileActionUpdated,
|
||||
Path: "dashboards/test.json",
|
||||
Name: "test-dashboard",
|
||||
Kind: "Dashboard",
|
||||
Group: "dashboards",
|
||||
}).Return()
|
||||
},
|
||||
},
|
||||
@@ -311,7 +312,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
return result.Action == repository.FileActionUpdated &&
|
||||
result.Path == "dashboards/test.json" &&
|
||||
result.Name == "test-dashboard" &&
|
||||
result.Resource == "Dashboard" &&
|
||||
result.Kind == "Dashboard" &&
|
||||
result.Group == "dashboards" &&
|
||||
result.Error != nil &&
|
||||
result.Error.Error() == "writing resource from file dashboards/test.json: write error"
|
||||
@@ -335,9 +336,8 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
Action: repository.FileActionCreated,
|
||||
Path: "one/two/three/",
|
||||
Name: "some-folder",
|
||||
// FIXME: this is probably inconsistent across the codebase
|
||||
Resource: "folders",
|
||||
Group: "folder.grafana.app",
|
||||
Kind: "Folder",
|
||||
Group: "folder.grafana.app",
|
||||
}).Return()
|
||||
},
|
||||
},
|
||||
@@ -362,7 +362,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
return result.Action == repository.FileActionCreated &&
|
||||
result.Path == "one/two/three/" &&
|
||||
result.Name == "" &&
|
||||
result.Resource == "folders" &&
|
||||
result.Kind == "Folder" &&
|
||||
result.Group == "folder.grafana.app" &&
|
||||
result.Error != nil &&
|
||||
result.Error.Error() == "ensuring folder exists at path one/two/three/: folder creation error"
|
||||
@@ -378,7 +378,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
Path: "dashboards/test.json",
|
||||
Existing: &provisioning.ResourceListItem{
|
||||
Name: "test-dashboard",
|
||||
Resource: "Dashboard",
|
||||
Resource: "dashboards",
|
||||
Group: "dashboards",
|
||||
},
|
||||
},
|
||||
@@ -411,7 +411,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
|
||||
clients.On("ForResource", mock.Anything, schema.GroupVersionResource{
|
||||
Group: "dashboards",
|
||||
Resource: "Dashboard",
|
||||
Resource: "dashboards",
|
||||
}).Return(fakeDynamicClient.Resource(resources.DashboardResource), schema.GroupVersionKind{
|
||||
Kind: "Dashboard",
|
||||
Group: "dashboards",
|
||||
@@ -419,12 +419,12 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
}, nil)
|
||||
|
||||
progress.On("Record", mock.Anything, jobs.JobResourceResult{
|
||||
Action: repository.FileActionDeleted,
|
||||
Path: "dashboards/test.json",
|
||||
Name: "test-dashboard",
|
||||
Resource: "Dashboard",
|
||||
Group: "dashboards",
|
||||
Error: nil,
|
||||
Action: repository.FileActionDeleted,
|
||||
Path: "dashboards/test.json",
|
||||
Name: "test-dashboard",
|
||||
Kind: "Dashboard",
|
||||
Group: "dashboards",
|
||||
Error: nil,
|
||||
}).Return()
|
||||
},
|
||||
},
|
||||
@@ -437,7 +437,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
Path: "dashboards/test.json",
|
||||
Existing: &provisioning.ResourceListItem{
|
||||
Name: "test-dashboard",
|
||||
Resource: "Dashboard",
|
||||
Resource: "dashboards",
|
||||
Group: "dashboards",
|
||||
},
|
||||
},
|
||||
@@ -470,7 +470,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
|
||||
clients.On("ForResource", mock.Anything, schema.GroupVersionResource{
|
||||
Group: "dashboards",
|
||||
Resource: "Dashboard",
|
||||
Resource: "dashboards",
|
||||
}).Return(fakeDynamicClient.Resource(resources.DashboardResource), schema.GroupVersionKind{
|
||||
Kind: "Dashboard",
|
||||
Group: "dashboards",
|
||||
@@ -481,7 +481,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
return result.Action == repository.FileActionDeleted &&
|
||||
result.Path == "dashboards/test.json" &&
|
||||
result.Name == "test-dashboard" &&
|
||||
result.Resource == "Dashboard" &&
|
||||
result.Kind == "Dashboard" &&
|
||||
result.Group == "dashboards" &&
|
||||
result.Error != nil &&
|
||||
result.Error.Error() == "deleting resource dashboards/Dashboard test-dashboard: delete failed"
|
||||
@@ -538,7 +538,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
Existing: &provisioning.ResourceListItem{
|
||||
Name: "test-dashboard",
|
||||
Group: "dashboards",
|
||||
Resource: "Dashboard",
|
||||
Resource: "dashboards",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -547,16 +547,16 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
|
||||
clients.On("ForResource", mock.Anything, schema.GroupVersionResource{
|
||||
Group: "dashboards",
|
||||
Resource: "Dashboard",
|
||||
Resource: "dashboards",
|
||||
}).Return(nil, schema.GroupVersionKind{}, errors.New("didn't work"))
|
||||
|
||||
progress.On("Record", mock.Anything, jobs.JobResourceResult{
|
||||
Name: "test-dashboard",
|
||||
Group: "dashboards",
|
||||
Resource: "Dashboard",
|
||||
Action: repository.FileActionDeleted,
|
||||
Path: "dashboards/test.json",
|
||||
Error: fmt.Errorf("get client for deleted object: %w", errors.New("didn't work")),
|
||||
Name: "test-dashboard",
|
||||
Group: "dashboards",
|
||||
Kind: "dashboards", // could not find a real kind
|
||||
Action: repository.FileActionDeleted,
|
||||
Path: "dashboards/test.json",
|
||||
Error: fmt.Errorf("get client for deleted object: %w", errors.New("didn't work")),
|
||||
}).Return()
|
||||
},
|
||||
},
|
||||
@@ -610,12 +610,12 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
}, nil)
|
||||
|
||||
progress.On("Record", mock.Anything, jobs.JobResourceResult{
|
||||
Action: repository.FileActionDeleted,
|
||||
Path: "to-be-deleted/",
|
||||
Name: "test-folder",
|
||||
Resource: "Folder",
|
||||
Group: "folders",
|
||||
Error: nil,
|
||||
Action: repository.FileActionDeleted,
|
||||
Path: "to-be-deleted/",
|
||||
Name: "test-folder",
|
||||
Kind: "Folder",
|
||||
Group: "folders",
|
||||
Error: nil,
|
||||
}).Return()
|
||||
},
|
||||
},
|
||||
@@ -672,7 +672,7 @@ func TestFullSync_ApplyChanges(t *testing.T) { //nolint:gocyclo
|
||||
return result.Action == repository.FileActionDeleted &&
|
||||
result.Path == "to-be-deleted/" &&
|
||||
result.Name == "test-folder" &&
|
||||
result.Resource == "Folder" &&
|
||||
result.Kind == "Folder" &&
|
||||
result.Group == "folders" &&
|
||||
result.Error != nil &&
|
||||
result.Error.Error() == "deleting resource folders/Folder test-folder: delete failed"
|
||||
|
||||
@@ -63,11 +63,11 @@ func IncrementalSync(ctx context.Context, repo repository.Versioned, previousRef
|
||||
}
|
||||
|
||||
progress.Record(ensureFolderCtx, jobs.JobResourceResult{
|
||||
Path: safeSegment,
|
||||
Action: repository.FileActionCreated,
|
||||
Resource: resources.FolderResource.Resource,
|
||||
Group: resources.FolderResource.Group,
|
||||
Name: folder,
|
||||
Path: safeSegment,
|
||||
Action: repository.FileActionCreated,
|
||||
Group: resources.FolderResource.Group,
|
||||
Kind: resources.FolderKind.Kind,
|
||||
Name: folder,
|
||||
})
|
||||
ensureFolderSpan.End()
|
||||
continue
|
||||
@@ -95,7 +95,7 @@ func IncrementalSync(ctx context.Context, repo repository.Versioned, previousRef
|
||||
result.Error = fmt.Errorf("writing resource from file %s: %w", change.Path, err)
|
||||
}
|
||||
result.Name = name
|
||||
result.Resource = gvk.Kind
|
||||
result.Kind = gvk.Kind
|
||||
result.Group = gvk.Group
|
||||
writeSpan.End()
|
||||
case repository.FileActionDeleted:
|
||||
@@ -106,7 +106,7 @@ func IncrementalSync(ctx context.Context, repo repository.Versioned, previousRef
|
||||
result.Error = fmt.Errorf("removing resource from file %s: %w", change.Path, err)
|
||||
}
|
||||
result.Name = name
|
||||
result.Resource = gvk.Kind
|
||||
result.Kind = gvk.Kind
|
||||
result.Group = gvk.Group
|
||||
removeSpan.End()
|
||||
case repository.FileActionRenamed:
|
||||
@@ -117,7 +117,7 @@ func IncrementalSync(ctx context.Context, repo repository.Versioned, previousRef
|
||||
result.Error = fmt.Errorf("renaming resource file from %s to %s: %w", change.PreviousPath, change.Path, err)
|
||||
}
|
||||
result.Name = name
|
||||
result.Resource = gvk.Kind
|
||||
result.Kind = gvk.Kind
|
||||
result.Group = gvk.Group
|
||||
renameSpan.End()
|
||||
case repository.FileActionIgnored:
|
||||
|
||||
@@ -5,13 +5,14 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
"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/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
func TestIncrementalSync_ContextCancelled(t *testing.T) {
|
||||
@@ -131,11 +132,11 @@ func TestIncrementalSync(t *testing.T) {
|
||||
|
||||
// Mock progress recording
|
||||
progress.On("Record", mock.Anything, jobs.JobResourceResult{
|
||||
Action: repository.FileActionCreated,
|
||||
Path: "unsupported/path/",
|
||||
Resource: resources.FolderResource.Resource,
|
||||
Group: resources.FolderResource.Group,
|
||||
Name: "test-folder",
|
||||
Action: repository.FileActionCreated,
|
||||
Path: "unsupported/path/",
|
||||
Kind: resources.FolderKind.Kind,
|
||||
Group: resources.FolderResource.Group,
|
||||
Name: "test-folder",
|
||||
}).Return()
|
||||
|
||||
progress.On("TooManyErrors").Return(nil)
|
||||
@@ -190,11 +191,11 @@ func TestIncrementalSync(t *testing.T) {
|
||||
|
||||
// Mock progress recording
|
||||
progress.On("Record", mock.Anything, jobs.JobResourceResult{
|
||||
Action: repository.FileActionDeleted,
|
||||
Path: "dashboards/old.json",
|
||||
Name: "old-dashboard",
|
||||
Resource: "Dashboard",
|
||||
Group: "dashboards",
|
||||
Action: repository.FileActionDeleted,
|
||||
Path: "dashboards/old.json",
|
||||
Name: "old-dashboard",
|
||||
Kind: "Dashboard",
|
||||
Group: "dashboards",
|
||||
}).Return()
|
||||
|
||||
progress.On("TooManyErrors").Return(nil)
|
||||
@@ -226,11 +227,11 @@ func TestIncrementalSync(t *testing.T) {
|
||||
|
||||
// Mock progress recording
|
||||
progress.On("Record", mock.Anything, jobs.JobResourceResult{
|
||||
Action: repository.FileActionRenamed,
|
||||
Path: "dashboards/new.json",
|
||||
Name: "renamed-dashboard",
|
||||
Resource: "Dashboard",
|
||||
Group: "dashboards",
|
||||
Action: repository.FileActionRenamed,
|
||||
Path: "dashboards/new.json",
|
||||
Name: "renamed-dashboard",
|
||||
Kind: "Dashboard",
|
||||
Group: "dashboards",
|
||||
}).Return()
|
||||
|
||||
progress.On("TooManyErrors").Return(nil)
|
||||
@@ -310,7 +311,7 @@ func TestIncrementalSync(t *testing.T) {
|
||||
return result.Action == repository.FileActionCreated &&
|
||||
result.Path == "dashboards/test.json" &&
|
||||
result.Name == "test-dashboard" &&
|
||||
result.Resource == "Dashboard" &&
|
||||
result.Kind == "Dashboard" &&
|
||||
result.Group == "dashboards" &&
|
||||
result.Error != nil &&
|
||||
result.Error.Error() == "writing resource from file dashboards/test.json: write failed"
|
||||
@@ -346,7 +347,7 @@ func TestIncrementalSync(t *testing.T) {
|
||||
return result.Action == repository.FileActionDeleted &&
|
||||
result.Path == "dashboards/old.json" &&
|
||||
result.Name == "old-dashboard" &&
|
||||
result.Resource == "Dashboard" &&
|
||||
result.Kind == "Dashboard" &&
|
||||
result.Group == "dashboards" &&
|
||||
result.Error != nil &&
|
||||
result.Error.Error() == "removing resource from file dashboards/old.json: delete failed"
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
var (
|
||||
UserResource = iam.UserResourceInfo.GroupVersionResource()
|
||||
FolderResource = folders.FolderResourceInfo.GroupVersionResource()
|
||||
FolderKind = folders.FolderResourceInfo.GroupVersionKind()
|
||||
DashboardResource = dashboardV1.DashboardResourceInfo.GroupVersionResource()
|
||||
DashboardResourceV2alpha1 = dashboardV2alpha1.DashboardResourceInfo.GroupVersionResource()
|
||||
DashboardResourceV2beta1 = dashboardV2beta1.DashboardResourceInfo.GroupVersionResource()
|
||||
|
||||
@@ -3706,14 +3706,14 @@
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string"
|
||||
},
|
||||
"noop": {
|
||||
"description": "No action required (useful for sync)",
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"resource": {
|
||||
"type": "string"
|
||||
},
|
||||
"total": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
|
||||
@@ -1010,9 +1010,9 @@ export type JobResourceSummary = {
|
||||
/** Report errors for this resource type This may not be an exhaustive list and recommend looking at the logs for more info */
|
||||
errors?: string[];
|
||||
group?: string;
|
||||
kind?: string;
|
||||
/** No action required (useful for sync) */
|
||||
noop?: number;
|
||||
resource?: string;
|
||||
total?: number;
|
||||
update?: number;
|
||||
write?: number;
|
||||
|
||||
@@ -11,7 +11,7 @@ const getSummaryColumns = () => [
|
||||
{
|
||||
id: 'resource',
|
||||
header: 'Resource',
|
||||
cell: ({ row: { original: item } }: SummaryCell) => item.resource,
|
||||
cell: ({ row: { original: item } }: SummaryCell) => item.kind,
|
||||
},
|
||||
{
|
||||
id: 'created',
|
||||
@@ -58,7 +58,7 @@ export function JobSummary({ summary }: Props) {
|
||||
<InteractiveTable
|
||||
data={summary}
|
||||
columns={getSummaryColumns()}
|
||||
getRowId={(item) => item.resource || ''}
|
||||
getRowId={(item) => item.kind || ''}
|
||||
pageSize={10}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
Reference in New Issue
Block a user