update annotations

pull/101598/head
Ryan McKinley 5 months ago
parent e51c5796df
commit 0922a86c02
  1. 6
      pkg/registry/apis/provisioning/controller/finalizers.go
  2. 4
      pkg/registry/apis/provisioning/jobs/export/resources.go
  3. 9
      pkg/registry/apis/provisioning/jobs/migrate/resources.go
  4. 13
      pkg/registry/apis/provisioning/jobs/sync/worker.go
  5. 20
      pkg/registry/apis/provisioning/resources/parser.go
  6. 3
      pkg/registry/apis/provisioning/resources/tree.go
  7. 16
      public/app/features/apiserver/types.ts
  8. 16
      public/app/features/dashboard-scene/saving/provisioned/hooks.ts
  9. 8
      public/app/features/provisioning/dashboard.ts

@ -54,9 +54,9 @@ func (f *finalizer) process(ctx context.Context,
err := f.processExistingItems(ctx, repo.Config(), err := f.processExistingItems(ctx, repo.Config(),
func(client dynamic.ResourceInterface, item *provisioning.ResourceListItem) error { func(client dynamic.ResourceInterface, item *provisioning.ResourceListItem) error {
_, err := client.Patch(ctx, item.Name, types.JSONPatchType, []byte(`[ _, err := client.Patch(ctx, item.Name, types.JSONPatchType, []byte(`[
{"op": "remove", "path": "/metadata/annotations/`+utils.AnnoKeyRepoName+`" }, {"op": "remove", "path": "/metadata/annotations/`+utils.AnnoKeyManagerKind+`" },
{"op": "remove", "path": "/metadata/annotations/`+utils.AnnoKeyRepoPath+`" }, {"op": "remove", "path": "/metadata/annotations/`+utils.AnnoKeyManagerIdentity+`" },
{"op": "remove", "path": "/metadata/annotations/`+utils.AnnoKeyRepoHash+`" } {"op": "remove", "path": "/metadata/annotations/`+utils.AnnoKeySourcePath+`" }
]`), v1.PatchOptions{}) ]`), v1.PatchOptions{})
return err return err
}) })

@ -92,8 +92,8 @@ func (r *exportJob) write(ctx context.Context, obj *unstructured.Unstructured) j
} }
name := meta.GetName() name := meta.GetName()
repoName := meta.GetRepositoryName() manager, _ := meta.GetManagerProperties()
if repoName == r.target.Config().GetName() { if manager.Identity == r.target.Config().GetName() {
result.Action = repository.FileActionIgnored result.Action = repository.FileActionIgnored
return result return result
} }

@ -48,8 +48,9 @@ func (r *resourceReader) Write(ctx context.Context, key *resource.ResourceKey, v
return fmt.Errorf("failed to unmarshal unstructured: %w", err) return fmt.Errorf("failed to unmarshal unstructured: %w", err)
} }
// clear anything so it will get written // clear all manager fields so they are not exported
parsed.Meta.SetRepositoryInfo(nil) parsed.Meta.SetManagerProperties(utils.ManagerProperties{})
parsed.Meta.SetSourceProperties(utils.SourceProperties{})
if result := r.job.write(ctx, parsed.Obj); result.Error != nil { if result := r.job.write(ctx, parsed.Obj); result.Error != nil {
r.job.progress.Record(ctx, result) r.job.progress.Record(ctx, result)
@ -134,8 +135,8 @@ func (j *migrationJob) write(ctx context.Context, obj *unstructured.Unstructured
} }
name := meta.GetName() name := meta.GetName()
repoName := meta.GetRepositoryName() manager, _ := meta.GetManagerProperties()
if repoName == j.target.Config().GetName() { if manager.Identity == j.target.Config().GetName() {
result.Action = repository.FileActionIgnored result.Action = repository.FileActionIgnored
return result return result
} }

@ -538,7 +538,7 @@ func (r *syncJob) ensureFolderExists(ctx context.Context, folder resources.Folde
cfg := r.repository.Config() cfg := r.repository.Config()
obj, err := r.folders.Get(ctx, folder.ID, metav1.GetOptions{}) obj, err := r.folders.Get(ctx, folder.ID, metav1.GetOptions{})
if err == nil { if err == nil {
current, ok := obj.GetAnnotations()[utils.AnnoKeyRepoName] current, ok := obj.GetAnnotations()[utils.AnnoKeyManagerIdentity]
if !ok { if !ok {
return fmt.Errorf("target folder is not managed by a repository") return fmt.Errorf("target folder is not managed by a repository")
} }
@ -568,11 +568,12 @@ func (r *syncJob) ensureFolderExists(ctx context.Context, folder resources.Folde
if parent != "" { if parent != "" {
meta.SetFolder(parent) meta.SetFolder(parent)
} }
meta.SetRepositoryInfo(&utils.ResourceRepositoryInfo{ meta.SetManagerProperties(utils.ManagerProperties{
Name: cfg.GetName(), Kind: utils.ManagerKindRepo,
Path: folder.Path, Identity: cfg.GetName(),
Hash: "", // FIXME: which hash? })
Timestamp: nil, // ???&info.Modified.Time, meta.SetSourceProperties(utils.SourceProperties{
Path: folder.Path,
}) })
result := jobs.JobResourceResult{ result := jobs.JobResourceResult{

@ -130,11 +130,14 @@ func (r *Parser) Parse(ctx context.Context, info *repository.FileInfo, validate
} }
obj.SetNamespace(cfg.GetNamespace()) obj.SetNamespace(cfg.GetNamespace())
parsed.Meta.SetRepositoryInfo(&utils.ResourceRepositoryInfo{ parsed.Meta.SetManagerProperties(utils.ManagerProperties{
Name: cfg.Name, Kind: utils.ManagerKindRepo,
Path: info.Path, // joinPathWithRef(info.Path, info.Ref), Identity: cfg.Name,
Hash: info.Hash, })
Timestamp: nil, // ???&info.Modified.Time, parsed.Meta.SetSourceProperties(utils.SourceProperties{
Path: info.Path, // joinPathWithRef(info.Path, info.Ref),
Checksum: info.Hash,
TimestampMillis: asMillis(info.Modified),
}) })
// Calculate name+folder from the file path // Calculate name+folder from the file path
@ -211,6 +214,13 @@ func (f *ParsedResource) ToSaveBytes() ([]byte, error) {
} }
} }
func asMillis(t *metav1.Time) int64 {
if t == nil || t.IsZero() {
return 0
}
return t.UnixMilli()
}
func (f *ParsedResource) AsResourceWrapper() *provisioning.ResourceWrapper { func (f *ParsedResource) AsResourceWrapper() *provisioning.ResourceWrapper {
info := f.Info info := f.Info
res := provisioning.ResourceObjects{ res := provisioning.ResourceObjects{

@ -104,7 +104,8 @@ func (t *FolderTree) AddUnstructured(item *unstructured.Unstructured, skipRepo s
if err != nil { if err != nil {
return fmt.Errorf("extract meta accessor: %w", err) return fmt.Errorf("extract meta accessor: %w", err)
} }
if meta.GetRepositoryName() == skipRepo { manager, _ := meta.GetManagerProperties()
if manager.Identity == skipRepo {
return nil // skip it... already in tree? return nil // skip it... already in tree?
} }
folder := Folder{ folder := Folder{

@ -44,10 +44,10 @@ export const AnnoKeyMessage = 'grafana.app/message';
export const AnnoKeySlug = 'grafana.app/slug'; export const AnnoKeySlug = 'grafana.app/slug';
// Identify where values came from // Identify where values came from
export const AnnoKeyRepoName = 'grafana.app/repoName'; export const AnnoKeyManagerKind = 'grafana.app/managerKind';
export const AnnoKeyRepoPath = 'grafana.app/repoPath'; export const AnnoKeyManagerIdentity = 'grafana.app/managerIdentity';
export const AnnoKeyRepoHash = 'grafana.app/repoHash'; export const AnnoKeySourcePath = 'grafana.app/sourcePath';
export const AnnoKeyRepoTimestamp = 'grafana.app/repoTimestamp'; export const AnnoKeySourceChecksum = 'grafana.app/sourceChecksum';
export const AnnoKeySavedFromUI = 'grafana.app/saved-from-ui'; export const AnnoKeySavedFromUI = 'grafana.app/saved-from-ui';
export const AnnoKeyDashboardNotFound = 'grafana.app/dashboard-not-found'; export const AnnoKeyDashboardNotFound = 'grafana.app/dashboard-not-found';
@ -66,10 +66,10 @@ type GrafanaAnnotations = {
[AnnoKeyFolder]?: string; [AnnoKeyFolder]?: string;
[AnnoKeySlug]?: string; [AnnoKeySlug]?: string;
[AnnoKeyRepoName]?: string; [AnnoKeyManagerKind]?: string;
[AnnoKeyRepoPath]?: string; [AnnoKeyManagerIdentity]?: string;
[AnnoKeyRepoHash]?: string; [AnnoKeySourcePath]?: string;
[AnnoKeyRepoTimestamp]?: string; [AnnoKeySourceChecksum]?: string;
}; };
// Annotations provided by the front-end client // Annotations provided by the front-end client

@ -1,7 +1,7 @@
import { Chance } from 'chance'; import { Chance } from 'chance';
import { dateTime } from '@grafana/data'; import { dateTime } from '@grafana/data';
import { AnnoKeyRepoName, AnnoKeyRepoPath } from 'app/features/apiserver/types'; import { AnnoKeyManagerKind, AnnoKeyManagerIdentity, AnnoKeySourcePath } from 'app/features/apiserver/types';
import { useGetResourceRepository } from 'app/features/provisioning/hooks'; import { useGetResourceRepository } from 'app/features/provisioning/hooks';
import { DashboardMeta } from 'app/types'; import { DashboardMeta } from 'app/types';
@ -25,10 +25,12 @@ function generatePath(timestamp: string, pathFromAnnotation?: string, slug?: str
export function useDefaultValues({ meta, defaultTitle, defaultDescription }: UseDefaultValuesParams) { export function useDefaultValues({ meta, defaultTitle, defaultDescription }: UseDefaultValuesParams) {
const annotations = meta.k8s?.annotations; const annotations = meta.k8s?.annotations;
const annoName = annotations?.[AnnoKeyRepoName]; const managerKind = annotations?.[AnnoKeyManagerKind];
const annoPath = annotations?.[AnnoKeyRepoPath]; const managerId = annotations?.[AnnoKeyManagerIdentity];
const sourcePath = annotations?.[AnnoKeySourcePath];
// Get config by resource name or folder UID for new resources // Get config by resource name or folder UID for new resources
const repositoryConfig = useGetResourceRepository({ name: annoName, folderUid: meta.folderUid }); const repositoryConfig =
managerKind === 'repo' ? useGetResourceRepository({ name: managerId, folderUid: meta.folderUid }) : undefined;
const repository = repositoryConfig?.spec; const repository = repositoryConfig?.spec;
const random = Chance(1); const random = Chance(1);
@ -37,8 +39,8 @@ export function useDefaultValues({ meta, defaultTitle, defaultDescription }: Use
return { return {
values: { values: {
ref: `dashboard/${timestamp}`, ref: `dashboard/${timestamp}`,
path: generatePath(timestamp, annoPath, meta.slug), path: generatePath(timestamp, sourcePath, meta.slug),
repo: annoName || repositoryConfig?.metadata?.name || '', repo: managerId || repositoryConfig?.metadata?.name || '',
comment: '', comment: '',
folder: { folder: {
uid: meta.folderUid, uid: meta.folderUid,
@ -48,7 +50,7 @@ export function useDefaultValues({ meta, defaultTitle, defaultDescription }: Use
description: defaultDescription ?? '', description: defaultDescription ?? '',
workflow: getDefaultWorkflow(repository), workflow: getDefaultWorkflow(repository),
}, },
isNew: !annoName, isNew: !managerId,
repositoryConfig: repository, repositoryConfig: repository,
isGitHub: repository?.type === 'github', isGitHub: repository?.type === 'github',
}; };

@ -1,7 +1,7 @@
import { getBackendSrv } from '@grafana/runtime'; import { getBackendSrv } from '@grafana/runtime';
import { DashboardDTO } from 'app/types'; import { DashboardDTO } from 'app/types';
import { AnnoKeyRepoName, AnnoKeyRepoPath } from '../apiserver/types'; import { AnnoKeyManagerIdentity, AnnoKeySourcePath } from '../apiserver/types';
import { BASE_URL } from './api/baseAPI'; import { BASE_URL } from './api/baseAPI';
@ -32,10 +32,10 @@ export async function loadDashboardFromProvisioning(repo: string, path: string):
if (!anno) { if (!anno) {
dryRun.metadata.annotations = anno = {}; dryRun.metadata.annotations = anno = {};
} }
anno[AnnoKeyRepoName] = repo; anno[AnnoKeyManagerIdentity] = repo;
anno[AnnoKeyRepoPath] = path; anno[AnnoKeySourcePath] = path;
if (ref) { if (ref) {
anno[AnnoKeyRepoPath] = path + '#' + ref; anno[AnnoKeySourcePath] = path + '#' + ref;
} }
return { return {

Loading…
Cancel
Save