Skip to content

Commit

Permalink
Refactor main and environment variables (#185)
Browse files Browse the repository at this point in the history
* Refactor main and environment variables

- Move cluster controller creationg logic to controller.SetupClusterMonitoringReconciler
- Move grafana controller creationg logic to controller.SetupGrafanaOrganizationReconciler
- Load environment variables using https://github.com/Netflix/go-env
  • Loading branch information
TheoBrigitte authored Dec 9, 2024
1 parent a7f6ca4 commit 8df42b3
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 92 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ toolchain go1.23.4

require (
github.com/Masterminds/sprig/v3 v3.3.0
github.com/Netflix/go-env v0.1.2
github.com/blang/semver v3.5.1+incompatible
github.com/giantswarm/apiextensions-application v0.6.2
github.com/go-logr/logr v1.4.2
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/Netflix/go-env v0.1.2 h1:0DRoLR9lECQ9Zqvkswuebm3jJ/2enaDX6Ei8/Z+EnK0=
github.com/Netflix/go-env v0.1.2/go.mod h1:WlIhYi++8FlKNJtrop1mjXYAJMzv1f43K4MqCoh0yGE=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
Expand Down
60 changes: 60 additions & 0 deletions internal/controller/cluster_monitoring_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package controller

import (
"context"
"fmt"
"time"

"github.com/blang/semver"
Expand All @@ -29,11 +30,15 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

"github.com/giantswarm/observability-operator/pkg/bundle"
"github.com/giantswarm/observability-operator/pkg/common"
commonmonitoring "github.com/giantswarm/observability-operator/pkg/common/monitoring"
"github.com/giantswarm/observability-operator/pkg/common/organization"
"github.com/giantswarm/observability-operator/pkg/common/password"
"github.com/giantswarm/observability-operator/pkg/config"
"github.com/giantswarm/observability-operator/pkg/monitoring"
"github.com/giantswarm/observability-operator/pkg/monitoring/alloy"
"github.com/giantswarm/observability-operator/pkg/monitoring/heartbeat"
Expand Down Expand Up @@ -64,6 +69,61 @@ type ClusterMonitoringReconciler struct {
MonitoringConfig monitoring.Config
}

func SetupClusterMonitoringReconciler(mgr manager.Manager, conf config.Config) error {
managerClient := mgr.GetClient()

if conf.Environment.OpsgenieApiKey == "" {
return fmt.Errorf("OpsgenieApiKey not set: %q", conf.Environment.OpsgenieApiKey)
}

heartbeatRepository, err := heartbeat.NewOpsgenieHeartbeatRepository(conf.Environment.OpsgenieApiKey, conf.ManagementCluster)
if err != nil {
return fmt.Errorf("unable to create heartbeat repository: %w", err)
}

organizationRepository := organization.NewNamespaceRepository(managerClient)

prometheusAgentService := prometheusagent.PrometheusAgentService{
Client: managerClient,
OrganizationRepository: organizationRepository,
PasswordManager: password.SimpleManager{},
ManagementCluster: conf.ManagementCluster,
MonitoringConfig: conf.Monitoring,
}

alloyService := alloy.Service{
Client: managerClient,
OrganizationRepository: organizationRepository,
PasswordManager: password.SimpleManager{},
ManagementCluster: conf.ManagementCluster,
MonitoringConfig: conf.Monitoring,
}

mimirService := mimir.MimirService{
Client: managerClient,
PasswordManager: password.SimpleManager{},
ManagementCluster: conf.ManagementCluster,
}

r := &ClusterMonitoringReconciler{
Client: managerClient,
ManagementCluster: conf.ManagementCluster,
HeartbeatRepository: heartbeatRepository,
PrometheusAgentService: prometheusAgentService,
AlloyService: alloyService,
MimirService: mimirService,
MonitoringConfig: conf.Monitoring,
BundleConfigurationService: bundle.NewBundleConfigurationService(managerClient, conf.Monitoring),
}

err = r.SetupWithManager(mgr)
if err != nil {
return err
}

return nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *ClusterMonitoringReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
Expand Down
42 changes: 42 additions & 0 deletions internal/controller/grafanaorganization_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package controller

import (
"context"
"fmt"
"slices"
"strings"

Expand All @@ -34,8 +35,12 @@ import (
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

"github.com/giantswarm/observability-operator/pkg/config"
grafanaclient "github.com/giantswarm/observability-operator/pkg/grafana/client"

"github.com/giantswarm/observability-operator/api/v1alpha1"
"github.com/giantswarm/observability-operator/internal/controller/predicates"
"github.com/giantswarm/observability-operator/pkg/grafana"
Expand All @@ -49,6 +54,43 @@ type GrafanaOrganizationReconciler struct {
GrafanaAPI *grafanaAPI.GrafanaHTTPAPI
}

func SetupGrafanaOrganizationReconciler(mgr manager.Manager, environment config.Environment) error {
// Generate Grafana client
// Get grafana admin-password and admin-user
grafanaAdminCredentials := grafanaclient.AdminCredentials{
Username: environment.GrafanaAdminUsername,
Password: environment.GrafanaAdminPassword,
}
if grafanaAdminCredentials.Username == "" {
return fmt.Errorf("GrafanaAdminUsername not set: %q", environment.GrafanaAdminUsername)
}
if grafanaAdminCredentials.Password == "" {
return fmt.Errorf("GrafanaAdminPassword not set: %q", environment.GrafanaAdminPassword)
}

grafanaTLSConfig := grafanaclient.TLSConfig{
Cert: environment.GrafanaTLSCertFile,
Key: environment.GrafanaTLSKeyFile,
}
grafanaAPI, err := grafanaclient.GenerateGrafanaClient(grafanaAdminCredentials, grafanaTLSConfig)
if err != nil {
return fmt.Errorf("unable to create grafana client: %w", err)
}

r := &GrafanaOrganizationReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
GrafanaAPI: grafanaAPI,
}

err = r.SetupWithManager(mgr)
if err != nil {
return err
}

return nil
}

//+kubebuilder:rbac:groups=observability.giantswarm.io,resources=grafanaorganizations,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=observability.giantswarm.io,resources=grafanaorganizations/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=observability.giantswarm.io,resources=grafanaorganizations/finalizers,verbs=update
Expand Down
110 changes: 18 additions & 92 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
// to ensure that exec-entrypoint and run can make use of them.
_ "k8s.io/client-go/plugin/pkg/client/auth"

"github.com/Netflix/go-env"
appv1 "github.com/giantswarm/apiextensions-application/api/v1alpha1"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
Expand All @@ -41,16 +42,8 @@ import (

observabilityv1alpha1 "github.com/giantswarm/observability-operator/api/v1alpha1"
"github.com/giantswarm/observability-operator/internal/controller"
"github.com/giantswarm/observability-operator/pkg/bundle"
commonmonitoring "github.com/giantswarm/observability-operator/pkg/common/monitoring"
"github.com/giantswarm/observability-operator/pkg/common/organization"
"github.com/giantswarm/observability-operator/pkg/common/password"
"github.com/giantswarm/observability-operator/pkg/config"
"github.com/giantswarm/observability-operator/pkg/grafana/client"
"github.com/giantswarm/observability-operator/pkg/monitoring/alloy"
"github.com/giantswarm/observability-operator/pkg/monitoring/heartbeat"
"github.com/giantswarm/observability-operator/pkg/monitoring/mimir"
"github.com/giantswarm/observability-operator/pkg/monitoring/prometheusagent"
//+kubebuilder:scaffold:imports
)

Expand All @@ -61,15 +54,6 @@ var (
setupLog = ctrl.Log.WithName("setup")
)

const (
grafanaAdminUsernameEnvVar = "GRAFANA_ADMIN_USERNAME" // #nosec G101
grafanaAdminPasswordEnvVar = "GRAFANA_ADMIN_PASSWORD" // #nosec G101
grafanaTLSCertFileEnvVar = "GRAFANA_TLS_CERT_FILE" // #nosec G101
grafanaTLSKeyFileEnvVar = "GRAFANA_TLS_KEY_FILE" // #nosec G101

opsgenieApiKeyEnvVar = "OPSGENIE_API_KEY" // #nosec G101
)

func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
utilruntime.Must(clusterv1.AddToScheme(scheme))
Expand All @@ -90,6 +74,8 @@ func main() {
"If set the metrics endpoint is served securely")
flag.BoolVar(&conf.EnableHTTP2, "enable-http2", false,
"If set, HTTP/2 will be enabled for the metrics and webhook servers")

// Management cluster configuration flags.
flag.StringVar(&conf.ManagementCluster.BaseDomain, "management-cluster-base-domain", "",
"The base domain of the management cluster.")
flag.StringVar(&conf.ManagementCluster.Customer, "management-cluster-customer", "",
Expand All @@ -102,6 +88,7 @@ func main() {
"The pipeline of the management cluster.")
flag.StringVar(&conf.ManagementCluster.Region, "management-cluster-region", "",
"The region of the management cluster.")

// Monitoring configuration flags.
flag.StringVar(&conf.Monitoring.MonitoringAgent, "monitoring-agent", commonmonitoring.MonitoringAgentAlloy,
fmt.Sprintf("select monitoring agent to use (%s or %s)", commonmonitoring.MonitoringAgentPrometheus, commonmonitoring.MonitoringAgentAlloy))
Expand All @@ -118,9 +105,17 @@ func main() {
opts := zap.Options{
Development: false,
}

opts.BindFlags(flag.CommandLine)
flag.Parse()

// Load environment variables.
_, err := env.UnmarshalFromEnviron(&conf.Environment)
if err != nil {
setupLog.Error(err, "failed to unmarshal environment variables")
os.Exit(1)
}

ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))

// if the enable-http2 flag is false (the default), http/2 should be disabled
Expand Down Expand Up @@ -174,86 +169,17 @@ func main() {
// Initialize event recorder.
record.InitFromRecorder(mgr.GetEventRecorderFor("observability-operator"))

var opsgenieApiKey = os.Getenv(opsgenieApiKeyEnvVar)
if opsgenieApiKey == "" {
setupLog.Error(nil, fmt.Sprintf("environment variable %s not set", opsgenieApiKeyEnvVar))
os.Exit(1)
}

heartbeatRepository, err := heartbeat.NewOpsgenieHeartbeatRepository(opsgenieApiKey, conf.ManagementCluster)
// Setup controller for the Cluster resource.
err = controller.SetupClusterMonitoringReconciler(mgr, conf)
if err != nil {
setupLog.Error(err, "unable to create heartbeat repository")
os.Exit(1)
}

organizationRepository := organization.NewNamespaceRepository(mgr.GetClient())

prometheusAgentService := prometheusagent.PrometheusAgentService{
Client: mgr.GetClient(),
OrganizationRepository: organizationRepository,
PasswordManager: password.SimpleManager{},
ManagementCluster: conf.ManagementCluster,
MonitoringConfig: conf.Monitoring,
}

alloyService := alloy.Service{
Client: mgr.GetClient(),
OrganizationRepository: organizationRepository,
PasswordManager: password.SimpleManager{},
ManagementCluster: conf.ManagementCluster,
MonitoringConfig: conf.Monitoring,
}

mimirService := mimir.MimirService{
Client: mgr.GetClient(),
PasswordManager: password.SimpleManager{},
ManagementCluster: conf.ManagementCluster,
}

if err = (&controller.ClusterMonitoringReconciler{
Client: mgr.GetClient(),
ManagementCluster: conf.ManagementCluster,
HeartbeatRepository: heartbeatRepository,
PrometheusAgentService: prometheusAgentService,
AlloyService: alloyService,
MimirService: mimirService,
MonitoringConfig: conf.Monitoring,
BundleConfigurationService: bundle.NewBundleConfigurationService(mgr.GetClient(), conf.Monitoring),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Cluster")
setupLog.Error(err, "unable to create controller", "controller", "ClusterMonitoringReconciler")
os.Exit(1)
}

// Generate Grafana client
// Get grafana admin-password and admin-user
grafanaAdminCredentials := client.AdminCredentials{
Username: os.Getenv(grafanaAdminUsernameEnvVar),
Password: os.Getenv(grafanaAdminPasswordEnvVar),
}
if grafanaAdminCredentials.Username == "" {
setupLog.Error(nil, fmt.Sprintf("environment variable %s not set", grafanaAdminUsernameEnvVar))
os.Exit(1)
}
if grafanaAdminCredentials.Password == "" {
setupLog.Error(nil, fmt.Sprintf("environment variable %s not set", grafanaAdminPasswordEnvVar))
os.Exit(1)
}
grafanaTLSConfig := client.TLSConfig{
Cert: os.Getenv(grafanaTLSCertFileEnvVar),
Key: os.Getenv(grafanaTLSKeyFileEnvVar),
}
grafanaAPI, err := client.GenerateGrafanaClient(grafanaAdminCredentials, grafanaTLSConfig)
// Setup controller for the GrafanaOrganization resource.
err = controller.SetupGrafanaOrganizationReconciler(mgr, conf.Environment)
if err != nil {
setupLog.Error(err, "unable to create grafana client")
os.Exit(1)
}

if err = (&controller.GrafanaOrganizationReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
GrafanaAPI: grafanaAPI,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "GrafanaOrganization")
setupLog.Error(err, "unable to setup controller", "controller", "GrafanaOrganizationReconciler")
os.Exit(1)
}
//+kubebuilder:scaffold:builder
Expand Down
11 changes: 11 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,15 @@ type Config struct {
ManagementCluster common.ManagementCluster

Monitoring monitoring.Config

Environment Environment
}

type Environment struct {
GrafanaAdminUsername string `env:"GRAFANA_ADMIN_USERNAME,required=true"`
GrafanaAdminPassword string `env:"GRAFANA_ADMIN_PASSWORD,required=true"`
GrafanaTLSCertFile string `env:"GRAFANA_TLS_CERT_FILE,required=true"`
GrafanaTLSKeyFile string `env:"GRAFANA_TLS_KEY_FILE,required=true"`

OpsgenieApiKey string `env:"OPSGENIE_API_KEY,required=true"`
}

0 comments on commit 8df42b3

Please sign in to comment.