consul/internal/controller/testing.go

80 lines
2.8 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package controller
import (
"context"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/consul/internal/controller/cache"
"github.com/hashicorp/consul/proto-public/pbresource"
)
// TestController is most useful when writing unit tests for a controller where
// individual Reconcile calls need to be made instead of having a Manager
// execute the controller in response to watch events.
//
// TODO(controller-testing) Ideally this would live within the controllertest
// package. However it makes light use of unexported fields on the Controller
// and therefore cannot live in another package without more refactorings
// to have the Controller include a config struct of sorts defined in an
// internal package with exported fields. For now this seems fine.
type TestController struct {
c *Controller
cache cache.Cache
client pbresource.ResourceServiceClient
logger hclog.Logger
}
// NewTestController will create a new TestController from the provided Controller
// and ResourceServiceClient. The test controller will build the controllers
// cache with the configured indexes and will maintain the cached state in response
// to Write, WriteStatus and Delete calls made on the wrapped ResourceServiceClient.
// Call the Runtime() method to get at the wrapped client.
func NewTestController(ctl *Controller, client pbresource.ResourceServiceClient) *TestController {
ctlCache := ctl.buildCache()
return &TestController{
c: ctl,
cache: ctlCache,
client: cache.NewCachedClient(ctlCache, client),
logger: ctl.buildLogger(hclog.NewNullLogger()),
}
}
func (tc *TestController) WithLogger(logger hclog.Logger) *TestController {
tc.logger = tc.c.buildLogger(logger)
return tc
}
// Reconcile invokes the controllers configured reconciler with the cache enabled Runtime
func (tc *TestController) Reconcile(ctx context.Context, req Request) error {
return tc.c.reconciler.Reconcile(ctx, tc.Runtime(), req)
}
// Reconciler returns the controllers configured reconciler
func (tc *TestController) Reconciler() Reconciler {
return tc.c.reconciler
}
// Runtime returns the Runtime that should be used for calls to reconcile or to perform
// operations that would also affect the managed cache.
func (tc *TestController) Runtime() Runtime {
return Runtime{
Client: tc.client,
Logger: tc.logger,
Cache: tc.cache,
}
}
// DryRunMapper will trigger the appropriate DependencyMapper for an update of
// the provided type and return the requested reconciles.
//
// Useful for testing just the DependencyMapper+Cache interactions for chains
// that are more complicated than just a full controller interaction test would
// be able to easily verify.
func (tc *TestController) DryRunMapper(ctx context.Context, res *pbresource.Resource) ([]Request, error) {
return tc.c.dryRunMapper(ctx, tc.Runtime(), res)
}