Skip to content

Commit

Permalink
Merge pull request #33 from pb82/dashboard-fixes
Browse files Browse the repository at this point in the history
reimport dashboards after operator restart if not already imported
  • Loading branch information
pb82 authored Aug 14, 2019
2 parents 8509478 + b84ccbd commit 1a3d3c0
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 101 deletions.
15 changes: 8 additions & 7 deletions cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ import (
"context"
"flag"
"fmt"
"github.com/integr8ly/grafana-operator/pkg/controller/common"
"github.com/integr8ly/grafana-operator/pkg/controller/grafanadashboard"
"k8s.io/client-go/rest"
"os"
"runtime"
"sigs.k8s.io/controller-runtime/pkg/runtime/signals"

"github.com/integr8ly/grafana-operator/pkg/apis"
"github.com/integr8ly/grafana-operator/pkg/controller"
"github.com/integr8ly/grafana-operator/pkg/controller/common"
"github.com/integr8ly/grafana-operator/pkg/controller/grafanadashboard"
"github.com/integr8ly/grafana-operator/version"
"github.com/operator-framework/operator-sdk/pkg/k8sutil"
"github.com/operator-framework/operator-sdk/pkg/leader"
"github.com/operator-framework/operator-sdk/pkg/ready"
sdkVersion "github.com/operator-framework/operator-sdk/version"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"k8s.io/client-go/rest"
"os"
"runtime"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/manager"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
"sigs.k8s.io/controller-runtime/pkg/runtime/signals"
)

var log = logf.Log.WithName("cmd")
Expand All @@ -35,6 +35,7 @@ func printVersion() {
log.Info(fmt.Sprintf("Go Version: %s", runtime.Version()))
log.Info(fmt.Sprintf("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH))
log.Info(fmt.Sprintf("operator-sdk Version: %v", sdkVersion.Version))
log.Info(fmt.Sprintf("operator Version: %v", version.Version))
}

func init() {
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/integreatly/v1alpha1/grafanadashboard_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const GrafanaDashboardKind = "GrafanaDashboard"

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/integreatly/v1alpha1/grafanadatasource_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const GrafanaDataSourceKind = "GrafanaDataSource"

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

Expand Down
31 changes: 31 additions & 0 deletions pkg/apis/integreatly/v1alpha1/selectors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package v1alpha1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
)

func (d *GrafanaDashboard) matchesSelector(s *metav1.LabelSelector) (bool, error) {
selector, err := metav1.LabelSelectorAsSelector(s)
if err != nil {
return false, err
}

return selector.Empty() || selector.Matches(labels.Set(d.Labels)), nil
}

// Check if the dashboard matches at least one of the selectors
func (d *GrafanaDashboard) MatchesSelectors(s []*metav1.LabelSelector) (bool, error) {
result := false

for _, selector := range s {
match, err := d.matchesSelector(selector)
if err != nil {
return false, err
}

result = result || match
}

return result, nil
}
2 changes: 1 addition & 1 deletion pkg/controller/common/controller_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const (
PluginsMinAge = 5
InitContainerName = "grafana-plugins-init"
ResourceFinalizerName = "grafana.cleanup"
RequeueDelaySeconds = 10
RequeueDelay = time.Second * 15
)

type ControllerConfig struct {
Expand Down
97 changes: 62 additions & 35 deletions pkg/controller/common/kubeHelper.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
package common

import (
stdErrors "errors"
"fmt"
"github.com/integr8ly/grafana-operator/pkg/apis/integreatly/v1alpha1"
apps "k8s.io/api/apps/v1"
core "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/client/config"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
"strings"
"time"
)

var log = logf.Log.WithName("kube_helper")

type KubeHelperImpl struct {
k8client *kubernetes.Clientset
config *ControllerConfig
}

func NewKubeHelper() *KubeHelperImpl {
Expand All @@ -25,32 +31,41 @@ func NewKubeHelper() *KubeHelperImpl {

helper := new(KubeHelperImpl)
helper.k8client = k8client
helper.config = GetControllerConfig()
return helper
}

func (h KubeHelperImpl) getConfigMap(namespace, name string) (*v1.ConfigMap, error) {
opts := metav1.GetOptions{}
return h.k8client.CoreV1().ConfigMaps(namespace).Get(name, opts)
func (h KubeHelperImpl) getConfigMapKey(namespace, name string) string {
return fmt.Sprintf("%s_%s", namespace, strings.ToLower(name))
}

func (h KubeHelperImpl) getGrafanaDeployment(namespaceName string) (*apps.Deployment, error) {
opts := metav1.GetOptions{}
return h.k8client.AppsV1().Deployments(namespaceName).Get(GrafanaDeploymentName, opts)
func (h KubeHelperImpl) getConfigMap(name string) (*v1.ConfigMap, error) {
namespace := h.config.GetConfigString(ConfigOperatorNamespace, "")
return h.k8client.CoreV1().ConfigMaps(namespace).Get(name, metav1.GetOptions{})
}

func (h KubeHelperImpl) updateConfigMap(c *v1.ConfigMap) error {
namespace := h.config.GetConfigString(ConfigOperatorNamespace, "")
_, err := h.k8client.CoreV1().ConfigMaps(namespace).Update(c)
return err
}

func (h KubeHelperImpl) getGrafanaDeployment() (*apps.Deployment, error) {
namespace := h.config.GetConfigString(ConfigOperatorNamespace, "")
return h.k8client.AppsV1().Deployments(namespace).Get(GrafanaDeploymentName, metav1.GetOptions{})
}

func (h KubeHelperImpl) UpdateGrafanaConfig(config string, cr *v1alpha1.Grafana) error {
configMap, err := h.getConfigMap(cr.Namespace, GrafanaConfigMapName)
configMap, err := h.getConfigMap(GrafanaConfigMapName)
if err != nil {
return err
}

configMap.Data[GrafanaConfigFileName] = config
_, err = h.k8client.CoreV1().ConfigMaps(cr.Namespace).Update(configMap)
return err
return h.updateConfigMap(configMap)
}

func (h KubeHelperImpl) UpdateDashboard(ns string, d *v1alpha1.GrafanaDashboard) (bool, error) {
configMap, err := h.getConfigMap(ns, GrafanaDashboardsConfigMapName)
func (h KubeHelperImpl) UpdateDashboard(d *v1alpha1.GrafanaDashboard) (bool, error) {
configMap, err := h.getConfigMap(GrafanaDashboardsConfigMapName)
if err != nil {
if errors.IsNotFound(err) {
return false, nil
Expand All @@ -60,23 +75,22 @@ func (h KubeHelperImpl) UpdateDashboard(ns string, d *v1alpha1.GrafanaDashboard)

// Prefix the dashboard filename with the namespace to allow multiple namespaces
// to import the same dashboard
dashboardName := fmt.Sprintf("%s_%s", d.Namespace, d.Spec.Name)

dashboardName := h.getConfigMapKey(d.Namespace, d.Spec.Name)
if configMap.Data == nil {
configMap.Data = make(map[string]string)
}

configMap.Data[dashboardName] = d.Spec.Json
configMap, err = h.k8client.CoreV1().ConfigMaps(ns).Update(configMap)
err = h.updateConfigMap(configMap)
if err != nil {
return false, err
}

return true, nil
}

func (h KubeHelperImpl) IsKnownDataSource(ds *v1alpha1.GrafanaDataSource) (bool, error) {
configMap, err := h.getConfigMap(ds.Namespace, GrafanaDatasourcesConfigMapName)
func (h KubeHelperImpl) isKnown(config, namespace, name string) (bool, error) {
configMap, err := h.getConfigMap(config)
if err != nil {
if errors.IsNotFound(err) {
return false, nil
Expand All @@ -88,14 +102,26 @@ func (h KubeHelperImpl) IsKnownDataSource(ds *v1alpha1.GrafanaDataSource) (bool,
return false, nil
}

key := fmt.Sprintf("%s_%s", ds.Namespace, strings.ToLower(ds.Spec.Name))
key := h.getConfigMapKey(namespace, name)
_, found := configMap.Data[key]

return found, nil
}

func (h KubeHelperImpl) IsKnown(kind string, o runtime.Object) (bool, error) {
switch kind {
case v1alpha1.GrafanaDashboardKind:
d := o.(*v1alpha1.GrafanaDashboard)
return h.isKnown(GrafanaDashboardsConfigMapName, d.Namespace, d.Spec.Name)
case v1alpha1.GrafanaDataSourceKind:
d := o.(*v1alpha1.GrafanaDataSource)
return h.isKnown(GrafanaDatasourcesConfigMapName, d.Namespace, d.Spec.Name)
default:
return false, stdErrors.New(fmt.Sprintf("unknown kind '%v'", kind))
}
}

func (h KubeHelperImpl) UpdateDataSources(name, namespace, ds string) (bool, error) {
configMap, err := h.getConfigMap(namespace, GrafanaDatasourcesConfigMapName)
configMap, err := h.getConfigMap(GrafanaDatasourcesConfigMapName)
if err != nil {
if errors.IsNotFound(err) {
return false, nil
Expand All @@ -105,22 +131,22 @@ func (h KubeHelperImpl) UpdateDataSources(name, namespace, ds string) (bool, err

// Prefix the data source filename with the namespace to allow multiple namespaces
// to import the same dashboard
key := fmt.Sprintf("%s_%s", namespace, strings.ToLower(name))
key := h.getConfigMapKey(namespace, name)

if configMap.Data == nil {
configMap.Data = make(map[string]string)
}

configMap.Data[key] = ds
configMap, err = h.k8client.CoreV1().ConfigMaps(namespace).Update(configMap)
err = h.updateConfigMap(configMap)
if err != nil {
return false, err
}
return true, nil
}

func (h KubeHelperImpl) DeleteDataSources(name, namespace string) error {
configMap, err := h.getConfigMap(namespace, GrafanaDatasourcesConfigMapName)
configMap, err := h.getConfigMap(GrafanaDatasourcesConfigMapName)
if err != nil {
// Grafana may already be uninstalled
if errors.IsNotFound(err) {
Expand All @@ -131,7 +157,7 @@ func (h KubeHelperImpl) DeleteDataSources(name, namespace string) error {

// Prefix the dashboard filename with the namespace to allow multiple namespaces
// to import the same dashboard
key := fmt.Sprintf("%s_%s", namespace, strings.ToLower(name))
key := h.getConfigMapKey(namespace, name)

if configMap.Data == nil {
return nil
Expand All @@ -143,12 +169,12 @@ func (h KubeHelperImpl) DeleteDataSources(name, namespace string) error {
}

delete(configMap.Data, key)
configMap, err = h.k8client.CoreV1().ConfigMaps(namespace).Update(configMap)
err = h.updateConfigMap(configMap)
return err
}

func (h KubeHelperImpl) DeleteDashboard(monitoringNamespace string, dashboardNamespace string, dashboard *v1alpha1.GrafanaDashboard) error {
configMap, err := h.getConfigMap(monitoringNamespace, GrafanaDashboardsConfigMapName)
func (h KubeHelperImpl) DeleteDashboard(d *v1alpha1.GrafanaDashboard) error {
configMap, err := h.getConfigMap(GrafanaDashboardsConfigMapName)
if err != nil {
if errors.IsNotFound(err) {
// Grafana may already be uninstalled
Expand All @@ -157,10 +183,7 @@ func (h KubeHelperImpl) DeleteDashboard(monitoringNamespace string, dashboardNam
return err
}

// Prefix the dashboard filename with the namespace to allow multiple namespaces
// to import the same dashboard
dashboardName := fmt.Sprintf("%s_%s", dashboardNamespace, dashboard.Spec.Name)

dashboardName := h.getConfigMapKey(d.Namespace, d.Spec.Name)
if configMap.Data == nil {
return nil
}
Expand All @@ -171,7 +194,7 @@ func (h KubeHelperImpl) DeleteDashboard(monitoringNamespace string, dashboardNam
}

delete(configMap.Data, dashboardName)
configMap, err = h.k8client.CoreV1().ConfigMaps(monitoringNamespace).Update(configMap)
err = h.updateConfigMap(configMap)
if err != nil {
return err
}
Expand Down Expand Up @@ -199,8 +222,10 @@ func (h KubeHelperImpl) getGrafanaPod(namespaceName string) (*core.Pod, error) {
return &pods.Items[0], nil
}

func (h KubeHelperImpl) UpdateGrafanaDeployment(monitoringNamespace string, newEnv string) error {
deployment, err := h.getGrafanaDeployment(monitoringNamespace)
func (h KubeHelperImpl) UpdateGrafanaDeployment(newEnv string) error {
monitoringNamespace := h.config.GetConfigString(ConfigOperatorNamespace, "")
deployment, err := h.getGrafanaDeployment()

if err != nil {
return err
}
Expand Down Expand Up @@ -228,8 +253,10 @@ func (h KubeHelperImpl) UpdateGrafanaDeployment(monitoringNamespace string, newE
return nil
}

func (h KubeHelperImpl) RestartGrafana(monitoringNamespace string) error {
func (h KubeHelperImpl) RestartGrafana() error {
monitoringNamespace := h.config.GetConfigString(ConfigOperatorNamespace, "")
pod, err := h.getGrafanaPod(monitoringNamespace)

if err != nil {
if errors.IsNotFound(err) {
// No need to restart if grafana has not yet been deployed
Expand Down
1 change: 1 addition & 0 deletions pkg/controller/common/resource_states.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ const (
StatusResourceUninitialized int = iota
StatusResourceSetFinalizer
StatusResourceCreated
StatusResourceOrphaned
)
Loading

0 comments on commit 1a3d3c0

Please sign in to comment.