Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 23 additions & 8 deletions cmd/reference-addon-manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
refapis "github.com/openshift/reference-addon/apis"
"github.com/openshift/reference-addon/internal/controllers"
"github.com/openshift/reference-addon/internal/metrics"
opsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
)

var (
Expand All @@ -28,11 +29,18 @@ var (
func init() {
_ = clientgoscheme.AddToScheme(scheme)
_ = refapis.AddToScheme(scheme)
_ = opsv1alpha1.AddToScheme(scheme)

// Register metrics with the global Prometheus registry
metrics.RegisterMetrics()
}

const (
addonNamespace = "redhat-reference-addon"
operatorName = "reference-addon"
deleteLabel = "addon-reference-addon-delete"
)

func main() {
var (
metricsAddr string
Expand Down Expand Up @@ -113,19 +121,26 @@ func main() {
os.Exit(1)
}
// the following section hooks up a heartbeat reporter with the current addon/operator
r := controllers.ReferenceAddonReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("ReferenceAddon"),
Scheme: mgr.GetScheme(),
r, err := controllers.NewReferenceAddonReconciler(
mgr.GetClient(),
controllers.WithLog{Log: ctrl.Log.WithName("controllers").WithName("ReferenceAddon")},
controllers.WithAddonNamespace(addonNamespace),
controllers.WithOperatorName(operatorName),
controllers.WithDeleteLabel(deleteLabel),
)
if err != nil {
setupLog.Error(err, "unable to create controller", "controller", "ReferenceAddon")
os.Exit(1)
}

if err = r.SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "ReferenceAddon")
if err := r.SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to setup controller", "controller", "ReferenceAddon")
os.Exit(1)
}

// add sample metrics
metrics.RequestSampleResponseData()
// ensure at least one data point for sample metrics
sampler := metrics.NewResponseSamplerImpl()
sampler.RequestSampleResponseData("https://httpstat.us/503", "https://httpstat.us/200")

setupLog.Info("starting manager")
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
Expand Down
16 changes: 10 additions & 6 deletions e2e/e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"strings"
"testing"

opsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
Expand Down Expand Up @@ -47,23 +48,26 @@ var (

func init() {
// Client/Scheme setup.
err := clientgoscheme.AddToScheme(Scheme)
if err != nil {
if err := clientgoscheme.AddToScheme(Scheme); err != nil {
panic(err)
}

err = refapis.AddToScheme(Scheme)
if err != nil {
if err := refapis.AddToScheme(Scheme); err != nil {
panic(err)
}

err = apiextensionsv1.AddToScheme(Scheme)
if err != nil {
if err := apiextensionsv1.AddToScheme(Scheme); err != nil {
panic(err)
}

if err := opsv1alpha1.AddToScheme(Scheme); err != nil {
panic(err)
}

Config = ctrl.GetConfigOrDie()

var err error

Client, err = client.New(Config, client.Options{
Scheme: Scheme,
})
Expand Down
16 changes: 9 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ go 1.16

require (
github.com/go-logr/logr v0.4.0
github.com/prometheus/client_golang v1.7.1 // indirect
github.com/stretchr/testify v1.6.1
k8s.io/api v0.20.2
k8s.io/apiextensions-apiserver v0.20.1
k8s.io/apimachinery v0.21.1
k8s.io/client-go v0.20.2
sigs.k8s.io/controller-runtime v0.8.3
github.com/operator-framework/api v0.10.7
github.com/prometheus/client_golang v1.11.0
github.com/stretchr/testify v1.7.0
go.uber.org/multierr v1.6.0
k8s.io/api v0.22.1
k8s.io/apiextensions-apiserver v0.22.1
k8s.io/apimachinery v0.22.1
k8s.io/client-go v0.22.1
sigs.k8s.io/controller-runtime v0.10.0
sigs.k8s.io/yaml v1.2.0
)
493 changes: 403 additions & 90 deletions go.sum

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions internal/controllers/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package controllers

import "github.com/go-logr/logr"

type WithLog struct{ Log logr.Logger }

func (w WithLog) ConfigureReferenceAddonReconciler(c *ReferenceAddonReconcilerConfig) {
c.Log = w.Log
}

func (w WithLog) ConfigurePhaseSimulateReconciliation(c *PhaseSimulateReconciliationConfig) {
c.Log = w.Log
}

func (w WithLog) ConfigurePhaseUninstall(c *PhaseUninstallConfig) {
c.Log = w.Log
}

type WithAddonNamespace string

func (w WithAddonNamespace) ConfigureConfigMapUninstallSignaler(c *ConfigMapUninstallSignalerConfig) {
c.AddonNamespace = string(w)
}

func (w WithAddonNamespace) ConfigureReferenceAddonReconciler(c *ReferenceAddonReconcilerConfig) {
c.AddonNamespace = string(w)
}

func (w WithAddonNamespace) ConfigurePhaseUninstall(c *PhaseUninstallConfig) {
c.AddonNamespace = string(w)
}

type WithOperatorName string

func (w WithOperatorName) ConfigureConfigMapUninstallSignaler(c *ConfigMapUninstallSignalerConfig) {
c.OperatorName = string(w)
}

func (w WithOperatorName) ConfigurePhaseUninstall(c *PhaseUninstallConfig) {
c.OperatorName = string(w)
}

func (w WithOperatorName) ConfigureReferenceAddonReconciler(c *ReferenceAddonReconcilerConfig) {
c.OperatorName = string(w)
}

type WithDeleteLabel string

func (w WithDeleteLabel) ConfigureConfigMapUninstallSignaler(c *ConfigMapUninstallSignalerConfig) {
c.DeleteLabel = string(w)
}

func (w WithDeleteLabel) ConfigureReferenceAddonReconciler(c *ReferenceAddonReconcilerConfig) {
c.DeleteLabel = string(w)
}

type WithNamespace string

func (w WithNamespace) ConfigureListCSVs(c *ListCSVsConfig) {
c.Namespace = string(w)
}

type WithPrefix string

func (w WithPrefix) ConfigureListCSVs(c *ListCSVsConfig) {
c.Prefix = string(w)
}

type WithSampleURLs []string

func (w WithSampleURLs) ConfigurePhaseSendDummyMetrics(c *PhaseSendDummyMetricsConfig) {
c.SampleURLs = []string(w)
}
73 changes: 73 additions & 0 deletions internal/controllers/phase/phase.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package phase

import (
"context"

"k8s.io/apimachinery/pkg/types"
)

type Phase interface {
Execute(ctx context.Context, req Request) Result
}

type Request struct {
Object types.NamespacedName
}

func Success() Result {
return Result{
status: StatusSuccess,
}
}

func Blocking() Result {
return Result{
status: StatusSuccess,
blocking: true,
}
}

func Failure(msg string) Result {
return Result{
status: StatusFailure,
failureMsg: msg,
}
}

func Error(err error) Result {
return Result{
status: StatusError,
err: err,
}
}

type Result struct {
err error
failureMsg string
status Status
blocking bool
}

func (r Result) IsSuccess() bool {
return r.status == StatusSuccess
}

func (r Result) IsBlocking() bool {
return r.blocking
}

func (r Result) FailureMessage() string {
return r.failureMsg
}

func (r Result) Error() error {
return r.err
}

type Status string

const (
StatusSuccess = "success"
StatusFailure = "failure"
StatusError = "error"
)
49 changes: 49 additions & 0 deletions internal/controllers/phase_send_dummy_metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package controllers

import (
"context"

"github.com/openshift/reference-addon/internal/controllers/phase"
)

func NewPhaseSendDummyMetrics(sampler ResponseSampler, opts ...PhaseSendDummyMetricsOption) *PhaseSendDummyMetrics {
var cfg PhaseSendDummyMetricsConfig

cfg.Option(opts...)

return &PhaseSendDummyMetrics{
cfg: cfg,

sampler: sampler,
}
}

type PhaseSendDummyMetrics struct {
cfg PhaseSendDummyMetricsConfig

sampler ResponseSampler
}

func (p *PhaseSendDummyMetrics) Execute(ctx context.Context, req phase.Request) phase.Result {
p.sampler.RequestSampleResponseData(p.cfg.SampleURLs...)

return phase.Success()
}

type PhaseSendDummyMetricsConfig struct {
SampleURLs []string
}

func (c *PhaseSendDummyMetricsConfig) Option(opts ...PhaseSendDummyMetricsOption) {
for _, opt := range opts {
opt.ConfigurePhaseSendDummyMetrics(c)
}
}

type PhaseSendDummyMetricsOption interface {
ConfigurePhaseSendDummyMetrics(*PhaseSendDummyMetricsConfig)
}

type ResponseSampler interface {
RequestSampleResponseData(urls ...string)
}
67 changes: 67 additions & 0 deletions internal/controllers/phase_send_dummy_metrics_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package controllers

import (
"context"
"testing"

"github.com/openshift/reference-addon/internal/controllers/phase"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)

func TestPhaseSendDummyMetricsInterface(t *testing.T) {
t.Parallel()

require.Implements(t, new(phase.Phase), new(PhaseSendDummyMetrics))
}

func TestPhaseSendDummyMetrics(t *testing.T) {
t.Parallel()

for name, tc := range map[string]struct {
SampleURLs []string
}{
"happy path": {
SampleURLs: []string{"https://fake.io"},
},
} {
tc := tc

t.Run(name, func(t *testing.T) {
t.Parallel()

argList := make([]interface{}, 0, len(tc.SampleURLs))

for _, url := range tc.SampleURLs {
argList = append(argList, url)
}

var sampler ResponseSamplerMock
sampler.
On("RequestSampleResponseData", argList...).
Return()

p := NewPhaseSendDummyMetrics(&sampler, WithSampleURLs(tc.SampleURLs))

res := p.Execute(context.Background(), phase.Request{})
require.NoError(t, res.Error())

assert.True(t, res.IsSuccess())
})
}
}

type ResponseSamplerMock struct {
mock.Mock
}

func (r *ResponseSamplerMock) RequestSampleResponseData(urls ...string) {
argList := make([]interface{}, 0, len(urls))

for _, url := range urls {
argList = append(argList, url)
}

r.Called(argList...)
}
Loading