diff --git a/pkg/registry/apis/dashboard/legacy/sql_dashboards.go b/pkg/registry/apis/dashboard/legacy/sql_dashboards.go index 63048f6f7b2..5238b7ffd83 100644 --- a/pkg/registry/apis/dashboard/legacy/sql_dashboards.go +++ b/pkg/registry/apis/dashboard/legacy/sql_dashboards.go @@ -304,14 +304,17 @@ func (a *dashboardSqlAccess) scanRow(rows *sql.Rows, history bool) (*dashboardRo } if origin_name.String != "" { + editable := a.provisioning.GetAllowUIUpdatesFromConfig(origin_name.String) + prefix := a.provisioning.GetDashboardProvisionerResolvedPath(origin_name.String) + "/" meta.SetSourceProperties(utils.SourceProperties{ - Path: origin_path.String, + Path: strings.TrimPrefix(origin_path.String, prefix), Checksum: origin_hash.String, TimestampMillis: origin_ts.Int64, }) meta.SetManagerProperties(utils.ManagerProperties{ - Kind: utils.ManagerKindClassicFP, // nolint:staticcheck - Identity: origin_name.String, + Kind: utils.ManagerKindClassicFP, // nolint:staticcheck + Identity: origin_name.String, + AllowsEdits: editable, }) } else if plugin_id.String != "" { meta.SetManagerProperties(utils.ManagerProperties{ diff --git a/pkg/services/dashboards/service/dashboard_service.go b/pkg/services/dashboards/service/dashboard_service.go index 0d1c9cebcb0..cb0e8352b2e 100644 --- a/pkg/services/dashboards/service/dashboard_service.go +++ b/pkg/services/dashboards/service/dashboard_service.go @@ -1849,6 +1849,8 @@ func (dr *DashboardServiceImpl) saveProvisionedDashboardThroughK8s(ctx context.C m := utils.ManagerProperties{} s := utils.SourceProperties{} if !unprovision { + // TODO: the path should be relative to the root + // HOWEVER, maybe OK to leave this for now and "fix" it by using file provisioning for mode 4 m.Kind = utils.ManagerKindClassicFP // nolint:staticcheck m.Identity = provisioning.Name s.Path = provisioning.ExternalID diff --git a/pkg/storage/unified/apistore/managed.go b/pkg/storage/unified/apistore/managed.go index 531a5efec03..1bb9e9f5c65 100644 --- a/pkg/storage/unified/apistore/managed.go +++ b/pkg/storage/unified/apistore/managed.go @@ -114,11 +114,13 @@ func (s *Storage) handleManagedResourceRouting(ctx context.Context, return fmt.Errorf("expected managed resource") } if repo.Kind != utils.ManagerKindRepo { - return fmt.Errorf("expected managed repository") + if !repo.AllowsEdits { + return fmt.Errorf("managed resource does not allow edits") + } } src, ok := obj.GetSourceProperties() if !ok || src.Path == "" { - return fmt.Errorf("missing source properties") + return fmt.Errorf("managed resource is missing source path annotation") } cfg, err := s.configProvider.GetRestConfig(ctx) diff --git a/public/app/features/apiserver/types.ts b/public/app/features/apiserver/types.ts index 36730c2ba7a..ebede3c24d0 100644 --- a/public/app/features/apiserver/types.ts +++ b/public/app/features/apiserver/types.ts @@ -48,6 +48,7 @@ export enum ManagerKind { export const AnnoKeyManagerKind = 'grafana.app/managedBy'; export const AnnoKeyManagerIdentity = 'grafana.app/managerId'; +export const AnnoKeyManagerAllowsEdits = 'grafana.app/managerAllowsEdits'; export const AnnoKeySourcePath = 'grafana.app/sourcePath'; export const AnnoKeySourceChecksum = 'grafana.app/sourceChecksum'; export const AnnoKeySourceTimestamp = 'grafana.app/sourceTimestamp'; @@ -84,6 +85,7 @@ type GrafanaAnnotations = { [AnnoKeyManagerKind]?: ManagerKind; [AnnoKeyManagerIdentity]?: string; + [AnnoKeyManagerAllowsEdits]?: string; [AnnoKeySourcePath]?: string; [AnnoKeySourceChecksum]?: string; [AnnoKeySourceTimestamp]?: string; diff --git a/public/app/features/dashboard/api/v1.ts b/public/app/features/dashboard/api/v1.ts index 00b3a56a7a9..3235d9dbbf0 100644 --- a/public/app/features/dashboard/api/v1.ts +++ b/public/app/features/dashboard/api/v1.ts @@ -12,6 +12,10 @@ import { AnnoKeyGrantPermissions, Resource, DeprecatedInternalId, + AnnoKeyManagerKind, + AnnoKeySourcePath, + AnnoKeyManagerAllowsEdits, + ManagerKind, } from 'app/features/apiserver/types'; import { getDashboardUrl } from 'app/features/dashboard-scene/utils/getDashboardUrl'; import { DeleteDashboardResponse } from 'app/features/manage-dashboards/types'; @@ -126,6 +130,14 @@ export class K8sDashboardAPI implements DashboardAPI { }, }; + const annotations = dash.metadata.annotations ?? {}; + const managerKind = annotations[AnnoKeyManagerKind]; + + if (managerKind) { + result.meta.provisioned = annotations[AnnoKeyManagerAllowsEdits] === 'true' || managerKind === ManagerKind.Repo; + result.meta.provisionedExternalId = annotations[AnnoKeySourcePath]; + } + if (dash.metadata.labels?.[DeprecatedInternalId]) { result.dashboard.id = parseInt(dash.metadata.labels[DeprecatedInternalId], 10); }