Skip to content

Commit

Permalink
clean up types, add unit tests
Browse files Browse the repository at this point in the history
Signed-off-by: Florian Bacher <[email protected]>
  • Loading branch information
bacherfl committed May 7, 2024
1 parent bfa890b commit f5f580a
Show file tree
Hide file tree
Showing 16 changed files with 710 additions and 229 deletions.
14 changes: 14 additions & 0 deletions controllers/core/flagd/common/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package resources

type FlagdConfiguration struct {
FlagdPort int
OFREPPort int
SyncPort int
ManagementPort int
DebugLogging bool
Image string
Tag string

OperatorNamespace string
OperatorDeploymentName string
}
18 changes: 3 additions & 15 deletions controllers/core/flagd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,11 @@ package flagd
import (
"github.com/open-feature/open-feature-operator/common"
"github.com/open-feature/open-feature-operator/common/types"
"github.com/open-feature/open-feature-operator/controllers/core/flagd/common"
)

type FlagdConfiguration struct {
FlagdPort int
OFREPPort int
SyncPort int
ManagementPort int
DebugLogging bool
Image string
Tag string

OperatorNamespace string
OperatorDeploymentName string
}

func NewFlagdConfiguration(env types.EnvConfig) FlagdConfiguration {
return FlagdConfiguration{
func NewFlagdConfiguration(env types.EnvConfig) resources.FlagdConfiguration {
return resources.FlagdConfiguration{
Image: env.FlagdImage,
Tag: env.FlagdTag,
OperatorDeploymentName: common.OperatorDeploymentName,
Expand Down
40 changes: 31 additions & 9 deletions controllers/core/flagd/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ import (
"fmt"
"github.com/go-logr/logr"
api "github.com/open-feature/open-feature-operator/apis/core/v1beta1"
resources2 "github.com/open-feature/open-feature-operator/controllers/core/flagd/common"
"github.com/open-feature/open-feature-operator/controllers/core/flagd/resources"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
Expand All @@ -33,15 +38,17 @@ type FlagdReconciler struct {
Scheme *runtime.Scheme
Log logr.Logger

FlagdConfig FlagdConfiguration
FlagdConfig resources2.FlagdConfiguration

FlagdDeployment IFlagdResource
FlagdService IFlagdResource
FlagdIngress IFlagdResource
ResourceReconciler IFlagdResourceReconciler

FlagdDeployment resources.IFlagdResource
FlagdService resources.IFlagdResource
FlagdIngress resources.IFlagdResource
}

type IFlagdResource interface {
Reconcile(ctx context.Context, flagd *api.Flagd) error
type IFlagdResourceReconciler interface {
Reconcile(ctx context.Context, flagd *api.Flagd, obj client.Object, resource resources.IFlagdResource) error
}

//+kubebuilder:rbac:groups=core.openfeature.dev,resources=flagds,verbs=get;list;watch;create;update;patch;delete
Expand Down Expand Up @@ -72,15 +79,30 @@ func (r *FlagdReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
return ctrl.Result{}, err
}

if err := r.FlagdDeployment.Reconcile(ctx, flagd); err != nil {
if err := r.ResourceReconciler.Reconcile(
ctx,
flagd,
&appsv1.Deployment{},
r.FlagdDeployment,
); err != nil {
return ctrl.Result{}, err
}

if err := r.FlagdService.Reconcile(ctx, flagd); err != nil {
if err := r.ResourceReconciler.Reconcile(
ctx,
flagd,
&v1.Service{},
r.FlagdService,
); err != nil {
return ctrl.Result{}, err
}

if err := r.FlagdIngress.Reconcile(ctx, flagd); err != nil {
if err := r.ResourceReconciler.Reconcile(
ctx,
flagd,
&networkingv1.Ingress{},
r.FlagdIngress,
); err != nil {
return ctrl.Result{}, err
}

Expand Down
147 changes: 109 additions & 38 deletions controllers/core/flagd/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ import (
"fmt"
"github.com/golang/mock/gomock"
api "github.com/open-feature/open-feature-operator/apis/core/v1beta1"
"github.com/open-feature/open-feature-operator/controllers/core/flagd/common"
commonmock "github.com/open-feature/open-feature-operator/controllers/core/flagd/mock"
resourcemock "github.com/open-feature/open-feature-operator/controllers/core/flagd/resources/mock"
"github.com/stretchr/testify/require"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/scheme"
Expand All @@ -18,7 +23,7 @@ import (
"testing"
)

var testFlagdConfig = FlagdConfiguration{
var testFlagdConfig = resources.FlagdConfiguration{
FlagdPort: 8013,
OFREPPort: 8016,
ManagementPort: 8014,
Expand Down Expand Up @@ -62,16 +67,37 @@ func TestFlagdReconciler_Reconcile(t *testing.T) {

ctrl := gomock.NewController(t)

deploymentReconciler := commonmock.NewMockIFlagdResource(ctrl)
serviceReconciler := commonmock.NewMockIFlagdResource(ctrl)
ingressReconciler := commonmock.NewMockIFlagdResource(ctrl)

// deployment creation succeeds
deploymentReconciler.EXPECT().Reconcile(gomock.Any(), flagdMatcher{flagdObj: *flagdObj}).Times(1).Return(nil)
serviceReconciler.EXPECT().Reconcile(gomock.Any(), flagdMatcher{flagdObj: *flagdObj}).Times(1).Return(nil)
ingressReconciler.EXPECT().Reconcile(gomock.Any(), flagdMatcher{flagdObj: *flagdObj}).Times(1).Return(nil)

r := setupReconciler(fakeClient, deploymentReconciler, serviceReconciler, ingressReconciler)
deploymentResource := resourcemock.NewMockIFlagdResource(ctrl)
serviceResource := resourcemock.NewMockIFlagdResource(ctrl)
ingressResource := resourcemock.NewMockIFlagdResource(ctrl)

resourceReconciler := commonmock.NewMockIFlagdResourceReconciler(ctrl)

resourceReconciler.EXPECT().
Reconcile(
gomock.Any(),
flagdMatcher{flagdObj: *flagdObj},
gomock.AssignableToTypeOf(&appsv1.Deployment{}),
deploymentResource,
).Times(1).Return(nil)

resourceReconciler.EXPECT().
Reconcile(
gomock.Any(),
flagdMatcher{flagdObj: *flagdObj},
gomock.AssignableToTypeOf(&v1.Service{}),
serviceResource,
).Times(1).Return(nil)

resourceReconciler.EXPECT().
Reconcile(
gomock.Any(),
flagdMatcher{flagdObj: *flagdObj},
gomock.AssignableToTypeOf(&networkingv1.Ingress{}),
ingressResource,
).Times(1).Return(nil)

r := setupReconciler(fakeClient, deploymentResource, serviceResource, ingressResource, resourceReconciler)

result, err := r.Reconcile(context.Background(), controllerruntime.Request{
NamespacedName: types.NamespacedName{
Expand All @@ -90,7 +116,7 @@ func TestFlagdReconciler_ReconcileResourceNotFound(t *testing.T) {

fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects().Build()

r := setupReconciler(fakeClient, nil, nil, nil)
r := setupReconciler(fakeClient, nil, nil, nil, nil)

result, err := r.Reconcile(context.Background(), controllerruntime.Request{
NamespacedName: types.NamespacedName{
Expand Down Expand Up @@ -119,12 +145,19 @@ func TestFlagdReconciler_ReconcileFailDeployment(t *testing.T) {

ctrl := gomock.NewController(t)

deploymentReconciler := commonmock.NewMockIFlagdResource(ctrl)
deploymentResource := resourcemock.NewMockIFlagdResource(ctrl)

// deployment creation succeeds
deploymentReconciler.EXPECT().Reconcile(gomock.Any(), flagdMatcher{flagdObj: *flagdObj}).Times(1).Return(errors.New("oops"))
resourceReconciler := commonmock.NewMockIFlagdResourceReconciler(ctrl)

r := setupReconciler(fakeClient, deploymentReconciler, nil, nil)
resourceReconciler.EXPECT().
Reconcile(
gomock.Any(),
flagdMatcher{flagdObj: *flagdObj},
gomock.AssignableToTypeOf(&appsv1.Deployment{}),
deploymentResource,
).Times(1).Return(errors.New("oops"))

r := setupReconciler(fakeClient, deploymentResource, nil, nil, resourceReconciler)

result, err := r.Reconcile(context.Background(), controllerruntime.Request{
NamespacedName: types.NamespacedName{
Expand Down Expand Up @@ -153,13 +186,28 @@ func TestFlagdReconciler_ReconcileFailService(t *testing.T) {

ctrl := gomock.NewController(t)

deploymentReconciler := commonmock.NewMockIFlagdResource(ctrl)
serviceReconciler := commonmock.NewMockIFlagdResource(ctrl)
deploymentResource := resourcemock.NewMockIFlagdResource(ctrl)
serviceResource := resourcemock.NewMockIFlagdResource(ctrl)

resourceReconciler := commonmock.NewMockIFlagdResourceReconciler(ctrl)

deploymentReconciler.EXPECT().Reconcile(gomock.Any(), flagdMatcher{flagdObj: *flagdObj}).Times(1).Return(nil)
serviceReconciler.EXPECT().Reconcile(gomock.Any(), flagdMatcher{flagdObj: *flagdObj}).Times(1).Return(errors.New("oops"))
resourceReconciler.EXPECT().
Reconcile(
gomock.Any(),
flagdMatcher{flagdObj: *flagdObj},
gomock.AssignableToTypeOf(&appsv1.Deployment{}),
deploymentResource,
).Times(1).Return(nil)

r := setupReconciler(fakeClient, deploymentReconciler, serviceReconciler, nil)
resourceReconciler.EXPECT().
Reconcile(
gomock.Any(),
flagdMatcher{flagdObj: *flagdObj},
gomock.AssignableToTypeOf(&v1.Service{}),
serviceResource,
).Times(1).Return(errors.New("oops"))

r := setupReconciler(fakeClient, deploymentResource, serviceResource, nil, resourceReconciler)

result, err := r.Reconcile(context.Background(), controllerruntime.Request{
NamespacedName: types.NamespacedName{
Expand Down Expand Up @@ -188,15 +236,37 @@ func TestFlagdReconciler_ReconcileFailIngress(t *testing.T) {

ctrl := gomock.NewController(t)

deploymentReconciler := commonmock.NewMockIFlagdResource(ctrl)
serviceReconciler := commonmock.NewMockIFlagdResource(ctrl)
ingressReconciler := commonmock.NewMockIFlagdResource(ctrl)

deploymentReconciler.EXPECT().Reconcile(gomock.Any(), flagdMatcher{flagdObj: *flagdObj}).Times(1).Return(nil)
serviceReconciler.EXPECT().Reconcile(gomock.Any(), flagdMatcher{flagdObj: *flagdObj}).Times(1).Return(nil)
ingressReconciler.EXPECT().Reconcile(gomock.Any(), flagdMatcher{flagdObj: *flagdObj}).Times(1).Return(errors.New("oops"))

r := setupReconciler(fakeClient, deploymentReconciler, serviceReconciler, ingressReconciler)
deploymentResource := resourcemock.NewMockIFlagdResource(ctrl)
serviceResource := resourcemock.NewMockIFlagdResource(ctrl)
ingressResource := resourcemock.NewMockIFlagdResource(ctrl)

resourceReconciler := commonmock.NewMockIFlagdResourceReconciler(ctrl)

resourceReconciler.EXPECT().
Reconcile(
gomock.Any(),
flagdMatcher{flagdObj: *flagdObj},
gomock.AssignableToTypeOf(&appsv1.Deployment{}),
deploymentResource,
).Times(1).Return(nil)

resourceReconciler.EXPECT().
Reconcile(
gomock.Any(),
flagdMatcher{flagdObj: *flagdObj},
gomock.AssignableToTypeOf(&v1.Service{}),
serviceResource,
).Times(1).Return(nil)

resourceReconciler.EXPECT().
Reconcile(
gomock.Any(),
flagdMatcher{flagdObj: *flagdObj},
gomock.AssignableToTypeOf(&networkingv1.Ingress{}),
ingressResource,
).Times(1).Return(errors.New("oops"))

r := setupReconciler(fakeClient, deploymentResource, serviceResource, ingressResource, resourceReconciler)

result, err := r.Reconcile(context.Background(), controllerruntime.Request{
NamespacedName: types.NamespacedName{
Expand All @@ -209,14 +279,15 @@ func TestFlagdReconciler_ReconcileFailIngress(t *testing.T) {
require.Equal(t, controllerruntime.Result{}, result)
}

func setupReconciler(fakeClient client.WithWatch, deploymentReconciler *commonmock.MockIFlagdResource, serviceReconciler *commonmock.MockIFlagdResource, ingressReconciler *commonmock.MockIFlagdResource) *FlagdReconciler {
func setupReconciler(fakeClient client.WithWatch, deploymentReconciler, serviceReconciler, ingressReconciler *resourcemock.MockIFlagdResource, resourceReconciler *commonmock.MockIFlagdResourceReconciler) *FlagdReconciler {
return &FlagdReconciler{
Client: fakeClient,
Scheme: fakeClient.Scheme(),
Log: controllerruntime.Log.WithName("flagd controller"),
FlagdConfig: testFlagdConfig,
FlagdDeployment: deploymentReconciler,
FlagdService: serviceReconciler,
FlagdIngress: ingressReconciler,
Client: fakeClient,
Scheme: fakeClient.Scheme(),
Log: controllerruntime.Log.WithName("flagd controller"),
FlagdConfig: testFlagdConfig,
FlagdDeployment: deploymentReconciler,
FlagdService: serviceReconciler,
FlagdIngress: ingressReconciler,
ResourceReconciler: resourceReconciler,
}
}
32 changes: 17 additions & 15 deletions controllers/core/flagd/mock/mock.go

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

Loading

0 comments on commit f5f580a

Please sign in to comment.