Skip to content

Commit

Permalink
Merge branch 'main' into pf5
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewazores committed Sep 3, 2024
2 parents 7eadcff + 318389e commit 822c662
Show file tree
Hide file tree
Showing 36 changed files with 93 additions and 19 deletions.
2 changes: 2 additions & 0 deletions locales/en/public.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
},
"AboutDescription": {
"BUGS": "Bugs",
"BUILD_INFO": "Build Information",
"COMMIT": "commit {{ hash }}",
"FILE_A_REPORT": "File a report",
"HOMEPAGE": "Homepage",
"KNOWN_ISSUES": "Known issues",
Expand Down
36 changes: 29 additions & 7 deletions src/app/About/AboutDescription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
*/

import build from '@app/build.json';
import { BuildInfo } from '@app/Shared/Services/api.types';
import { NotificationsContext } from '@app/Shared/Services/Notifications.service';
import { ServiceContext } from '@app/Shared/Services/Services';
import { useSubscriptions } from '@app/utils/hooks/useSubscriptions';
import { Text, TextContent, TextList, TextListItem, TextVariants } from '@patternfly/react-core';
import * as React from 'react';
import { useTranslation } from 'react-i18next';
Expand All @@ -25,14 +27,16 @@ export const AboutDescription: React.FC = () => {
const serviceContext = React.useContext(ServiceContext);
const notificationsContext = React.useContext(NotificationsContext);
const [cryostatVersion, setCryostatVersion] = React.useState(undefined as string | undefined);
const [buildInfo, setBuildInfo] = React.useState<BuildInfo>({ git: { hash: '' } });
const { t } = useTranslation();
const addSubscription = useSubscriptions();

React.useEffect(() => {
const sub = serviceContext.api.cryostatVersion().subscribe(setCryostatVersion);
return () => sub.unsubscribe();
}, [serviceContext]);
addSubscription(serviceContext.api.cryostatVersion().subscribe(setCryostatVersion));
addSubscription(serviceContext.api.buildInfo().subscribe(setBuildInfo));
}, [addSubscription, serviceContext]);

const cryostatCommitHash = React.useMemo(() => {
const cryostatReleaseTag = React.useMemo(() => {
if (!cryostatVersion) {
return;
}
Expand All @@ -55,8 +59,8 @@ export const AboutDescription: React.FC = () => {
component={TextVariants.a}
target="_blank"
href={
cryostatCommitHash
? build.releaseTagUrl.replace('__REPLACE_HASH__', cryostatCommitHash)
cryostatReleaseTag
? build.releaseTagUrl.replace('__REPLACE_HASH__', cryostatReleaseTag)
: build.developmentUrl
}
>
Expand All @@ -66,14 +70,32 @@ export const AboutDescription: React.FC = () => {
} else {
return <Text component={TextVariants.p}>{cryostatVersion}</Text>;
}
}, [cryostatVersion, cryostatCommitHash]);
}, [cryostatVersion, cryostatReleaseTag]);

const buildInfoComponent = React.useMemo(() => {
if (build.commitUrl) {
return (
<Text
component={TextVariants.a}
target="_blank"
href={build.commitUrl.replace('__REPLACE_HASH__', buildInfo.git.hash)}
>
{t('AboutDescription.COMMIT', { hash: buildInfo.git.hash })}
</Text>
);
} else {
return <Text component={TextVariants.p}>{t('AboutDescription.COMMIT', { hash: buildInfo.git.hash })}</Text>;
}
}, [t, buildInfo]);

return (
<>
<TextContent>
<TextList component="dl">
<TextListItem component="dt">{t('AboutDescription.VERSION')}</TextListItem>
<TextListItem component="dd">{versionComponent}</TextListItem>
<TextListItem component="dt">{t('AboutDescription.BUILD_INFO')}</TextListItem>
<TextListItem component="dd">{buildInfoComponent}</TextListItem>
<TextListItem component="dt">{t('AboutDescription.HOMEPAGE')}</TextListItem>
<TextListItem component="dd">
<Text component={TextVariants.a} target="_blank" href={build.homePageUrl}>
Expand Down
2 changes: 2 additions & 0 deletions src/app/Archives/AllTargetsArchivedRecordingsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ export const AllTargetsArchivedRecordingsTable: React.FC<AllTargetsArchivedRecor
setArchivesForTargets(
targetNodes.map((node) => {
const target: Target = {
agent: node.target.agent,
id: node.target.id,
jvmId: node.target.jvmId,
connectUrl: node.target.connectUrl,
Expand Down Expand Up @@ -183,6 +184,7 @@ export const AllTargetsArchivedRecordingsTable: React.FC<AllTargetsArchivedRecor
`query AllTargetsArchives {
targetNodes {
target {
agent
id
connectUrl
alias
Expand Down
1 change: 1 addition & 0 deletions src/app/Archives/Archives.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { AllTargetsArchivedRecordingsTable } from './AllTargetsArchivedRecording
notification handling in the ArchivedRecordingsTable.
*/
export const uploadAsTarget: Target = {
agent: false,
connectUrl: UPLOADS_SUBDIRECTORY,
alias: '',
labels: [],
Expand Down
1 change: 1 addition & 0 deletions src/app/Archives/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const indexOfDirectory = (arr: RecordingDirectory[], dir: RecordingDirect

export const getTargetFromDirectory = (dir: RecordingDirectory): Target => {
return {
agent: dir.connectUrl.startsWith('http'),
connectUrl: dir.connectUrl,
alias: dir.jvmId,
labels: [],
Expand Down
3 changes: 1 addition & 2 deletions src/app/CreateRecording/CustomRecordingForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import {
Target,
KeyValue,
} from '@app/Shared/Services/api.types';
import { isTargetAgentHttp } from '@app/Shared/Services/api.utils';
import { NotificationsContext } from '@app/Shared/Services/Notifications.service';
import { ServiceContext } from '@app/Shared/Services/Services';
import { useSubscriptions } from '@app/utils/hooks/useSubscriptions';
Expand Down Expand Up @@ -289,7 +288,7 @@ export const CustomRecordingForm: React.FC = () => {
setAdvancedRecordingOptions(recordingOptions);
},
error: (error) => {
setErrorMessage(isTargetAgentHttp(target) ? 'Unsupported operation: Create Recordings' : error.message);
setErrorMessage(error.message);
setTemplates([]);
setFormData((old) => ({ ...old, template: undefined }));
setAdvancedRecordingOptions({});
Expand Down
4 changes: 4 additions & 0 deletions src/app/Shared/Redux/Filters/TopologyFilterSlice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export interface TopologyFilters {
targetFilters: {
category: string;
filters: {
Agent: string[];
Alias: string[];
ConnectionUrl: string[];
JvmId: string[];
Expand All @@ -119,6 +120,8 @@ export const categoryToNodeField = (filterCategory: string): keyof EnvironmentNo
return 'name';
case 'Label':
return 'labels';
case 'Agent':
return 'agent';
case 'Annotation':
return 'annotations';
case 'JvmId':
Expand All @@ -139,6 +142,7 @@ export const defaultEmptyGroupFilters = {

export const defaultEmptyTargetFilters = {
// Below will be taken from node.target
Agent: [],
Alias: [],
ConnectionUrl: [],
JvmId: [],
Expand Down
7 changes: 7 additions & 0 deletions src/app/Shared/Services/Api.service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import {
TargetMetadata,
isTargetMetadata,
MBeanMetricsResponse,
BuildInfo,
} from './api.types';
import {
isHttpError,
Expand All @@ -91,6 +92,7 @@ import { TargetService } from './Target.service';
export class ApiService {
private readonly archiveEnabled = new BehaviorSubject<boolean>(true);
private readonly cryostatVersionSubject = new ReplaySubject<string>(1);
private readonly buildInfoSubject = new ReplaySubject<BuildInfo>(1);
private readonly grafanaDatasourceUrlSubject = new ReplaySubject<string>(1);
private readonly grafanaDashboardUrlSubject = new ReplaySubject<string>(1);

Expand Down Expand Up @@ -128,6 +130,7 @@ export class ApiService {
.pipe(
concatMap((jsonResp) => {
this.cryostatVersionSubject.next(jsonResp.cryostatVersion);
this.buildInfoSubject.next(jsonResp.build);
const toFetch: unknown[] = [];
const unconfigured: string[] = [];
const unavailable: string[] = [];
Expand Down Expand Up @@ -737,6 +740,10 @@ export class ApiService {
return this.cryostatVersionSubject.asObservable();
}

buildInfo(): Observable<BuildInfo> {
return this.buildInfoSubject.asObservable();
}

grafanaDatasourceUrl(): Observable<string> {
return this.grafanaDatasourceUrlSubject.asObservable();
}
Expand Down
11 changes: 10 additions & 1 deletion src/app/Shared/Services/api.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ export type ApiVersion = 'v1' | 'v2' | 'v2.1' | 'v2.2' | 'v2.3' | 'v2.4' | 'v3'
// ======================================
// Common Resources
// ======================================

export interface BuildInfo {
git: {
hash: string;
};
}

export interface KeyValue {
key: string;
value: string;
Expand Down Expand Up @@ -106,7 +113,7 @@ export class XMLHttpError extends Error {
}
}

export type TargetStub = Omit<Target, 'jvmId' | 'labels' | 'annotations'>;
export type TargetStub = Omit<Target, 'agent' | 'jvmId' | 'labels' | 'annotations'>;

export type TargetForTest = Pick<Target, 'alias' | 'connectUrl'> & {
labels: object;
Expand All @@ -126,6 +133,7 @@ export interface GrafanaDatasourceUrlGetResponse {

export interface HealthGetResponse {
cryostatVersion: string;
build: BuildInfo;
datasourceConfigured: boolean;
datasourceAvailable: boolean;
dashboardConfigured: boolean;
Expand Down Expand Up @@ -472,6 +480,7 @@ export const TEMPLATE_UNSUPPORTED_MESSAGE = 'The template type used in this Reco
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
agent: boolean;
connectUrl: string;
alias: string;
labels: KeyValue[];
Expand Down
2 changes: 0 additions & 2 deletions src/app/Shared/Services/api.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,6 @@ export const indexOfTarget = (arr: Target[], target: Target): number => {
export const getTargetRepresentation = (t: Target) =>
!t.alias || t.alias === t.connectUrl ? `${t.connectUrl}` : `${t.alias} (${t.connectUrl})`;

export const isTargetAgentHttp = (t: Target) => t.connectUrl.startsWith('http');

export const isTargetNode = (node: EnvironmentNode | TargetNode): node is TargetNode => {
return node['target'] !== undefined;
};
Expand Down
2 changes: 1 addition & 1 deletion src/app/Topology/Actions/CreateTarget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ export const CreateTarget: React.FC<CreateTargetProps> = ({ prefilled }) => {
};

export interface SampleNodeDonutProps {
target: Target;
target: Omit<Target, 'agent'>;
testing?: boolean;
validation: {
option: ValidatedOptions;
Expand Down
2 changes: 1 addition & 1 deletion src/app/Topology/GraphView/CustomNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ const CustomNode: React.FC<CustomNodeProps> = ({

const data: TargetNode = element.getData();

const graphic = React.useMemo(() => (data.target.connectUrl.startsWith('http') ? cryostatSvg : openjdkSvg), [data]);
const graphic = React.useMemo(() => (data.target.agent ? cryostatSvg : openjdkSvg), [data]);

const [nodeStatus] = getStatusTargetNode(data);

Expand Down
3 changes: 3 additions & 0 deletions src/app/Topology/Shared/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ export const isTargetNodeFiltered = ({ target }: TargetNode, filters?: TopologyF
return true;
}
let matched = true;
if (filters.Agent && filters.Agent.length) {
matched = matched && filters.Agent.includes(target.agent.toString());
}
if (filters.Alias && filters.Alias.length) {
matched = matched && filters.Alias.includes(target.alias);
}
Expand Down
1 change: 1 addition & 0 deletions src/app/build.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"productName": "Cryostat",
"developmentUrl": "https://github.com/cryostatio/cryostat",
"releaseTagUrl": "https://github.com/cryostatio/cryostat/releases/tag/__REPLACE_HASH__",
"commitUrl": "https://github.com/cryostatio/cryostat/commit/__REPLACE_HASH__",
"homePageUrl": "https://cryostat.io",
"blogPageUrl": "https://cryostat.io/blog",
"documentationUrl": "https://cryostat.io/guides",
Expand Down
1 change: 1 addition & 0 deletions src/app/utils/fakeData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { TargetService } from '@app/Shared/Services/Target.service';
import { Observable, of } from 'rxjs';

export const fakeTarget: Target = {
agent: false,
jvmId: 'rpZeYNB9wM_TEnXoJvAFuR0jdcUBXZgvkXiKhjQGFvY=',
connectUrl: 'service:jmx:rmi:///jndi/rmi://10-128-2-25.my-namespace.pod:9097/jmxrmi',
alias: 'quarkus-test-77f556586c-25bkv',
Expand Down
1 change: 1 addition & 0 deletions src/mirage/factories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { FactoryDefinition } from 'miragejs/-types';
import { Resource } from './typings';

export const targetFactory: FactoryDefinition<any> = Factory.extend({
agent: true,
alias: 'Fake Target',
connectUrl: 'http://fake-target.local:1234',
jvmId: '1234',
Expand Down
1 change: 1 addition & 0 deletions src/test/Agent/AgentLiveProbes.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { render, renderSnapshot } from '../utils';
const mockConnectUrl = 'service:jmx:rmi://someUrl';
const mockJvmId = 'id';
const mockTarget = {
agent: false,
connectUrl: mockConnectUrl,
alias: 'fooTarget',
jvmId: mockJvmId,
Expand Down
4 changes: 4 additions & 0 deletions src/test/Archives/AllTargetsArchivedRecordingsTable.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { render, renderSnapshot } from '../utils';
const mockConnectUrl1 = 'service:jmx:rmi://someUrl1';
const mockAlias1 = 'fooTarget1';
const mockTarget1: Target = {
agent: false,
jvmId: 'target1',
connectUrl: mockConnectUrl1,
alias: mockAlias1,
Expand All @@ -36,6 +37,7 @@ const mockTarget1: Target = {
const mockConnectUrl2 = 'service:jmx:rmi://someUrl2';
const mockAlias2 = 'fooTarget2';
const mockTarget2: Target = {
agent: false,
jvmId: 'target2',
connectUrl: mockConnectUrl2,
alias: mockAlias2,
Expand All @@ -48,6 +50,7 @@ const mockTarget2: Target = {
const mockConnectUrl3 = 'service:jmx:rmi://someUrl3';
const mockAlias3 = 'fooTarget3';
const mockTarget3: Target = {
agent: false,
jvmId: 'target3',
connectUrl: mockConnectUrl3,
alias: mockAlias3,
Expand All @@ -60,6 +63,7 @@ const mockTarget3: Target = {
const mockNewConnectUrl = 'service:jmx:rmi://someNewUrl';
const mockNewAlias = 'newTarget';
const mockNewTarget: Target = {
agent: false,
jvmId: 'target4',
connectUrl: mockNewConnectUrl,
alias: mockNewAlias,
Expand Down
1 change: 1 addition & 0 deletions src/test/CreateRecording/CustomRecordingForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ jest.mock('react-router-dom', () => ({

const mockConnectUrl = 'service:jmx:rmi://someUrl';
const mockTarget = {
agent: false,
connectUrl: mockConnectUrl,
alias: 'fooTarget',
jvmId: 'foo',
Expand Down
1 change: 1 addition & 0 deletions src/test/CreateRecording/SnapshotRecordingForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { render, renderSnapshot } from '../utils';

const mockConnectUrl = 'service:jmx:rmi://someUrl';
const mockTarget = {
agent: false,
connectUrl: mockConnectUrl,
alias: 'fooTarget',
jvmId: 'foo',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ jest.mock('@app/Dashboard/AutomatedAnalysis/AutomatedAnalysisCardList', () => {
});

const mockTarget = {
agent: false,
connectUrl: 'service:jmx:rmi://someUrl',
alias: 'fooTarget',
jvmId: 'foo',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { of } from 'rxjs';
import { render, testT } from '../../utils';

const mockTarget = {
agent: false,
connectUrl: 'service:jmx:rmi://someUrl',
alias: 'fooTarget',
jvmId: 'foo',
Expand Down
1 change: 1 addition & 0 deletions src/test/Dashboard/Charts/jfr/JFRMetricsChartCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const mockDashboardUrl = 'http://localhost:3000';
jest.spyOn(defaultServices.api, 'grafanaDashboardUrl').mockReturnValue(of(mockDashboardUrl));

const mockTarget = {
agent: false,
connectUrl: 'service:jmx:rmi://someUrl',
alias: 'fooTarget',
jvmId: 'foo',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ jest.spyOn(defaultServices.target, 'authRetry').mockReturnValue(of());
jest.spyOn(defaultServices.target, 'sslFailure').mockReturnValue(of());

const mockTarget = {
agent: false,
connectUrl: 'service:jmx:rmi://someUrl',
alias: 'fooTarget',
jvmId: 'foo',
Expand Down
1 change: 1 addition & 0 deletions src/test/Dashboard/Dashboard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { of } from 'rxjs';
const mockFooConnectUrl = 'service:jmx:rmi://someFooUrl';

const mockFooTarget: Target = {
agent: false,
connectUrl: mockFooConnectUrl,
alias: 'fooTarget',
labels: [],
Expand Down
1 change: 1 addition & 0 deletions src/test/Events/EventTemplates.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { render, renderSnapshot } from '../utils';

const mockConnectUrl = 'service:jmx:rmi://someUrl';
const mockTarget = {
agent: false,
connectUrl: mockConnectUrl,
alias: 'fooTarget',
jvmId: 'foo',
Expand Down
Loading

0 comments on commit 822c662

Please sign in to comment.