R.B. Boyer 6742340878
mesh: add ComputedImplicitDestinations resource for future use (#20547)
Creates a new controller to create ComputedImplicitDestinations resources by 
composing ComputedRoutes, Services, and ComputedTrafficPermissions to 
infer all ParentRef services that could possibly send some portion of traffic to a 
Service that has at least one accessible Workload Identity. A followup PR will 
rewire the sidecar controller to make use of this new resource.

As this is a performance optimization, rather than a security feature the following 
aspects of traffic permissions have been ignored:

- DENY rules
- port rules (all ports are allowed)

Also:

- Add some v2 TestController machinery to help test complex dependency mappers.
2024-02-09 15:42:10 -06:00

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)
}