Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .mk/static.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
##@ Static

.PHONY: build-frontend-static
build-frontend-static: install-frontend fmt-frontend ## Run npm install, format and build static frontend
@echo "### Building static frontend"
cd web && npm run build:static
3 changes: 3 additions & 0 deletions Dockerfile.cypress
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ WORKDIR /opt/app-root

COPY --chown=node web/package.json web/package.json
COPY --chown=node web/package-lock.json web/package-lock.json
COPY --chown=node web/manage-extension.sh web/manage-extension.sh

WORKDIR /opt/app-root/web
RUN npm ci

Expand All @@ -19,6 +21,7 @@ COPY mocks mocks
WORKDIR /opt/app-root/web
RUN npm run format-all
RUN npm run build$BUILDSCRIPT
RUN npm run build:static

FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.24 as go-builder

Expand Down
3 changes: 3 additions & 0 deletions Dockerfile.downstream
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ WORKDIR /opt/app-root

COPY --chown=default web/package.json web/package.json
COPY --chown=default web/package-lock.json web/package-lock.json
COPY --chown=node web/manage-extension.sh web/manage-extension.sh

WORKDIR /opt/app-root/web

RUN CYPRESS_INSTALL_BINARY=0 node --max-old-space-size=6000 $(which npm) --legacy-peer-deps ci --ignore-scripts
Expand All @@ -18,6 +20,7 @@ COPY --chown=default mocks mocks
WORKDIR /opt/app-root/web
RUN npm run format-all
RUN npm run build
RUN npm run build:static

FROM brew.registry.redhat.io/rh-osbs/openshift-golang-builder:v1.24 as go-builder

Expand Down
3 changes: 3 additions & 0 deletions Dockerfile.front
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ WORKDIR /opt/app-root

COPY --chown=node web/package-lock.json web/package-lock.json
COPY --chown=node web/package.json web/package.json
COPY --chown=node web/manage-extension.sh web/manage-extension.sh

WORKDIR /opt/app-root/web
RUN CYPRESS_INSTALL_BINARY=0 npm --legacy-peer-deps ci

Expand All @@ -17,6 +19,7 @@ COPY mocks mocks
WORKDIR /opt/app-root/web
RUN npm run format-all
RUN npm run build$BUILDSCRIPT
RUN npm run build:static

FROM scratch

Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,4 @@ endif
include .mk/cypress.mk
include .mk/shortcuts.mk
include .mk/standalone.mk
include .mk/static.mk
8 changes: 6 additions & 2 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,16 @@ type Config struct {
Frontend Frontend `yaml:"frontend" json:"frontend"`
Server Server `yaml:"server,omitempty" json:"server,omitempty"`
Path string `yaml:"-" json:"-"`
Static bool
}

func ReadFile(version, date, filename string) (*Config, error) {
isStatic := len(filename) == 0

// set default values
cfg := Config{
Path: filename,
Path: filename,
Static: isStatic,
Server: Server{
Port: 9001,
MetricsPort: 9002,
Expand Down Expand Up @@ -242,7 +246,7 @@ func (c *Config) IsPromEnabled() bool {
}

func (c *Config) Validate() error {
if !c.IsLokiEnabled() && !c.IsPromEnabled() {
if !c.Static && !c.IsLokiEnabled() && !c.IsPromEnabled() {
return errors.New("neither Loki nor Prometheus is configured; at least one of them should have a URL defined")
}

Expand Down
40 changes: 23 additions & 17 deletions pkg/server/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,32 @@ func setupRoutes(ctx context.Context, cfg *config.Config, authChecker auth.Check

// Server status
api.HandleFunc("/status", h.Status(ctx))
api.HandleFunc("/frontend-config", h.GetFrontendConfig())

// Loki endpoints
api.HandleFunc("/loki/ready", h.LokiReady())
api.HandleFunc("/loki/metrics", forceCheckAdmin(authChecker, h.LokiMetrics()))
api.HandleFunc("/loki/buildinfo", forceCheckAdmin(authChecker, h.LokiBuildInfos()))
api.HandleFunc("/loki/config/limits", forceCheckAdmin(authChecker, h.LokiLimits()))
api.HandleFunc("/loki/flow/records", h.GetFlows(ctx))
api.HandleFunc("/loki/export", h.ExportFlows(ctx))
if cfg.Static {
// Expose static files only
r.PathPrefix("/").Handler(http.FileServer(http.Dir("./web/dist/static")))
} else {
// Loki endpoints
api.HandleFunc("/loki/ready", h.LokiReady())
api.HandleFunc("/loki/metrics", forceCheckAdmin(authChecker, h.LokiMetrics()))
api.HandleFunc("/loki/buildinfo", forceCheckAdmin(authChecker, h.LokiBuildInfos()))
api.HandleFunc("/loki/config/limits", forceCheckAdmin(authChecker, h.LokiLimits()))
api.HandleFunc("/loki/flow/records", h.GetFlows(ctx))
api.HandleFunc("/loki/export", h.ExportFlows(ctx))

// Common endpoints
api.HandleFunc("/flow/metrics", h.GetTopology(ctx))
api.HandleFunc("/resources/clusters", h.GetClusters(ctx))
api.HandleFunc("/resources/udns", h.GetUDNs(ctx))
api.HandleFunc("/resources/zones", h.GetZones(ctx))
api.HandleFunc("/resources/namespaces", h.GetNamespaces(ctx))
api.HandleFunc("/resources/names", h.GetNames(ctx))
// Common endpoints
api.HandleFunc("/flow/metrics", h.GetTopology(ctx))
api.HandleFunc("/resources/clusters", h.GetClusters(ctx))
api.HandleFunc("/resources/udns", h.GetUDNs(ctx))
api.HandleFunc("/resources/zones", h.GetZones(ctx))
api.HandleFunc("/resources/namespaces", h.GetNamespaces(ctx))
api.HandleFunc("/resources/names", h.GetNames(ctx))

// Frontend files
r.PathPrefix("/").Handler(http.FileServer(http.Dir("./web/dist/")))
}

// Frontend files
api.HandleFunc("/frontend-config", h.GetFrontendConfig())
r.PathPrefix("/").Handler(http.FileServer(http.Dir("./web/dist/")))
return r
}

Expand Down
78 changes: 75 additions & 3 deletions web/locales/en/plugin__netobserv-plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,81 @@
"S": "S",
"XS": "XS",
"None": "None",
"Cluster metrics": "Cluster metrics",
"Bandwidth": "Bandwidth",
"Nodes": "Nodes",
"Namespaces": "Namespaces",
"Pods": "Pods",
"Recommendations": "Recommendations",
"The example outlined in the table demonstrates a scenario that is tailored to your workload. Consider this example only as a baseline from which adjustments can be made to accommodate your needs.": "The example outlined in the table demonstrates a scenario that is tailored to your workload. Consider this example only as a baseline from which adjustments can be made to accommodate your needs.",
"vCPU": "vCPU",
"Memory": "Memory",
"LokiStack size": "LokiStack size",
"Kafka": "Kafka",
"Performance tuning and estimation": "Performance tuning and estimation",
"The sampling interval is one of the main settings used to balance performance and accuracy. The lower the interval, the higher the accuracy.": "The sampling interval is one of the main settings used to balance performance and accuracy. The lower the interval, the higher the accuracy.",
"Use the slider below to configure the desired sampling interval.": "Use the slider below to configure the desired sampling interval.",
"Sampling interval": "Sampling interval",
"The estimations are based on the number of nodes in the cluster and the sampling rate. They do not take into account the number of namespaces or pods, as their impact is comparatively lower than that of nodes.\nThey are calculated using a linear regression model based on data collected from various OpenShift clusters. Actual resource consumption may vary depending on your specific workload and cluster configuration.": "The estimations are based on the number of nodes in the cluster and the sampling rate. They do not take into account the number of namespaces or pods, as their impact is comparatively lower than that of nodes.\nThey are calculated using a linear regression model based on data collected from various OpenShift clusters. Actual resource consumption may vary depending on your specific workload and cluster configuration.",
"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.",
"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.",
"(see more...)": "(see more...)",
"Remove {{singularLabel}}": "Remove {{singularLabel}}",
"Add {{singularLabel}}": "Add {{singularLabel}}",
"Error": "Error",
"Fix the following errors:": "Fix the following errors:",
"True": "True",
"False": "False",
"Select {{title}}": "Select {{title}}",
"Configure via:": "Configure via:",
"Form view": "Form view",
"YAML view": "YAML view",
"This object has been updated.": "This object has been updated.",
"Click reload to see the new version.": "Click reload to see the new version.",
"Update": "Update",
"Create": "Create",
"Reload": "Reload",
"Cancel": "Cancel",
"Delete": "Delete",
"Network Observability FlowCollector status": "Network Observability FlowCollector status",
"Edit FlowCollector": "Edit FlowCollector",
"Open Network Traffic page": "Open Network Traffic page",
"An error occured while retreiving FlowCollector: {{error}}": "An error occured while retreiving FlowCollector: {{error}}",
"Create FlowCollector": "Create FlowCollector",
"Network Observability FlowCollector setup": "Network Observability FlowCollector setup",
"Overview": "Overview",
"The FlowCollector resource is used to configure the Network Observability operator and its managed components. When it is created, network flows start being collected.": "The FlowCollector resource is used to configure the Network Observability operator and its managed components. When it is created, network flows start being collected.",
"This wizard is a helper to create a first FlowCollector resource. It does not cover all the available configuration options, but only the most common ones.\nFor advanced configuration, please use YAML or the": "This wizard is a helper to create a first FlowCollector resource. It does not cover all the available configuration options, but only the most common ones.\nFor advanced configuration, please use YAML or the",
"FlowCollector form": "FlowCollector form",
", which includes more options such as:\n- Filtering options\n- Configuring custom exporters\n- Custom labels based on IP\n- Pod identification for secondary networks\n- Performance fine-tuning\nYou can always edit a FlowCollector later when you start with the simplified configuration.": ", which includes more options such as:\n- Filtering options\n- Configuring custom exporters\n- Custom labels based on IP\n- Pod identification for secondary networks\n- Performance fine-tuning\nYou can always edit a FlowCollector later when you start with the simplified configuration.",
"Operator configuration": "Operator configuration",
"Processing": "Processing",
"Consumption": "Consumption",
"Submit": "Submit",
"Network Observability FlowMetric setup": "Network Observability FlowMetric setup",
"You can create custom metrics out of the network flows using the FlowMetric API. A FlowCollector resource must be created as well in order to produce the flows. Each flow consists in a set of fields with values, such as source name and destination name. These fields can be leveraged as Prometheus labels to enable customized metrics and dashboards.": "You can create custom metrics out of the network flows using the FlowMetric API. A FlowCollector resource must be created as well in order to produce the flows. Each flow consists in a set of fields with values, such as source name and destination name. These fields can be leveraged as Prometheus labels to enable customized metrics and dashboards.",
"This simplified setup guides you through the common aspects of the FlowMetric configuration. For advanced configuration, please use YAML or the ": "This simplified setup guides you through the common aspects of the FlowMetric configuration. For advanced configuration, please use YAML or the ",
"FlowMetric form": "FlowMetric form",
"Resource configuration": "Resource configuration",
"Metric": "Metric",
"Data": "Data",
"Review": "Review",
"Unknown": "Unknown",
"Update {{kind}}": "Update {{kind}}",
"Create {{kind}}": "Create {{kind}}",
"Update by completing the form. Current values are from the existing resource.": "Update by completing the form. Current values are from the existing resource.",
"Create by completing the form. Default values are provided as example.": "Create by completing the form. Default values are provided as example.",
"Delete {{kind}}?": "Delete {{kind}}?",
"This action cannot be undone.": "This action cannot be undone.",
"It will destroy all pods, services and other objects in the namespace": "It will destroy all pods, services and other objects in the namespace",
"The following metric will not be collected anymore": "The following metric will not be collected anymore",
"{{kind}} resource doesn't exists yet.": "{{kind}} resource doesn't exists yet.",
"Type": "Type",
"Status": "Status",
"Reason": "Reason",
"Message": "Message",
"Changed": "Changed",
"Unable to get {{kind}}": "Unable to get {{kind}}",
"Step {{index}}/{{count}}": "Step {{index}}/{{count}}",
"Step {{index}}/{{count}}_plural": "Step {{index}}/{{count}}",
"Previous tip": "Previous tip",
Expand Down Expand Up @@ -231,7 +306,6 @@
"Unselect all": "Unselect all",
"Select all": "Select all",
"Restore default columns": "Restore default columns",
"Cancel": "Cancel",
"At least one column must be selected": "At least one column must be selected",
"Save": "Save",
"Export": "Export",
Expand Down Expand Up @@ -350,7 +424,6 @@
"Pin this element": "Pin this element",
"Could not fetch drop information": "Could not fetch drop information",
"Sorry, 3D view is not implemented anymore.": "Sorry, 3D view is not implemented anymore.",
"Overview": "Overview",
"Traffic flows": "Traffic flows",
"Topology": "Topology",
"Hide histogram": "Hide histogram",
Expand Down Expand Up @@ -397,7 +470,6 @@
"Export view": "Export view",
"Observe": "Observe",
"External": "External",
"Unknown": "Unknown",
"Last 5 minutes": "Last 5 minutes",
"Last 15 minutes": "Last 15 minutes",
"Last 30 minutes": "Last 30 minutes",
Expand Down
93 changes: 91 additions & 2 deletions web/console-extensions.json → web/manage-extension.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,4 +1,78 @@
[
#!/bin/bash

if [ "$1" == "static" ]; then
echo '[
{
"type": "console.page/route",
"properties": {
"path": "/k8s/ns/:namespace/operators.coreos.com~v1alpha1~ClusterServiceVersion/:operator/flows.netobserv.io~v1beta2~FlowCollector/~new",
"component": {
"$codeRef": "flowCollectorWizard.default"
}
}
},
{
"type": "console.page/route",
"properties": {
"path": [
"/k8s/cluster/flows.netobserv.io~v1beta2~FlowCollector/~new",
"/k8s/cluster/flows.netobserv.io~v1beta2~FlowCollector/:name"
],
"component": {
"$codeRef": "flowCollectorForm.default"
}
}
},
{
"type": "console.page/route",
"properties": {
"path": "/k8s/cluster/flows.netobserv.io~v1beta2~FlowCollector/status",
"component": {
"$codeRef": "flowCollectorStatus.default"
}
}
},
{
"type": "console.page/route",
"properties": {
"path": "k8s/ns/:namespace/operators.coreos.com~v1alpha1~ClusterServiceVersion/:operator/flows.netobserv.io~v1alpha1~FlowMetric/~new",
"component": {
"$codeRef": "flowMetricWizard.default"
}
}
},
{
"type": "console.page/route",
"properties": {
"path": [
"/k8s/ns/:namespace/clusterserviceversions/:operator/flows.netobserv.io~v1alpha1~FlowMetric/:name",
"/k8s/ns/:namespace/flows.netobserv.io~v1alpha1~FlowMetric/~new",
"/k8s/ns/:namespace/flows.netobserv.io~v1alpha1~FlowMetric/:name"
],
"component": {
"$codeRef": "flowMetricForm.default"
}
}
}
]' > console-extensions.json
echo $(cat package.json | jq '.consolePlugin = {
"name": "netobserv-plugin-static",
"version": "0.1.0",
"displayName": "NetObserv Static Plugin for OCP Console",
"description": "This plugin adds custom forms for FlowCollector and FlowMetrics API",
"exposedModules": {
"flowCollectorWizard": "./components/forms/flowCollector-wizard.tsx",
"flowCollectorForm": "./components/forms/flowCollector.tsx",
"flowCollectorStatus": "./components/forms/flowCollector-status.tsx",
"flowMetricWizard": "./components/forms/flowMetric-wizard.tsx",
"flowMetricForm": "./components/forms/flowMetric.tsx"
},
"dependencies": {
"@console/pluginAPI": "*"
}
}') > package.json
else
echo '[
{
"type": "console.flag",
"properties": {
Expand Down Expand Up @@ -286,4 +360,19 @@
}
}
}
]
]' > console-extensions.json
echo $(cat package.json | jq '.consolePlugin = {
"name": "netobserv-plugin",
"version": "0.1.0",
"displayName": "NetObserv Plugin for Console",
"description": "This plugin adds network observability functionality to Openshift console",
"exposedModules": {
"netflowParent": "./components/netflow-traffic-parent.tsx",
"netflowTab": "./components/netflow-traffic-tab.tsx",
"netflowDevTab": "./components/netflow-traffic-dev-tab.tsx"
},
"dependencies": {
"@console/pluginAPI": "*"
}
}') > package.json
fi
Loading
Loading