Skip to content

Commit

Permalink
Pass allow loops option from controller creation all the way down to …
Browse files Browse the repository at this point in the history
…the topology builder

Signed-off-by: Jim Fitzpatrick <[email protected]>
  • Loading branch information
Boomatang committed Sep 6, 2024
1 parent 0e333ca commit e24369f
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 30 deletions.
71 changes: 42 additions & 29 deletions controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ import (
)

type ControllerOptions struct {
name string
logger logr.Logger
client *dynamic.DynamicClient
manager ctrlruntime.Manager
runnables map[string]RunnableBuilder
reconcile ReconcileFunc
policyKinds []schema.GroupKind
objectKinds []schema.GroupKind
objectLinks []LinkFunc
name string
logger logr.Logger
client *dynamic.DynamicClient
manager ctrlruntime.Manager
runnables map[string]RunnableBuilder
reconcile ReconcileFunc
policyKinds []schema.GroupKind
objectKinds []schema.GroupKind
objectLinks []LinkFunc
allowTopologyLoops bool
}

type ControllerOption func(*ControllerOptions)
Expand Down Expand Up @@ -94,6 +95,12 @@ func ManagedBy(manager ctrlruntime.Manager) ControllerOption {
}
}

func AllowLoops() ControllerOption {
return func(o *ControllerOptions) {
o.allowTopologyLoops = true
}
}

func NewController(f ...ControllerOption) *Controller {
opts := &ControllerOptions{
name: "controller",
Expand All @@ -107,14 +114,15 @@ func NewController(f ...ControllerOption) *Controller {
}

controller := &Controller{
name: opts.name,
logger: opts.logger,
client: opts.client,
manager: opts.manager,
cache: &watchableCacheStore{},
topology: newGatewayAPITopologyBuilder(opts.policyKinds, opts.objectKinds, opts.objectLinks),
runnables: map[string]Runnable{},
reconcile: opts.reconcile,
name: opts.name,
logger: opts.logger,
client: opts.client,
manager: opts.manager,
cache: &watchableCacheStore{},
topology: newGatewayAPITopologyBuilder(opts.policyKinds, opts.objectKinds, opts.objectLinks),
runnables: map[string]Runnable{},
reconcile: opts.reconcile,
allowTopologyLoops: opts.allowTopologyLoops,
}

for name, builder := range opts.runnables {
Expand All @@ -129,16 +137,17 @@ type WatchFunc func(ctrlruntime.Manager) ctrlruntimesrc.Source

type Controller struct {
sync.Mutex
name string
logger logr.Logger
client *dynamic.DynamicClient
manager ctrlruntime.Manager
cache Cache
topology *gatewayAPITopologyBuilder
runnables map[string]Runnable
listFuncs []ListFunc
watchFuncs []WatchFunc
reconcile ReconcileFunc
name string
logger logr.Logger
client *dynamic.DynamicClient
manager ctrlruntime.Manager
cache Cache
topology *gatewayAPITopologyBuilder
runnables map[string]Runnable
listFuncs []ListFunc
watchFuncs []WatchFunc
reconcile ReconcileFunc
allowTopologyLoops bool
}

// Start starts the runnables and blocks until the context is cancelled
Expand Down Expand Up @@ -239,8 +248,12 @@ func (c *Controller) delete(obj Object) {
}

func (c *Controller) propagate(resourceEvents []ResourceEvent) {
topology, err := c.topology.Build(c.cache.List())
if err != nil {
opts := make([]machinery.GatewayAPITopologyOptionsFunc, 0)
if c.allowTopologyLoops {
opts = append(opts, machinery.AllowTopologyLoops())
}
topology, err := c.topology.Build(c.cache.List(), opts...)
if !c.allowTopologyLoops && err != nil {
panic(err)
}
c.reconcile(LoggerIntoContext(context.TODO(), c.logger), resourceEvents, topology)
Expand Down
5 changes: 5 additions & 0 deletions controller/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ func TestControllerOptions(t *testing.T) {
if opts.reconcile == nil {
t.Errorf("expected reconcile func, got nil")
}

AllowLoops()(opts)
if opts.allowTopologyLoops == false {
t.Errorf("expected allowTopologyLoops true, got false")
}
}

func TestNewController(t *testing.T) {
Expand Down
4 changes: 3 additions & 1 deletion controller/topology_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type gatewayAPITopologyBuilder struct {
objectLinks []LinkFunc
}

func (t *gatewayAPITopologyBuilder) Build(objs Store) (*machinery.Topology, error) {
func (t *gatewayAPITopologyBuilder) Build(objs Store, options ...machinery.GatewayAPITopologyOptionsFunc) (*machinery.Topology, error) {
gatewayClasses := lo.Map(objs.FilterByGroupKind(machinery.GatewayClassGroupKind), ObjectAs[*gwapiv1.GatewayClass])
gateways := lo.Map(objs.FilterByGroupKind(machinery.GatewayGroupKind), ObjectAs[*gwapiv1.Gateway])
httpRoutes := lo.Map(objs.FilterByGroupKind(machinery.HTTPRouteGroupKind), ObjectAs[*gwapiv1.HTTPRoute])
Expand All @@ -44,6 +44,8 @@ func (t *gatewayAPITopologyBuilder) Build(objs Store) (*machinery.Topology, erro
machinery.WithGatewayAPITopologyLinks(linkFuncs...),
}

opts = append(opts, options...)

for i := range t.policyKinds {
policyKind := t.policyKinds[i]
policies := lo.Map(objs.FilterByGroupKind(policyKind), ObjectAs[machinery.Policy])
Expand Down
13 changes: 13 additions & 0 deletions machinery/gateway_api_topology.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ type GatewayAPITopologyOptions struct {
ExpandTLSRouteRules bool
ExpandUDPRouteRules bool
ExpandServicePorts bool

allowTopologyLoops bool
}

type GatewayAPITopologyOptionsFunc func(*GatewayAPITopologyOptions)
Expand Down Expand Up @@ -178,6 +180,13 @@ func ExpandServicePorts() GatewayAPITopologyOptionsFunc {
}
}

// AllowTopologyLoops adds AllowLoops to the options to initialize a new Gateway API topology.
func AllowTopologyLoops() GatewayAPITopologyOptionsFunc {
return func(o *GatewayAPITopologyOptions) {
o.allowTopologyLoops = true
}
}

// NewGatewayAPITopology returns a topology of Gateway API objects and attached policies.
//
// The links between the targetables are established based on the relationships defined by Gateway API.
Expand Down Expand Up @@ -356,6 +365,10 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) (*Topology,
opts = append(opts, WithLinks(LinkServiceToServicePortFunc())) // Service -> ServicePort
}

if o.allowTopologyLoops {
opts = append(opts, AllowLoops())
}

return NewTopology(opts...)
}

Expand Down

0 comments on commit e24369f

Please sign in to comment.