Skip to content

Commit

Permalink
Adapt reconcile (#76)
Browse files Browse the repository at this point in the history
  • Loading branch information
dstiliadis authored Apr 13, 2019
1 parent 08c7b06 commit 63fafb4
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 35 deletions.
20 changes: 13 additions & 7 deletions manipvortex/manipulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,13 +406,16 @@ func (m *vortexManipulator) shouldProcess(mctx manipulate.Context, identity elem
// return the upstream error.
func (m *vortexManipulator) commitUpstream(ctx context.Context, operation elemental.Operation, mctx manipulate.Context, object elemental.Identifiable) error {

var reconcile bool
var err error

if m.upstreamManipulator == nil {
return nil
}

// If we have an accepter, we see if it accepts the write
if m.upstreamReconciler != nil {
reconcile, err := m.upstreamReconciler.Reconcile(mctx, operation, object)
object, reconcile, err = m.upstreamReconciler.Reconcile(mctx, operation, object)
if err != nil {
return err
}
Expand All @@ -424,11 +427,11 @@ func (m *vortexManipulator) commitUpstream(ctx context.Context, operation elemen
// If it is managed object we apply the pre-hook.
cfg, ok := m.processors[object.Identity().Name]
if ok && cfg.UpstreamReconciler != nil {
accept, err := cfg.UpstreamReconciler.Reconcile(mctx, operation, object)
object, reconcile, err = cfg.UpstreamReconciler.Reconcile(mctx, operation, object)
if err != nil {
return err
}
if !accept {
if !reconcile {
return nil
}
}
Expand All @@ -452,17 +455,20 @@ func (m *vortexManipulator) commitUpstream(ctx context.Context, operation elemen
// fail for some reason.
func (m *vortexManipulator) commitLocal(operation elemental.Operation, mctx manipulate.Context, object elemental.Identifiable) error {

var reconcile bool
var err error

if mctx == nil {
mctx = manipulate.NewContext(context.Background())
}

// If we have a global Reconciler, we see if it accepts the write.
if m.downstreamReconciler != nil {
accept, err := m.downstreamReconciler.Reconcile(mctx, operation, object)
object, reconcile, err = m.downstreamReconciler.Reconcile(mctx, operation, object)
if err != nil {
return err
}
if !accept {
if !reconcile {
return nil
}
}
Expand All @@ -474,11 +480,11 @@ func (m *vortexManipulator) commitLocal(operation elemental.Operation, mctx mani

// If we have a processor Reconciler, we see if it accepts the write.
if cfg.DownstreamReconciler != nil {
accept, err := cfg.DownstreamReconciler.Reconcile(mctx, operation, object)
object, reconcile, err = cfg.DownstreamReconciler.Reconcile(mctx, operation, object)
if err != nil {
return err
}
if !accept {
if !reconcile {
return nil
}
}
Expand Down
34 changes: 17 additions & 17 deletions manipvortex/manipulator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,11 +476,11 @@ func Test_Create(t *testing.T) {

objConfig := v.(*vortexManipulator).processors[testmodel.ListIdentity.Name]
objConfig.UpstreamReconciler = NewTestReconciler()
objConfig.UpstreamReconciler.(TestReconciler).MockReconcile(t, func(mctx manipulate.Context, op elemental.Operation, i ...elemental.Identifiable) (bool, error) {
objConfig.UpstreamReconciler.(TestReconciler).MockReconcile(t, func(mctx manipulate.Context, op elemental.Operation, i elemental.Identifiable) (elemental.Identifiable, bool, error) {
if mctx.Parent() != nil {
return false, nil
return i, false, nil
}
return true, nil
return i, true, nil
})

Convey("When I create objects", func() {
Expand Down Expand Up @@ -508,8 +508,8 @@ func Test_Create(t *testing.T) {

Convey("When the backend succeeds, the object must not be stored in the DB if accepter did not accept", func() {

a.MockReconcile(t, func(manipulate.Context, elemental.Operation, ...elemental.Identifiable) (bool, error) {
return false, nil
a.MockReconcile(t, func(manipulate.Context, elemental.Operation, elemental.Identifiable) (elemental.Identifiable, bool, error) {
return nil, false, nil
})

m.MockCreate(t, func(mctx manipulate.Context, object elemental.Identifiable) error {
Expand Down Expand Up @@ -598,11 +598,11 @@ func Test_Update(t *testing.T) {

objConfig := v.(*vortexManipulator).processors[testmodel.ListIdentity.Name]
objConfig.UpstreamReconciler = NewTestReconciler()
objConfig.UpstreamReconciler.(TestReconciler).MockReconcile(t, func(mctx manipulate.Context, op elemental.Operation, i ...elemental.Identifiable) (bool, error) {
objConfig.UpstreamReconciler.(TestReconciler).MockReconcile(t, func(mctx manipulate.Context, op elemental.Operation, i elemental.Identifiable) (elemental.Identifiable, bool, error) {
if mctx.Parent() != nil {
return false, nil
return i, false, nil
}
return true, nil
return i, true, nil
})

obj := newObject("obj1", []string{"label"})
Expand Down Expand Up @@ -640,8 +640,8 @@ func Test_Update(t *testing.T) {

Convey("When the backend succeeds, the object must not be stored in the DB if accepter did not accept", func() {

a.MockReconcile(t, func(manipulate.Context, elemental.Operation, ...elemental.Identifiable) (bool, error) {
return false, nil
a.MockReconcile(t, func(ctx manipulate.Context, op elemental.Operation, obj elemental.Identifiable) (elemental.Identifiable, bool, error) {
return obj, false, nil
})

m.MockUpdate(t, func(mctx manipulate.Context, object elemental.Identifiable) error {
Expand Down Expand Up @@ -730,11 +730,11 @@ func Test_Delete(t *testing.T) {

objConfig := v.(*vortexManipulator).processors[testmodel.ListIdentity.Name]
objConfig.UpstreamReconciler = NewTestReconciler()
objConfig.UpstreamReconciler.(TestReconciler).MockReconcile(t, func(mctx manipulate.Context, op elemental.Operation, i ...elemental.Identifiable) (bool, error) {
objConfig.UpstreamReconciler.(TestReconciler).MockReconcile(t, func(mctx manipulate.Context, op elemental.Operation, i elemental.Identifiable) (elemental.Identifiable, bool, error) {
if mctx.Parent() != nil {
return false, nil
return i, false, nil
}
return true, nil
return i, true, nil
})

obj := newObject("obj1", []string{"label"})
Expand Down Expand Up @@ -770,8 +770,8 @@ func Test_Delete(t *testing.T) {

Convey("When the backend succeeds, the object must not be deleted in the DB if accepter did not accept", func() {

a.MockReconcile(t, func(manipulate.Context, elemental.Operation, ...elemental.Identifiable) (bool, error) {
return false, nil
a.MockReconcile(t, func(_ manipulate.Context, _ elemental.Operation, obj elemental.Identifiable) (elemental.Identifiable, bool, error) {
return obj, false, nil
})

m.MockDelete(t, func(mctx manipulate.Context, object elemental.Identifiable) error {
Expand Down Expand Up @@ -1186,8 +1186,8 @@ func Test_Monitor(t *testing.T) {

Convey("When I push a create event, the object must not be written in the DB when accepter rejects it", func() {

a.MockReconcile(t, func(manipulate.Context, elemental.Operation, ...elemental.Identifiable) (bool, error) {
return false, nil
a.MockReconcile(t, func(_ manipulate.Context, _ elemental.Operation, obj elemental.Identifiable) (elemental.Identifiable, bool, error) {
return obj, false, nil
})

obj := newObject("push1", []string{"test=push"})
Expand Down
14 changes: 7 additions & 7 deletions manipvortex/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ type Reconciler interface {
// false, the objects are ignored.
// If it returns an error, the error will be forwarded to the caller.
// The Reconcile function may modify the objects to perform transformations.
Reconcile(manipulate.Context, elemental.Operation, ...elemental.Identifiable) (bool, error)
Reconcile(manipulate.Context, elemental.Operation, elemental.Identifiable) (elemental.Identifiable, bool, error)
}

// A TestReconciler is an Reconciler that can be used for
// testing purposes.
type TestReconciler interface {
Reconciler
MockReconcile(t *testing.T, impl func(manipulate.Context, elemental.Operation, ...elemental.Identifiable) (bool, error))
MockReconcile(t *testing.T, impl func(manipulate.Context, elemental.Operation, elemental.Identifiable) (elemental.Identifiable, bool, error))
}

type mockedReconcilerMethods struct {
reconcileMock func(manipulate.Context, elemental.Operation, ...elemental.Identifiable) (bool, error)
reconcileMock func(manipulate.Context, elemental.Operation, elemental.Identifiable) (elemental.Identifiable, bool, error)
}

type testReconciler struct {
Expand All @@ -46,16 +46,16 @@ func NewTestReconciler() TestReconciler {
}

// MockPrefetch sets the mocked implementation of Reconcile.
func (p *testReconciler) MockReconcile(t *testing.T, impl func(manipulate.Context, elemental.Operation, ...elemental.Identifiable) (bool, error)) {
func (p *testReconciler) MockReconcile(t *testing.T, impl func(manipulate.Context, elemental.Operation, elemental.Identifiable) (elemental.Identifiable, bool, error)) {
p.currentMocks(t).reconcileMock = impl
}

func (p *testReconciler) Reconcile(mctx manipulate.Context, op elemental.Operation, i ...elemental.Identifiable) (bool, error) {
func (p *testReconciler) Reconcile(mctx manipulate.Context, op elemental.Operation, i elemental.Identifiable) (elemental.Identifiable, bool, error) {
if mock := p.currentMocks(p.currentTest); mock != nil && mock.reconcileMock != nil {
return mock.reconcileMock(mctx, op, i...)
return mock.reconcileMock(mctx, op, i)
}

return true, nil
return i, true, nil
}

func (p *testReconciler) currentMocks(t *testing.T) *mockedReconcilerMethods {
Expand Down
17 changes: 13 additions & 4 deletions manipvortex/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func TestTestReconciler(t *testing.T) {

Convey("When I call the Accept method without mock", func() {

ok, err := r.Reconcile(manipulate.NewContext(context.Background()), elemental.OperationCreate, nil)
obj, ok, err := r.Reconcile(manipulate.NewContext(context.Background()), elemental.OperationCreate, nil)

Convey("Then err should be nil", func() {
So(err, ShouldBeNil)
Expand All @@ -33,15 +33,19 @@ func TestTestReconciler(t *testing.T) {
Convey("Then ok should be true", func() {
So(ok, ShouldBeTrue)
})

Convey("The object should be nil", func() {
So(obj, ShouldBeNil)
})
})

Convey("When I call the Accept method with a mock", func() {

r.MockReconcile(t, func(manipulate.Context, elemental.Operation, ...elemental.Identifiable) (bool, error) {
return false, fmt.Errorf("boom")
r.MockReconcile(t, func(_ manipulate.Context, _ elemental.Operation, obj elemental.Identifiable) (elemental.Identifiable, bool, error) {
return obj, false, fmt.Errorf("boom")
})

ok, err := r.Reconcile(manipulate.NewContext(context.Background()), elemental.OperationCreate, nil)
obj, ok, err := r.Reconcile(manipulate.NewContext(context.Background()), elemental.OperationCreate, nil)

Convey("Then err should not be nil", func() {
So(err, ShouldNotBeNil)
Expand All @@ -51,6 +55,11 @@ func TestTestReconciler(t *testing.T) {
Convey("Then ok should be false", func() {
So(ok, ShouldBeFalse)
})

Convey("The object should be nil", func() {
So(obj, ShouldBeNil)
})

})
})
}

0 comments on commit 63fafb4

Please sign in to comment.