Skip to content

Commit

Permalink
add godoc and make the reconciler struct private
Browse files Browse the repository at this point in the history
  • Loading branch information
hugoShaka committed Nov 15, 2024
1 parent 933a44c commit b06203b
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 26 deletions.
2 changes: 1 addition & 1 deletion lib/autoupdate/rolloutcontroller/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
)

// mockClient is a mock implementation if the Client interface for testing purposes.
// This is used to precisely check which calls are made by the Reconciler during tests.
// This is used to precisely check which calls are made by the reconciler during tests.
// Use newMockClient to create one from stubs. Once the test is over, you must call
// mockClient.checkIfEmpty to validate all expected calls were made.
type mockClient struct {
Expand Down
14 changes: 10 additions & 4 deletions lib/autoupdate/rolloutcontroller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,29 @@ const (
reconcilerPeriod = time.Minute
)

// Controller wakes up every minute to reconcile the autoupdate_agent_rollout resource.
// See the reconciler godoc for more details about the reconciliation process.
// We currently wake up every minute, in the future we might decide to also watch for events
// (from autoupdate_config and autoupdate_version changefeed) to react faster.
type Controller struct {
reconciler Reconciler
reconciler reconciler
clock clockwork.Clock
log *slog.Logger
}

// New creates a new Controller for the autoupdate_agent_rollout kind.
func New(client Client, log *slog.Logger, clock clockwork.Clock) *Controller {
return &Controller{
clock: clock,
log: log,
reconciler: Reconciler{
reconciler: reconciler{
clt: client,
log: log,
},
}
}

// Run the autoupdate_agent_rollout controller. This function returns only when its context is cancelled.
func (c *Controller) Run(ctx context.Context) error {
config := interval.Config{
Duration: reconcilerPeriod,
Expand All @@ -47,8 +53,8 @@ func (c *Controller) Run(ctx context.Context) error {
c.log.InfoContext(ctx, "Stopping autoupdate_agent_rollout controller", "reason", ctx.Err())
return ctx.Err()
case <-ticker.Next():
c.log.DebugContext(ctx, "Running autoupdate_agent_rollout reconciler")
err := c.reconciler.Reconcile(ctx)
c.log.DebugContext(ctx, "Reconciling autoupdate_agent_rollout")
err := c.reconciler.reconcile(ctx)
if err != nil {
c.log.ErrorContext(ctx, "Failed to reconcile autoudpate_agent_controller", "error", err)
}
Expand Down
12 changes: 6 additions & 6 deletions lib/autoupdate/rolloutcontroller/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,21 @@ const (
maxConflictRetry = 3
)

// Reconciler reconciles the AutoUpdateAgentRollout singleton based on the content of the AutoUpdateVersion and
// reconciler reconciles the AutoUpdateAgentRollout singleton based on the content of the AutoUpdateVersion and
// AutoUpdateConfig singletons. This reconciler is not based on the services.GenericReconciler because:
// - we reconcile 2 resources with one
// - both input and output are singletons, we don't need the multi resource logic nor stream/paginated APIs
type Reconciler struct {
type reconciler struct {
clt Client
log *slog.Logger

// mutex ensures we only run one reconciliation at a time
mutex sync.Mutex
}

// Reconcile the AutoUpdateAgentRollout singleton. The reconciliation can fail because of a conflict (multiple auths
// reconcile the AutoUpdateAgentRollout singleton. The reconciliation can fail because of a conflict (multiple auths
// are racing), in this case we retry the reconciliation immediately.
func (r *Reconciler) Reconcile(ctx context.Context) error {
func (r *reconciler) reconcile(ctx context.Context) error {
r.mutex.Lock()
defer r.mutex.Unlock()

Expand Down Expand Up @@ -88,7 +88,7 @@ func (r *Reconciler) Reconcile(ctx context.Context) error {
// The creation/update/deletion can fail with a trace.CompareFailedError or trace.NotFoundError
// if the resource change while we were computing it.
// The caller must handle those error and retry the reconciliation.
func (r *Reconciler) tryReconcile(ctx context.Context) error {
func (r *reconciler) tryReconcile(ctx context.Context) error {
// get autoupdate_config
var config *autoupdate.AutoUpdateConfig
if c, err := r.clt.GetAutoUpdateConfig(ctx); err == nil {
Expand Down Expand Up @@ -171,7 +171,7 @@ func (r *Reconciler) tryReconcile(ctx context.Context) error {
return trace.Wrap(err, "updating rollout")
}

func (r *Reconciler) buildRolloutSpec(config *autoupdate.AutoUpdateConfigSpecAgents, version *autoupdate.AutoUpdateVersionSpecAgents) (*autoupdate.AutoUpdateAgentRolloutSpec, error) {
func (r *reconciler) buildRolloutSpec(config *autoupdate.AutoUpdateConfigSpecAgents, version *autoupdate.AutoUpdateVersionSpecAgents) (*autoupdate.AutoUpdateAgentRolloutSpec, error) {
// reconcile mode
mode, err := getMode(config.GetMode(), version.GetMode())
if err != nil {
Expand Down
30 changes: 15 additions & 15 deletions lib/autoupdate/rolloutcontroller/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ func TestTryReconcile(t *testing.T) {

// Test execution: Running the reconciliation

reconciler := &Reconciler{
reconciler := &reconciler{
clt: client,
log: log,
}
Expand Down Expand Up @@ -375,13 +375,13 @@ func TestReconciler_Reconcile(t *testing.T) {
}

client := newMockClient(t, stubs)
reconciler := &Reconciler{
reconciler := &reconciler{
clt: client,
log: log,
}

// Test execution: run the reconciliation loop
require.NoError(t, reconciler.Reconcile(ctx))
require.NoError(t, reconciler.reconcile(ctx))

// Test validation: check that all the expected calls were received
client.checkIfEmpty(t)
Expand All @@ -397,13 +397,13 @@ func TestReconciler_Reconcile(t *testing.T) {
}

client := newMockClient(t, stubs)
reconciler := &Reconciler{
reconciler := &reconciler{
clt: client,
log: log,
}

// Test execution: run the reconciliation loop
require.NoError(t, reconciler.Reconcile(ctx))
require.NoError(t, reconciler.reconcile(ctx))

// Test validation: check that all the expected calls were received
client.checkIfEmpty(t)
Expand All @@ -421,13 +421,13 @@ func TestReconciler_Reconcile(t *testing.T) {
}

client := newMockClient(t, stubs)
reconciler := &Reconciler{
reconciler := &reconciler{
clt: client,
log: log,
}

// Test execution: run the reconciliation loop
require.NoError(t, reconciler.Reconcile(ctx))
require.NoError(t, reconciler.reconcile(ctx))

// Test validation: check that all the expected calls were received
client.checkIfEmpty(t)
Expand Down Expand Up @@ -461,13 +461,13 @@ func TestReconciler_Reconcile(t *testing.T) {
}

client := newMockClient(t, stubs)
reconciler := &Reconciler{
reconciler := &reconciler{
clt: client,
log: log,
}

// Test execution: run the reconciliation loop
require.NoError(t, reconciler.Reconcile(ctx))
require.NoError(t, reconciler.reconcile(ctx))

// Test validation: check that all the expected calls were received
client.checkIfEmpty(t)
Expand Down Expand Up @@ -499,13 +499,13 @@ func TestReconciler_Reconcile(t *testing.T) {
}

client := newMockClient(t, stubs)
reconciler := &Reconciler{
reconciler := &reconciler{
clt: client,
log: log,
}

// Test execution: run the reconciliation loop
require.NoError(t, reconciler.Reconcile(ctx))
require.NoError(t, reconciler.reconcile(ctx))

// Test validation: check that all the expected calls were received
client.checkIfEmpty(t)
Expand All @@ -523,13 +523,13 @@ func TestReconciler_Reconcile(t *testing.T) {
}

client := newMockClient(t, stubs)
reconciler := &Reconciler{
reconciler := &reconciler{
clt: client,
log: log,
}

// Test execution: run the reconciliation loop
require.ErrorContains(t, reconciler.Reconcile(ctx), "the DB fell on the floor")
require.ErrorContains(t, reconciler.reconcile(ctx), "the DB fell on the floor")

// Test validation: check that all the expected calls were received
client.checkIfEmpty(t)
Expand All @@ -553,13 +553,13 @@ func TestReconciler_Reconcile(t *testing.T) {
}

client := newMockClient(t, stubs)
reconciler := &Reconciler{
reconciler := &reconciler{
clt: client,
log: log,
}

// Test execution: run the reconciliation loop
require.ErrorContains(t, reconciler.Reconcile(cancelableCtx), "canceled")
require.ErrorContains(t, reconciler.reconcile(cancelableCtx), "canceled")

// Test validation: check that all the expected calls were received
client.checkIfEmpty(t)
Expand Down

0 comments on commit b06203b

Please sign in to comment.