Skip to content

Commit

Permalink
fix: add support for ConsolePlugin v1 (#530)
Browse files Browse the repository at this point in the history
  • Loading branch information
jgbernalp authored Jul 18, 2024
1 parent 150b708 commit dc492f6
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 20 deletions.
52 changes: 49 additions & 3 deletions pkg/controllers/uiplugin/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import (
"hash/fnv"
"io"
"sort"
"strings"
"text/template"

osv1 "github.com/openshift/api/console/v1"
osv1alpha1 "github.com/openshift/api/console/v1alpha1"
"golang.org/x/mod/semver"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
Expand Down Expand Up @@ -45,14 +48,32 @@ var (
korrel8rConfigYAMLTmplFile embed.FS
)

func pluginComponentReconcilers(plugin *uiv1alpha1.UIPlugin, pluginInfo UIPluginInfo) []reconciler.Reconciler {
func isVersionAheadOrEqual(currentVersion, version string) bool {
if !strings.HasPrefix(currentVersion, "v") {
currentVersion = "v" + currentVersion
}
if version == "" {
return false
}

canonicalMinVersion := fmt.Sprintf("%s-0", semver.Canonical(version))

return semver.Compare(currentVersion, canonicalMinVersion) >= 0
}

func pluginComponentReconcilers(plugin *uiv1alpha1.UIPlugin, pluginInfo UIPluginInfo, clusterVersion string) []reconciler.Reconciler {
namespace := pluginInfo.ResourceNamespace

components := []reconciler.Reconciler{
reconciler.NewUpdater(newServiceAccount(pluginInfo, namespace), plugin),
reconciler.NewUpdater(newDeployment(pluginInfo, namespace, plugin.Spec.Deployment), plugin),
reconciler.NewUpdater(newService(pluginInfo, namespace), plugin),
reconciler.NewUpdater(newConsolePlugin(pluginInfo, namespace), plugin),
}

if isVersionAheadOrEqual(clusterVersion, "v4.17") {
components = append(components, reconciler.NewUpdater(newConsolePlugin(pluginInfo, namespace), plugin))
} else {
components = append(components, reconciler.NewUpdater(newLegacyConsolePlugin(pluginInfo, namespace), plugin))
}

if pluginInfo.Role != nil {
Expand Down Expand Up @@ -112,7 +133,7 @@ func newRoleBinding(info UIPluginInfo) *rbacv1.RoleBinding {
return info.RoleBinding
}

func newConsolePlugin(info UIPluginInfo, namespace string) *osv1alpha1.ConsolePlugin {
func newLegacyConsolePlugin(info UIPluginInfo, namespace string) *osv1alpha1.ConsolePlugin {
return &osv1alpha1.ConsolePlugin{
TypeMeta: metav1.TypeMeta{
APIVersion: osv1alpha1.SchemeGroupVersion.String(),
Expand All @@ -129,6 +150,31 @@ func newConsolePlugin(info UIPluginInfo, namespace string) *osv1alpha1.ConsolePl
Port: port,
BasePath: "/",
},
Proxy: info.LegacyProxies,
},
}
}

func newConsolePlugin(info UIPluginInfo, namespace string) *osv1.ConsolePlugin {
return &osv1.ConsolePlugin{
TypeMeta: metav1.TypeMeta{
APIVersion: osv1.SchemeGroupVersion.String(),
Kind: "ConsolePlugin",
},
ObjectMeta: metav1.ObjectMeta{
Name: info.ConsoleName,
},
Spec: osv1.ConsolePluginSpec{
DisplayName: info.DisplayName,
Backend: osv1.ConsolePluginBackend{
Type: osv1.Service,
Service: &osv1.ConsolePluginService{
Name: info.Name,
Namespace: namespace,
Port: port,
BasePath: "/",
},
},
Proxy: info.Proxies,
},
}
Expand Down
56 changes: 56 additions & 0 deletions pkg/controllers/uiplugin/components_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package uiplugin

import (
"testing"

"gotest.tools/v3/assert"
)

func TestIsVersionAheadOrEqual(t *testing.T) {
testCases := []struct {
clusterVersion string
nextClusterVersion string
expected bool
}{
{
clusterVersion: "v4.18",
nextClusterVersion: "v4.17",
expected: true,
},
{
clusterVersion: "v4.17",
nextClusterVersion: "v4.17",
expected: true,
},
{
clusterVersion: "v4.16",
nextClusterVersion: "v4.17",
expected: false,
},
{
clusterVersion: "4.18",
nextClusterVersion: "v4.17",
expected: true,
},
{
clusterVersion: "4.17.0-0.nightly-2024-07-09-121045",
nextClusterVersion: "v4.17",
expected: true,
},
{
clusterVersion: "4.16.0-0.nightly-2024-07-09-121045",
nextClusterVersion: "v4.17",
expected: false,
},
{
clusterVersion: "v4.18",
nextClusterVersion: "",
expected: false,
},
}

for _, tc := range testCases {
actual := isVersionAheadOrEqual(tc.clusterVersion, tc.nextClusterVersion)
assert.Equal(t, tc.expected, actual)
}
}
33 changes: 24 additions & 9 deletions pkg/controllers/uiplugin/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/go-logr/logr"
configv1 "github.com/openshift/api/config/v1"
osv1 "github.com/openshift/api/console/v1"
osv1alpha1 "github.com/openshift/api/console/v1alpha1"
operatorv1 "github.com/openshift/api/operator/v1"
appsv1 "k8s.io/api/apps/v1"
Expand Down Expand Up @@ -109,15 +110,22 @@ func RegisterWithManager(mgr ctrl.Manager, opts Options) error {

generationChanged := builder.WithPredicates(predicate.GenerationChangedPredicate{})

ctrl, err := ctrl.NewControllerManagedBy(mgr).
ctrlBuilder := ctrl.NewControllerManagedBy(mgr).
For(&uiv1alpha1.UIPlugin{}).
Owns(&appsv1.Deployment{}, generationChanged).
Owns(&v1.Service{}, generationChanged).
Owns(&v1.ServiceAccount{}, generationChanged).
Owns(&rbacv1.Role{}, generationChanged).
Owns(&rbacv1.RoleBinding{}, generationChanged).
Owns(&osv1alpha1.ConsolePlugin{}, generationChanged).
Build(rm)
Owns(&rbacv1.RoleBinding{}, generationChanged)

if isVersionAheadOrEqual(rm.clusterVersion, "v4.17") {
ctrlBuilder.Owns(&osv1.ConsolePlugin{}, generationChanged)
} else {
ctrlBuilder.Owns(&osv1alpha1.ConsolePlugin{}, generationChanged)
}

ctrl, err := ctrlBuilder.Build(rm)

if err != nil {
return err
}
Expand All @@ -135,17 +143,24 @@ func getClusterVersion(k8client client.Reader) (*configv1.ClusterVersion, error)
return clusterVersion, nil
}

func (rm resourceManager) consolePluginCapabilityEnabled(ctx context.Context, name types.NamespacedName) bool {
current := &osv1alpha1.ConsolePlugin{}
err := rm.k8sClient.Get(ctx, name, current)
func (rm resourceManager) consolePluginCapabilityEnabled(ctx context.Context, name types.NamespacedName, clusterVersion string) bool {
var err error

if isVersionAheadOrEqual(clusterVersion, "v4.17") {
consolePlugin := &osv1.ConsolePlugin{}
err = rm.k8sClient.Get(ctx, name, consolePlugin)
} else {
legacyConsolePlugin := &osv1alpha1.ConsolePlugin{}
err = rm.k8sClient.Get(ctx, name, legacyConsolePlugin)
}

return err == nil || !metaerrors.IsNoMatchError(err)
}

func (rm resourceManager) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := rm.logger.WithValues("plugin", req.NamespacedName)

if !rm.consolePluginCapabilityEnabled(ctx, req.NamespacedName) {
if !rm.consolePluginCapabilityEnabled(ctx, req.NamespacedName, rm.clusterVersion) {
logger.Info("Cluster console plugin not supported or not accessible. Skipping observability UI plugin reconciliation")
return ctrl.Result{}, nil
}
Expand Down Expand Up @@ -175,7 +190,7 @@ func (rm resourceManager) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
return ctrl.Result{}, err
}

reconcilers := pluginComponentReconcilers(plugin, *pluginInfo)
reconcilers := pluginComponentReconcilers(plugin, *pluginInfo, rm.clusterVersion)
for _, reconciler := range reconcilers {
err := reconciler.Reconcile(ctx, rm.k8sClient, rm.scheme)
// handle creation / updation errors that can happen due to a stale cache by
Expand Down
19 changes: 17 additions & 2 deletions pkg/controllers/uiplugin/distributed_tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"strings"

osv1 "github.com/openshift/api/console/v1"
osv1alpha1 "github.com/openshift/api/console/v1alpha1"
"gopkg.in/yaml.v3"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -37,15 +38,29 @@ func createDistributedTracingPluginInfo(plugin *uiv1alpha1.UIPlugin, namespace,
DisplayName: "Distributed Tracing Console Plugin",
ResourceNamespace: namespace,
ExtraArgs: extraArgs,
Proxies: []osv1alpha1.ConsolePluginProxy{
LegacyProxies: []osv1alpha1.ConsolePluginProxy{
{
Type: osv1alpha1.ProxyTypeService,
Alias: "backend",
Authorize: true,
Service: osv1alpha1.ConsolePluginProxyServiceConfig{
Name: name,
Namespace: namespace,
Port: 9443,
Port: port,
},
},
},
Proxies: []osv1.ConsolePluginProxy{
{
Alias: "backend",
Authorization: "UserToken",
Endpoint: osv1.ConsolePluginProxyEndpoint{
Type: osv1.ProxyTypeService,
Service: &osv1.ConsolePluginProxyServiceConfig{
Name: name,
Namespace: namespace,
Port: port,
},
},
},
},
Expand Down
29 changes: 28 additions & 1 deletion pkg/controllers/uiplugin/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
"time"

osv1 "github.com/openshift/api/console/v1"
osv1alpha1 "github.com/openshift/api/console/v1alpha1"
"gopkg.in/yaml.v3"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -51,7 +52,7 @@ func createLoggingPluginInfo(plugin *uiv1alpha1.UIPlugin, namespace, name, image
DisplayName: "Logging View",
ExtraArgs: extraArgs,
ResourceNamespace: namespace,
Proxies: []osv1alpha1.ConsolePluginProxy{
LegacyProxies: []osv1alpha1.ConsolePluginProxy{
{
Type: "Service",
Alias: "backend",
Expand All @@ -73,6 +74,32 @@ func createLoggingPluginInfo(plugin *uiv1alpha1.UIPlugin, namespace, name, image
},
},
},
Proxies: []osv1.ConsolePluginProxy{
{
Alias: "backend",
Authorization: "UserToken",
Endpoint: osv1.ConsolePluginProxyEndpoint{
Type: osv1.ProxyTypeService,
Service: &osv1.ConsolePluginProxyServiceConfig{
Name: fmt.Sprintf("%s-gateway-http", plugin.Spec.Logging.LokiStack.Name),
Namespace: "openshift-logging", // TODO decide if we want to support LokiStack in other namespaces
Port: 8080,
},
},
},
{
Alias: "korrel8r",
Authorization: "UserToken",
Endpoint: osv1.ConsolePluginProxyEndpoint{
Type: osv1.ProxyTypeService,
Service: &osv1.ConsolePluginProxyServiceConfig{
Name: korrel8rName,
Namespace: namespace,
Port: port,
},
},
},
},
ConfigMap: &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: corev1.SchemeGroupVersion.String(),
Expand Down
22 changes: 19 additions & 3 deletions pkg/controllers/uiplugin/plugin_info_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"

osv1 "github.com/openshift/api/console/v1"
osv1alpha1 "github.com/openshift/api/console/v1alpha1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
Expand All @@ -21,7 +22,8 @@ type UIPluginInfo struct {
ConsoleName string
DisplayName string
ExtraArgs []string
Proxies []osv1alpha1.ConsolePluginProxy
LegacyProxies []osv1alpha1.ConsolePluginProxy
Proxies []osv1.ConsolePluginProxy
Role *rbacv1.Role
RoleBinding *rbacv1.RoleBinding
ClusterRoles []*rbacv1.ClusterRole
Expand Down Expand Up @@ -54,15 +56,29 @@ func PluginInfoBuilder(ctx context.Context, k client.Client, plugin *uiv1alpha1.
ConsoleName: "console-dashboards-plugin",
DisplayName: "Console Enhanced Dashboards",
ResourceNamespace: namespace,
Proxies: []osv1alpha1.ConsolePluginProxy{
LegacyProxies: []osv1alpha1.ConsolePluginProxy{
{
Type: osv1alpha1.ProxyTypeService,
Alias: "backend",
Authorize: true,
Service: osv1alpha1.ConsolePluginProxyServiceConfig{
Name: name,
Namespace: namespace,
Port: 9443,
Port: port,
},
},
},
Proxies: []osv1.ConsolePluginProxy{
{
Alias: "backend",
Authorization: "UserToken",
Endpoint: osv1.ConsolePluginProxyEndpoint{
Type: osv1.ProxyTypeService,
Service: &osv1.ConsolePluginProxyServiceConfig{
Name: name,
Namespace: namespace,
Port: port,
},
},
},
},
Expand Down
19 changes: 17 additions & 2 deletions pkg/controllers/uiplugin/troubleshooting_panel.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"strings"

osv1 "github.com/openshift/api/console/v1"
osv1alpha1 "github.com/openshift/api/console/v1alpha1"
"gopkg.in/yaml.v3"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -44,15 +45,29 @@ func createTroubleshootingPanelPluginInfo(plugin *uiv1alpha1.UIPlugin, namespace
ResourceNamespace: namespace,
LokiServiceNames: make(map[string]string),
ExtraArgs: extraArgs,
Proxies: []osv1alpha1.ConsolePluginProxy{
LegacyProxies: []osv1alpha1.ConsolePluginProxy{
{
Type: osv1alpha1.ProxyTypeService,
Alias: "korrel8r",
Authorize: true,
Service: osv1alpha1.ConsolePluginProxyServiceConfig{
Name: korrel8rSvcName,
Namespace: namespace,
Port: 9443,
Port: port,
},
},
},
Proxies: []osv1.ConsolePluginProxy{
{
Alias: "korrel8r",
Authorization: "UserToken",
Endpoint: osv1.ConsolePluginProxyEndpoint{
Type: osv1.ProxyTypeService,
Service: &osv1.ConsolePluginProxyServiceConfig{
Name: korrel8rSvcName,
Namespace: namespace,
Port: port,
},
},
},
},
Expand Down
Loading

0 comments on commit dc492f6

Please sign in to comment.