mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
K8s: improve frontend resource client (#89621)
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { config, getBackendSrv } from '@grafana/runtime';
|
||||
import { contextSrv } from 'app/core/core';
|
||||
|
||||
import {
|
||||
ListOptions,
|
||||
@@ -9,6 +10,7 @@ import {
|
||||
ResourceForCreate,
|
||||
ResourceList,
|
||||
ResourceClient,
|
||||
ObjectMeta,
|
||||
} from './types';
|
||||
|
||||
export interface GroupVersionResource {
|
||||
@@ -26,13 +28,6 @@ export class ScopedResourceClient<T = object, K = string> implements ResourceCli
|
||||
this.url = `/apis/${gvr.group}/${gvr.version}/${ns}${gvr.resource}`;
|
||||
}
|
||||
|
||||
public async create(obj: ResourceForCreate<T, K>): Promise<void> {
|
||||
if (!obj.metadata.name && !obj.metadata.generateName) {
|
||||
obj.metadata.generateName = 'g'; // Triggers the server to create a unique value
|
||||
}
|
||||
return getBackendSrv().post(this.url, obj);
|
||||
}
|
||||
|
||||
public async get(name: string): Promise<Resource<T, K>> {
|
||||
return getBackendSrv().get<Resource<T, K>>(`${this.url}/${name}`);
|
||||
}
|
||||
@@ -49,7 +44,19 @@ export class ScopedResourceClient<T = object, K = string> implements ResourceCli
|
||||
return getBackendSrv().get<ResourceList<T, K>>(this.url, opts);
|
||||
}
|
||||
|
||||
public async create(obj: ResourceForCreate<T, K>): Promise<Resource<T, K>> {
|
||||
if (!obj.metadata.name && !obj.metadata.generateName) {
|
||||
const login = contextSrv.user.login;
|
||||
// GenerateName lets the apiserver create a new uid for the name
|
||||
// THe passed in value is the suggested prefix
|
||||
obj.metadata.generateName = login ? login.slice(0, 2) : 'g';
|
||||
}
|
||||
setOriginAsUI(obj.metadata);
|
||||
return getBackendSrv().post(this.url, obj);
|
||||
}
|
||||
|
||||
public async update(obj: Resource<T, K>): Promise<Resource<T, K>> {
|
||||
setOriginAsUI(obj.metadata);
|
||||
return getBackendSrv().put<Resource<T, K>>(`${this.url}/${obj.metadata.name}`, obj);
|
||||
}
|
||||
|
||||
@@ -90,3 +97,13 @@ export class ScopedResourceClient<T = object, K = string> implements ResourceCli
|
||||
.join(',');
|
||||
}
|
||||
}
|
||||
|
||||
// add the origin annotations so we know what was set from the UI
|
||||
function setOriginAsUI(meta: Partial<ObjectMeta>) {
|
||||
if (!meta.annotations) {
|
||||
meta.annotations = {};
|
||||
}
|
||||
meta.annotations.AnnoKeyOriginName = 'UI';
|
||||
meta.annotations.AnnoKeyOriginPath = window.location.pathname;
|
||||
meta.annotations.AnnoKeyOriginHash = config.buildInfo.versionString;
|
||||
}
|
||||
|
||||
@@ -33,12 +33,13 @@ export const AnnoKeyCreatedBy = 'grafana.app/createdBy';
|
||||
export const AnnoKeyUpdatedTimestamp = 'grafana.app/updatedTimestamp';
|
||||
export const AnnoKeyUpdatedBy = 'grafana.app/updatedBy';
|
||||
export const AnnoKeyFolder = 'grafana.app/folder';
|
||||
export const AnnoKeyMessage = 'grafana.app/message';
|
||||
export const AnnoKeySlug = 'grafana.app/slug';
|
||||
|
||||
// Identify where values came from
|
||||
const AnnoKeyOriginName = 'grafana.app/originName';
|
||||
const AnnoKeyOriginPath = 'grafana.app/originPath';
|
||||
const AnnoKeyOriginKey = 'grafana.app/originKey';
|
||||
const AnnoKeyOriginHash = 'grafana.app/originHash';
|
||||
const AnnoKeyOriginTimestamp = 'grafana.app/originTimestamp';
|
||||
|
||||
type GrafanaAnnotations = {
|
||||
@@ -50,7 +51,7 @@ type GrafanaAnnotations = {
|
||||
|
||||
[AnnoKeyOriginName]?: string;
|
||||
[AnnoKeyOriginPath]?: string;
|
||||
[AnnoKeyOriginKey]?: string;
|
||||
[AnnoKeyOriginHash]?: string;
|
||||
[AnnoKeyOriginTimestamp]?: string;
|
||||
|
||||
// Any key value
|
||||
@@ -142,7 +143,7 @@ export interface MetaStatus {
|
||||
}
|
||||
|
||||
export interface ResourceClient<T = object, K = string> {
|
||||
create(obj: ResourceForCreate<T, K>): Promise<void>;
|
||||
create(obj: ResourceForCreate<T, K>): Promise<Resource<T, K>>;
|
||||
get(name: string): Promise<Resource<T, K>>;
|
||||
subresource<S>(name: string, path: string): Promise<S>;
|
||||
list(opts?: ListOptions): Promise<ResourceList<T, K>>;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ResourceClient } from 'app/features/apiserver/types';
|
||||
import { SaveDashboardCommand } from 'app/features/dashboard/components/SaveDashboard/types';
|
||||
import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher';
|
||||
import { DeleteDashboardResponse } from 'app/features/manage-dashboards/types';
|
||||
import { DashboardDTO, DashboardDataDTO } from 'app/types';
|
||||
import { DashboardDTO, DashboardDataDTO, SaveDashboardResponseDTO } from 'app/types';
|
||||
|
||||
import { getScopesFromUrl } from '../utils/getScopesFromUrl';
|
||||
|
||||
@@ -12,7 +12,7 @@ export interface DashboardAPI {
|
||||
/** Get a dashboard with the access control metadata */
|
||||
getDashboardDTO(uid: string): Promise<DashboardDTO>;
|
||||
/** Save dashboard */
|
||||
saveDashboard(options: SaveDashboardCommand): Promise<unknown>;
|
||||
saveDashboard(options: SaveDashboardCommand): Promise<SaveDashboardResponseDTO>;
|
||||
/** Delete a dashboard */
|
||||
deleteDashboard(uid: string, showSuccessAlert: boolean): Promise<DeleteDashboardResponse>;
|
||||
}
|
||||
@@ -21,10 +21,10 @@ export interface DashboardAPI {
|
||||
class LegacyDashboardAPI implements DashboardAPI {
|
||||
constructor() {}
|
||||
|
||||
saveDashboard(options: SaveDashboardCommand): Promise<unknown> {
|
||||
saveDashboard(options: SaveDashboardCommand): Promise<SaveDashboardResponseDTO> {
|
||||
dashboardWatcher.ignoreNextSave();
|
||||
|
||||
return getBackendSrv().post('/api/dashboards/db/', {
|
||||
return getBackendSrv().post<SaveDashboardResponseDTO>('/api/dashboards/db/', {
|
||||
dashboard: options.dashboard,
|
||||
message: options.message ?? '',
|
||||
overwrite: options.overwrite ?? false,
|
||||
@@ -48,6 +48,7 @@ class LegacyDashboardAPI implements DashboardAPI {
|
||||
// Implemented using /apis/dashboards.grafana.app/*
|
||||
class K8sDashboardAPI implements DashboardAPI {
|
||||
private client: ResourceClient<DashboardDataDTO>;
|
||||
|
||||
constructor(private legacy: DashboardAPI) {
|
||||
this.client = new ScopedResourceClient<DashboardDataDTO>({
|
||||
group: 'dashboard.grafana.app',
|
||||
@@ -56,7 +57,7 @@ class K8sDashboardAPI implements DashboardAPI {
|
||||
});
|
||||
}
|
||||
|
||||
saveDashboard(options: SaveDashboardCommand): Promise<unknown> {
|
||||
saveDashboard(options: SaveDashboardCommand): Promise<SaveDashboardResponseDTO> {
|
||||
return this.legacy.saveDashboard(options);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,9 @@ class K8sAPI implements PlaylistAPI {
|
||||
|
||||
async createPlaylist(playlist: Playlist): Promise<void> {
|
||||
const body = this.playlistAsK8sResource(playlist);
|
||||
await withErrorHandling(() => this.server.create(body));
|
||||
await withErrorHandling(async () => {
|
||||
await this.server.create(body);
|
||||
});
|
||||
}
|
||||
|
||||
async updatePlaylist(playlist: Playlist): Promise<void> {
|
||||
|
||||
Reference in New Issue
Block a user