Skip to content

Commit

Permalink
Patching ConsolePlugin CR with Prometheus service info
Browse files Browse the repository at this point in the history
Signed-off-by: Arun Kumar Mohan <[email protected]>
  • Loading branch information
aruniiird committed Oct 3, 2022
1 parent 53c36a6 commit e58d9b2
Show file tree
Hide file tree
Showing 13 changed files with 798 additions and 0 deletions.
63 changes: 63 additions & 0 deletions controllers/managedocs_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"io/ioutil"
"math"
"net/url"
"reflect"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -50,6 +51,7 @@ import (

"github.com/go-logr/logr"
configv1 "github.com/openshift/api/config/v1"
consolev1alpha1 "github.com/openshift/api/console/v1alpha1"
openshiftv1 "github.com/openshift/api/network/v1"
promv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
promv1a1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1alpha1"
Expand Down Expand Up @@ -104,6 +106,7 @@ const (
providerDeploymentType = "provider"
rhobsRemoteWriteConfigIdSecretKey = "prom-remote-write-config-id"
rhobsRemoteWriteConfigSecretName = "prom-remote-write-config-secret"
ocpConsolePluginName = "odf-console"
)

// ManagedOCSReconciler reconciles a ManagedOCS object
Expand Down Expand Up @@ -151,6 +154,7 @@ type ManagedOCSReconciler struct {
onboardingValidationKeySecret *corev1.Secret
prometheusKubeRBACConfigMap *corev1.ConfigMap
rhobsRemoteWriteConfigSecret *corev1.Secret
ocpConsolePlugin *consolev1alpha1.ConsolePlugin
}

// Add necessary rbac permissions for managedocs finalizer in order to set blockOwnerDeletion.
Expand Down Expand Up @@ -443,6 +447,10 @@ func (r *ManagedOCSReconciler) initReconciler(ctx context.Context, req ctrl.Requ
r.rhobsRemoteWriteConfigSecret = &corev1.Secret{}
r.rhobsRemoteWriteConfigSecret.Name = r.RHOBSSecretName
r.rhobsRemoteWriteConfigSecret.Namespace = r.namespace

r.ocpConsolePlugin = &consolev1alpha1.ConsolePlugin{}
r.ocpConsolePlugin.Name = ocpConsolePluginName
r.ocpConsolePlugin.Namespace = r.namespace
}

func (r *ManagedOCSReconciler) reconcilePhases() (reconcile.Result, error) {
Expand Down Expand Up @@ -584,6 +592,9 @@ func (r *ManagedOCSReconciler) reconcilePhases() (reconcile.Result, error) {
if err := r.reconcileProviderAPIServerNetworkPolicy(); err != nil {
return ctrl.Result{}, err
}
if err := r.reconcileOCSConsolePlugin(); err != nil {
return ctrl.Result{}, err
}

r.managedOCS.Status.ReconcileStrategy = r.reconcileStrategy

Expand Down Expand Up @@ -1767,6 +1778,58 @@ func (r *ManagedOCSReconciler) updateMCGCSV(csv *opv1a1.ClusterServiceVersion) e
return nil
}

func (r *ManagedOCSReconciler) reconcileOCSConsolePlugin() error {
// Console UI plugin is used only in 'provider' / 'consumer' deployment types,
// for any other deployment type opt out
if r.DeploymentType != consumerDeploymentType && r.DeploymentType != providerDeploymentType {
r.Log.Info("Non provider/consumer deployment, skipping reconcile for OCS ConsolePlugin",
"Current DeploymentType", r.DeploymentType)
return nil
}
r.Log.Info("Reconciling OCSConsolePlugin")
if err := r.get(r.ocpConsolePlugin); err != nil && !errors.IsNotFound(err) {
return err
}
if r.ocpConsolePlugin.UID == "" {
// ODF Operator has to bring this CR,
// so if OCP ConsolePlugin is not ready, we ruturn silently
r.Log.Info("OCSConsolePlugin CR not found, skipping console proxy configuration")
return nil
}
expectedProxy := templates.ConsolePluginProxyTemplate.DeepCopy()
expectedProxy.Service.Name = prometheusServiceName
expectedProxy.Service.Namespace = r.namespace

var matchingProxy *consolev1alpha1.ConsolePluginProxy
for i := range r.ocpConsolePlugin.Spec.Proxy {
currProxy := &r.ocpConsolePlugin.Spec.Proxy[i]
if currProxy.Service.Name == expectedProxy.Service.Name &&
currProxy.Service.Namespace == expectedProxy.Service.Namespace {
matchingProxy = currProxy
break
}
}
shouldUpdateConsolePlugin := false
if matchingProxy == nil {
// if we didn't find any matching ConsolePluginProxy, append the expected proxy
r.ocpConsolePlugin.Spec.Proxy = append(r.ocpConsolePlugin.Spec.Proxy, *expectedProxy)
shouldUpdateConsolePlugin = true
} else if !reflect.DeepEqual(*matchingProxy, *expectedProxy) {
// if both, expected and matching PluginProxies, are not the same
// then we have to update the matched proxy with the expected one
expectedProxy.DeepCopyInto(matchingProxy)
shouldUpdateConsolePlugin = true
}
if shouldUpdateConsolePlugin {
// since the proxy array is changed at this point, update the console plugin
if err := r.update(r.ocpConsolePlugin); err != nil {
return fmt.Errorf("could not update OCP ConsolePlugin: %v", err)
}

}
return nil
}

func (r *ManagedOCSReconciler) removeOLMComponents() error {

r.Log.Info("deleting deployer csv")
Expand Down
4 changes: 4 additions & 0 deletions controllers/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
configv1 "github.com/openshift/api/config/v1"
consolev1alpha1 "github.com/openshift/api/console/v1alpha1"
openshiftv1 "github.com/openshift/api/network/v1"
opv1a1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
promv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
Expand Down Expand Up @@ -159,6 +160,9 @@ var _ = BeforeSuite(func() {
err = configv1.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())

err = consolev1alpha1.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())

// +kubebuilder:scaffold:scheme

// Client to be use by the test code, using a non cached client
Expand Down
3 changes: 3 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (

"github.com/go-logr/logr"
configv1 "github.com/openshift/api/config/v1"
consolev1alpha1 "github.com/openshift/api/console/v1alpha1"
openshiftv1 "github.com/openshift/api/network/v1"
operators "github.com/operator-framework/api/pkg/operators/v1alpha1"
promv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
Expand Down Expand Up @@ -90,6 +91,8 @@ func addAllSchemes(scheme *runtime.Scheme) {
utilruntime.Must(ocsv1alpha1.AddToScheme(scheme))

utilruntime.Must(configv1.AddToScheme(scheme))

utilruntime.Must(consolev1alpha1.AddToScheme(scheme))
// +kubebuilder:scaffold:scheme
}

Expand Down
133 changes: 133 additions & 0 deletions shim/crds/consoleplugins.console.openshift.io.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
api-approved.openshift.io: https://github.com/openshift/api/pull/764
description: Extension for configuring openshift web console plugins.
displayName: ConsolePlugin
include.release.openshift.io/ibm-cloud-managed: "true"
include.release.openshift.io/self-managed-high-availability: "true"
include.release.openshift.io/single-node-developer: "true"
name: consoleplugins.console.openshift.io
spec:
group: console.openshift.io
names:
kind: ConsolePlugin
listKind: ConsolePluginList
plural: consoleplugins
singular: consoleplugin
scope: Cluster
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: "ConsolePlugin is an extension for customizing OpenShift web console by dynamically loading code from another service running on the cluster. \n Compatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support."
type: object
required:
- metadata
- spec
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ConsolePluginSpec is the desired plugin configuration.
type: object
required:
- service
properties:
displayName:
description: displayName is the display name of the plugin.
type: string
minLength: 1
proxy:
description: proxy is a list of proxies that describe various service type to which the plugin needs to connect to.
type: array
items:
description: ConsolePluginProxy holds information on various service types to which console's backend will proxy the plugin's requests.
type: object
required:
- alias
- type
properties:
alias:
description: "alias is a proxy name that identifies the plugin's proxy. An alias name should be unique per plugin. The console backend exposes following proxy endpoint: \n /api/proxy/plugin/<plugin-name>/<proxy-alias>/<request-path>?<optional-query-parameters> \n Request example path: \n /api/proxy/plugin/acm/search/pods?namespace=openshift-apiserver"
type: string
maxLength: 128
minLength: 1
pattern: ^[A-Za-z0-9-_]+$
authorize:
description: "authorize indicates if the proxied request should contain the logged-in user's OpenShift access token in the \"Authorization\" request header. For example: \n Authorization: Bearer sha256~kV46hPnEYhCWFnB85r5NrprAxggzgb6GOeLbgcKNsH0 \n By default the access token is not part of the proxied request."
type: boolean
default: false
caCertificate:
description: caCertificate provides the cert authority certificate contents, in case the proxied Service is using custom service CA. By default, the service CA bundle provided by the service-ca operator is used.
type: string
pattern: ^-----BEGIN CERTIFICATE-----([\s\S]*)-----END CERTIFICATE-----\s?$
service:
description: 'service is an in-cluster Service that the plugin will connect to. The Service must use HTTPS. The console backend exposes an endpoint in order to proxy communication between the plugin and the Service. Note: service field is required for now, since currently only "Service" type is supported.'
type: object
required:
- name
- namespace
- port
properties:
name:
description: name of Service that the plugin needs to connect to.
type: string
maxLength: 128
minLength: 1
namespace:
description: namespace of Service that the plugin needs to connect to
type: string
maxLength: 128
minLength: 1
port:
description: port on which the Service that the plugin needs to connect to is listening on.
type: integer
format: int32
maximum: 65535
minimum: 1
type:
description: type is the type of the console plugin's proxy. Currently only "Service" is supported.
type: string
pattern: ^(Service)$
service:
description: service is a Kubernetes Service that exposes the plugin using a deployment with an HTTP server. The Service must use HTTPS and Service serving certificate. The console backend will proxy the plugins assets from the Service using the service CA bundle.
type: object
required:
- basePath
- name
- namespace
- port
properties:
basePath:
description: basePath is the path to the plugin's assets. The primary asset it the manifest file called `plugin-manifest.json`, which is a JSON document that contains metadata about the plugin and the extensions.
type: string
default: /
minLength: 1
pattern: ^/
name:
description: name of Service that is serving the plugin assets.
type: string
maxLength: 128
minLength: 1
namespace:
description: namespace of Service that is serving the plugin assets.
type: string
maxLength: 128
minLength: 1
port:
description: port on which the Service that is serving the plugin is listening to.
type: integer
format: int32
maximum: 65535
minimum: 1
served: true
storage: true

30 changes: 30 additions & 0 deletions templates/ocsconsoleplugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package templates

import (
consolev1alpha1 "github.com/openshift/api/console/v1alpha1"
)

const (
ocpConsoleProxyAlias = "odf-managed-service-prom"
)

var ConsolePluginProxyTemplate = consolev1alpha1.ConsolePluginProxy{
Type: consolev1alpha1.ProxyTypeService,
Authorize: true,
Alias: ocpConsoleProxyAlias,
Service: consolev1alpha1.ConsolePluginProxyServiceConfig{
Port: int32(KubeRBACProxyPortNumber),
},
}
Loading

0 comments on commit e58d9b2

Please sign in to comment.