Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
df95743
wip: rewrite reconciliation loop, migrate to go modules and use grafa…
pb82 Nov 10, 2019
ff96602
INTLY-4183-Updating grafana version
R-Lawton Nov 20, 2019
ce79073
travis should work with go modules
pb82 Nov 20, 2019
b1cc302
update go version requirement
pb82 Nov 20, 2019
dfa0309
update modules
pb82 Nov 20, 2019
d8573a2
update Dockerfile, remove templates
pb82 Nov 20, 2019
f52fbc5
basic dashboard api create/update/delete implemented
pb82 Nov 22, 2019
e7f3de0
implement dashboard logic: resync and updates
pb82 Nov 24, 2019
40ff24a
enable metrics
pb82 Nov 24, 2019
b6a092b
cleanup and version update
pb82 Nov 24, 2019
e297fc1
feat: import dashboards after grafana reinstall, improve unavailabili…
pb82 Nov 24, 2019
addeba5
wip - plugin installation
pb82 Nov 24, 2019
8b7bb76
wip: start working on a way to reset dashboards
pb82 Nov 25, 2019
2c1b8da
wip: resilient dashboards (should survive restarts)
pb82 Nov 25, 2019
211d1c2
remove dashboard wait time because it prevents updating plugins
pb82 Nov 25, 2019
f15e6b3
add oauth example
pb82 Nov 25, 2019
820a8d6
fix: persist admin user back to cr to prevent deploymetn from getting…
pb82 Nov 25, 2019
350b9b5
mount extra containers when specified in the cr
pb82 Nov 25, 2019
b480615
fix: missing arg to read grafana deployment
pb82 Nov 25, 2019
3bb2ba8
wip: set default resource requests and limits, hide empty config sect…
pb82 Nov 26, 2019
9acb449
feat: grafana admin credentials from secret
pb82 Nov 26, 2019
63db388
gofmt fixes
pb82 Nov 26, 2019
f45c0f9
graffanaServiceAccount modifications
R-Lawton Nov 28, 2019
f6a2413
update autogenerated code
pb82 Nov 28, 2019
b65d461
add datasources
StevenTobin Nov 29, 2019
2d25d10
delete datasources
pb82 Nov 29, 2019
fa462fd
adding permissions
R-Lawton Nov 29, 2019
275331e
add grafanadatasourceconfig to model
StevenTobin Nov 29, 2019
de46e59
mount datasources volume to provisioning directory
StevenTobin Nov 29, 2019
6789289
fix codee checks
StevenTobin Nov 29, 2019
08c705a
fixing forrmatting error
R-Lawton Nov 29, 2019
44302f9
comment changes and hardcode provisioning path
StevenTobin Nov 29, 2019
cae6afe
code check fixes
StevenTobin Nov 29, 2019
9cad949
updates to ensure new reconciler and grafana api work on vanilla kube
pb82 Nov 30, 2019
d33fc49
update permissions
pb82 Nov 30, 2019
8677d17
restart grafana on datasource change, do not reconcile datasources wh…
pb82 Dec 1, 2019
f63d7a6
implement datasource hashing
pb82 Dec 1, 2019
e711e83
improve datasource update handling
pb82 Dec 1, 2019
8b80abc
allow configuration of service ports and route target ports
pb82 Dec 1, 2019
908aede
wip: ensure config defaults
pb82 Dec 1, 2019
4a83a2e
wip: rework ini configuration
pb82 Dec 1, 2019
b2a6143
add client configuration options
pb82 Dec 1, 2019
318f7cd
update examples, only update datasource status if they have changed
pb82 Dec 1, 2019
ce9f3c2
rewrite ini config system
pb82 Dec 1, 2019
a757d2a
update oauth example
pb82 Dec 1, 2019
8d799f2
fix: service ports did not return existing
pb82 Dec 1, 2019
a5724f4
remove unused code
pb82 Dec 1, 2019
021347a
remove ini dependency
pb82 Dec 2, 2019
95fa747
add backwards compatibility options
pb82 Dec 2, 2019
74437bc
fix: correctly identify dashboards when scan all is enabled
pb82 Dec 2, 2019
63577da
update documentation
pb82 Dec 5, 2019
aac4c49
add changelog
pb82 Dec 5, 2019
df00168
add a note about the Grafana version
pb82 Dec 6, 2019
dee56ca
bump version to 3.0.0
pb82 Dec 6, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: grafana admin credentials from secret
  • Loading branch information
pb82 committed Dec 1, 2019
commit 9acb449984124698cbb657c45c3584f1a2014639
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,7 @@ k8s.io/kubelet v0.0.0-20190918202550-958285cf3eef/go.mod h1:y3faEeGRJ9L54/YJWIF0
k8s.io/kubernetes v1.11.7-beta.0.0.20181219023948-b875d52ea96d/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/kubernetes v1.11.8-beta.0.0.20190124204751-3a10094374f2/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/kubernetes v1.14.2/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/kubernetes v1.15.4 h1:ykcH+DoCr9wYjYfHvd2xU0HoSo/Y9m4+/0+zHqkYjbw=
k8s.io/kubernetes v1.15.4/go.mod h1:4Ggyo4AFgjbIzULOminzUJAvgbzY3j5ysXlW/a0PdcQ=
k8s.io/legacy-cloud-providers v0.0.0-20190918203421-225f0541b3ea/go.mod h1:qd7ZEaONgkMZRdUbaoK6ngxjuJz8kLBImMukwL7mOIg=
k8s.io/metrics v0.0.0-20190918202012-3c1ca76f5bda/go.mod h1:LxAN6ulYLPVQGTtRkXEUyylgseTWArq1iCZ9Zve8edc=
Expand Down
23 changes: 0 additions & 23 deletions pkg/controller/common/clusterActions.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ type ActionRunner interface {
create(obj runtime.Object) error
update(obj runtime.Object) error
delete(obj runtime.Object) error
updateCr(obj runtime.Object) error
routeReady(obj runtime.Object) error
deploymentReady(obj runtime.Object) error
}
Expand Down Expand Up @@ -105,19 +104,6 @@ func (i *ClusterActionRunner) update(obj runtime.Object) error {
return nil
}

func (i *ClusterActionRunner) updateCr(obj runtime.Object) error {
err := i.client.Update(i.ctx, obj)
if err != nil {
// Update conflicts can happen frequently when kubernetes updates the resource
// in the background
if errors.IsConflict(err) {
return nil
}
return err
}
return nil
}

func (i *ClusterActionRunner) delete(obj runtime.Object) error {
return i.client.Delete(i.ctx, obj)
}
Expand Down Expand Up @@ -175,11 +161,6 @@ type DeploymentReadyAction struct {
Msg string
}

type UpdateCrAction struct {
Ref runtime.Object
Msg string
}

// An action to delete generic kubernetes resources
// (resources that don't require special treatment)
type GenericDeleteAction struct {
Expand Down Expand Up @@ -210,7 +191,3 @@ func (i RouteReadyAction) Run(runner ActionRunner) (string, error) {
func (i DeploymentReadyAction) Run(runner ActionRunner) (string, error) {
return i.Msg, runner.deploymentReady(i.Ref)
}

func (i UpdateCrAction) Run(runner ActionRunner) (string, error) {
return i.Msg, runner.updateCr(i.Ref)
}
22 changes: 22 additions & 0 deletions pkg/controller/common/clusterState.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type ClusterState struct {
GrafanaRoute *v12.Route
GrafanaIngress *v1beta1.Ingress
GrafanaDeployment *v13.Deployment
AdminSecret *v1.Secret
}

func NewClusterState() *ClusterState {
Expand Down Expand Up @@ -50,6 +51,11 @@ func (i *ClusterState) Read(ctx context.Context, cr *v1alpha1.Grafana, client cl
return err
}

err = i.readGrafanaAdminUserSecret(ctx, cr, client)
if err != nil {
return err
}

if isOpenshift {
err = i.readGrafanaRoute(ctx, cr, client)
} else {
Expand Down Expand Up @@ -148,3 +154,19 @@ func (i *ClusterState) readGrafanaDeployment(ctx context.Context, cr *v1alpha1.G
}
return nil
}

func (i *ClusterState) readGrafanaAdminUserSecret(ctx context.Context, cr *v1alpha1.Grafana, client client.Client) error {
currentState := model.AdminSecret(cr)
selector := model.AdminSecretSelector(cr)
err := client.Get(ctx, selector, currentState)
if err != nil {
if errors.IsNotFound(err) {
i.AdminSecret = nil
return nil
}
return err
}

i.AdminSecret = currentState.DeepCopy()
return nil
}
2 changes: 1 addition & 1 deletion pkg/controller/config/configHelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

const (
PathsSectionName = "paths"
PathsSectionName = "paths"
)

type IniConfig struct {
Expand Down
7 changes: 2 additions & 5 deletions pkg/controller/grafana/grafana_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ func (r *ReconcileGrafana) Reconcile(request reconcile.Request) (reconcile.Resul
actionRunner := common.NewClusterActionRunner(r.context, r.client, r.scheme, cr)
err = actionRunner.RunAll(desiredState)
if err != nil {
log.Error(err, "error reconciling")
return r.manageError(cr, err)
}

Expand Down Expand Up @@ -202,8 +201,6 @@ func (r *ReconcileGrafana) manageError(cr *i8ly.Grafana, issue error) (reconcile

func (r *ReconcileGrafana) manageSuccess(cr *i8ly.Grafana, state *common.ClusterState) (reconcile.Result, error) {
cr.Status.Phase = i8ly.PhaseReconciling
cr.Status.AdminUser = cr.Spec.Config.Security.AdminUser
cr.Status.AdminPassword = cr.Spec.Config.Security.AdminPassword

// Only update the status if the dashboard controller had a chance to sync the cluster
// dashboards first. Otherwise reuse the existing dashboard config from the CR.
Expand Down Expand Up @@ -236,8 +233,8 @@ func (r *ReconcileGrafana) manageSuccess(cr *i8ly.Grafana, state *common.Cluster
// Publish controller state
controllerState := common.ControllerState{
DashboardSelectors: cr.Spec.DashboardLabelSelector,
AdminUsername: cr.Status.AdminUser,
AdminPassword: cr.Status.AdminPassword,
AdminUsername: string(state.AdminSecret.Data[model.GrafanaAdminUserEnvVar]),
AdminPassword: string(state.AdminSecret.Data[model.GrafanaAdminPasswordEnvVar]),
AdminUrl: grafanaRoute,
GrafanaReady: true,
}
Expand Down
23 changes: 14 additions & 9 deletions pkg/controller/grafana/grafana_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func NewGrafanaReconciler() *GrafanaReconciler {
func (i *GrafanaReconciler) Reconcile(state *common.ClusterState, cr *v1alpha1.Grafana) common.DesiredClusterState {
desired := common.DesiredClusterState{}

desired = desired.AddAction(i.getGrafanaAdminUserSecretDesiredState(state, cr))
desired = desired.AddAction(i.getGrafanaServiceDesiredState(state, cr))
desired = desired.AddAction(i.getGrafanaServiceAccountDesiredState(state, cr))
desired = desired.AddActions(i.getGrafanaConfigDesiredState(state, cr))
Expand Down Expand Up @@ -93,8 +94,6 @@ func (i *GrafanaReconciler) getGrafanaConfigDesiredState(state *common.ClusterSt
actions := []common.ClusterAction{}

if state.GrafanaConfig == nil {
hasAdminUser := model.HasAdminUser(cr)

config, err := model.GrafanaConfig(cr)
if err != nil {
log.Error(err, "error creating grafana config")
Expand All @@ -109,13 +108,6 @@ func (i *GrafanaReconciler) getGrafanaConfigDesiredState(state *common.ClusterSt
Ref: config,
Msg: "create grafana config",
})

if !hasAdminUser {
actions = append(actions, common.UpdateCrAction{
Ref: cr,
Msg: fmt.Sprintf("add admin user to %v", cr.Name),
})
}
} else {
config, err := model.GrafanaConfigReconciled(cr, state.GrafanaConfig)
if err != nil {
Expand Down Expand Up @@ -161,6 +153,19 @@ func (i *GrafanaReconciler) getGrafanaExternalAccessDesiredState(state *common.C
}
}

func (i *GrafanaReconciler) getGrafanaAdminUserSecretDesiredState(state *common.ClusterState, cr *v1alpha1.Grafana) common.ClusterAction {
if state.AdminSecret == nil {
return common.GenericCreateAction{
Ref: model.AdminSecret(cr),
Msg: "create admin credentials secret",
}
}
return common.GenericUpdateAction{
Ref: model.AdminSecretReconciled(cr, state.AdminSecret),
Msg: "update admin credentials secret",
}
}

func (i *GrafanaReconciler) getGrafanaIngressDesiredState(state *common.ClusterState, cr *v1alpha1.Grafana) common.ClusterAction {
if state.GrafanaIngress == nil {
return common.GenericCreateAction{
Expand Down
61 changes: 61 additions & 0 deletions pkg/controller/model/adminUserSecret.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package model

import (
"github.com/integr8ly/grafana-operator/pkg/apis/integreatly/v1alpha1"
v12 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

func getAdminUser(cr *v1alpha1.Grafana, current *v12.Secret) []byte {
if cr.Spec.Config.Security.AdminUser == "" {
// If a user is already set, don't change it
if current != nil && current.Data[GrafanaAdminUserEnvVar] != nil {
return current.Data[GrafanaAdminUserEnvVar]
}
return []byte(DefaultAdminUser)
}
return []byte(cr.Spec.Config.Security.AdminUser)
}

func getAdminPassword(cr *v1alpha1.Grafana, current *v12.Secret) []byte {
if cr.Spec.Config.Security.AdminPassword == "" {
// If a password is already set, don't change it
if current != nil && current.Data[GrafanaAdminPasswordEnvVar] != nil {
return current.Data[GrafanaAdminPasswordEnvVar]
}
return []byte(RandStringRunes(10))
}
return []byte(cr.Spec.Config.Security.AdminPassword)
}

func getData(cr *v1alpha1.Grafana, current *v12.Secret) map[string][]byte {
return map[string][]byte{
GrafanaAdminUserEnvVar: getAdminUser(cr, current),
GrafanaAdminPasswordEnvVar: getAdminPassword(cr, current),
}
}

func AdminSecret(cr *v1alpha1.Grafana) *v12.Secret {
return &v12.Secret{
ObjectMeta: v1.ObjectMeta{
Name: GrafanaAdminSecretName,
Namespace: cr.Namespace,
},
Data: getData(cr, nil),
Type: v12.SecretTypeOpaque,
}
}

func AdminSecretReconciled(cr *v1alpha1.Grafana, currentState *v12.Secret) *v12.Secret {
reconciled := currentState.DeepCopy()
reconciled.Data = getData(cr, currentState)
return reconciled
}

func AdminSecretSelector(cr *v1alpha1.Grafana) client.ObjectKey {
return client.ObjectKey{
Namespace: cr.Namespace,
Name: GrafanaAdminSecretName,
}
}
37 changes: 20 additions & 17 deletions pkg/controller/model/constants.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
package model

const (
GrafanaServiceAccountName = "grafana-serviceaccount"
GrafanaServiceName = "grafana-service"
GrafanaConfigName = "grafana-config"
GrafanaConfigFileName = "grafana.ini"
GrafanaIngressName = "grafana-ingress"
GrafanaRouteName = "grafana-route"
GrafanaDeploymentName = "grafana-deployment"
GrafanaPluginsVolumeName = "grafana-plugins"
GrafanaInitContainerName = "grafana-plugins-init"
GrafanaLogsVolumeName = "grafana-logs"
GrafanaDataVolumeName = "grafana-data"
GrafanaHealthEndpoint = "/api/health"
GrafanaPodLabel = "grafana"
LastConfigAnnotation = "last-config"
LastConfigEnvVar = "LAST_CONFIG"
DefaultAdminUser = "admin"
GrafanaHttpPort int = 3000
GrafanaServiceAccountName = "grafana-serviceaccount"
GrafanaServiceName = "grafana-service"
GrafanaConfigName = "grafana-config"
GrafanaConfigFileName = "grafana.ini"
GrafanaIngressName = "grafana-ingress"
GrafanaRouteName = "grafana-route"
GrafanaDeploymentName = "grafana-deployment"
GrafanaPluginsVolumeName = "grafana-plugins"
GrafanaInitContainerName = "grafana-plugins-init"
GrafanaLogsVolumeName = "grafana-logs"
GrafanaDataVolumeName = "grafana-data"
GrafanaHealthEndpoint = "/api/health"
GrafanaPodLabel = "grafana"
LastConfigAnnotation = "last-config"
LastConfigEnvVar = "LAST_CONFIG"
GrafanaAdminSecretName = "admin-credentials"
DefaultAdminUser = "admin"
GrafanaAdminUserEnvVar = "GF_SECURITY_ADMIN_USER"
GrafanaAdminPasswordEnvVar = "GF_SECURITY_ADMIN_PASSWORD"
GrafanaHttpPort int = 3000
)
21 changes: 0 additions & 21 deletions pkg/controller/model/grafanaConfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
)

func ensureAdminUser(cr *v1alpha1.Grafana) {
if cr.Spec.Config.Security.AdminUser == "" {
cr.Spec.Config.Security.AdminUser = DefaultAdminUser
}

if cr.Spec.Config.Security.AdminPassword == "" {
cr.Spec.Config.Security.AdminPassword = RandStringRunes(10)
}
}

func HasAdminUser(cr *v1alpha1.Grafana) bool {
if cr.Spec.Config.Security.AdminUser == "" || cr.Spec.Config.Security.AdminPassword == "" {
return true
}
return false
}

func GrafanaConfig(cr *v1alpha1.Grafana) (*v1.ConfigMap, error) {
// Make sure the admin user has known credentials because it is
// used to access the Grafana API
ensureAdminUser(cr)

grafanaIni := config.NewIniConfig(cr)
err := grafanaIni.Build()
if err != nil {
Expand Down
22 changes: 22 additions & 0 deletions pkg/controller/model/grafanaDeployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,28 @@ func getContainers(cr *v1alpha1.Grafana, configHash string) []v13.Container {
Name: LastConfigEnvVar,
Value: configHash,
},
{
Name: GrafanaAdminUserEnvVar,
ValueFrom: &v13.EnvVarSource{
SecretKeyRef: &v13.SecretKeySelector{
LocalObjectReference: v13.LocalObjectReference{
Name: GrafanaAdminSecretName,
},
Key: GrafanaAdminUserEnvVar,
},
},
},
{
Name: GrafanaAdminPasswordEnvVar,
ValueFrom: &v13.EnvVarSource{
SecretKeyRef: &v13.SecretKeySelector{
LocalObjectReference: v13.LocalObjectReference{
Name: GrafanaAdminSecretName,
},
Key: GrafanaAdminPasswordEnvVar,
},
},
},
},
Resources: getResources(cr),
VolumeMounts: getVolumeMounts(cr),
Expand Down
File renamed without changes.