Skip to content

Commit

Permalink
refactor: set operator options via functional options
Browse files Browse the repository at this point in the history
And add some default checking and setting.

Signed-off-by: Jan Fajerski <[email protected]>
  • Loading branch information
jan--f committed Jan 18, 2024
1 parent f46bc1b commit c6b064c
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 43 deletions.
39 changes: 36 additions & 3 deletions cmd/operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package main

import (
"flag"
"fmt"
"os"

"github.com/rhobs/observability-operator/pkg/operator"
Expand All @@ -28,20 +29,38 @@ import (
"sigs.k8s.io/controller-runtime/pkg/log/zap"
)

// validateImages merges the passed images with the defaults and checks if any
// unknown image names are passed. If an unknown image is found, this raises an
// error.
func validateImages(images *k8sflag.MapStringString) (map[string]string, error) {
res := operator.DefaultImages
if !images.Empty() {
imgs := *images.Map
for k, v := range imgs {
if _, ok := res[k]; !ok {
return nil, fmt.Errorf(fmt.Sprintf("image %v is unknows", k))
}
res[k] = v
}
}
return res, nil
}

func main() {
var (
namespace string
metricsAddr string
healthProbeAddr string
images k8sflag.MapStringString

setupLog = ctrl.Log.WithName("setup")
)
m := make(map[string]string)
images := k8sflag.NewMapStringString(&m)

flag.StringVar(&namespace, "namespace", "default", "The namespace in which the operator runs")
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&healthProbeAddr, "health-probe-bind-address", ":8081", "The address the health probe endpoint binds to.")
flag.Var(&images, "images", "Full images refs to use for containers managed by the operator. E.g thanos=quay.io/thanos/thanos:v0.33.0")
flag.Var(images, "images", fmt.Sprintf("Full images refs to use for containers managed by the operator. E.g thanos=quay.io/thanos/thanos:v0.33.0. Images used are %v", operator.ImagesUsed()))
opts := zap.Options{
Development: true,
TimeEncoder: zapcore.RFC3339TimeEncoder,
Expand All @@ -55,7 +74,21 @@ func main() {
"namespace", namespace,
"metrics-bind-address", metricsAddr)

op, err := operator.New(operator.NewOperatorConfiguration(metricsAddr, healthProbeAddr, *images.Map))
imgMap, err := validateImages(images)
if err != nil {
setupLog.Error(err, "cannot create a new operator")
os.Exit(1)
}

op, err := operator.New(
operator.NewOperatorConfiguration(
operator.WithMetricsAddr(metricsAddr),
operator.WithHealthProbeAddr(healthProbeAddr),
operator.WithPrometheusImage(imgMap["prometheus"]),
operator.WithAlertmanagerImage(imgMap["alertmanager"]),
operator.WithThanosSidecarImage(imgMap["thanos"]),
operator.WithThanosQuerierImage(imgMap["thanos"]),
))
if err != nil {
setupLog.Error(err, "cannot create a new operator")
os.Exit(1)
Expand Down
7 changes: 1 addition & 6 deletions pkg/controllers/monitoring/monitoring-stack/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,16 +191,11 @@ func newPrometheus(
RuleSelector: prometheusSelector,
RuleNamespaceSelector: ms.Spec.NamespaceSelector,
Thanos: &monv1.ThanosSpec{
BaseImage: stringPtr("quay.io/thanos/thanos"),
Version: stringPtr("v0.24.0"),
Image: stringPtr(thanosCfg.Image),
},
},
}

if thanosCfg.Image != "" {
prometheus.Spec.Thanos.Image = stringPtr(thanosCfg.Image)
}

if prometheusCfg.Image != "" {
prometheus.Spec.CommonPrometheusFields.Image = stringPtr(prometheusCfg.Image)
}
Expand Down
9 changes: 0 additions & 9 deletions pkg/controllers/monitoring/monitoring-stack/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import (

"github.com/go-logr/logr"
monv1 "github.com/rhobs/obo-prometheus-operator/pkg/apis/monitoring/v1"
obopo "github.com/rhobs/obo-prometheus-operator/pkg/operator"
)

type resourceManager struct {
Expand All @@ -67,14 +66,6 @@ type ThanosConfiguration struct {
Image string
}

func (t ThanosConfiguration) GetImageRef() string {
image := "quay.io/thanos/thanos" + obopo.DefaultThanosVersion
if t.Image != "" {
image = t.Image
}
return image
}

// Options allows for controller options to be set
type Options struct {
InstanceSelector string
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/monitoring/thanos-querier/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func newThanosQuerierDeployment(name string, spec *msoapi.ThanosQuerier, sidecar
{
Name: "thanos-querier",
Args: args,
Image: thanosCfg.GetImageRef(),
Image: thanosCfg.Image,
Ports: []corev1.ContainerPort{
{
ContainerPort: 9090,
Expand Down
9 changes: 0 additions & 9 deletions pkg/controllers/monitoring/thanos-querier/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"fmt"
"time"

obopo "github.com/rhobs/obo-prometheus-operator/pkg/operator"
msoapi "github.com/rhobs/observability-operator/pkg/apis/monitoring/v1alpha1"

appsv1 "k8s.io/api/apps/v1"
Expand Down Expand Up @@ -49,14 +48,6 @@ type ThanosConfiguration struct {
Image string
}

func (t ThanosConfiguration) GetImageRef() string {
image := "quay.io/thanos/thanos" + obopo.DefaultThanosVersion
if t.Image != "" {
image = t.Image
}
return image
}

// Options allows for controller options to be set
type Options struct {
Thanos ThanosConfiguration
Expand Down
81 changes: 66 additions & 15 deletions pkg/operator/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
stackctrl "github.com/rhobs/observability-operator/pkg/controllers/monitoring/monitoring-stack"
tqctrl "github.com/rhobs/observability-operator/pkg/controllers/monitoring/thanos-querier"

obopo "github.com/rhobs/obo-prometheus-operator/pkg/operator"

"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/healthz"

Expand All @@ -21,16 +23,30 @@ const instanceSelector = "app.kubernetes.io/managed-by=observability-operator"

const ObservabilityOperatorName = "observability-operator"

// The default values we use. Prometheus and Alertmanager are handled by
// prometheus-operator. For thanos we use the default version from
// prometheus-operator.
var DefaultImages = map[string]string{
"prometheus": "",
"alertmanager": "",
"thanos": "quay.io/thanos/thanos:" + obopo.DefaultThanosVersion,
}

func ImagesUsed() []string {
i := 0
imgs := make([]string, len(DefaultImages))
for k := range DefaultImages {
imgs[i] = k
i++
}
return imgs
}

// Operator embedds manager and exposes only the minimal set of functions
type Operator struct {
manager manager.Manager
}

type OperandConfiguration struct {
Image string
Version string
}

type OperatorConfiguration struct {
MetricsAddr string
HealthProbeAddr string
Expand All @@ -40,18 +56,51 @@ type OperatorConfiguration struct {
ThanosQuerier tqctrl.ThanosConfiguration
}

func NewOperatorConfiguration(metricsAddr string, healthProbeAddr string, images map[string]string) OperatorConfiguration {
return OperatorConfiguration{
MetricsAddr: metricsAddr,
HealthProbeAddr: healthProbeAddr,
Prometheus: stackctrl.PrometheusConfiguration{Image: images["prometheus"]},
Alertmanager: stackctrl.AlertmanagerConfiguration{Image: images["alertmanager"]},
ThanosSidecar: stackctrl.ThanosConfiguration{Image: images["thanos"]},
ThanosQuerier: tqctrl.ThanosConfiguration{Image: images["thanos"]},
func WithPrometheusImage(image string) func(*OperatorConfiguration) {
return func(oc *OperatorConfiguration) {
oc.Prometheus = stackctrl.PrometheusConfiguration{Image: image}
}
}

func WithAlertmanagerImage(image string) func(*OperatorConfiguration) {
return func(oc *OperatorConfiguration) {
oc.Alertmanager = stackctrl.AlertmanagerConfiguration{Image: image}
}
}

func WithThanosSidecarImage(image string) func(*OperatorConfiguration) {
return func(oc *OperatorConfiguration) {
oc.ThanosSidecar = stackctrl.ThanosConfiguration{Image: image}
}
}

func WithThanosQuerierImage(image string) func(*OperatorConfiguration) {
return func(oc *OperatorConfiguration) {
oc.ThanosQuerier = tqctrl.ThanosConfiguration{Image: image}
}
}

func WithMetricsAddr(addr string) func(*OperatorConfiguration) {
return func(oc *OperatorConfiguration) {
oc.MetricsAddr = addr
}
}

func WithHealthProbeAddr(addr string) func(*OperatorConfiguration) {
return func(oc *OperatorConfiguration) {
oc.HealthProbeAddr = addr
}
}

func NewOperatorConfiguration(opts ...func(*OperatorConfiguration)) *OperatorConfiguration {
cfg := &OperatorConfiguration{}
for _, o := range opts {
o(cfg)
}
return cfg
}

func New(cfg OperatorConfiguration) (*Operator, error) {
func New(cfg *OperatorConfiguration) (*Operator, error) {
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: NewScheme(),
Metrics: metricsserver.Options{
Expand All @@ -66,7 +115,9 @@ func New(cfg OperatorConfiguration) (*Operator, error) {
if err := stackctrl.RegisterWithManager(mgr, stackctrl.Options{
InstanceSelector: instanceSelector,
Prometheus: cfg.Prometheus,
Alertmanager: cfg.Alertmanager}); err != nil {
Alertmanager: cfg.Alertmanager,
Thanos: cfg.ThanosSidecar,
}); err != nil {
return nil, fmt.Errorf("unable to register monitoring stack controller: %w", err)
}

Expand Down

0 comments on commit c6b064c

Please sign in to comment.