Skip to content

Commit 53b9ea0

Browse files
authored
feat(autoconfig): wizard supports callback-port, harvester-template, harvester-max-files labels (#886)
1 parent b370e6a commit 53b9ea0

15 files changed

Lines changed: 1216 additions & 593 deletions

locales/en/common.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,24 @@
4646
"DEPLOYMENT_ACTION_CONTAINER_NO_CONFIG": "None",
4747
"DEPLOYMENT_ACTION_CONTAINER_SINGLE_AUTO_SELECTED": "Single container automatically selected",
4848
"DEPLOYMENT_ACTION_CONTAINER_MUST_SELECT_ONE": "You must select exactly one container to instrument",
49+
"DEPLOYMENT_ACTION_WIZARD_STEP_AGENT_CONFIG": "Agent Configuration",
50+
"DEPLOYMENT_ACTION_WIZARD_STEP_AGENT_CONFIG_DESC": "Configure Agent settings",
4951
"DEPLOYMENT_ACTION_JAVA_OPTS_VAR_LABEL": "Java Options Environment Variable:",
5052
"DEPLOYMENT_ACTION_JAVA_OPTS_VAR_HELPER": "The environment variable name used to pass Java options to the JVM (default: JAVA_TOOL_OPTIONS)",
53+
"DEPLOYMENT_ACTION_CALLBACK_PORT_LABEL": "Callback Port:",
54+
"DEPLOYMENT_ACTION_CALLBACK_PORT_HELPER": "HTTP port for the Cryostat Agent (leave empty for Operator default)",
55+
"DEPLOYMENT_ACTION_CALLBACK_PORT_PLACEHOLDER": "<Default>",
5156
"DEPLOYMENT_ACTION_HARVESTER_TEMPLATE_LABEL": "Harvester Template:",
5257
"DEPLOYMENT_ACTION_HARVESTER_TEMPLATE_NONE": "None",
5358
"DEPLOYMENT_ACTION_HARVESTER_TEMPLATE_CONTINUOUS": "Continuous",
5459
"DEPLOYMENT_ACTION_HARVESTER_TEMPLATE_PROFILING": "Profiling",
5560
"DEPLOYMENT_ACTION_HARVESTER_TEMPLATE_NONE_DESC": "No automatic JFR harvesting",
5661
"DEPLOYMENT_ACTION_HARVESTER_TEMPLATE_CONTINUOUS_DESC": "Continuous JFR recording with periodic harvesting",
5762
"DEPLOYMENT_ACTION_HARVESTER_TEMPLATE_PROFILING_DESC": "Profiling template for performance analysis",
63+
"DEPLOYMENT_ACTION_HARVESTER_PERIOD_LABEL": "Harvester Period:",
64+
"DEPLOYMENT_ACTION_HARVESTER_PERIOD_HELPER": "How often to push JFR data to Cryostat (default: 15 minutes)",
65+
"DEPLOYMENT_ACTION_HARVESTER_MAX_FILES_LABEL": "Harvester Max Files:",
66+
"DEPLOYMENT_ACTION_HARVESTER_MAX_FILES_HELPER": "Maximum number of JFR files to retain locally (default: 4 files)",
5867
"DEPLOYMENT_ACTION_HARVESTER_EXIT_MAX_AGE_LABEL": "Harvester Exit Max Age:",
5968
"DEPLOYMENT_ACTION_HARVESTER_EXIT_MAX_AGE_HELPER": "Maximum age of data retained in the local recording file before it is pushed to Cryostat on shutdown (default: 5 minutes)",
6069
"DEPLOYMENT_ACTION_HARVESTER_EXIT_MAX_SIZE_LABEL": "Harvester Exit Max Size:",
@@ -69,7 +78,10 @@
6978
"DEPLOYMENT_ACTION_REVIEW_INSTANCE": "Cryostat Instance",
7079
"DEPLOYMENT_ACTION_REVIEW_CONTAINER": "Selected Container",
7180
"DEPLOYMENT_ACTION_REVIEW_JAVA_OPTS_VAR": "Java Options Variable",
81+
"DEPLOYMENT_ACTION_REVIEW_CALLBACK_PORT": "Callback Port",
7282
"DEPLOYMENT_ACTION_REVIEW_HARVESTER": "Harvester Template",
83+
"DEPLOYMENT_ACTION_REVIEW_HARVESTER_PERIOD": "Harvester Period",
84+
"DEPLOYMENT_ACTION_REVIEW_HARVESTER_MAX_FILES": "Harvester Max Files",
7385
"DEPLOYMENT_ACTION_REVIEW_HARVESTER_EXIT_MAX_AGE": "Harvester Exit Max Age",
7486
"DEPLOYMENT_ACTION_REVIEW_HARVESTER_EXIT_MAX_SIZE": "Harvester Exit Max Size",
7587
"DEPLOYMENT_ACTION_REVIEW_LOG_LEVEL": "Log Level",
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright The Cryostat Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
import { useCryostatTranslation } from '@i18n/i18nextUtil';
17+
import {
18+
Form,
19+
FormGroup,
20+
TextInput,
21+
NumberInput,
22+
FormHelperText,
23+
HelperText,
24+
HelperTextItem,
25+
} from '@patternfly/react-core';
26+
import * as React from 'react';
27+
28+
interface AgentConfigStepProps {
29+
javaOptsVar: string;
30+
callbackPort?: number;
31+
onJavaOptsVarChange: (value: string) => void;
32+
onCallbackPortChange: (value: number | undefined) => void;
33+
}
34+
35+
export const AgentConfigStep: React.FC<AgentConfigStepProps> = ({
36+
javaOptsVar,
37+
callbackPort,
38+
onJavaOptsVarChange,
39+
onCallbackPortChange,
40+
}) => {
41+
const { t } = useCryostatTranslation();
42+
43+
const handleCallbackPortChange = (event: React.FormEvent<HTMLInputElement>) => {
44+
const value = (event.target as HTMLInputElement).value;
45+
if (value === '') {
46+
onCallbackPortChange(undefined);
47+
} else {
48+
const numValue = Number(value);
49+
if (!isNaN(numValue) && numValue > 0) {
50+
onCallbackPortChange(numValue);
51+
}
52+
}
53+
};
54+
55+
const handleCallbackPortMinus = () => {
56+
if (callbackPort !== undefined && callbackPort > 1) {
57+
onCallbackPortChange(callbackPort - 1);
58+
}
59+
};
60+
61+
const handleCallbackPortPlus = () => {
62+
if (callbackPort !== undefined) {
63+
onCallbackPortChange(callbackPort + 1);
64+
} else {
65+
onCallbackPortChange(1);
66+
}
67+
};
68+
69+
return (
70+
<Form>
71+
<FormGroup label={t('DEPLOYMENT_ACTION_JAVA_OPTS_VAR_LABEL')} fieldId="java-opts-var">
72+
<TextInput
73+
id="java-opts-var"
74+
name="java-opts-var"
75+
value={javaOptsVar}
76+
onChange={(_event, value) => onJavaOptsVarChange(value)}
77+
placeholder="JAVA_TOOL_OPTIONS"
78+
/>
79+
<FormHelperText>
80+
<HelperText>
81+
<HelperTextItem>{t('DEPLOYMENT_ACTION_JAVA_OPTS_VAR_HELPER')}</HelperTextItem>
82+
</HelperText>
83+
</FormHelperText>
84+
</FormGroup>
85+
<FormGroup label={t('DEPLOYMENT_ACTION_CALLBACK_PORT_LABEL')} fieldId="callback-port">
86+
<NumberInput
87+
id="callback-port"
88+
value={callbackPort ?? ''}
89+
onMinus={handleCallbackPortMinus}
90+
onPlus={handleCallbackPortPlus}
91+
onChange={handleCallbackPortChange}
92+
min={1}
93+
widthChars={10}
94+
placeholder={t('DEPLOYMENT_ACTION_CALLBACK_PORT_PLACEHOLDER')}
95+
/>
96+
<FormHelperText>
97+
<HelperText>
98+
<HelperTextItem>{t('DEPLOYMENT_ACTION_CALLBACK_PORT_HELPER')}</HelperTextItem>
99+
</HelperText>
100+
</FormHelperText>
101+
</FormGroup>
102+
</Form>
103+
);
104+
};

src/openshift/actions/DeploymentLabelAction/ContainerSelectionStep.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
DescriptionListDescription,
2727
} from '@patternfly/react-core';
2828
import * as React from 'react';
29-
import { Container, getAgentConfig, formatAgentConfig, LogLevel } from './envVarUtils';
29+
import { Container, getAgentConfig, formatAgentConfig, LogLevel } from './utils';
3030

3131
interface ContainerSelectionStepProps {
3232
containers: Container[];

src/openshift/actions/DeploymentLabelAction/DeploymentDecorator.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import CryostatIcon from '@console-plugin/assets/CryostatIcon';
1717
import { k8sGet, K8sResourceKind, useK8sModel, useK8sWatchResource } from '@openshift-console/dynamic-plugin-sdk';
1818
import { Node } from '@patternfly/react-topology';
1919
import * as React from 'react';
20+
import { AGENT_LABEL_KEYS } from './utils';
2021

2122
type DeploymentDecoratorProps = {
2223
element: Node;
@@ -50,7 +51,7 @@ export const DeploymentDecorator: React.FC<DeploymentDecoratorProps> = ({ elemen
5051
React.useEffect(() => {
5152
if (deploymentLoaded && cryostatsLoaded) {
5253
const deploymentLabels = deployment.spec?.template.metadata.labels;
53-
if (deploymentLabels && deploymentLabels['cryostat.io/name'] && deploymentLabels['cryostat.io/namespace']) {
54+
if (deploymentLabels && deploymentLabels[AGENT_LABEL_KEYS.NAME] && deploymentLabels[AGENT_LABEL_KEYS.NAMESPACE]) {
5455
setIsRegistered(true);
5556
} else {
5657
setIsRegistered(false);
@@ -61,16 +62,16 @@ export const DeploymentDecorator: React.FC<DeploymentDecoratorProps> = ({ elemen
6162
React.useEffect(() => {
6263
if (deploymentLoaded && cryostatsLoaded && isRegistered) {
6364
const labels = deployment.spec?.template.metadata.labels;
64-
if (labels && labels['cryostat.io/name'] && labels['cryostat.io/namespace']) {
65+
if (labels && labels[AGENT_LABEL_KEYS.NAME] && labels[AGENT_LABEL_KEYS.NAMESPACE]) {
6566
cryostats.forEach((cryostat) => {
6667
if (
67-
cryostat.metadata?.name === labels['cryostat.io/name'] &&
68-
cryostat.metadata?.namespace === labels['cryostat.io/namespace']
68+
cryostat.metadata?.name === labels[AGENT_LABEL_KEYS.NAME] &&
69+
cryostat.metadata?.namespace === labels[AGENT_LABEL_KEYS.NAMESPACE]
6970
) {
7071
k8sGet({
7172
model: routeModel,
72-
name: labels['cryostat.io/name'],
73-
ns: labels['cryostat.io/namespace'],
73+
name: labels[AGENT_LABEL_KEYS.NAME],
74+
ns: labels[AGENT_LABEL_KEYS.NAMESPACE],
7475
})
7576
.catch(() => '')
7677
.then(

0 commit comments

Comments
 (0)