Skip to content

Commit 6ec375c

Browse files
committed
wip
1 parent 518e1fd commit 6ec375c

37 files changed

+10763
-64
lines changed

web/console-extensions.json

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,5 +287,60 @@
287287
"$codeRef": "netflowDevTab.default"
288288
}
289289
}
290+
},
291+
{
292+
"type": "console.yaml-template",
293+
"properties": {
294+
"model": {
295+
"version": "v1beta2",
296+
"group": "flows.netobserv.io",
297+
"kind": "FlowCollector"
298+
},
299+
"name": "default",
300+
"template": {
301+
"$codeRef": "yamlTemplates.FlowCollector"
302+
}
303+
}
304+
},
305+
{
306+
"type": "console.page/route",
307+
"properties": {
308+
"path": "/k8s/cluster/flows.netobserv.io~v1beta2~FlowCollector/~new/wizard",
309+
"component": {
310+
"$codeRef": "flowCollectorWizard.default"
311+
}
312+
}
313+
},
314+
{
315+
"type": "console.page/route",
316+
"properties": {
317+
"path": "/k8s/cluster/flows.netobserv.io~v1beta2~FlowCollector/~new/form",
318+
"component": {
319+
"$codeRef": "flowCollectorForm.default"
320+
}
321+
}
322+
},
323+
{
324+
"type": "console.yaml-template",
325+
"properties": {
326+
"model": {
327+
"version": "v1alpha1",
328+
"group": "flows.netobserv.io",
329+
"kind": "FlowMetric"
330+
},
331+
"name": "default",
332+
"template": {
333+
"$codeRef": "yamlTemplates.FlowMetric"
334+
}
335+
}
336+
},
337+
{
338+
"type": "console.page/route",
339+
"properties": {
340+
"path": "/k8s/cluster/flows.netobserv.io~v1alpha1~FlowMetric/~new/form",
341+
"component": {
342+
"$codeRef": "flowMetricForm.default"
343+
}
344+
}
290345
}
291346
]

web/locales/en/plugin__netobserv-plugin.json

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,52 @@
159159
"M": "M",
160160
"S": "S",
161161
"XS": "XS",
162+
"There is some issue in this form view. Please select \"YAML view\" for full control.": "There is some issue in this form view. Please select \"YAML view\" for full control.",
163+
"Note: Some fields may not be represented in this form view. Please select \"YAML view\" for full control.": "Note: Some fields may not be represented in this form view. Please select \"YAML view\" for full control.",
164+
"Remove {{singularLabel}}": "Remove {{singularLabel}}",
165+
"Add {{singularLabel}}": "Add {{singularLabel}}",
166+
"Error": "Error",
167+
"Fix the following errors:": "Fix the following errors:",
168+
"Enabled": "Enabled",
169+
"Disabled": "Disabled",
170+
"Select {{title}}": "Select {{title}}",
171+
"Configure via:": "Configure via:",
172+
"Form view": "Form view",
173+
"YAML view": "YAML view",
174+
"This object has been updated.": "This object has been updated.",
175+
"Click reload to see the new version.": "Click reload to see the new version.",
176+
"Update": "Update",
177+
"Create": "Create",
178+
"Reload": "Reload",
179+
"Cancel": "Cancel",
180+
"Network Observability FlowCollector setup": "Network Observability FlowCollector setup",
181+
"Overview": "Overview",
182+
"Network Observability Operator deploys a monitoring pipeline that consists in:\n - an eBPF agent, that generates network flows from captured packets\n - flowlogs-pipeline, a component that collects, enriches and exports these flows\n - a Console plugin for flows visualization with powerful filtering options, a topology representation and more\n\nFlow data is then available in multiple ways, each optional:\n - As Prometheus metrics\n - As raw flow logs stored in Grafana Loki\n - As raw flow logs exported to a collector\n\nThe FlowCollector resource is used to configure the operator and its managed components.\nThis setup will guide you on the common aspects of the FlowCollector configuration.": "Network Observability Operator deploys a monitoring pipeline that consists in:\n - an eBPF agent, that generates network flows from captured packets\n - flowlogs-pipeline, a component that collects, enriches and exports these flows\n - a Console plugin for flows visualization with powerful filtering options, a topology representation and more\n\nFlow data is then available in multiple ways, each optional:\n - As Prometheus metrics\n - As raw flow logs stored in Grafana Loki\n - As raw flow logs exported to a collector\n\nThe FlowCollector resource is used to configure the operator and its managed components.\nThis setup will guide you on the common aspects of the FlowCollector configuration.",
183+
"Operator configuration": "Operator configuration",
184+
"Capture": "Capture",
185+
"Filters": "Filters",
186+
"Options": "Options",
187+
"Pipeline": "Pipeline",
188+
"Storage": "Storage",
189+
"Integration": "Integration",
190+
"Review": "Review",
191+
"Network Observability FlowMetric setup": "Network Observability FlowMetric setup",
192+
"You can create custom metrics out of the flowlogs data using the FlowMetric API. In every flowlogs data that is collected, there are a number of fields labeled per log, such as source name and destination name. These fields can be leveraged as Prometheus labels to enable the customization of cluster information on your dashboard.\nThis setup will guide you on the common aspects of the FlowMetric configuration.": "You can create custom metrics out of the flowlogs data using the FlowMetric API. In every flowlogs data that is collected, there are a number of fields labeled per log, such as source name and destination name. These fields can be leveraged as Prometheus labels to enable the customization of cluster information on your dashboard.\nThis setup will guide you on the common aspects of the FlowMetric configuration.",
193+
"General configuration": "General configuration",
194+
"Metric": "Metric",
195+
"Data": "Data",
196+
"Charts": "Charts",
197+
"Update {{kind}}": "Update {{kind}}",
198+
"Create {{kind}}": "Create {{kind}}",
199+
"Update by completing the form. Current values are from the existing resource.": "Update by completing the form. Current values are from the existing resource.",
200+
"Create by completing the form. Default values are provided as example.": "Create by completing the form. Default values are provided as example.",
201+
"{{kind}} resource doesn't exists yet.": "{{kind}} resource doesn't exists yet.",
202+
"Type": "Type",
203+
"Status": "Status",
204+
"Reason": "Reason",
205+
"Message": "Message",
206+
"Changed": "Changed",
207+
"Unable to get {{kind}}": "Unable to get {{kind}}",
162208
"Step {{index}}/{{count}}": "Step {{index}}/{{count}}",
163209
"Step {{index}}/{{count}}_plural": "Step {{index}}/{{count}}",
164210
"Previous tip": "Previous tip",
@@ -231,7 +277,6 @@
231277
"Unselect all": "Unselect all",
232278
"Select all": "Select all",
233279
"Restore default columns": "Restore default columns",
234-
"Cancel": "Cancel",
235280
"At least one column must be selected": "At least one column must be selected",
236281
"Save": "Save",
237282
"Export": "Export",
@@ -351,7 +396,6 @@
351396
"Pin this element": "Pin this element",
352397
"Could not fetch drop information": "Could not fetch drop information",
353398
"Sorry, 3D view is not implemented anymore.": "Sorry, 3D view is not implemented anymore.",
354-
"Overview": "Overview",
355399
"Traffic flows": "Traffic flows",
356400
"Topology": "Topology",
357401
"Hide histogram": "Hide histogram",

web/moduleMapper/dummy.tsx

Lines changed: 172 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
import {
3+
K8sGroupVersionKind,
4+
K8sModel,
5+
K8sResourceKind,
6+
K8sResourceKindReference,
7+
ResourceIconProps,
8+
ResourceLinkProps,
9+
ResourceYAMLEditorProps
10+
} from '@openshift-console/dynamic-plugin-sdk';
11+
import { CodeEditor, Language } from '@patternfly/react-code-editor';
12+
import _ from 'lodash';
113
import * as React from 'react';
2-
import { ResourceIconProps, ResourceLinkProps } from '@openshift-console/dynamic-plugin-sdk';
14+
import { GetFlowCollectorJS } from '../src/components/forms/config/templates';
315
import { useK8sModelsWithColors } from '../src/utils/k8s-models-hook';
16+
import { useTheme } from '../src/utils/theme-hook';
17+
import { safeJSToYAML } from '../src/utils/yaml';
418
import { k8sModels } from './k8s-models';
519

620
// This dummy file is used to resolve @Console imports from @openshift-console for JEST / Standalone
@@ -35,6 +49,139 @@ export function useK8sModels() {
3549
]
3650
}
3751

52+
export function getK8sModel(k8s: any, k8sGroupVersionKind?: K8sResourceKindReference | K8sGroupVersionKind): K8sModel {
53+
const models = Object.keys(k8sModels);
54+
55+
for (let i = 0; i < models.length; i++) {
56+
const model = (k8sModels as any)[models[i]];
57+
if (model.kind === k8s.kind) {
58+
return model;
59+
}
60+
}
61+
62+
return {
63+
abbr: '',
64+
kind: '',
65+
label: '',
66+
labelPlural: '',
67+
plural: '',
68+
apiVersion: ''
69+
};
70+
}
71+
72+
export function k8sGet(k8s: any): Promise<any> {
73+
console.log("k8sGet", k8s);
74+
return Promise.resolve(k8s);
75+
}
76+
77+
export function k8sCreate(k8s: any): Promise<any> {
78+
console.log("k8sCreate", k8s);
79+
return Promise.resolve(k8s);
80+
}
81+
82+
export function k8sUpdate(k8s: any): Promise<any> {
83+
console.log("k8sUpdate", k8s);
84+
return Promise.resolve(k8s);
85+
}
86+
87+
export function useK8sWatchResource(req: any) {
88+
console.log("useK8sWatchResource", req);
89+
90+
const [loaded, setLoaded] = React.useState(false);
91+
const [resource, setResource] = React.useState<K8sResourceKind | null>(null);
92+
93+
React.useEffect(() => {
94+
// simulate a loading
95+
if (resource == null) {
96+
setTimeout(() => {
97+
switch (req.groupVersionKind.kind) {
98+
case 'FlowCollector':
99+
const fc = _.cloneDeep(GetFlowCollectorJS());
100+
fc.spec!.loki.enable = false;
101+
fc.status = {
102+
"conditions": [
103+
{
104+
"lastTransitionTime": "2025-04-08T09:01:44Z",
105+
"message": "4 ready components, 0 with failure, 1 pending",
106+
"reason": "Pending",
107+
"status": "False",
108+
"type": "Ready"
109+
},
110+
{
111+
"lastTransitionTime": "2025-04-08T09:01:44Z",
112+
"message": "Deployment netobserv-plugin not ready: 1/1 (Deployment does not have minimum availability.)",
113+
"reason": "DeploymentNotReady",
114+
"status": "True",
115+
"type": "WaitingFlowCollectorLegacy"
116+
},
117+
{
118+
"lastTransitionTime": "2025-04-08T09:01:44Z",
119+
"message": "",
120+
"reason": "Ready",
121+
"status": "False",
122+
"type": "WaitingMonitoring"
123+
},
124+
{
125+
"lastTransitionTime": "2025-04-08T09:01:43Z",
126+
"message": "",
127+
"reason": "Ready",
128+
"status": "False",
129+
"type": "WaitingNetworkPolicy"
130+
},
131+
{
132+
"lastTransitionTime": "2025-04-08T09:01:43Z",
133+
"message": "",
134+
"reason": "Valid",
135+
"status": "False",
136+
"type": "ConfigurationIssue"
137+
},
138+
{
139+
"lastTransitionTime": "2025-04-08T09:01:43Z",
140+
"message": "Loki is not configured in LokiStack mode",
141+
"reason": "Unused",
142+
"status": "Unknown",
143+
"type": "LokiIssue"
144+
},
145+
{
146+
"lastTransitionTime": "2025-04-08T09:01:45Z",
147+
"message": "",
148+
"reason": "Ready",
149+
"status": "False",
150+
"type": "WaitingFLPParent"
151+
},
152+
{
153+
"lastTransitionTime": "2025-04-08T09:01:45Z",
154+
"message": "",
155+
"reason": "Ready",
156+
"status": "False",
157+
"type": "WaitingFLPMonolith"
158+
},
159+
{
160+
"lastTransitionTime": "2025-04-08T09:01:44Z",
161+
"message": "Transformer only used with Kafka",
162+
"reason": "ComponentUnused",
163+
"status": "Unknown",
164+
"type": "WaitingFLPTransformer"
165+
}
166+
]
167+
}
168+
setResource(fc);
169+
break;
170+
}
171+
setLoaded(true);
172+
}, 1000);
173+
}
174+
}, [req.groupVersionKind.kind, req.kind, resource]);
175+
176+
return React.useMemo(() => {
177+
if (!resource) {
178+
return [null, loaded, null];
179+
} else {
180+
return [[resource], loaded, null];
181+
}
182+
}, [loaded, resource]);
183+
}
184+
38185
export const ResourceIcon: React.FC<ResourceIconProps> = ({
39186
className,
40187
kind,
@@ -80,4 +227,27 @@ export const ResourceLink: React.FC<ResourceLinkProps> = ({
80227
{children}
81228
</span>
82229
);
83-
};
230+
};
231+
232+
export const ResourceYAMLEditor: React.FC<ResourceYAMLEditorProps> = ({
233+
initialResource,
234+
header,
235+
onSave,
236+
}) => {
237+
const isDarkTheme = useTheme();
238+
const containerHeight = document.getElementById("editor-content-container")?.clientHeight || 800;
239+
const footerHeight = document.getElementById("editor-toggle-footer")?.clientHeight || 0;
240+
return (<>
241+
<CodeEditor
242+
isDarkTheme={isDarkTheme}
243+
isLineNumbersVisible={true}
244+
isReadOnly={false}
245+
isMinimapVisible={true}
246+
isLanguageLabelVisible
247+
code={safeJSToYAML(initialResource)}
248+
language={Language.yaml}
249+
height={`${containerHeight - footerHeight}px`}
250+
onChange={(value) => onSave && onSave(value)}
251+
/>
252+
</>);
253+
};

0 commit comments

Comments
 (0)