Skip to content

Commit

Permalink
feat: add Korrel8r plugin to UITroubleshootPanel
Browse files Browse the repository at this point in the history
Signed-off-by: Shweta Padubidri <[email protected]>
  • Loading branch information
shwetaap committed Jun 6, 2024
1 parent db0b62f commit 1b83cca
Show file tree
Hide file tree
Showing 12 changed files with 251 additions and 119 deletions.
11 changes: 0 additions & 11 deletions bundle/manifests/observability.openshift.io_uiplugins.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,6 @@ spec:
description: TroubleshootingPanel contains configuration for the troubleshooting
console plugin.
properties:
korrel8r:
description: korrel8r defines the Korrel8r instance that the troubleshooting
panel plugin will connect to
properties:
name:
description: Name of the korrel8r instance
type: string
namespace:
description: Namespace of the korrel8r instance
type: string
type: object
timeout:
description: |-
Timeout is the maximum duration before a query timeout.
Expand Down
1 change: 1 addition & 0 deletions cmd/operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ var defaultImages = map[string]string{
"ui-dashboards": "quay.io/openshift-observability-ui/console-dashboards-plugin:v0.1.0",
"ui-troubleshooting-panel": "quay.io/openshift-observability-ui/troubleshooting-panel-console-plugin:v0.1.0",
"ui-distributed-tracing": "quay.io/openshift-observability-ui/distributed-tracing-console-plugin:v0.1.0",
"korrel8r": "quay.io/korrel8r/korrel8r:0.6.5",
}

func imagesUsed() []string {
Expand Down
11 changes: 0 additions & 11 deletions deploy/crds/common/observability.openshift.io_uiplugins.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,6 @@ spec:
description: TroubleshootingPanel contains configuration for the troubleshooting
console plugin.
properties:
korrel8r:
description: korrel8r defines the Korrel8r instance that the troubleshooting
panel plugin will connect to
properties:
name:
description: Name of the korrel8r instance
type: string
namespace:
description: Namespace of the korrel8r instance
type: string
type: object
timeout:
description: |-
Timeout is the maximum duration before a query timeout.
Expand Down
41 changes: 0 additions & 41 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2923,13 +2923,6 @@ TroubleshootingPanel contains configuration for the troubleshooting console plug
</tr>
</thead>
<tbody><tr>
<td><b><a href="#uipluginspectroubleshootingpanelkorrel8r">korrel8r</a></b></td>
<td>object</td>
<td>
korrel8r defines the Korrel8r instance that the troubleshooting panel plugin will connect to<br/>
</td>
<td>false</td>
</tr><tr>
<td><b>timeout</b></td>
<td>string</td>
<td>
Expand All @@ -2944,40 +2937,6 @@ or 'm' (minutes).<br/>
</table>


### UIPlugin.spec.troubleshootingPanel.korrel8r
<sup><sup>[↩ Parent](#uipluginspectroubleshootingpanel)</sup></sup>



korrel8r defines the Korrel8r instance that the troubleshooting panel plugin will connect to

<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Required</th>
</tr>
</thead>
<tbody><tr>
<td><b>name</b></td>
<td>string</td>
<td>
Name of the korrel8r instance<br/>
</td>
<td>false</td>
</tr><tr>
<td><b>namespace</b></td>
<td>string</td>
<td>
Namespace of the korrel8r instance<br/>
</td>
<td>false</td>
</tr></tbody>
</table>


### UIPlugin.status
<sup><sup>[↩ Parent](#uiplugin)</sup></sup>

Expand Down
2 changes: 1 addition & 1 deletion docs/user-guides/observability-ui-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ spec:
### Troubleshooting Panel
The plugin will connect to a Korrel8r instance named `korrel8r` in the `korrel8r` namespace. A "Troubleshooting Panel" button is added to the alerts page, which will convert the current alert into a Korrel8r query, then retrieve related neighbors and display them in a topology view.
The plugin will connect to a Korrel8r service named `korrel8r` in the namespace where the observability operator(and Korrel8r) is deployed. A "Troubleshooting Panel" button is added to the alerts page, which will convert the current alert into a Korrel8r query, then retrieve related neighbors and display them in a topology view.

To enable the troubleshooting panel console plugin, create a `UIPlugin` CR. The following example shows how to create a CR to enable the troubleshooting panel console plugin:

Expand Down
19 changes: 0 additions & 19 deletions pkg/apis/uiplugin/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,6 @@ type TroubleshootingPanelConfig struct {
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="OCP Console Query Timeout",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:ocpConsoleTimeout"}
// +kubebuilder:validation:Pattern:="^([0-9]+)([sm]{1})$"
Timeout string `json:"timeout,omitempty"`
// korrel8r defines the Korrel8r instance that the troubleshooting panel plugin will connect to
//
// +optional
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Korrel8r Instance"
Korrel8r TroubleshootingPanelKorrel8rConfig `json:"korrel8r,omitempty"`
}

type TroubleshootingPanelKorrel8rConfig struct {
// Name of the korrel8r instance
//
// +optional
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Korrel8r Instance Name"
Name string `json:"name,omitempty"`

// Namespace of the korrel8r instance
//
// +optional
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Korrel8r Instance Namespace"
Namespace string `json:"namespace,omitempty"`
}

// DistributedTracingConfig contains options for configuring the Distributed Tracing plugin
Expand Down
16 changes: 0 additions & 16 deletions pkg/apis/uiplugin/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

188 changes: 185 additions & 3 deletions pkg/controllers/uiplugin/components.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package uiplugin

import (
"bytes"
"embed"
"fmt"
"io"
"text/template"

osv1alpha1 "github.com/openshift/api/console/v1alpha1"
appsv1 "k8s.io/api/apps/v1"
Expand All @@ -16,9 +20,18 @@ import (
)

const (
port = 9443
serviceAccountSuffix = "-sa"
servingCertVolumeName = "serving-cert"
port = 9443
serviceAccountSuffix = "-sa"
servingCertVolumeName = "serving-cert"
Korrel8rConfigFileName = "korrel8r.yaml"
Korrel8rConfigMountDir = "/config/"
OpenshiftLoggingNs = "openshift-logging"
OpenshiftNetobservNs = "netobserv"
)

var (
//go:embed config/korrel8r.yaml
korrel8rConfigYAMLTmplFile embed.FS
)

func pluginComponentReconcilers(plugin *uiv1alpha1.UIPlugin, pluginInfo UIPluginInfo) []reconciler.Reconciler {
Expand Down Expand Up @@ -55,6 +68,16 @@ func pluginComponentReconcilers(plugin *uiv1alpha1.UIPlugin, pluginInfo UIPlugin
}
}

if pluginInfo.Korrel8rImage != "" {
kname := "korrel8r"
components = append(components, reconciler.NewUpdater(newKorrel8rService(kname, namespace), plugin))
korrel8rCm, err := newKorrel8rConfigMap(kname, namespace, pluginInfo)
if err == nil && korrel8rCm != nil {
components = append(components, reconciler.NewUpdater(korrel8rCm, plugin))
components = append(components, reconciler.NewUpdater(newKorrel8rDeployment(kname, namespace, pluginInfo), plugin))
}
}

return components
}

Expand Down Expand Up @@ -248,6 +271,165 @@ func newService(info UIPluginInfo, namespace string) *corev1.Service {
}
}

func newKorrel8rDeployment(name string, namespace string, info UIPluginInfo) *appsv1.Deployment {
volumes := []corev1.Volume{
{
Name: servingCertVolumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: name,
DefaultMode: ptr.To(int32(420)),
},
},
},
}
volumeMounts := []corev1.VolumeMount{
{
Name: servingCertVolumeName,
ReadOnly: true,
MountPath: "/secrets/",
},
}

volumes = append(volumes, corev1.Volume{
Name: "korrel8r-config",
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: name,
},
},
},
})
volumeMounts = append(volumeMounts, corev1.VolumeMount{
Name: "korrel8r-config",
ReadOnly: true,
MountPath: Korrel8rConfigMountDir,
})

deploy := &appsv1.Deployment{
TypeMeta: metav1.TypeMeta{
APIVersion: appsv1.SchemeGroupVersion.String(),
Kind: "Deployment",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: componentLabels(name),
},
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: componentLabels(name),
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: componentLabels(name),
},
Spec: corev1.PodSpec{
ServiceAccountName: info.Name + serviceAccountSuffix,
Containers: []corev1.Container{
{
Name: name,
Image: info.Korrel8rImage,
Command: []string{"korrel8r", "web", "--https=:8443", "--cert=/secrets/tls.crt", "--key=/secrets/tls.key", "--config=/config/korrel8r.yaml"},
Ports: []corev1.ContainerPort{
{
ContainerPort: 8443,
Protocol: corev1.ProtocolTCP,
},
},
SecurityContext: &corev1.SecurityContext{
RunAsNonRoot: ptr.To(true),
AllowPrivilegeEscalation: ptr.To(false),
Capabilities: &corev1.Capabilities{
Drop: []corev1.Capability{
"ALL",
},
},
SeccompProfile: &corev1.SeccompProfile{
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
},
VolumeMounts: volumeMounts,
},
},
Volumes: volumes,
},
},
},
}
return deploy
}

func newKorrel8rService(name string, namespace string) *corev1.Service {
annotations := map[string]string{
"service.alpha.openshift.io/serving-cert-secret-name": name,
}

return &corev1.Service{
TypeMeta: metav1.TypeMeta{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "Service",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: componentLabels(name),
Annotations: annotations,
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
{
Port: port,
Name: "web",
Protocol: corev1.ProtocolTCP,
TargetPort: intstr.FromInt32(port),
},
},
Selector: componentLabels(name),
Type: corev1.ServiceTypeClusterIP,
},
}
}

func newKorrel8rConfigMap(name string, namespace string, info UIPluginInfo) (*corev1.ConfigMap, error) {

korrel8rData := map[string]string{"Metric": "thanos-querier", "MetricAlert": "alertmanager-main", "Log": "logging-loki-gateway-http", "Netflow": "loki-gateway-http", "MonitoringNs": "openshift-monitoring", "LoggingNs": OpenshiftLoggingNs, "NetobservNs": OpenshiftNetobservNs}

if info.LokiServiceNames[OpenshiftLoggingNs] != "" {
korrel8rData["LoggingNs"] = info.LokiServiceNames[OpenshiftLoggingNs]
}
if info.LokiServiceNames[OpenshiftNetobservNs] != "" {
korrel8rData["NetobservNs"] = info.LokiServiceNames[OpenshiftNetobservNs]
}

var korrel8rConfigYAMLTmpl = template.Must(template.ParseFS(korrel8rConfigYAMLTmplFile, "config/korrel8r.yaml"))
w := bytes.NewBuffer(nil)
err := korrel8rConfigYAMLTmpl.Execute(w, korrel8rData)
if err != nil {
return nil, err
}

cfg, _ := io.ReadAll(w)

return &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap",
APIVersion: corev1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: componentLabels(name),
},
Data: map[string]string{
Korrel8rConfigFileName: string(cfg),
},
}, nil
}

func componentLabels(pluginName string) map[string]string {
return map[string]string{
"app.kubernetes.io/instance": pluginName,
Expand Down
Loading

0 comments on commit 1b83cca

Please sign in to comment.