Skip to content

Commit

Permalink
Add ConsoleLink Create/Remove
Browse files Browse the repository at this point in the history
  • Loading branch information
rashelrr authored and myeung18 committed Sep 16, 2020
1 parent c941a20 commit 7f63a39
Show file tree
Hide file tree
Showing 9 changed files with 338 additions and 10 deletions.
6 changes: 6 additions & 0 deletions cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
crmetrics "sigs.k8s.io/controller-runtime/pkg/metrics"
consolev1 "github.com/openshift/api/console/v1"
)

// Change below variables to serve metrics on different host or port.
Expand Down Expand Up @@ -118,6 +119,11 @@ func main() {
os.Exit(1)
}

if err := consolev1.AddToScheme(mgr.GetScheme()); err != nil {
log.Error(err, "")
os.Exit(1)
}

// Setup Scheme for OpenShift imagestreams and related
if err := imagev1.AddToScheme(mgr.GetScheme()); err != nil {
log.Error(err, "")
Expand Down
13 changes: 13 additions & 0 deletions deploy/cluster_role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: 3scale-operator
rules:
- apiGroups:
- console.openshift.io
resources:
- consolelinks
verbs:
- create
- delete
- get
12 changes: 12 additions & 0 deletions deploy/cluster_role_binding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: 3scale-operator
subjects:
- kind: ServiceAccount
name: 3scale-operator
namespace: <placeholder>
roleRef:
kind: ClusterRole
name: 3scale-operator
apiGroup: rbac.authorization.k8s.io
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,17 @@ spec:
mediatype: image/png
install:
spec:
clusterPermissions:
- rules:
- apiGroups:
- console.openshift.io
resources:
- consolelinks
verbs:
- create
- delete
- get
serviceAccountName: 3scale-operator
deployments:
- name: 3scale-operator
spec:
Expand Down
22 changes: 12 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,29 @@ go 1.13

require (
github.com/3scale/3scale-porta-go-client v0.0.4
github.com/Azure/go-autorest v12.2.0+incompatible
github.com/RHsyseng/operator-utils v0.0.0-20200204194854-c5b0d8533458
github.com/coreos/prometheus-operator v0.34.0
github.com/Azure/go-autorest v12.2.0+incompatible // indirect
github.com/RHsyseng/operator-utils v0.0.0-20200506183821-e3b4a2ba9c30
github.com/coreos/prometheus-operator v0.35.1
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
github.com/go-bindata/go-bindata v3.1.1+incompatible
github.com/go-bindata/go-bindata v3.1.2+incompatible
github.com/go-logr/logr v0.1.0
github.com/go-openapi/spec v0.19.4
github.com/go-openapi/spec v0.19.6
github.com/go-playground/validator/v10 v10.2.0
github.com/google/go-cmp v0.3.1
github.com/integr8ly/grafana-operator/v3 v3.1.0
github.com/luci/go-render v0.0.0-20160219211803-9a04cc21af0f
github.com/mitchellh/go-homedir v1.1.0
github.com/openshift/api v3.9.1-0.20190924102528-32369d4db2ad+incompatible
github.com/openshift/client-go v0.0.0-20190923180330-3b6373338c9b
github.com/openshift/client-go v3.9.0+incompatible
github.com/operator-framework/operator-sdk v0.15.2
github.com/prometheus/client_golang v1.2.1
github.com/spf13/cobra v0.0.5
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.4.0
github.com/stretchr/testify v1.4.0
gopkg.in/yaml.v2 v2.2.4
k8s.io/api v0.0.0
k8s.io/apimachinery v0.0.0
gopkg.in/yaml.v2 v2.2.8
k8s.io/api v0.17.2
k8s.io/apimachinery v0.17.2
k8s.io/client-go v12.0.0+incompatible
k8s.io/kube-openapi v0.0.0-20190918143330-0270cf2f1c1d
sigs.k8s.io/controller-runtime v0.4.0
Expand Down Expand Up @@ -59,4 +59,6 @@ replace (

replace github.com/docker/docker => github.com/moby/moby v0.7.3-0.20190826074503-38ab9da00309 // Required by Helm

replace github.com/openshift/api => github.com/openshift/api v0.0.0-20190924102528-32369d4db2ad // Required until https://github.com/operator-framework/operator-lifecycle-manager/pull/1241 is resolved
replace github.com/openshift/api => github.com/openshift/api v0.0.0-20200527184302-a843dc3262a0 // Required until https://github.com/operator-framework/operator-lifecycle-manager/pull/1241 is resolved

replace github.com/openshift/client-go => github.com/openshift/client-go v0.0.0-20191125132246-f6563a70e19a
147 changes: 147 additions & 0 deletions go.sum

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions pkg/3scale/amp/operator/base_apimanager_logic_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,13 @@ func (r *BaseAPIManagerLogicReconciler) ReconcilePodMonitor(desired *monitoringv
return r.ReconcileResource(&monitoringv1.PodMonitor{}, desired, mutateFn)
}

//Reconcile: create or update Consolelink for a route
func (r *BaseAPIManagerLogicReconciler) ReconcileConsoleLink() {
if err := helper.ConsoleLinkSupported(); err == nil {
helper.CreateConsoleLink(r.Context(), r.Client(), r.apiManager)
}
}

func (r *BaseAPIManagerLogicReconciler) hasPodMonitors() (bool, error) {
return k8sutil.ResourceExists(r.DiscoveryClient(),
monitoringv1.SchemeGroupVersion.String(),
Expand Down
18 changes: 18 additions & 0 deletions pkg/controller/apimanager/apimanager_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ import (
"github.com/3scale/3scale-operator/pkg/3scale/amp/product"
appsv1alpha1 "github.com/3scale/3scale-operator/pkg/apis/apps/v1alpha1"
"github.com/3scale/3scale-operator/pkg/common"
"github.com/3scale/3scale-operator/pkg/helper"
"github.com/3scale/3scale-operator/pkg/reconcilers"
"github.com/3scale/3scale-operator/version"

"github.com/RHsyseng/operator-utils/pkg/olm"
appsv1 "github.com/openshift/api/apps/v1"
routev1 "github.com/openshift/api/route/v1"
"k8s.io/api/policy/v1beta1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/discovery"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -101,6 +104,11 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
return err
}

err = c.Watch(&source.Kind{Type: &routev1.Route{}}, &handler.EnqueueRequestForObject{})
if err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -216,6 +224,13 @@ func (r *ReconcileAPIManager) apiManagerInstance(namespacedName types.Namespaced
// Request object not found, could have been deleted after reconcile request.
// Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
// Return and don't requeue
if err := helper.ConsoleLinkSupported(); err == nil {
instance.ObjectMeta = metav1.ObjectMeta {
Name: namespacedName.Name,
Namespace: namespacedName.Namespace,
}
helper.RemoveConsoleLink(r.Context(), r.Client(), instance)
}
return nil, nil
}
return nil, err
Expand Down Expand Up @@ -243,6 +258,9 @@ func (r *ReconcileAPIManager) reconcileAPIManagerLogic(cr *appsv1alpha1.APIManag
return result, err
}

consoleLinkReconciler := operator.NewBaseAPIManagerLogicReconciler(r.BaseReconciler, cr)
consoleLinkReconciler.ReconcileConsoleLink()

if !cr.IsExternalDatabaseEnabled() {
redisReconciler := operator.NewRedisReconciler(operator.NewBaseAPIManagerLogicReconciler(r.BaseReconciler, cr))
result, err = redisReconciler.Reconcile()
Expand Down
112 changes: 112 additions & 0 deletions pkg/helper/webconsole.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package helper

import (
"context"
"fmt"
appsv1alpha1 "github.com/3scale/3scale-operator/pkg/apis/apps/v1alpha1"
"github.com/RHsyseng/operator-utils/pkg/logs"
"github.com/RHsyseng/operator-utils/pkg/resource/read"
"github.com/RHsyseng/operator-utils/pkg/utils/kubernetes"
consolev1 "github.com/openshift/api/console/v1"
routev1 "github.com/openshift/api/route/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"strings"
)

var logger = logs.GetLogger("openshift-webconsole")

// ConsoleLinkText is the text of the consoleLink shown on the webconsole
const ConsoleLinkText = "APIManager - 3scale"

// ConsoleLinkSupported checks if a ConsoleLink CRD exists
func ConsoleLinkSupported() error {
gvk := schema.GroupVersionKind{Group: "console.openshift.io", Version: "v1", Kind: "ConsoleLink"}
return kubernetes.CustomResourceDefinitionExists(gvk)
}

// CreateConsoleLink creates a ConsoleLink object if it doesn't already exist
func CreateConsoleLink(ctx context.Context, c client.Client, apimanager *appsv1alpha1.APIManager) {
route := getRoute(ctx, c, apimanager)
if route != nil {
consoleLinkName := fmt.Sprintf("%s-%s", apimanager.ObjectMeta.Name, apimanager.Namespace)
consoleLink := &consolev1.ConsoleLink{}
err := c.Get(ctx, types.NamespacedName{Name: consoleLinkName}, consoleLink)
if err != nil && apierrors.IsNotFound(err) {
consoleLink = createConsoleLinkPointer(consoleLinkName, route, apimanager)
if err := c.Create(ctx, consoleLink); err != nil {
logger.Error(err, "Console link is not created.")
} else {
logger.Info("Console link has been created:", consoleLinkName)
}
} else if err == nil && consoleLink != nil {
reconcileConsoleLink(ctx, route, consoleLink, c)
}
}
}

func getRoute(ctx context.Context, c client.Client, apimanager *appsv1alpha1.APIManager) *routev1.Route {
reader := read.New(c).WithNamespace(apimanager.Namespace)
deployedRoutes, err := reader.List(&routev1.RouteList{})
if err != nil {
return nil
}
for _, route := range deployedRoutes { //look for 3scale admin routes, capture route object
realr := route.(*routev1.Route)
if strings.Compare(realr.Spec.To.Name, "system-master") == 0 {
return realr
}
}
return nil
}

func reconcileConsoleLink(ctx context.Context, route *routev1.Route, consoleLink *consolev1.ConsoleLink, c client.Client) {
url := "https://" + route.Spec.Host
linkTxt := ConsoleLinkText
if url != consoleLink.Spec.Href || linkTxt != consoleLink.Spec.Text {
consoleLink.Spec.Href = url
consoleLink.Spec.Text = linkTxt
if err := c.Update(ctx, consoleLink); err != nil {
logger.Error(err, "failed to reconcile Console Link", consoleLink)
}
}
}

func createConsoleLinkPointer(consoleLinkName string, route *routev1.Route, apimanager *appsv1alpha1.APIManager) *consolev1.ConsoleLink {
return &consolev1.ConsoleLink{
ObjectMeta: metav1.ObjectMeta{
Name: consoleLinkName,
Labels: map[string]string{
"3scale.net/name": apimanager.ObjectMeta.Name,
},
},
Spec: consolev1.ConsoleLinkSpec{
Link: consolev1.Link{
Text: ConsoleLinkText,
Href: "https://" + route.Spec.Host,
},
Location: consolev1.NamespaceDashboard,
NamespaceDashboard: &consolev1.NamespaceDashboardSpec{
Namespaces: []string{apimanager.Namespace},
},
},
}
}

// RemoveConsoleLink removes a ConsoleLink object if it exists
func RemoveConsoleLink(ctx context.Context, c client.Client, apimanager *appsv1alpha1.APIManager) {
consoleLink := &consolev1.ConsoleLink{}
consoleLinkName := fmt.Sprintf("%s-%s", apimanager.ObjectMeta.Name, apimanager.Namespace)
err := c.Get(ctx, types.NamespacedName{Name: consoleLinkName}, consoleLink)
if err == nil && consoleLink != nil {
err = c.Delete(ctx, consoleLink)
if err != nil {
logger.Error(err, "Failed to delete the consolelink:", consoleLinkName)
} else {
logger.Info("Deleted the consolelink:", consoleLinkName)
}
}
}

0 comments on commit 7f63a39

Please sign in to comment.