Skip to content

Commit

Permalink
operator: Replace deprecated ctrl-runtime cfg with custom package
Browse files Browse the repository at this point in the history
  • Loading branch information
periklis committed Jan 15, 2024
1 parent 86f2001 commit 9c5ea9c
Show file tree
Hide file tree
Showing 7 changed files with 349 additions and 4 deletions.
4 changes: 4 additions & 0 deletions operator/apis/config/v1/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ var (
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)

func init() {
SchemeBuilder.Register(&ControllerManagerConfiguration{})
}
65 changes: 63 additions & 2 deletions operator/apis/config/v1/projectconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package v1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
cfg "sigs.k8s.io/controller-runtime/pkg/config/v1alpha1" //nolint:staticcheck
configv1alpha1 "k8s.io/component-base/config/v1alpha1"
)

// BuiltInCertManagement is the configuration for the built-in facility to generate and rotate
Expand Down Expand Up @@ -142,14 +142,75 @@ const (
TLSProfileModernType TLSProfileType = "Modern"
)

// ControllerManagerConfigurationSpec defines the desired state of GenericControllerManagerConfiguration.
type ControllerManagerConfigurationSpec struct {
// LeaderElection is the LeaderElection config to be used when configuring
// the manager.Manager leader election
// +optional
LeaderElection *configv1alpha1.LeaderElectionConfiguration `json:"leaderElection,omitempty"`

// Metrics contains the controller metrics configuration
// +optional
Metrics ControllerMetrics `json:"metrics,omitempty"`

// Health contains the controller health configuration
// +optional
Health ControllerHealth `json:"health,omitempty"`

// Webhook contains the controllers webhook configuration
// +optional
Webhook ControllerWebhook `json:"webhook,omitempty"`
}

// ControllerMetrics defines the metrics configs.
type ControllerMetrics struct {
// BindAddress is the TCP address that the controller should bind to
// for serving prometheus metrics.
// It can be set to "0" to disable the metrics serving.
// +optional
BindAddress string `json:"bindAddress,omitempty"`
}

// ControllerHealth defines the health configs.
type ControllerHealth struct {
// HealthProbeBindAddress is the TCP address that the controller should bind to
// for serving health probes
// It can be set to "0" or "" to disable serving the health probe.
// +optional
HealthProbeBindAddress string `json:"healthProbeBindAddress,omitempty"`
}

// ControllerWebhook defines the webhook server for the controller.
type ControllerWebhook struct {
// Port is the port that the webhook server serves at.
// It is used to set webhook.Server.Port.
// +optional
Port *int `json:"port,omitempty"`
}

//+kubebuilder:object:root=true

// ControllerManagerConfiguration is the Schema for the GenericControllerManagerConfigurations API.
type ControllerManagerConfiguration struct {
metav1.TypeMeta `json:",inline"`

// ControllerManagerConfiguration returns the contfigurations for controllers
ControllerManagerConfigurationSpec `json:",inline"`
}

// Complete returns the configuration for controller-runtime.
func (c *ControllerManagerConfigurationSpec) Complete() (ControllerManagerConfigurationSpec, error) {
return *c, nil
}

//+kubebuilder:object:root=true

// ProjectConfig is the Schema for the projectconfigs API
type ProjectConfig struct {
metav1.TypeMeta `json:",inline"`

// ControllerManagerConfigurationSpec returns the contfigurations for controllers
cfg.ControllerManagerConfigurationSpec `json:",inline"`
ControllerManagerConfigurationSpec `json:",inline"`

Gates FeatureGates `json:"featureGates,omitempty"`
}
Expand Down
99 changes: 99 additions & 0 deletions operator/apis/config/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion operator/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ require (
k8s.io/apimachinery v0.27.7
k8s.io/apiserver v0.27.7
k8s.io/client-go v0.27.7
k8s.io/component-base v0.27.7
k8s.io/utils v0.0.0-20230505201702-9f6742963106
sigs.k8s.io/controller-runtime v0.15.3
sigs.k8s.io/yaml v1.3.0
Expand Down Expand Up @@ -150,7 +151,6 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.27.7 // indirect
k8s.io/component-base v0.27.7 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
Expand Down
98 changes: 98 additions & 0 deletions operator/internal/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package v1

import (
"errors"
"fmt"
"os"
"sync"

"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"

configv1 "github.com/grafana/loki/operator/apis/config/v1"
)

var (
errSchemeNotSupplied = errors.New("scheme not supplied to controller configuration loader")
errConfigFileLoading = errors.New("could not read file at path")
errRuntimeObjectDecoding = errors.New("could not decode file into runtime.Object")
)

// ControllerManagerConfiguration defines the functions necessary to parse a config file
// and to configure the Options struct for the ctrl.Manager.
type ControllerManagerConfiguration interface {
runtime.Object

// Complete returns the versioned configuration
Complete() (configv1.ControllerManagerConfigurationSpec, error)
}

// DeferredFileLoader is used to configure the decoder for loading controller
// runtime component config types.
type DeferredFileLoader struct {
ControllerManagerConfiguration
path string
scheme *runtime.Scheme
once sync.Once
err error
}

// File will set up the deferred file loader for the configuration
// this will also configure the defaults for the loader if nothing is
//
// Defaults:
// * Path: "./config.yaml"
// * Kind: GenericControllerManagerConfiguration
func File() *DeferredFileLoader {
scheme := runtime.NewScheme()
utilruntime.Must(configv1.AddToScheme(scheme))
return &DeferredFileLoader{
path: "./config.yaml",
ControllerManagerConfiguration: &configv1.ControllerManagerConfiguration{},
scheme: scheme,
}
}

// Complete will use sync.Once to set the scheme.
func (d *DeferredFileLoader) Complete() (configv1.ControllerManagerConfigurationSpec, error) {
d.once.Do(d.loadFile)
if d.err != nil {
return configv1.ControllerManagerConfigurationSpec{}, d.err
}
return d.ControllerManagerConfiguration.Complete()
}

// AtPath will set the path to load the file for the decoder.
func (d *DeferredFileLoader) AtPath(path string) *DeferredFileLoader {
d.path = path
return d
}

// OfKind will set the type to be used for decoding the file into.
func (d *DeferredFileLoader) OfKind(obj ControllerManagerConfiguration) *DeferredFileLoader {
d.ControllerManagerConfiguration = obj
return d
}

// loadFile is used from the mutex.Once to load the file.
func (d *DeferredFileLoader) loadFile() {
if d.scheme == nil {
d.err = errSchemeNotSupplied
return
}

content, err := os.ReadFile(d.path)
if err != nil {
d.err = fmt.Errorf("%w %s", errConfigFileLoading, d.path)
return
}

codecs := serializer.NewCodecFactory(d.scheme)

// Regardless of if the bytes are of any external version,
// it will be read successfully and converted into the internal version
if err = runtime.DecodeInto(codecs.UniversalDecoder(), content, d.ControllerManagerConfiguration); err != nil {
d.err = errRuntimeObjectDecoding
}
}
Loading

0 comments on commit 9c5ea9c

Please sign in to comment.