From b173d9f8efd44665579c5ed171271ca4a3512f9f Mon Sep 17 00:00:00 2001 From: James Shubin Date: Tue, 18 Mar 2025 03:07:27 -0400 Subject: [PATCH] engine: Split out the etcd cluster size options This is clean up work so that it's easier to generalize the world backends. --- engine/resources/config_etcd.go | 14 +++++++++++--- engine/world.go | 14 ++++++++++---- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/engine/resources/config_etcd.go b/engine/resources/config_etcd.go index aebaf33a..36abb885 100644 --- a/engine/resources/config_etcd.go +++ b/engine/resources/config_etcd.go @@ -65,6 +65,8 @@ type ConfigEtcdRes struct { // IdealClusterSize to zero. AllowSizeShutdown bool `lang:"allow_size_shutdown"` + world engine.EtcdWorld + // sizeFlag determines whether sizeCheckApply already ran or not. sizeFlag bool @@ -93,6 +95,12 @@ func (obj *ConfigEtcdRes) Validate() error { func (obj *ConfigEtcdRes) Init(init *engine.Init) error { obj.init = init // save for later + world, ok := obj.init.World.(engine.EtcdWorld) + if !ok { + return fmt.Errorf("world backend does not support the EtcdWorld interface") + } + obj.world = world + obj.interruptChan = make(chan struct{}) return nil @@ -109,7 +117,7 @@ func (obj *ConfigEtcdRes) Watch(ctx context.Context) error { defer wg.Wait() innerCtx, cancel := context.WithCancel(ctx) defer cancel() - ch, err := obj.init.World.IdealClusterSizeWatch(util.CtxWithWg(innerCtx, wg)) + ch, err := obj.world.IdealClusterSizeWatch(util.CtxWithWg(innerCtx, wg)) if err != nil { return errwrap.Wrapf(err, "could not watch ideal cluster size") } @@ -158,7 +166,7 @@ func (obj *ConfigEtcdRes) sizeCheckApply(ctx context.Context, apply bool) (bool, } }() - val, err := obj.init.World.IdealClusterSizeGet(ctx) + val, err := obj.world.IdealClusterSizeGet(ctx) if err != nil { return false, errwrap.Wrapf(err, "could not get ideal cluster size") } @@ -181,7 +189,7 @@ func (obj *ConfigEtcdRes) sizeCheckApply(ctx context.Context, apply bool) (bool, // set! // This is run as a transaction so we detect if we needed to change it. - changed, err := obj.init.World.IdealClusterSizeSet(ctx, obj.IdealClusterSize) + changed, err := obj.world.IdealClusterSizeSet(ctx, obj.IdealClusterSize) if err != nil { return false, errwrap.Wrapf(err, "could not set ideal cluster size") } diff --git a/engine/world.go b/engine/world.go index 21462d99..6306777d 100644 --- a/engine/world.go +++ b/engine/world.go @@ -45,10 +45,6 @@ type World interface { // TODO: is there a better name for this interface? // FIXME: should this method take a "filter" data struct instead of many args? ResCollect(ctx context.Context, hostnameFilter, kindFilter []string) ([]Res, error) - IdealClusterSizeWatch(context.Context) (chan error, error) - IdealClusterSizeGet(context.Context) (uint16, error) - IdealClusterSizeSet(context.Context, uint16) (bool, error) - StrWatch(ctx context.Context, namespace string) (chan error, error) StrIsNotExist(error) bool StrGet(ctx context.Context, namespace string) (string, error) @@ -75,3 +71,13 @@ type World interface { // TODO: is there a better name for this interface? // WatchMembers returns a channel of changing members in the cluster. WatchMembers(context.Context) (<-chan *interfaces.MembersResult, error) } + +// EtcdWorld is a world interface that should be implemented if the world +// backend is implementing etcd, and if it supports dynamically resizing things. +// TODO: In theory we could generalize this to support other backends, but lets +// assume it's specific to etcd only for now. +type EtcdWorld interface { + IdealClusterSizeWatch(context.Context) (chan error, error) + IdealClusterSizeGet(context.Context) (uint16, error) + IdealClusterSizeSet(context.Context, uint16) (bool, error) +}