From 811bd991001adb43508e8110926e8fbd49c4eda2 Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Mon, 4 Mar 2024 14:10:27 -0500 Subject: [PATCH 01/11] fix(topology): update for new GraphQL schema --- .../CreateRecording/CustomRecordingForm.tsx | 2 +- src/app/CreateRecording/types.ts | 2 + src/app/RecordingMetadata/BulkEditLabels.tsx | 2 +- src/app/Shared/Services/Api.service.tsx | 132 ++++++++++++------ src/app/Shared/Services/api.types.ts | 43 ++++-- src/app/Topology/Actions/utils.tsx | 63 +++++---- src/app/utils/fakeData.ts | 4 +- .../CustomRecordingForm.test.tsx | 2 +- .../RecordingMetadata/BulkEditLabels.test.tsx | 8 +- 9 files changed, 160 insertions(+), 98 deletions(-) diff --git a/src/app/CreateRecording/CustomRecordingForm.tsx b/src/app/CreateRecording/CustomRecordingForm.tsx index ee34aa0ea..dfe0a1688 100644 --- a/src/app/CreateRecording/CustomRecordingForm.tsx +++ b/src/app/CreateRecording/CustomRecordingForm.tsx @@ -253,7 +253,7 @@ export const CustomRecordingForm: React.FC = () => { events: eventSpecifierString, duration: continuous ? undefined : duration * (durationUnit / 1000), archiveOnStop: archiveOnStop && !continuous, - restart: restart, + replace: restart ? 'ALWAYS' : 'NEVER', advancedOptions: { toDisk: toDisk, maxAge: toDisk ? (continuous ? maxAge * maxAgeUnit : undefined) : undefined, diff --git a/src/app/CreateRecording/types.ts b/src/app/CreateRecording/types.ts index e11288c17..00d9492b7 100644 --- a/src/app/CreateRecording/types.ts +++ b/src/app/CreateRecording/types.ts @@ -18,6 +18,8 @@ import { ValidatedOptions } from '@patternfly/react-core'; export type EventTemplateIdentifier = Pick; +export type RecordingReplace = 'ALWAYS' | 'NEVER' | 'STOPPED'; + interface _FormBaseData { name: string; template?: EventTemplateIdentifier; diff --git a/src/app/RecordingMetadata/BulkEditLabels.tsx b/src/app/RecordingMetadata/BulkEditLabels.tsx index 3ecb392ec..cd5b931be 100644 --- a/src/app/RecordingMetadata/BulkEditLabels.tsx +++ b/src/app/RecordingMetadata/BulkEditLabels.tsx @@ -205,7 +205,7 @@ export const BulkEditLabels: React.FC = ({ { connectUrl: target.connectUrl }, ), ), - map((v) => v.data.targetNodes[0].recordings.archived.data as ArchivedRecording[]), + map((v) => v.data.targetNodes[0].target.recordings.archived.data as ArchivedRecording[]), first(), ); } diff --git a/src/app/Shared/Services/Api.service.tsx b/src/app/Shared/Services/Api.service.tsx index 4f8b3b7a4..faf531d50 100644 --- a/src/app/Shared/Services/Api.service.tsx +++ b/src/app/Shared/Services/Api.service.tsx @@ -45,21 +45,23 @@ import { CredentialsResponse, RulesResponse, EnvironmentNode, - DiscoveryResponse, - ActiveRecordingFilterInput, + ActiveRecordingsFilterInput, RecordingCountResponse, MBeanMetrics, MBeanMetricsResponse, EventType, NotificationCategory, - NullableTarget, HttpError, SimpleResponse, XMLHttpError, XMLHttpRequestConfig, XMLHttpResponse, KeyValue, - CustomTargetStub, + TargetStub, + TargetForTest, + Metadata, + TargetMetadata, + isTargetMetadata, } from './api.types'; import { isHttpError, includesTarget, isHttpOk, isXMLHttpError } from './api.utils'; import { LoginService } from './Login.service'; @@ -171,7 +173,7 @@ export class ApiService { } createTarget( - target: CustomTargetStub, + target: TargetStub, credentials?: { username?: string; password?: string }, storeCredentials = false, dryrun = false, @@ -207,7 +209,7 @@ export class ApiService { ); } - deleteTarget(target: Target): Observable { + deleteTarget(target: TargetStub): Observable { return this.sendRequest('v2', `targets/${encodeURIComponent(target.connectUrl)}`, { method: 'DELETE', }).pipe( @@ -296,7 +298,7 @@ export class ApiService { name, events, duration, - restart, + replace, archiveOnStop, metadata, advancedOptions, @@ -310,19 +312,11 @@ export class ApiService { if (archiveOnStop != undefined) { form.append('archiveOnStop', String(archiveOnStop)); } - const transformedMetadata = { - labels: {}, - annotations: { - cryostat: {}, - platform: {}, - }, - }; - metadata?.labels.forEach((label) => (transformedMetadata.labels[label.key] = label.value)); if (metadata) { - form.append('metadata', JSON.stringify(transformedMetadata)); + form.append('metadata', JSON.stringify(this.transformMetadataToObject(metadata))); } - if (restart != undefined) { - form.append('restart', String(restart)); + if (replace != undefined) { + form.append('replace', String(replace)); } if (advancedOptions) { if (advancedOptions.toDisk != undefined) { @@ -489,7 +483,7 @@ export class ApiService { } uploadArchivedRecordingToGrafana( - sourceTarget: Observable, + sourceTarget: Observable, recordingName: string, ): Observable { return sourceTarget.pipe( @@ -531,7 +525,13 @@ export class ApiService { ); } - transformAndStringifyToRawLabels(labels: KeyValue[]) { + // FIXME remove this, all API endpoints that allow us to send labels in the request body should accept it in as-is JSON form + stringifyRecordingLabels(labels: KeyValue | KeyValue[]): string { + return JSON.stringify(labels).replace(/"([^"]+)":/g, '$1:'); + } + + // FIXME remove this, all API endpoints that allow us to send labels in the request body should accept it in as-is JSON form + transformAndStringifyToRawLabels(labels: KeyValue[]): string { const rawLabels = {}; for (const label of labels) { rawLabels[label.key] = label.value; @@ -539,6 +539,30 @@ export class ApiService { return JSON.stringify(rawLabels); } + transformMetadataToObject(metadata: Metadata | TargetMetadata): object { + if (isTargetMetadata(metadata)) { + return { + labels: this.transformLabelsToObject(metadata.labels), + annotations: { + cryostat: this.transformLabelsToObject(metadata?.annotations?.cryostat), + platform: this.transformLabelsToObject(metadata?.annotations?.platform), + }, + }; + } else { + return { + labels: this.transformLabelsToObject(metadata.labels), + }; + } + } + + transformLabelsToObject(labels: KeyValue[]): object { + const out = {}; + for (const label of labels) { + out[label.key] = label.value; + } + return out; + } + postRecordingMetadataFromPath(jvmId: string, recordingName: string, labels: KeyValue[]): Observable { return this.sendRequest( 'beta', @@ -734,7 +758,7 @@ export class ApiService { } getActiveProbesForTarget( - target: Target, + target: TargetStub, suppressNotifications = false, skipStatusCheck = false, ): Observable { @@ -922,7 +946,7 @@ export class ApiService { { connectUrl: target.connectUrl, recordingName, labels: this.stringifyRecordingLabels(labels) }, ), ), - map((v) => v.data.targetNodes[0].recordings.archived as ArchivedRecording[]), + map((v) => v.data.targetNodes[0].target.recordings.archived as ArchivedRecording[]), ); } @@ -969,7 +993,7 @@ export class ApiService { { connectUrl: target.connectUrl, recordingName, labels: this.stringifyRecordingLabels(labels) }, ), ), - map((v) => v.data.targetNodes[0].recordings.active as ActiveRecording[]), + map((v) => v.data.targetNodes[0].target.recordings.active as ActiveRecording[]), ); } @@ -1043,11 +1067,10 @@ export class ApiService { } getDiscoveryTree(): Observable { - return this.sendRequest('v2.1', 'discovery', { + return this.sendRequest('v3', 'discovery', { method: 'GET', }).pipe( concatMap((resp) => resp.json()), - map((body: DiscoveryResponse) => body.data.result), first(), ); } @@ -1056,7 +1079,7 @@ export class ApiService { matchTargetsWithExpr(matchExpression: string, targets: Target[]): Observable { const body = JSON.stringify({ matchExpression, - targets, + targets: targets.map((t) => this.transformTarget(t)), }); const headers = new Headers(); headers.set('Content-Type', 'application/json'); @@ -1087,20 +1110,22 @@ export class ApiService { ); } - groupHasRecording(group: EnvironmentNode, filter: ActiveRecordingFilterInput): Observable { + groupHasRecording(group: EnvironmentNode, filter: ActiveRecordingsFilterInput): Observable { return this.graphql( ` - query GetRecordingForGroup ($groupFilter: EnvironmentNodeFilterInput, $recordingFilter: ActiveRecordingFilterInput){ + query GetRecordingForGroup ($groupFilter: EnvironmentNodesFilterInput, $recordingFilter: ActiveRecordingsFilterInput){ environmentNodes(filter: $groupFilter) { name descendantTargets { name - recordings { + target { + recordings { active(filter: $recordingFilter) { - data { - name - } + data { + name + } } + } } } } @@ -1114,7 +1139,7 @@ export class ApiService { first(), map((body) => body.data.environmentNodes[0].descendantTargets.reduce( - (acc: Partial[], curr) => acc.concat(curr.recordings?.active?.data || []), + (acc: Partial[], curr) => acc.concat(curr.target.recordings?.active?.data || []), [] as Partial[], ), ), @@ -1123,10 +1148,10 @@ export class ApiService { ); } - targetHasRecording(target: Target, filter: ActiveRecordingFilterInput = {}): Observable { + targetHasRecording(target: TargetStub, filter: ActiveRecordingsFilterInput = {}): Observable { return this.graphql( ` - query ActiveRecordingsForJFRMetrics($connectUrl: String, $recordingFilter: ActiveRecordingFilterInput) { + query ActiveRecordingsForJFRMetrics($connectUrl: String, $recordingFilter: ActiveRecordingsFilterInput) { targetNodes(filter: { name: $connectUrl }) { recordings { active (filter: $recordingFilter) { @@ -1149,7 +1174,7 @@ export class ApiService { if (nodes.length === 0) { return false; } - const count = nodes[0].recordings.active.aggregate.count; + const count = nodes[0].target.recordings.active.aggregate.count; return count > 0; }), catchError((_) => of(false)), @@ -1157,7 +1182,7 @@ export class ApiService { } checkCredentialForTarget( - target: Target, + target: TargetStub, credentials: { username: string; password: string }, ): Observable< | { @@ -1210,7 +1235,7 @@ export class ApiService { ); } - getTargetMBeanMetrics(target: Target, queries: string[]): Observable { + getTargetMBeanMetrics(target: TargetStub, queries: string[]): Observable { return this.graphql( ` query MBeanMXMetricsForTarget($connectUrl: String) { @@ -1235,7 +1260,7 @@ export class ApiService { ); } - getTargetArchivedRecordings(target: Target): Observable { + getTargetArchivedRecordings(target: TargetStub): Observable { return this.graphql( ` query ArchivedRecordingsForTarget($connectUrl: String) { @@ -1245,7 +1270,10 @@ export class ApiService { downloadUrl reportUrl metadata { - labels + labels { + key + value + } } size archivedTime @@ -1258,7 +1286,7 @@ export class ApiService { ).pipe(map((v) => v.data.archivedRecordings.data as ArchivedRecording[])); } - getTargetActiveRecordings(target: Target): Observable { + getTargetActiveRecordings(target: TargetStub): Observable { return this.doGet( `targets/${encodeURIComponent(target.connectUrl)}/recordings`, 'v1', @@ -1268,7 +1296,7 @@ export class ApiService { ); } - getTargetEventTemplates(target: Target): Observable { + getTargetEventTemplates(target: TargetStub): Observable { return this.doGet( `targets/${encodeURIComponent(target.connectUrl)}/templates`, 'v1', @@ -1278,7 +1306,7 @@ export class ApiService { ); } - getTargetEventTypes(target: Target): Observable { + getTargetEventTypes(target: TargetStub): Observable { return this.doGet( `targets/${encodeURIComponent(target.connectUrl)}/events`, 'v1', @@ -1317,8 +1345,22 @@ export class ApiService { anchor.remove(); } - stringifyRecordingLabels(labels: KeyValue[]): string { - return JSON.stringify(labels).replace(/"([^"]+)":/g, '$1:'); + private transformTarget(target: Target): TargetForTest { + const out: TargetForTest = { + alias: target.alias, + connectUrl: target.connectUrl, + labels: {}, + annotations: { cryostat: {}, platform: {} }, + }; + for (const l of target.labels) { + out.labels[l.key] = l.value; + } + for (const s of ['cryostat', 'platform']) { + for (const e of out.annotations[s]) { + target.annotations[s][e.key] = e.value; + } + } + return out; } private sendRequest( diff --git a/src/app/Shared/Services/api.types.ts b/src/app/Shared/Services/api.types.ts index 2bd3b0ba3..b7a92003b 100644 --- a/src/app/Shared/Services/api.types.ts +++ b/src/app/Shared/Services/api.types.ts @@ -14,10 +14,11 @@ * limitations under the License. */ +import { RecordingReplace } from '@app/CreateRecording/types'; import { AlertVariant } from '@patternfly/react-core'; import { Observable } from 'rxjs'; -export type ApiVersion = 'v1' | 'v2' | 'v2.1' | 'v2.2' | 'v2.3' | 'v2.4' | 'beta'; +export type ApiVersion = 'v1' | 'v2' | 'v2.1' | 'v2.2' | 'v2.3' | 'v2.4' | 'v3' | 'beta'; // ====================================== // Common Resources @@ -29,7 +30,17 @@ export interface KeyValue { export interface Metadata { labels: KeyValue[]; - annotations?: KeyValue[]; +} + +export type TargetMetadata = Metadata & { + annotations: { + cryostat: KeyValue[]; + platform: KeyValue[]; + }; +}; + +export function isTargetMetadata(metadata: Metadata | TargetMetadata): metadata is TargetMetadata { + return (metadata as TargetMetadata).annotations !== undefined; } export interface ApiV2Response { @@ -88,7 +99,12 @@ export class XMLHttpError extends Error { } } -export type CustomTargetStub = Omit; +export type TargetStub = Omit; + +export type TargetForTest = Pick & { + labels: object; + annotations: { cryostat: object; platform: object }; +}; // ====================================== // Health Resources @@ -210,7 +226,7 @@ export interface RecordingAttributes { events: string; duration?: number; archiveOnStop?: boolean; - restart?: boolean; + replace?: RecordingReplace; advancedOptions?: AdvancedRecordingOptions; metadata?: Metadata; } @@ -238,7 +254,7 @@ export interface ActiveRecording extends Recording { maxAge: number; } -export interface ActiveRecordingFilterInput { +export interface ActiveRecordingsFilterInput { name?: string; state?: string; continuous?: boolean; @@ -265,10 +281,12 @@ export interface RecordingResponse extends ApiV2Response { export interface RecordingCountResponse { data: { targetNodes: { - recordings: { - active: { - aggregate: { - count: number; + target: { + recordings: { + active: { + aggregate: { + count: number; + }; }; }; }; @@ -446,6 +464,7 @@ export const TEMPLATE_UNSUPPORTED_MESSAGE = 'The template type used in this reco // Discovery/Target resources // ====================================== export interface Target { + id?: number; // present in responses but we must not include it in requests to create targets jvmId?: string; // present in responses, but we do not need to provide it in requests connectUrl: string; alias: string; @@ -499,12 +518,6 @@ export interface TargetNode extends _AbstractNode { readonly target: Target; } -export interface DiscoveryResponse extends ApiV2Response { - data: { - result: EnvironmentNode; - }; -} - // ====================================== // Notification resources // ====================================== diff --git a/src/app/Topology/Actions/utils.tsx b/src/app/Topology/Actions/utils.tsx index aee7c9300..dd108d2f9 100644 --- a/src/app/Topology/Actions/utils.tsx +++ b/src/app/Topology/Actions/utils.tsx @@ -122,23 +122,23 @@ export const nodeActions: NodeAction[] = [ services.api .graphql( ` - query StartRecordingForGroup($filter: EnvironmentNodeFilterInput, $recordingName: String!, $labels: String) { + query StartRecordingForGroup($filter: EnvironmentNodesFilterInput!, $recordingName: String!, $metadata: RecordingMetadataInput!) { environmentNodes(filter: $filter) { name descendantTargets { name - doStartRecording(recording: { - name: $recordingName, - template: "Continuous", - templateType: "TARGET", - duration: 0, - restart: true, - metadata: { - labels: $labels - }, - }) { - name - state + target { + doStartRecording(recording: { + name: $recordingName, + template: "Continuous", + templateType: "TARGET", + duration: 0, + replace: "STOPPED", + metadata: $metadata, + }) { + name + state + } } } } @@ -147,12 +147,9 @@ export const nodeActions: NodeAction[] = [ { filter: { id: group.id }, recordingName: QUICK_RECORDING_NAME, - labels: services.api.stringifyRecordingLabels([ - { - key: QUICK_RECORDING_LABEL_KEY, - value: group.name.replace(/[\s+-]/g, '_'), - }, - ]), + metadata: { + labels: [{ key: QUICK_RECORDING_LABEL_KEY, value: group.name.replace(/[\s+-]/g, '_') }], + }, }, false, true, @@ -171,12 +168,13 @@ export const nodeActions: NodeAction[] = [ services.api .graphql( ` - query DeleteRecordingForGroup ($groupFilter: EnvironmentNodeFilterInput, $recordingFilter: ActiveRecordingFilterInput){ + query DeleteRecordingForGroup ($groupFilter: EnvironmentNodesFilterInput, $recordingFilter: ActiveRecordingsFilterInput) { environmentNodes(filter: $groupFilter) { name descendantTargets { name - recordings { + target { + recordings { active(filter: $recordingFilter) { data { doArchive { @@ -184,6 +182,7 @@ export const nodeActions: NodeAction[] = [ } } } + } } } } @@ -213,20 +212,22 @@ export const nodeActions: NodeAction[] = [ services.api .graphql( ` - query StopRecordingForGroup ($groupFilter: EnvironmentNodeFilterInput, $recordingFilter: ActiveRecordingFilterInput){ + query StopRecordingForGroup ($groupFilter: EnvironmentNodesFilterInput, $recordingFilter: ActiveRecordingsFilterInput) { environmentNodes(filter: $groupFilter) { name descendantTargets { name - recordings { + target { + recordings { active(filter: $recordingFilter) { - data { - doStop { - name - state - } + data { + doStop { + name + state } + } } + } } } } @@ -257,12 +258,13 @@ export const nodeActions: NodeAction[] = [ services.api .graphql( ` - query DeleteRecordingForGroup ($groupFilter: EnvironmentNodeFilterInput, $recordingFilter: ActiveRecordingFilterInput){ + query DeleteRecordingForGroup ($groupFilter: EnvironmentNodesFilterInput, $recordingFilter: ActiveRecordingsFilterInput) { environmentNodes(filter: $groupFilter) { name descendantTargets { name - recordings { + target { + recordings { active(filter: $recordingFilter) { data { doDelete { @@ -271,6 +273,7 @@ export const nodeActions: NodeAction[] = [ } } } + } } } } diff --git a/src/app/utils/fakeData.ts b/src/app/utils/fakeData.ts index 0075d0fa0..f6a6443d6 100644 --- a/src/app/utils/fakeData.ts +++ b/src/app/utils/fakeData.ts @@ -23,7 +23,7 @@ import { RecordingState, Recording, MBeanMetrics, - ActiveRecordingFilterInput, + ActiveRecordingsFilterInput, ArchivedRecording, EventTemplate, EventProbe, @@ -301,7 +301,7 @@ class FakeApiService extends ApiService { } // JFR Metrics card - targetHasRecording(_target: Target, _filter?: ActiveRecordingFilterInput): Observable { + targetHasRecording(_target: Target, _filter?: ActiveRecordingsFilterInput): Observable { return of(true); } diff --git a/src/test/CreateRecording/CustomRecordingForm.test.tsx b/src/test/CreateRecording/CustomRecordingForm.test.tsx index bdc185501..9392a3094 100644 --- a/src/test/CreateRecording/CustomRecordingForm.test.tsx +++ b/src/test/CreateRecording/CustomRecordingForm.test.tsx @@ -118,7 +118,7 @@ describe('', () => { events: 'template=someEventTemplate,type=CUSTOM', duration: 30, archiveOnStop: true, - restart: false, + replace: 'NEVER', advancedOptions: { maxAge: undefined, maxSize: 0, diff --git a/src/test/RecordingMetadata/BulkEditLabels.test.tsx b/src/test/RecordingMetadata/BulkEditLabels.test.tsx index cec202ce1..458eef774 100644 --- a/src/test/RecordingMetadata/BulkEditLabels.test.tsx +++ b/src/test/RecordingMetadata/BulkEditLabels.test.tsx @@ -107,9 +107,11 @@ const mockArchivedRecordingsResponse = { data: { targetNodes: [ { - recordings: { - archived: { - data: [mockArchivedRecording] as ArchivedRecording[], + target: { + recordings: { + archived: { + data: [mockArchivedRecording] as ArchivedRecording[], + }, }, }, }, From cae8d54239a4c6f3518338998f0b4e29d5dbcce0 Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Thu, 7 Mar 2024 10:35:31 -0500 Subject: [PATCH 02/11] adjust queries to avoid 'recordings' struct field and use new direct activeRecordings/archivedRecordings accessors --- .../AllTargetsArchivedRecordingsTable.tsx | 20 ++--- .../AutomatedAnalysisCard.tsx | 60 ++++++------- src/app/RecordingMetadata/BulkEditLabels.tsx | 6 +- .../Recordings/ArchivedRecordingsTable.tsx | 26 +++--- src/app/Shared/Services/Api.service.tsx | 86 +++++++++---------- src/app/Shared/Services/api.types.ts | 8 +- 6 files changed, 101 insertions(+), 105 deletions(-) diff --git a/src/app/Archives/AllTargetsArchivedRecordingsTable.tsx b/src/app/Archives/AllTargetsArchivedRecordingsTable.tsx index 6ddb90d8a..260599425 100644 --- a/src/app/Archives/AllTargetsArchivedRecordingsTable.tsx +++ b/src/app/Archives/AllTargetsArchivedRecordingsTable.tsx @@ -123,7 +123,7 @@ export const AllTargetsArchivedRecordingsTable: React.FC query ActiveRecordingsForAutomatedAnalysis($connectUrl: String) { targetNodes(filter: { name: $connectUrl }) { target { - recordings { - active (filter: { - name: "${automatedAnalysisRecordingName}", - labels: ["origin=${automatedAnalysisRecordingName}"], - }) { - data { - state - name - downloadUrl - reportUrl - metadata { - labels { - key - value - } + activeRecordings(filter: { + name: "${automatedAnalysisRecordingName}", + labels: ["origin=${automatedAnalysisRecordingName}"], + }) { + data { + state + name + downloadUrl + reportUrl + metadata { + labels { + key + value } } } @@ -213,21 +211,25 @@ export const AutomatedAnalysisCard: DashboardCardFC /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ return context.api.graphql( `query ArchivedRecordingsForAutomatedAnalysis($connectUrl: String) { - archivedRecordings(filter: { sourceTarget: $connectUrl }) { - data { - name - downloadUrl - reportUrl - metadata { - labels { - key - value + targetNodes(filter: { name: $connectUrl }) { + target { + archivedRecordings { + data { + name + downloadUrl + reportUrl + metadata { + labels { + key + value + } + } + size + archivedTime + } } } - size - archivedTime } - } }`, { connectUrl }, ); @@ -311,7 +313,7 @@ export const AutomatedAnalysisCard: DashboardCardFC queryArchivedRecordings(connectUrl) .pipe( first(), - map((v) => v.data.archivedRecordings.data as ArchivedRecording[]), + map((v) => v.data.targetNodes[0].target.archivedRecordings.data as ArchivedRecording[]), ) .subscribe({ next: (recordings) => { @@ -366,7 +368,7 @@ export const AutomatedAnalysisCard: DashboardCardFC } } }), - map((v) => v.data.targetNodes[0].target.recordings.active.data[0] as Recording), + map((v) => v.data.targetNodes[0].target.activeRecordings.data[0] as Recording), tap((recording) => { if (recording === null || recording === undefined) { throw new Error(NO_RECORDINGS_MESSAGE); diff --git a/src/app/RecordingMetadata/BulkEditLabels.tsx b/src/app/RecordingMetadata/BulkEditLabels.tsx index cd5b931be..47ec48833 100644 --- a/src/app/RecordingMetadata/BulkEditLabels.tsx +++ b/src/app/RecordingMetadata/BulkEditLabels.tsx @@ -188,8 +188,8 @@ export const BulkEditLabels: React.FC = ({ context.api.graphql( `query ArchivedRecordingsForTarget($connectUrl: String) { targetNodes(filter: { name: $connectUrl }) { - recordings { - archived { + target { + archivedRecordings { data { name downloadUrl @@ -205,7 +205,7 @@ export const BulkEditLabels: React.FC = ({ { connectUrl: target.connectUrl }, ), ), - map((v) => v.data.targetNodes[0].target.recordings.archived.data as ArchivedRecording[]), + map((v) => v.data.targetNodes[0].target.archivedRecordings.data as ArchivedRecording[]), first(), ); } diff --git a/src/app/Recordings/ArchivedRecordingsTable.tsx b/src/app/Recordings/ArchivedRecordingsTable.tsx index 9c16de6e2..88ac40dcd 100644 --- a/src/app/Recordings/ArchivedRecordingsTable.tsx +++ b/src/app/Recordings/ArchivedRecordingsTable.tsx @@ -192,18 +192,22 @@ export const ArchivedRecordingsTable: React.FC = ( return context.api.graphql( ` query ArchivedRecordingsForTarget($connectUrl: String) { - archivedRecordings(filter: { sourceTarget: $connectUrl }) { - data { - name - downloadUrl - reportUrl - metadata { - labels { - key - value + targetNodes(filter: { name: $connectUrl }) { + target { + archivedRecordings { + data { + name + downloadUrl + reportUrl + metadata { + labels { + key + value + } + } + size } } - size } } }`, @@ -256,7 +260,7 @@ export const ArchivedRecordingsTable: React.FC = ( filter((target) => !!target), first(), concatMap((target: Target) => queryTargetRecordings(target.connectUrl)), - map((v) => v.data.archivedRecordings.data as ArchivedRecording[]), + map((v) => v.data.targetNodes[0].target.archivedRecordings.data as ArchivedRecording[]), ) .subscribe({ next: handleRecordings, diff --git a/src/app/Shared/Services/Api.service.tsx b/src/app/Shared/Services/Api.service.tsx index faf531d50..8b6df45bc 100644 --- a/src/app/Shared/Services/Api.service.tsx +++ b/src/app/Shared/Services/Api.service.tsx @@ -930,13 +930,11 @@ export class ApiService { ` query PostRecordingMetadata($connectUrl: String, $recordingName: String, $labels: String) { targetNodes(filter: { name: $connectUrl }) { - recordings { - archived(filter: { name: $recordingName }) { - data { - doPutMetadata(metadata: { labels: $labels }) { - metadata { - labels - } + archivedRecordings(filter: { name: $recordingName }) { + data { + doPutMetadata(metadata: { labels: $labels }) { + metadata { + labels } } } @@ -946,7 +944,7 @@ export class ApiService { { connectUrl: target.connectUrl, recordingName, labels: this.stringifyRecordingLabels(labels) }, ), ), - map((v) => v.data.targetNodes[0].target.recordings.archived as ArchivedRecording[]), + map((v) => v.data.targetNodes[0].target.archivedRecordings as ArchivedRecording[]), ); } @@ -977,13 +975,11 @@ export class ApiService { ` query PostActiveRecordingMetadata($connectUrl: String, $recordingName: String, $labels: String) { targetNodes(filter: { name: $connectUrl }) { - recordings { - active(filter: { name: $recordingName }) { - data { - doPutMetadata(metadata: { labels: $labels }) { - metadata { - labels - } + activeRecordings(filter: { name: $recordingName }) { + data { + doPutMetadata(metadata: { labels: $labels }) { + metadata { + labels } } } @@ -993,7 +989,7 @@ export class ApiService { { connectUrl: target.connectUrl, recordingName, labels: this.stringifyRecordingLabels(labels) }, ), ), - map((v) => v.data.targetNodes[0].target.recordings.active as ActiveRecording[]), + map((v) => v.data.targetNodes[0].target.activeRecordings as ActiveRecording[]), ); } @@ -1113,17 +1109,15 @@ export class ApiService { groupHasRecording(group: EnvironmentNode, filter: ActiveRecordingsFilterInput): Observable { return this.graphql( ` - query GetRecordingForGroup ($groupFilter: EnvironmentNodesFilterInput, $recordingFilter: ActiveRecordingsFilterInput){ + query GroupHasRecording ($groupFilter: EnvironmentNodesFilterInput, $recordingFilter: ActiveRecordingsFilterInput){ environmentNodes(filter: $groupFilter) { name descendantTargets { name target { - recordings { - active(filter: $recordingFilter) { - data { - name - } + activeRecordings(filter: $recordingFilter) { + aggregate { + count } } } @@ -1139,12 +1133,12 @@ export class ApiService { first(), map((body) => body.data.environmentNodes[0].descendantTargets.reduce( - (acc: Partial[], curr) => acc.concat(curr.target.recordings?.active?.data || []), - [] as Partial[], + (acc: number, curr) => acc + curr.target.activeRecordings.aggregate.count, + 0, ), ), catchError((_) => of([])), - map((recs: Partial[]) => recs.length > 0), // At least one + map((acc) => acc > 0), // At least one ); } @@ -1153,11 +1147,9 @@ export class ApiService { ` query ActiveRecordingsForJFRMetrics($connectUrl: String, $recordingFilter: ActiveRecordingsFilterInput) { targetNodes(filter: { name: $connectUrl }) { - recordings { - active (filter: $recordingFilter) { - aggregate { - count - } + activeRecordings(filter: $recordingFilter) { + aggregate { + count } } } @@ -1174,7 +1166,7 @@ export class ApiService { if (nodes.length === 0) { return false; } - const count = nodes[0].target.recordings.active.aggregate.count; + const count = nodes[0].target.activeRecordings.aggregate.count; return count > 0; }), catchError((_) => of(false)), @@ -1263,27 +1255,31 @@ export class ApiService { getTargetArchivedRecordings(target: TargetStub): Observable { return this.graphql( ` - query ArchivedRecordingsForTarget($connectUrl: String) { - archivedRecordings(filter: { sourceTarget: $connectUrl }) { - data { - name - downloadUrl - reportUrl - metadata { - labels { - key - value + query ArchivedRecordingsForTarget($connectUrl: String) { + targetNodes(filter: { name: $connectUrl }) { + target { + archivedRecordings { + data { + name + downloadUrl + reportUrl + metadata { + labels { + key + value + } } + size + archivedTime } - size - archivedTime } } - }`, + } + }`, { connectUrl: target.connectUrl }, true, true, - ).pipe(map((v) => v.data.archivedRecordings.data as ArchivedRecording[])); + ).pipe(map((v) => v.data.targetNodes[0].target.archivedRecordings.data as ArchivedRecording[])); } getTargetActiveRecordings(target: TargetStub): Observable { diff --git a/src/app/Shared/Services/api.types.ts b/src/app/Shared/Services/api.types.ts index b7a92003b..1f124d35c 100644 --- a/src/app/Shared/Services/api.types.ts +++ b/src/app/Shared/Services/api.types.ts @@ -282,11 +282,9 @@ export interface RecordingCountResponse { data: { targetNodes: { target: { - recordings: { - active: { - aggregate: { - count: number; - }; + activeRecordings: { + aggregate: { + count: number; }; }; }; From 95e18cb6d56fc87c94196f2198856ad7dae63f84 Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Thu, 7 Mar 2024 11:27:04 -0500 Subject: [PATCH 03/11] use new filter input type name --- src/app/Shared/Services/Api.service.tsx | 2 +- src/app/Topology/Actions/utils.tsx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/Shared/Services/Api.service.tsx b/src/app/Shared/Services/Api.service.tsx index 8b6df45bc..adab2d348 100644 --- a/src/app/Shared/Services/Api.service.tsx +++ b/src/app/Shared/Services/Api.service.tsx @@ -1109,7 +1109,7 @@ export class ApiService { groupHasRecording(group: EnvironmentNode, filter: ActiveRecordingsFilterInput): Observable { return this.graphql( ` - query GroupHasRecording ($groupFilter: EnvironmentNodesFilterInput, $recordingFilter: ActiveRecordingsFilterInput){ + query GroupHasRecording ($groupFilter: DiscoveryNodeFilterInput, $recordingFilter: ActiveRecordingsFilterInput){ environmentNodes(filter: $groupFilter) { name descendantTargets { diff --git a/src/app/Topology/Actions/utils.tsx b/src/app/Topology/Actions/utils.tsx index dd108d2f9..fc04d8901 100644 --- a/src/app/Topology/Actions/utils.tsx +++ b/src/app/Topology/Actions/utils.tsx @@ -122,7 +122,7 @@ export const nodeActions: NodeAction[] = [ services.api .graphql( ` - query StartRecordingForGroup($filter: EnvironmentNodesFilterInput!, $recordingName: String!, $metadata: RecordingMetadataInput!) { + query StartRecordingForGroup($filter: DiscoveryNodeFilterInput!, $recordingName: String!, $metadata: RecordingMetadataInput!) { environmentNodes(filter: $filter) { name descendantTargets { @@ -168,7 +168,7 @@ export const nodeActions: NodeAction[] = [ services.api .graphql( ` - query DeleteRecordingForGroup ($groupFilter: EnvironmentNodesFilterInput, $recordingFilter: ActiveRecordingsFilterInput) { + query DeleteRecordingForGroup ($groupFilter: DiscoveryNodeFilterInput, $recordingFilter: ActiveRecordingsFilterInput) { environmentNodes(filter: $groupFilter) { name descendantTargets { @@ -212,7 +212,7 @@ export const nodeActions: NodeAction[] = [ services.api .graphql( ` - query StopRecordingForGroup ($groupFilter: EnvironmentNodesFilterInput, $recordingFilter: ActiveRecordingsFilterInput) { + query StopRecordingForGroup ($groupFilter: DiscoveryNodeFilterInput, $recordingFilter: ActiveRecordingsFilterInput) { environmentNodes(filter: $groupFilter) { name descendantTargets { @@ -258,7 +258,7 @@ export const nodeActions: NodeAction[] = [ services.api .graphql( ` - query DeleteRecordingForGroup ($groupFilter: EnvironmentNodesFilterInput, $recordingFilter: ActiveRecordingsFilterInput) { + query DeleteRecordingForGroup ($groupFilter: DiscoveryNodeFilterInput, $recordingFilter: ActiveRecordingsFilterInput) { environmentNodes(filter: $groupFilter) { name descendantTargets { From 08aca67f3d6d6a8897573778b53a2be3f94b9063 Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Mon, 11 Mar 2024 10:46:17 -0400 Subject: [PATCH 04/11] indentation --- src/app/Topology/Actions/utils.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/app/Topology/Actions/utils.tsx b/src/app/Topology/Actions/utils.tsx index fc04d8901..f7f358a16 100644 --- a/src/app/Topology/Actions/utils.tsx +++ b/src/app/Topology/Actions/utils.tsx @@ -176,11 +176,11 @@ export const nodeActions: NodeAction[] = [ target { recordings { active(filter: $recordingFilter) { - data { - doArchive { - name - } + data { + doArchive { + name } + } } } } @@ -266,12 +266,12 @@ export const nodeActions: NodeAction[] = [ target { recordings { active(filter: $recordingFilter) { - data { - doDelete { - name - state - } + data { + doDelete { + name + state } + } } } } From 4de75119af9d176152529090c42d4a82352ccf68 Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Mon, 11 Mar 2024 12:06:32 -0400 Subject: [PATCH 05/11] update fake graphql query response format --- src/app/utils/fakeData.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/app/utils/fakeData.ts b/src/app/utils/fakeData.ts index f6a6443d6..bc88cf54e 100644 --- a/src/app/utils/fakeData.ts +++ b/src/app/utils/fakeData.ts @@ -347,8 +347,8 @@ class FakeApiService extends ApiService { return of([]); } - // Automatic Analysis Card - // This fakes the fetch for Automatic Analysis recording to return available. + // Automated Analysis Card + // This fakes the fetch for Automated Analysis recording to return available. // Then subsequent graphql call for archived recording is ignored graphql( _query: string, @@ -360,10 +360,8 @@ class FakeApiService extends ApiService { data: { targetNodes: [ { - recordings: { - active: { - data: [fakeAARecording], - }, + activeRecordings: { + data: [fakeAARecording], }, }, ], From 4bbda01b0c16dd5e3a27897aa3d6b10c3f00a4f7 Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Mon, 11 Mar 2024 12:06:50 -0400 Subject: [PATCH 06/11] use dynamic mock timestamp --- src/app/utils/fakeData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/utils/fakeData.ts b/src/app/utils/fakeData.ts index bc88cf54e..66d5f0f9f 100644 --- a/src/app/utils/fakeData.ts +++ b/src/app/utils/fakeData.ts @@ -208,7 +208,7 @@ export const fakeEvaluations: AnalysisResult[] = [ export const fakeCachedReport: CachedReportValue = { report: fakeEvaluations, - timestamp: 1663027200000, + timestamp: Date.now() - (1000 * 60 * 60), }; class FakeTargetService extends TargetService { From 387edd6809fd8a1310706e0e6b622eb45b39376a Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Mon, 11 Mar 2024 14:09:56 -0400 Subject: [PATCH 07/11] apply formatting --- src/app/utils/fakeData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/utils/fakeData.ts b/src/app/utils/fakeData.ts index 66d5f0f9f..faffa68c8 100644 --- a/src/app/utils/fakeData.ts +++ b/src/app/utils/fakeData.ts @@ -208,7 +208,7 @@ export const fakeEvaluations: AnalysisResult[] = [ export const fakeCachedReport: CachedReportValue = { report: fakeEvaluations, - timestamp: Date.now() - (1000 * 60 * 60), + timestamp: Date.now() - 1000 * 60 * 60, }; class FakeTargetService extends TargetService { From daa01bcf769bd0b733887f95a5ef05fc81a9c84e Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Mon, 11 Mar 2024 14:10:12 -0400 Subject: [PATCH 08/11] schema adjustments for Mirage preview --- src/mirage/index.ts | 82 ++++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/src/mirage/index.ts b/src/mirage/index.ts index d42a8b0f1..d78719320 100644 --- a/src/mirage/index.ts +++ b/src/mirage/index.ts @@ -126,35 +126,27 @@ export const startMirage = ({ environment = 'development' } = {}) => { }; }); this.get('api/v1/targets', (schema) => schema.all(Resource.TARGET).models); - this.get('api/v2.1/discovery', (schema) => { + this.get('api/v3/discovery', (schema) => { const models = schema.all(Resource.TARGET).models; const realmTypes = models.map((t) => t.annotations.cryostat['REALM']); return { - meta: { - status: 'OK', - type: 'application/json', - }, - data: { - result: { - name: 'Universe', - nodeType: 'Universe', - labels: [], - children: realmTypes.map((r: string) => ({ - name: r, - nodeType: 'Realm', - labels: [], - id: r, - children: models - .filter((t) => t.annotations.cryostat['REALM'] === r) - .map((t) => ({ - id: t.alias, - name: t.alias, - nodeType: r === 'Custom Targets' ? 'CustomTarget' : 'JVM', - target: t, - })), + name: 'Universe', + nodeType: 'Universe', + labels: [], + children: realmTypes.map((r: string) => ({ + name: r, + nodeType: 'Realm', + labels: [], + id: r, + children: models + .filter((t) => t.annotations.cryostat['REALM'] === r) + .map((t) => ({ + id: t.alias, + name: t.alias, + nodeType: r === 'Custom Targets' ? 'CustomTarget' : 'JVM', + target: t, })), - }, - }, + })), }; }); this.get('api/v1/recordings', (schema) => schema.all(Resource.ARCHIVE).models); @@ -505,17 +497,23 @@ export const startMirage = ({ environment = 'development' } = {}) => { case 'ArchivedRecordingsForTarget': case 'UploadedRecordings': data = { - archivedRecordings: { - data: schema.all(Resource.ARCHIVE).models, - }, + targetNodes: [ + { + target: { + archivedRecordings: { + data: schema.all(Resource.ARCHIVE).models, + }, + }, + }, + ], }; break; case 'ActiveRecordingsForTarget': data = { targetNodes: [ { - recordings: { - archived: { + target: { + archivedRecordings: { data: schema.all(Resource.ARCHIVE).models, }, }, @@ -525,17 +523,23 @@ export const startMirage = ({ environment = 'development' } = {}) => { break; case 'ArchivedRecordingsForAutomatedAnalysis': data = { - archivedRecordings: { - data: schema.all(Resource.ARCHIVE).models, - }, + targetNodes: [ + { + target: { + archivedRecordings: { + data: schema.all(Resource.ARCHIVE).models, + }, + }, + }, + ], }; break; case 'ActiveRecordingsForAutomatedAnalysis': data = { targetNodes: [ { - recordings: { - active: { + target: { + activeRecordings: { data: schema.all(Resource.RECORDING).models, }, }, @@ -556,8 +560,8 @@ export const startMirage = ({ environment = 'development' } = {}) => { data = { targetNodes: [ { - recordings: { - archived: { + target: { + archivedRecordings: { data: [ { doPutMetadata: { @@ -602,8 +606,8 @@ export const startMirage = ({ environment = 'development' } = {}) => { data = { targetNodes: [ { - recordings: { - active: { + target: { + activeRecordings: { data: [ { doPutMetadata: { From 3849ab47b4dafa1eaa46b7fb4ac106ccbcdca08f Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Mon, 11 Mar 2024 14:48:52 -0400 Subject: [PATCH 09/11] fixup --- src/app/Shared/Services/Api.service.tsx | 8 +++++--- src/app/utils/fakeData.ts | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/app/Shared/Services/Api.service.tsx b/src/app/Shared/Services/Api.service.tsx index adab2d348..388a1d107 100644 --- a/src/app/Shared/Services/Api.service.tsx +++ b/src/app/Shared/Services/Api.service.tsx @@ -1147,9 +1147,11 @@ export class ApiService { ` query ActiveRecordingsForJFRMetrics($connectUrl: String, $recordingFilter: ActiveRecordingsFilterInput) { targetNodes(filter: { name: $connectUrl }) { - activeRecordings(filter: $recordingFilter) { - aggregate { - count + target { + activeRecordings(filter: $recordingFilter) { + aggregate { + count + } } } } diff --git a/src/app/utils/fakeData.ts b/src/app/utils/fakeData.ts index faffa68c8..1723e190c 100644 --- a/src/app/utils/fakeData.ts +++ b/src/app/utils/fakeData.ts @@ -360,8 +360,10 @@ class FakeApiService extends ApiService { data: { targetNodes: [ { - activeRecordings: { - data: [fakeAARecording], + target: { + activeRecordings: { + data: [fakeAARecording], + }, }, }, ], From f122a6eff0988bb4687b9ea34d9e5547e23340fc Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Mon, 11 Mar 2024 15:07:11 -0400 Subject: [PATCH 10/11] indentation --- .../AllTargetsArchivedRecordingsTable.tsx | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/app/Archives/AllTargetsArchivedRecordingsTable.tsx b/src/app/Archives/AllTargetsArchivedRecordingsTable.tsx index 260599425..e9396ed54 100644 --- a/src/app/Archives/AllTargetsArchivedRecordingsTable.tsx +++ b/src/app/Archives/AllTargetsArchivedRecordingsTable.tsx @@ -146,18 +146,18 @@ export const AllTargetsArchivedRecordingsTable: React.FC( `query AllTargetsArchives { - targetNodes { - target { - connectUrl - alias - archivedRecordings { - aggregate { - count - } + targetNodes { + target { + connectUrl + alias + archivedRecordings { + aggregate { + count } } } - }`, + } + }`, ) .pipe(map((v) => v.data.targetNodes)) .subscribe({ @@ -173,18 +173,17 @@ export const AllTargetsArchivedRecordingsTable: React.FC( - ` - query ArchiveCountForTarget($connectUrl: String) { - targetNodes(filter: { name: $connectUrl }) { - target { - archivedRecordings { - aggregate { - count + `query ArchiveCountForTarget($connectUrl: String) { + targetNodes(filter: { name: $connectUrl }) { + target { + archivedRecordings { + aggregate { + count + } + } } } - } - } - }`, + }`, { connectUrl: target.connectUrl }, ) .subscribe((v) => { From 1f5f62da030f634003c0e978cf579cf810ee3058 Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Mon, 11 Mar 2024 15:09:41 -0400 Subject: [PATCH 11/11] test fixup --- ...AllTargetsArchivedRecordingsTable.test.tsx | 32 +++++++---------- .../AutomatedAnalysisCard.test.tsx | 36 +++++++++++-------- .../RecordingMetadata/BulkEditLabels.test.tsx | 6 ++-- .../ArchivedRecordingsTable.test.tsx | 28 +++++++++++++-- 4 files changed, 62 insertions(+), 40 deletions(-) diff --git a/src/test/Archives/AllTargetsArchivedRecordingsTable.test.tsx b/src/test/Archives/AllTargetsArchivedRecordingsTable.test.tsx index 0fdd8e029..8a021df10 100644 --- a/src/test/Archives/AllTargetsArchivedRecordingsTable.test.tsx +++ b/src/test/Archives/AllTargetsArchivedRecordingsTable.test.tsx @@ -79,11 +79,9 @@ const mockTargetsAndCountsResponse = { target: { alias: mockAlias1, connectUrl: mockConnectUrl1, - recordings: { - archived: { - aggregate: { - count: mockCount1, - }, + archivedRecordings: { + aggregate: { + count: mockCount1, }, }, }, @@ -92,11 +90,9 @@ const mockTargetsAndCountsResponse = { target: { alias: mockAlias2, connectUrl: mockConnectUrl2, - recordings: { - archived: { - aggregate: { - count: mockCount2, - }, + archivedRecordings: { + aggregate: { + count: mockCount2, }, }, }, @@ -105,11 +101,9 @@ const mockTargetsAndCountsResponse = { target: { alias: mockAlias3, connectUrl: mockConnectUrl3, - recordings: { - archived: { - aggregate: { - count: mockCount3, - }, + archivedRecordings: { + aggregate: { + count: mockCount3, }, }, }, @@ -123,11 +117,9 @@ const mockNewTargetCountResponse = { targetNodes: [ { target: { - recordings: { - archived: { - aggregate: { - count: mockNewCount, - }, + archivedRecordings: { + aggregate: { + count: mockNewCount, }, }, }, diff --git a/src/test/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.test.tsx b/src/test/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.test.tsx index 32b6bd382..6b27417d6 100644 --- a/src/test/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.test.tsx +++ b/src/test/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.test.tsx @@ -153,10 +153,8 @@ const mockCachedReport: CachedReportValue = { }; const mockTargetNode = { - recordings: { - active: { - data: [mockRecording], - }, + activeRecordings: { + data: [mockRecording], }, }; @@ -171,10 +169,8 @@ const mockEmptyActiveRecordingsResponse = { targetNodes: [ { target: { - recordings: { - active: { - data: [], - }, + activeRecordings: { + data: [], }, }, }, @@ -184,17 +180,29 @@ const mockEmptyActiveRecordingsResponse = { const mockArchivedRecordingsResponse = { data: { - archivedRecordings: { - data: [mockArchivedRecording], - }, + targetNodes: [ + { + target: { + archivedRecordings: { + data: [mockArchivedRecording], + }, + }, + }, + ], }, }; const mockEmptyArchivedRecordingsResponse = { data: { - archivedRecordings: { - data: [], - }, + targetNodes: [ + { + target: { + archivedRecordings: { + data: [], + }, + }, + }, + ], }, }; diff --git a/src/test/RecordingMetadata/BulkEditLabels.test.tsx b/src/test/RecordingMetadata/BulkEditLabels.test.tsx index 458eef774..4745612ec 100644 --- a/src/test/RecordingMetadata/BulkEditLabels.test.tsx +++ b/src/test/RecordingMetadata/BulkEditLabels.test.tsx @@ -108,10 +108,8 @@ const mockArchivedRecordingsResponse = { targetNodes: [ { target: { - recordings: { - archived: { - data: [mockArchivedRecording] as ArchivedRecording[], - }, + archivedRecordings: { + data: [mockArchivedRecording] as ArchivedRecording[], }, }, }, diff --git a/src/test/Recordings/ArchivedRecordingsTable.test.tsx b/src/test/Recordings/ArchivedRecordingsTable.test.tsx index e167c84c1..59a9509b9 100644 --- a/src/test/Recordings/ArchivedRecordingsTable.test.tsx +++ b/src/test/Recordings/ArchivedRecordingsTable.test.tsx @@ -90,9 +90,27 @@ const mockRecording: ArchivedRecording = { }; const mockArchivedRecordingsResponse = { + data: { + targetNodes: [ + { + target: { + archivedRecordings: { + data: [mockRecording], + }, + }, + }, + ], + }, +}; + +const mockAllArchivedRecordingsResponse = { data: { archivedRecordings: { - data: [mockRecording] as ArchivedRecording[], + data: [mockRecording], + aggregate: { + count: 1, + size: mockRecording.size, + }, }, }, }; @@ -135,7 +153,13 @@ jest.spyOn(defaultServices.api, 'deleteArchivedRecording').mockReturnValue(of(tr jest.spyOn(defaultServices.api, 'downloadRecording').mockReturnValue(); jest.spyOn(defaultServices.api, 'grafanaDatasourceUrl').mockReturnValue(of('/datasource')); jest.spyOn(defaultServices.api, 'grafanaDashboardUrl').mockReturnValue(of('/grafanaUrl')); -jest.spyOn(defaultServices.api, 'graphql').mockReturnValue(of(mockArchivedRecordingsResponse)); +jest.spyOn(defaultServices.api, 'graphql').mockImplementation((query: string) => { + if (query.includes('ArchivedRecordingsForTarget')) { + return of(mockArchivedRecordingsResponse); + } else { + return of(mockAllArchivedRecordingsResponse); + } +}); jest.spyOn(defaultServices.api, 'uploadArchivedRecordingToGrafana').mockReturnValue(of(true)); jest