From 8db49ca097b9197a3951ddd07b628f624ae0a1ae Mon Sep 17 00:00:00 2001 From: Lukasz Zajaczkowski Date: Tue, 18 Jun 2024 10:37:11 +0200 Subject: [PATCH] feat: make a configurable poll interval (#225) * make a configurable poll interval * add comment --- cmd/agent/agent.go | 6 ++++-- pkg/controller/controller.go | 3 +++ pkg/controller/controller_manager.go | 7 ++++++- pkg/controller/namespaces/reconciler.go | 4 ++++ pkg/controller/pipelinegates/reconciler.go | 8 +++++++- pkg/controller/restore/reconciler.go | 4 ++++ pkg/controller/service/reconciler.go | 4 ++++ pkg/controller/stacks/job_test.go | 2 +- pkg/controller/stacks/reconciler.go | 14 ++++++++++---- pkg/controller/stacks/reconciler_test.go | 12 ++++++------ pkg/test/mocks/Client_mock.go | 20 ++++++++++---------- 11 files changed, 59 insertions(+), 25 deletions(-) diff --git a/cmd/agent/agent.go b/cmd/agent/agent.go index adc68632..b54272fd 100644 --- a/cmd/agent/agent.go +++ b/cmd/agent/agent.go @@ -19,6 +19,8 @@ import ( "github.com/pluralsh/deployment-operator/pkg/controller/service" ) +const pollInterval = time.Second * 30 + func runAgent(opt *options, config *rest.Config, ctx context.Context, k8sClient ctrclient.Client) (*controller.ControllerManager, *service.ServiceReconciler, *pipelinegates.GateReconciler) { r, err := time.ParseDuration(opt.refreshInterval) if err != nil { @@ -48,7 +50,7 @@ func runAgent(opt *options, config *rest.Config, ctx context.Context, k8sClient Do: sr, Queue: sr.SvcQueue, }) - gr, err := pipelinegates.NewGateReconciler(mgr.GetClient(), k8sClient, config, r, opt.clusterId) + gr, err := pipelinegates.NewGateReconciler(mgr.GetClient(), k8sClient, config, r, pollInterval, opt.clusterId) if err != nil { setupLog.Errorw("unable to create gate reconciler", "error", err) os.Exit(1) @@ -79,7 +81,7 @@ func runAgent(opt *options, config *rest.Config, ctx context.Context, k8sClient os.Exit(1) } - s := stacks.NewStackReconciler(mgr.GetClient(), k8sClient, r, namespace, opt.consoleUrl, opt.deployToken) + s := stacks.NewStackReconciler(mgr.GetClient(), k8sClient, r, pollInterval, namespace, opt.consoleUrl, opt.deployToken) mgr.AddController(&controller.Controller{ Name: "Stack Controller", Do: s, diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 2cd78522..a9fda51f 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -33,6 +33,9 @@ type Reconciler interface { // ShutdownQueue containing Console resources. ShutdownQueue() + + // GetPollInterval returns custom poll interval. If 0 then controller manager use default from the options. + GetPollInterval() time.Duration } type Controller struct { diff --git a/pkg/controller/controller_manager.go b/pkg/controller/controller_manager.go index 6278537c..9a819d6b 100644 --- a/pkg/controller/controller_manager.go +++ b/pkg/controller/controller_manager.go @@ -83,8 +83,13 @@ func (cm *ControllerManager) Start() error { go func() { defer controller.Do.ShutdownQueue() defer controller.Do.WipeCache() + + pollInterval := cm.Refresh + if controllerPollInterval := controller.Do.GetPollInterval(); controllerPollInterval > 0 { + pollInterval = controllerPollInterval + } //nolint:all - _ = wait.PollImmediateInfinite(cm.Refresh, func() (done bool, err error) { + _ = wait.PollImmediateInfinite(pollInterval, func() (done bool, err error) { return controller.Do.Poll(cm.ctx) }) }() diff --git a/pkg/controller/namespaces/reconciler.go b/pkg/controller/namespaces/reconciler.go index 67a7381d..3d47f059 100644 --- a/pkg/controller/namespaces/reconciler.go +++ b/pkg/controller/namespaces/reconciler.go @@ -41,6 +41,10 @@ func NewNamespaceReconciler(consoleClient client.Client, k8sClient ctrlclient.Cl } } +func (n *NamespaceReconciler) GetPollInterval() time.Duration { + return 0 // use default poll interval +} + func (n *NamespaceReconciler) GetPublisher() (string, websocket.Publisher) { return "namespace.event", &socketPublisher{ restoreQueue: n.NamespaceQueue, diff --git a/pkg/controller/pipelinegates/reconciler.go b/pkg/controller/pipelinegates/reconciler.go index c94663ac..2e8fa9b2 100644 --- a/pkg/controller/pipelinegates/reconciler.go +++ b/pkg/controller/pipelinegates/reconciler.go @@ -36,9 +36,10 @@ type GateReconciler struct { discoveryClient *discovery.DiscoveryClient pinger *ping.Pinger operatorNamespace string + PollInterval time.Duration } -func NewGateReconciler(consoleClient client.Client, k8sClient ctrlclient.Client, config *rest.Config, refresh time.Duration, clusterId string) (*GateReconciler, error) { +func NewGateReconciler(consoleClient client.Client, k8sClient ctrlclient.Client, config *rest.Config, refresh, pollInterval time.Duration, clusterId string) (*GateReconciler, error) { utils.DisableClientLimits(config) discoveryClient, err := discovery.NewDiscoveryClientForConfig(config) @@ -74,9 +75,14 @@ func NewGateReconciler(consoleClient client.Client, k8sClient ctrlclient.Client, discoveryClient: discoveryClient, pinger: ping.New(consoleClient, discoveryClient, f), operatorNamespace: namespace, + PollInterval: pollInterval, }, nil } +func (s *GateReconciler) GetPollInterval() time.Duration { + return s.PollInterval +} + func (s *GateReconciler) WipeCache() { s.GateCache.Wipe() } diff --git a/pkg/controller/restore/reconciler.go b/pkg/controller/restore/reconciler.go index 4b8bc5a1..e3e7b9df 100644 --- a/pkg/controller/restore/reconciler.go +++ b/pkg/controller/restore/reconciler.go @@ -63,6 +63,10 @@ func NewRestoreReconciler(consoleClient client.Client, k8sClient ctrlclient.Clie } } +func (s *RestoreReconciler) GetPollInterval() time.Duration { + return 0 // use default poll interval +} + func (s *RestoreReconciler) GetPublisher() (string, websocket.Publisher) { return "restore.event", &socketPublisher{ restoreQueue: s.RestoreQueue, diff --git a/pkg/controller/service/reconciler.go b/pkg/controller/service/reconciler.go index 7935ac64..43573d9b 100644 --- a/pkg/controller/service/reconciler.go +++ b/pkg/controller/service/reconciler.go @@ -155,6 +155,10 @@ func CapabilitiesAPIVersions(discoveryClient *discovery.DiscoveryClient) error { return nil } +func (s *ServiceReconciler) GetPollInterval() time.Duration { + return 0 // use default poll interval +} + func (s *ServiceReconciler) GetPublisher() (string, websocket.Publisher) { return "service.event", &socketPublisher{ svcQueue: s.SvcQueue, diff --git a/pkg/controller/stacks/job_test.go b/pkg/controller/stacks/job_test.go index 600edee6..b6ba519f 100644 --- a/pkg/controller/stacks/job_test.go +++ b/pkg/controller/stacks/job_test.go @@ -15,7 +15,7 @@ func TestGetDefaultContainerImage(t *testing.T) { var kClient client.Client fakeConsoleClient := mocks.NewClientMock(t) namespace := "default" - reconciler := NewStackReconciler(fakeConsoleClient, kClient, time.Minute, namespace, "", "") + reconciler := NewStackReconciler(fakeConsoleClient, kClient, time.Minute, 0, namespace, "", "") run := &console.StackRunFragment{ Type: console.StackTypeTerraform, Configuration: &console.StackConfigurationFragment{ diff --git a/pkg/controller/stacks/reconciler.go b/pkg/controller/stacks/reconciler.go index 355eff78..ef0cf125 100644 --- a/pkg/controller/stacks/reconciler.go +++ b/pkg/controller/stacks/reconciler.go @@ -25,9 +25,10 @@ type StackReconciler struct { Namespace string ConsoleURL string DeployToken string + PollInterval time.Duration } -func NewStackReconciler(consoleClient client.Client, k8sClient ctrlclient.Client, refresh time.Duration, namespace, consoleURL, deployToken string) *StackReconciler { +func NewStackReconciler(consoleClient client.Client, k8sClient ctrlclient.Client, refresh, pollInterval time.Duration, namespace, consoleURL, deployToken string) *StackReconciler { return &StackReconciler{ ConsoleClient: consoleClient, K8sClient: k8sClient, @@ -35,12 +36,17 @@ func NewStackReconciler(consoleClient client.Client, k8sClient ctrlclient.Client StackCache: client.NewCache[console.StackRunFragment](refresh, func(id string) (*console.StackRunFragment, error) { return consoleClient.GetStackRun(id) }), - Namespace: namespace, - ConsoleURL: consoleURL, - DeployToken: deployToken, + Namespace: namespace, + ConsoleURL: consoleURL, + DeployToken: deployToken, + PollInterval: pollInterval, } } +func (r *StackReconciler) GetPollInterval() time.Duration { + return r.PollInterval +} + func (r *StackReconciler) GetPublisher() (string, websocket.Publisher) { return "stack.run.event", &socketPublisher{ stackRunQueue: r.StackQueue, diff --git a/pkg/controller/stacks/reconciler_test.go b/pkg/controller/stacks/reconciler_test.go index 06e04853..6be22b03 100644 --- a/pkg/controller/stacks/reconciler_test.go +++ b/pkg/controller/stacks/reconciler_test.go @@ -73,7 +73,7 @@ var _ = Describe("Reconciler", Ordered, func() { GqlErrors: &gqlerror.List{gqlerror.Errorf(errors2.ErrorNotFound.String())}, }) - reconciler := stacks.NewStackReconciler(fakeConsoleClient, kClient, time.Minute, namespace, "", "") + reconciler := stacks.NewStackReconciler(fakeConsoleClient, kClient, time.Minute, 0, namespace, "", "") _, err := reconciler.Reconcile(ctx, stackRunId) Expect(err).NotTo(HaveOccurred()) @@ -85,7 +85,7 @@ var _ = Describe("Reconciler", Ordered, func() { GqlErrors: &gqlerror.List{gqlerror.Errorf("unknown error")}, }) - reconciler := stacks.NewStackReconciler(fakeConsoleClient, kClient, time.Minute, namespace, "", "") + reconciler := stacks.NewStackReconciler(fakeConsoleClient, kClient, time.Minute, 0, namespace, "", "") _, err := reconciler.Reconcile(ctx, stackRunId) Expect(err).To(HaveOccurred()) @@ -100,7 +100,7 @@ var _ = Describe("Reconciler", Ordered, func() { Status: console.StackStatusPending, }, nil) - reconciler := stacks.NewStackReconciler(fakeConsoleClient, kClient, time.Minute, namespace, "", "") + reconciler := stacks.NewStackReconciler(fakeConsoleClient, kClient, time.Minute, 0, namespace, "", "") _, err := reconciler.Reconcile(ctx, stackRunId) Expect(err).NotTo(HaveOccurred()) @@ -118,7 +118,7 @@ var _ = Describe("Reconciler", Ordered, func() { fakeConsoleClient.On("GetStackRun", mock.Anything).Return(stackRun, nil) fakeConsoleClient.On("UpdateStackRun", mock.Anything, mock.Anything).Return(nil) - reconciler := stacks.NewStackReconciler(fakeConsoleClient, kClient, time.Minute, namespace, "", "") + reconciler := stacks.NewStackReconciler(fakeConsoleClient, kClient, time.Minute, 0, namespace, "", "") _, err := reconciler.Reconcile(ctx, stackRunId) Expect(err).NotTo(HaveOccurred()) @@ -157,7 +157,7 @@ var _ = Describe("Reconciler", Ordered, func() { fakeConsoleClient.On("GetStackRun", mock.Anything).Return(stackRun, nil) fakeConsoleClient.On("UpdateStackRun", mock.Anything, mock.Anything).Return(nil) - reconciler := stacks.NewStackReconciler(fakeConsoleClient, kClient, time.Minute, namespace, "", "") + reconciler := stacks.NewStackReconciler(fakeConsoleClient, kClient, time.Minute, 0, namespace, "", "") _, err := reconciler.Reconcile(ctx, stackRunId) Expect(err).NotTo(HaveOccurred()) @@ -213,7 +213,7 @@ var _ = Describe("Reconciler", Ordered, func() { fakeConsoleClient.On("GetStackRun", mock.Anything).Return(stackRun, nil) fakeConsoleClient.On("UpdateStackRun", mock.Anything, mock.Anything).Return(nil) - reconciler := stacks.NewStackReconciler(fakeConsoleClient, kClient, time.Minute, namespace, "", "") + reconciler := stacks.NewStackReconciler(fakeConsoleClient, kClient, time.Minute, 0, namespace, "", "") _, err = reconciler.Reconcile(ctx, stackRunId) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/test/mocks/Client_mock.go b/pkg/test/mocks/Client_mock.go index eb2be1d1..dbb749fe 100644 --- a/pkg/test/mocks/Client_mock.go +++ b/pkg/test/mocks/Client_mock.go @@ -4,11 +4,11 @@ package mocks import ( gqlclient "github.com/pluralsh/console-client-go" - "github.com/stretchr/testify/mock" + mock "github.com/stretchr/testify/mock" - stackrun "github.com/pluralsh/deployment-operator/pkg/harness/stackrun/v1" + v1 "github.com/pluralsh/deployment-operator/pkg/harness/stackrun/v1" - "github.com/pluralsh/deployment-operator/api/v1alpha1" + v1alpha1 "github.com/pluralsh/deployment-operator/api/v1alpha1" ) // ClientMock is an autogenerated mock type for the Client type @@ -735,23 +735,23 @@ func (_c *ClientMock_GetStackRun_Call) RunAndReturn(run func(string) (*gqlclient } // GetStackRunBase provides a mock function with given fields: id -func (_m *ClientMock) GetStackRunBase(id string) (*stackrun.StackRun, error) { +func (_m *ClientMock) GetStackRunBase(id string) (*v1.StackRun, error) { ret := _m.Called(id) if len(ret) == 0 { panic("no return value specified for GetStackRunBase") } - var r0 *stackrun.StackRun + var r0 *v1.StackRun var r1 error - if rf, ok := ret.Get(0).(func(string) (*stackrun.StackRun, error)); ok { + if rf, ok := ret.Get(0).(func(string) (*v1.StackRun, error)); ok { return rf(id) } - if rf, ok := ret.Get(0).(func(string) *stackrun.StackRun); ok { + if rf, ok := ret.Get(0).(func(string) *v1.StackRun); ok { r0 = rf(id) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*stackrun.StackRun) + r0 = ret.Get(0).(*v1.StackRun) } } @@ -782,12 +782,12 @@ func (_c *ClientMock_GetStackRunBase_Call) Run(run func(id string)) *ClientMock_ return _c } -func (_c *ClientMock_GetStackRunBase_Call) Return(_a0 *stackrun.StackRun, _a1 error) *ClientMock_GetStackRunBase_Call { +func (_c *ClientMock_GetStackRunBase_Call) Return(_a0 *v1.StackRun, _a1 error) *ClientMock_GetStackRunBase_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *ClientMock_GetStackRunBase_Call) RunAndReturn(run func(string) (*stackrun.StackRun, error)) *ClientMock_GetStackRunBase_Call { +func (_c *ClientMock_GetStackRunBase_Call) RunAndReturn(run func(string) (*v1.StackRun, error)) *ClientMock_GetStackRunBase_Call { _c.Call.Return(run) return _c }