From cbea4d426496550b7b866fa1fc3f63db58b571ea Mon Sep 17 00:00:00 2001 From: Simon Richardson Date: Wed, 23 Oct 2024 13:57:20 +0100 Subject: [PATCH 1/4] feat: wireup lease ownership The following wires up the lease ownership so that we can start to use it in the services. --- apiserver/auditconfig_test.go | 2 +- .../provisioner_integration_test.go | 8 +- .../provisioner/provisioninginfo_test.go | 4 +- .../storageprovisioner_iaas_test.go | 2 +- .../client/controller/controller_test.go | 3 +- .../agent/machine/manifolds.go | 1 + core/lease/lease.go | 27 + domain/lease_mock_test.go | 105 +++- domain/leasechecker_mock_test.go | 117 ----- domain/leaseservice.go | 16 +- domain/leaseservice_test.go | 33 +- domain/package_test.go | 3 +- domain/services/model.go | 2 + domain/services/service.go | 3 + domain/services/testing/suite.go | 56 ++- .../worker/domainservices/lease_mock_test.go | 460 ++++++++++++++++++ internal/worker/domainservices/manifold.go | 18 + .../worker/domainservices/manifold_test.go | 15 + .../worker/domainservices/package_test.go | 12 + internal/worker/domainservices/worker.go | 61 +++ internal/worker/domainservices/worker_test.go | 12 + juju/testing/apiserver.go | 8 +- 22 files changed, 800 insertions(+), 168 deletions(-) create mode 100644 core/lease/lease.go delete mode 100644 domain/leasechecker_mock_test.go create mode 100644 internal/worker/domainservices/lease_mock_test.go diff --git a/apiserver/auditconfig_test.go b/apiserver/auditconfig_test.go index 6b19a8e42ce..52377ecaa34 100644 --- a/apiserver/auditconfig_test.go +++ b/apiserver/auditconfig_test.go @@ -220,7 +220,7 @@ func (s *auditConfigSuite) TestAuditLoggingUsesExcludeMethods(c *gc.C) { func (s *auditConfigSuite) TestNewServerValidatesConfig(c *gc.C) { cfg := testing.DefaultServerConfig(c, nil) cfg.GetAuditConfig = nil - cfg.DomainServicesGetter = s.DomainServicesGetter(c, s.NoopObjectStore(c)) + cfg.DomainServicesGetter = s.DomainServicesGetter(c, s.NoopObjectStore(c), s.NoopLeaseManager(c)) srv, err := apiserver.NewServer(context.Background(), cfg) c.Assert(err, gc.ErrorMatches, "missing GetAuditConfig not valid") diff --git a/apiserver/facades/agent/provisioner/provisioner_integration_test.go b/apiserver/facades/agent/provisioner/provisioner_integration_test.go index 58dd2a97c43..c672ad81b4c 100644 --- a/apiserver/facades/agent/provisioner/provisioner_integration_test.go +++ b/apiserver/facades/agent/provisioner/provisioner_integration_test.go @@ -533,7 +533,7 @@ func (s *withoutControllerSuite) TestSetModificationStatus(c *gc.C) { func (s *withoutControllerSuite) TestMachinesWithTransientErrors(c *gc.C) { st := s.ControllerModel(c).State() - domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c)) + domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c), s.NoopLeaseManager(c)) machineService := domainServicesGetter.ServicesForModel(model.UUID(st.ModelUUID())).Machine() now := time.Now() @@ -1011,7 +1011,7 @@ func (s *withoutControllerSuite) TestDistributionGroup(c *gc.C) { defer release() st := s.ControllerModel(c).State() - domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c)) + domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c), s.NoopLeaseManager(c)) machineService := domainServicesGetter.ServicesForModel(model.UUID(st.ModelUUID())).Machine() addUnits := func(name string, machines ...*state.Machine) (units []*state.Unit) { @@ -1324,7 +1324,7 @@ func (s *withoutControllerSuite) TestConstraints(c *gc.C) { } func (s *withoutControllerSuite) TestSetInstanceInfo(c *gc.C) { - domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c)) + domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c), s.NoopLeaseManager(c)) st := s.ControllerModel(c).State() storageService := domainServicesGetter.ServicesForModel(model.UUID(st.ModelUUID())).Storage() @@ -1455,7 +1455,7 @@ func (s *withoutControllerSuite) TestSetInstanceInfo(c *gc.C) { func (s *withoutControllerSuite) TestInstanceId(c *gc.C) { st := s.ControllerModel(c).State() - domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c)) + domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c), s.NoopLeaseManager(c)) machineService := domainServicesGetter.ServicesForModel(model.UUID(st.ModelUUID())).Machine() // Provision 2 machines first. machine0UUID, err := machineService.GetMachineUUID(context.Background(), coremachine.Name(s.machines[0].Id())) diff --git a/apiserver/facades/agent/provisioner/provisioninginfo_test.go b/apiserver/facades/agent/provisioner/provisioninginfo_test.go index 4640c26adf4..efcbe27a49d 100644 --- a/apiserver/facades/agent/provisioner/provisioninginfo_test.go +++ b/apiserver/facades/agent/provisioner/provisioninginfo_test.go @@ -26,7 +26,7 @@ import ( ) func (s *withoutControllerSuite) TestProvisioningInfoWithStorage(c *gc.C) { - domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c)) + domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c), s.NoopLeaseManager(c)) st := s.ControllerModel(c).State() storageService := domainServicesGetter.ServicesForModel(model.UUID(st.ModelUUID())).Storage() @@ -126,7 +126,7 @@ func (s *withoutControllerSuite) TestProvisioningInfoWithStorage(c *gc.C) { } func (s *withoutControllerSuite) TestProvisioningInfoRootDiskVolume(c *gc.C) { - domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c)) + domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c), s.NoopLeaseManager(c)) st := s.ControllerModel(c).State() storageService := domainServicesGetter.ServicesForModel(model.UUID(st.ModelUUID())).Storage() diff --git a/apiserver/facades/agent/storageprovisioner/storageprovisioner_iaas_test.go b/apiserver/facades/agent/storageprovisioner/storageprovisioner_iaas_test.go index 68d95b7618a..407c29de349 100644 --- a/apiserver/facades/agent/storageprovisioner/storageprovisioner_iaas_test.go +++ b/apiserver/facades/agent/storageprovisioner/storageprovisioner_iaas_test.go @@ -71,7 +71,7 @@ func (s *iaasProvisionerSuite) newApi(c *gc.C, blockDeviceService storageprovisi c.Assert(err, jc.ErrorIsNil) registry := storageprovider.NewStorageProviderRegistry(env) s.st = s.ControllerModel(c).State() - domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c)) + domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c), s.NoopLeaseManager(c)) storageService := domainServicesGetter.ServicesForModel(model.UUID(s.st.ModelUUID())).Storage() s.authorizer = &apiservertesting.FakeAuthorizer{ diff --git a/apiserver/facades/client/controller/controller_test.go b/apiserver/facades/client/controller/controller_test.go index 70c31af6dea..18d275f6070 100644 --- a/apiserver/facades/client/controller/controller_test.go +++ b/apiserver/facades/client/controller/controller_test.go @@ -95,7 +95,8 @@ func (s *controllerSuite) SetUpTest(c *gc.C) { s.DomainServicesSuite.ControllerConfig = controllerCfg s.DomainServicesSuite.SetUpTest(c) - jujujujutesting.SeedDatabase(c, s.ControllerSuite.TxnRunner(), s.DomainServicesGetter(c, s.NoopObjectStore(c))(s.ControllerModelUUID), controllerCfg) + domainServiceGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c), s.NoopLeaseManager(c)) + jujujujutesting.SeedDatabase(c, s.ControllerSuite.TxnRunner(), domainServiceGetter(s.ControllerModelUUID), controllerCfg) s.hub = pubsub.NewStructuredHub(nil) diff --git a/cmd/jujud-controller/agent/machine/manifolds.go b/cmd/jujud-controller/agent/machine/manifolds.go index 4722118da6a..a9e9d0e83de 100644 --- a/cmd/jujud-controller/agent/machine/manifolds.go +++ b/cmd/jujud-controller/agent/machine/manifolds.go @@ -705,6 +705,7 @@ func commonManifolds(config ManifoldsConfig) dependency.Manifolds { ObjectStoreName: objectStoreName, StorageRegistryName: storageRegistryName, HTTPClientName: httpClientName, + LeaseManagerName: leaseManagerName, Logger: internallogger.GetLogger("juju.worker.services"), Clock: config.Clock, NewWorker: workerdomainservices.NewWorker, diff --git a/core/lease/lease.go b/core/lease/lease.go new file mode 100644 index 00000000000..77d7c21ce14 --- /dev/null +++ b/core/lease/lease.go @@ -0,0 +1,27 @@ +// Copyright 2024 Canonical Ltd. +// Licensed under the AGPLv3, see LICENCE file for details. + +package lease + +import "github.com/juju/juju/core/model" + +// LeaseCheckerWaiter is an interface that checks and waits if a lease is held +// by a holder. +type LeaseCheckerWaiter interface { + Waiter + Checker +} + +// ApplicationLeaseManagerGetter is an interface that provides a method to get a +// lease manager for a given application using its UUID. +type ApplicationLeaseManagerGetter interface { + // GetLeaseManager returns a lease manager for the given model UUID. + GetLeaseManager(model.UUID) (LeaseCheckerWaiter, error) +} + +// ModelApplicationLeaseManagerGetter is an interface that provides a method to +// get a lease manager in the scope of a model. +type ModelApplicationLeaseManagerGetter interface { + // GetLeaseManager returns a lease manager for the given model UUID. + GetLeaseManager() (LeaseCheckerWaiter, error) +} diff --git a/domain/lease_mock_test.go b/domain/lease_mock_test.go index a2ee5c55fed..7bcddb8a84b 100644 --- a/domain/lease_mock_test.go +++ b/domain/lease_mock_test.go @@ -1,17 +1,19 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/juju/juju/core/lease (interfaces: Token) +// Source: github.com/juju/juju/core/lease (interfaces: Token,LeaseCheckerWaiter) // // Generated by this command: // -// mockgen -typed -package domain -destination lease_mock_test.go github.com/juju/juju/core/lease Token +// mockgen -typed -package domain -destination lease_mock_test.go github.com/juju/juju/core/lease Token,LeaseCheckerWaiter // // Package domain is a generated GoMock package. package domain import ( + context "context" reflect "reflect" + lease "github.com/juju/juju/core/lease" gomock "go.uber.org/mock/gomock" ) @@ -75,3 +77,102 @@ func (c *MockTokenCheckCall) DoAndReturn(f func() error) *MockTokenCheckCall { c.Call = c.Call.DoAndReturn(f) return c } + +// MockLeaseCheckerWaiter is a mock of LeaseCheckerWaiter interface. +type MockLeaseCheckerWaiter struct { + ctrl *gomock.Controller + recorder *MockLeaseCheckerWaiterMockRecorder +} + +// MockLeaseCheckerWaiterMockRecorder is the mock recorder for MockLeaseCheckerWaiter. +type MockLeaseCheckerWaiterMockRecorder struct { + mock *MockLeaseCheckerWaiter +} + +// NewMockLeaseCheckerWaiter creates a new mock instance. +func NewMockLeaseCheckerWaiter(ctrl *gomock.Controller) *MockLeaseCheckerWaiter { + mock := &MockLeaseCheckerWaiter{ctrl: ctrl} + mock.recorder = &MockLeaseCheckerWaiterMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockLeaseCheckerWaiter) EXPECT() *MockLeaseCheckerWaiterMockRecorder { + return m.recorder +} + +// Token mocks base method. +func (m *MockLeaseCheckerWaiter) Token(arg0, arg1 string) lease.Token { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Token", arg0, arg1) + ret0, _ := ret[0].(lease.Token) + return ret0 +} + +// Token indicates an expected call of Token. +func (mr *MockLeaseCheckerWaiterMockRecorder) Token(arg0, arg1 any) *MockLeaseCheckerWaiterTokenCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Token", reflect.TypeOf((*MockLeaseCheckerWaiter)(nil).Token), arg0, arg1) + return &MockLeaseCheckerWaiterTokenCall{Call: call} +} + +// MockLeaseCheckerWaiterTokenCall wrap *gomock.Call +type MockLeaseCheckerWaiterTokenCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockLeaseCheckerWaiterTokenCall) Return(arg0 lease.Token) *MockLeaseCheckerWaiterTokenCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockLeaseCheckerWaiterTokenCall) Do(f func(string, string) lease.Token) *MockLeaseCheckerWaiterTokenCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockLeaseCheckerWaiterTokenCall) DoAndReturn(f func(string, string) lease.Token) *MockLeaseCheckerWaiterTokenCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// WaitUntilExpired mocks base method. +func (m *MockLeaseCheckerWaiter) WaitUntilExpired(arg0 context.Context, arg1 string, arg2 chan<- struct{}) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WaitUntilExpired", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// WaitUntilExpired indicates an expected call of WaitUntilExpired. +func (mr *MockLeaseCheckerWaiterMockRecorder) WaitUntilExpired(arg0, arg1, arg2 any) *MockLeaseCheckerWaiterWaitUntilExpiredCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WaitUntilExpired", reflect.TypeOf((*MockLeaseCheckerWaiter)(nil).WaitUntilExpired), arg0, arg1, arg2) + return &MockLeaseCheckerWaiterWaitUntilExpiredCall{Call: call} +} + +// MockLeaseCheckerWaiterWaitUntilExpiredCall wrap *gomock.Call +type MockLeaseCheckerWaiterWaitUntilExpiredCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockLeaseCheckerWaiterWaitUntilExpiredCall) Return(arg0 error) *MockLeaseCheckerWaiterWaitUntilExpiredCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockLeaseCheckerWaiterWaitUntilExpiredCall) Do(f func(context.Context, string, chan<- struct{}) error) *MockLeaseCheckerWaiterWaitUntilExpiredCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockLeaseCheckerWaiterWaitUntilExpiredCall) DoAndReturn(f func(context.Context, string, chan<- struct{}) error) *MockLeaseCheckerWaiterWaitUntilExpiredCall { + c.Call = c.Call.DoAndReturn(f) + return c +} diff --git a/domain/leasechecker_mock_test.go b/domain/leasechecker_mock_test.go deleted file mode 100644 index 61a0def3ccb..00000000000 --- a/domain/leasechecker_mock_test.go +++ /dev/null @@ -1,117 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/juju/juju/domain (interfaces: LeaseCheckerWaiter) -// -// Generated by this command: -// -// mockgen -typed -package domain -destination leasechecker_mock_test.go github.com/juju/juju/domain LeaseCheckerWaiter -// - -// Package domain is a generated GoMock package. -package domain - -import ( - context "context" - reflect "reflect" - - lease "github.com/juju/juju/core/lease" - gomock "go.uber.org/mock/gomock" -) - -// MockLeaseCheckerWaiter is a mock of LeaseCheckerWaiter interface. -type MockLeaseCheckerWaiter struct { - ctrl *gomock.Controller - recorder *MockLeaseCheckerWaiterMockRecorder -} - -// MockLeaseCheckerWaiterMockRecorder is the mock recorder for MockLeaseCheckerWaiter. -type MockLeaseCheckerWaiterMockRecorder struct { - mock *MockLeaseCheckerWaiter -} - -// NewMockLeaseCheckerWaiter creates a new mock instance. -func NewMockLeaseCheckerWaiter(ctrl *gomock.Controller) *MockLeaseCheckerWaiter { - mock := &MockLeaseCheckerWaiter{ctrl: ctrl} - mock.recorder = &MockLeaseCheckerWaiterMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockLeaseCheckerWaiter) EXPECT() *MockLeaseCheckerWaiterMockRecorder { - return m.recorder -} - -// Token mocks base method. -func (m *MockLeaseCheckerWaiter) Token(arg0, arg1 string) lease.Token { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Token", arg0, arg1) - ret0, _ := ret[0].(lease.Token) - return ret0 -} - -// Token indicates an expected call of Token. -func (mr *MockLeaseCheckerWaiterMockRecorder) Token(arg0, arg1 any) *MockLeaseCheckerWaiterTokenCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Token", reflect.TypeOf((*MockLeaseCheckerWaiter)(nil).Token), arg0, arg1) - return &MockLeaseCheckerWaiterTokenCall{Call: call} -} - -// MockLeaseCheckerWaiterTokenCall wrap *gomock.Call -type MockLeaseCheckerWaiterTokenCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *MockLeaseCheckerWaiterTokenCall) Return(arg0 lease.Token) *MockLeaseCheckerWaiterTokenCall { - c.Call = c.Call.Return(arg0) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *MockLeaseCheckerWaiterTokenCall) Do(f func(string, string) lease.Token) *MockLeaseCheckerWaiterTokenCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockLeaseCheckerWaiterTokenCall) DoAndReturn(f func(string, string) lease.Token) *MockLeaseCheckerWaiterTokenCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - -// WaitUntilExpired mocks base method. -func (m *MockLeaseCheckerWaiter) WaitUntilExpired(arg0 context.Context, arg1 string, arg2 chan<- struct{}) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WaitUntilExpired", arg0, arg1, arg2) - ret0, _ := ret[0].(error) - return ret0 -} - -// WaitUntilExpired indicates an expected call of WaitUntilExpired. -func (mr *MockLeaseCheckerWaiterMockRecorder) WaitUntilExpired(arg0, arg1, arg2 any) *MockLeaseCheckerWaiterWaitUntilExpiredCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WaitUntilExpired", reflect.TypeOf((*MockLeaseCheckerWaiter)(nil).WaitUntilExpired), arg0, arg1, arg2) - return &MockLeaseCheckerWaiterWaitUntilExpiredCall{Call: call} -} - -// MockLeaseCheckerWaiterWaitUntilExpiredCall wrap *gomock.Call -type MockLeaseCheckerWaiterWaitUntilExpiredCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *MockLeaseCheckerWaiterWaitUntilExpiredCall) Return(arg0 error) *MockLeaseCheckerWaiterWaitUntilExpiredCall { - c.Call = c.Call.Return(arg0) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *MockLeaseCheckerWaiterWaitUntilExpiredCall) Do(f func(context.Context, string, chan<- struct{}) error) *MockLeaseCheckerWaiterWaitUntilExpiredCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockLeaseCheckerWaiterWaitUntilExpiredCall) DoAndReturn(f func(context.Context, string, chan<- struct{}) error) *MockLeaseCheckerWaiterWaitUntilExpiredCall { - c.Call = c.Call.DoAndReturn(f) - return c -} diff --git a/domain/leaseservice.go b/domain/leaseservice.go index dc889478fe2..29d5129cac0 100644 --- a/domain/leaseservice.go +++ b/domain/leaseservice.go @@ -10,16 +10,16 @@ import ( internalerrors "github.com/juju/juju/internal/errors" ) -// LeaseCheckerWaiter is an interface that checks and waits if a lease is held -// by a holder. -type LeaseCheckerWaiter interface { - lease.Waiter - lease.Checker -} - // LeaseService creates a base service that offers lease capabilities. type LeaseService struct { - leaseChecker func() LeaseCheckerWaiter + leaseChecker func() lease.LeaseCheckerWaiter +} + +// NewLeaseService creates a new LeaseService. +func NewLeaseService(leaseChecker func() lease.LeaseCheckerWaiter) *LeaseService { + return &LeaseService{ + leaseChecker: leaseChecker, + } } // WithLease executes the closure function if the holder to the lease is diff --git a/domain/leaseservice_test.go b/domain/leaseservice_test.go index d09590f5f43..4f05a78e149 100644 --- a/domain/leaseservice_test.go +++ b/domain/leaseservice_test.go @@ -13,6 +13,7 @@ import ( "go.uber.org/mock/gomock" gc "gopkg.in/check.v1" + lease "github.com/juju/juju/core/lease" "github.com/juju/juju/internal/errors" ) @@ -48,11 +49,9 @@ func (s *leaseServiceSuite) TestWithLease(c *gc.C) { s.leaseCheckerWaiter.EXPECT().Token("leaseName", "holderName").Return(s.token) s.token.EXPECT().Check().Return(nil) - service := LeaseService{ - leaseChecker: func() LeaseCheckerWaiter { - return s.leaseCheckerWaiter - }, - } + service := NewLeaseService(func() lease.LeaseCheckerWaiter { + return s.leaseCheckerWaiter + }) var called bool err := service.WithLease(context.Background(), "leaseName", "holderName", func(ctx context.Context) error { @@ -71,11 +70,9 @@ func (s *leaseServiceSuite) TestWithLeaseWaitReturnsError(c *gc.C) { return fmt.Errorf("not holding lease") }) - service := LeaseService{ - leaseChecker: func() LeaseCheckerWaiter { - return s.leaseCheckerWaiter - }, - } + service := NewLeaseService(func() lease.LeaseCheckerWaiter { + return s.leaseCheckerWaiter + }) var called bool err := service.WithLease(context.Background(), "leaseName", "holderName", func(ctx context.Context) error { @@ -112,11 +109,9 @@ func (s *leaseServiceSuite) TestWithLeaseWaitHasLeaseChange(c *gc.C) { s.leaseCheckerWaiter.EXPECT().Token("leaseName", "holderName").Return(s.token) s.token.EXPECT().Check().Return(nil) - service := LeaseService{ - leaseChecker: func() LeaseCheckerWaiter { - return s.leaseCheckerWaiter - }, - } + service := NewLeaseService(func() lease.LeaseCheckerWaiter { + return s.leaseCheckerWaiter + }) // Finish is used to ensure that the lease function has completed and not // left running. @@ -171,11 +166,9 @@ func (s *leaseServiceSuite) TestWithLeaseFailsOnWaitCheck(c *gc.C) { s.leaseCheckerWaiter.EXPECT().Token("leaseName", "holderName").Return(s.token) s.token.EXPECT().Check().Return(errors.Errorf("not holding lease")) - service := LeaseService{ - leaseChecker: func() LeaseCheckerWaiter { - return s.leaseCheckerWaiter - }, - } + service := NewLeaseService(func() lease.LeaseCheckerWaiter { + return s.leaseCheckerWaiter + }) // The lease function should be a long running function. diff --git a/domain/package_test.go b/domain/package_test.go index 774131eaebc..ab23bd271da 100644 --- a/domain/package_test.go +++ b/domain/package_test.go @@ -11,8 +11,7 @@ import ( ) //go:generate go run go.uber.org/mock/mockgen -typed -package domain -destination changestream_mock_test.go github.com/juju/juju/core/changestream Subscription,EventSource -//go:generate go run go.uber.org/mock/mockgen -typed -package domain -destination leasechecker_mock_test.go github.com/juju/juju/domain LeaseCheckerWaiter -//go:generate go run go.uber.org/mock/mockgen -typed -package domain -destination lease_mock_test.go github.com/juju/juju/core/lease Token +//go:generate go run go.uber.org/mock/mockgen -typed -package domain -destination lease_mock_test.go github.com/juju/juju/core/lease Token,LeaseCheckerWaiter func TestPackage(t *testing.T) { defer goleak.VerifyNone(t) diff --git a/domain/services/model.go b/domain/services/model.go index 1e41509092d..4b75bae8430 100644 --- a/domain/services/model.go +++ b/domain/services/model.go @@ -10,6 +10,7 @@ import ( "github.com/juju/clock" "github.com/juju/juju/core/changestream" + "github.com/juju/juju/core/lease" "github.com/juju/juju/core/logger" "github.com/juju/juju/core/model" "github.com/juju/juju/core/objectstore" @@ -98,6 +99,7 @@ func NewModelFactory( objectStore objectstore.ModelObjectStoreGetter, storageRegistry corestorage.ModelStorageRegistryGetter, publicKeyImporter PublicKeyImporter, + leaseManager lease.ModelApplicationLeaseManagerGetter, clock clock.Clock, logger logger.Logger, ) *ModelFactory { diff --git a/domain/services/service.go b/domain/services/service.go index 624c5e4f169..20e007cc696 100644 --- a/domain/services/service.go +++ b/domain/services/service.go @@ -8,6 +8,7 @@ import ( "github.com/juju/juju/core/changestream" "github.com/juju/juju/core/database" + "github.com/juju/juju/core/lease" "github.com/juju/juju/core/logger" "github.com/juju/juju/core/model" "github.com/juju/juju/core/objectstore" @@ -32,6 +33,7 @@ func NewDomainServices( objectStore objectstore.ModelObjectStoreGetter, storageRegistry storage.ModelStorageRegistryGetter, publicKeyImporter PublicKeyImporter, + leaseManager lease.ModelApplicationLeaseManagerGetter, clock clock.Clock, logger logger.Logger, ) *DomainServices { @@ -46,6 +48,7 @@ func NewDomainServices( objectStore, storageRegistry, publicKeyImporter, + leaseManager, clock, logger, ), diff --git a/domain/services/testing/suite.go b/domain/services/testing/suite.go index 26acf45e001..ba780009aaa 100644 --- a/domain/services/testing/suite.go +++ b/domain/services/testing/suite.go @@ -17,6 +17,7 @@ import ( "github.com/juju/juju/cloud" "github.com/juju/juju/controller" "github.com/juju/juju/core/credential" + "github.com/juju/juju/core/lease" "github.com/juju/juju/core/model" coremodel "github.com/juju/juju/core/model" modeltesting "github.com/juju/juju/core/model/testing" @@ -97,19 +98,19 @@ func (s stubDBDeleter) DeleteDB(namespace string) error { // ControllerDomainServices conveniently constructs a domain services for the // controller model. func (s *DomainServicesSuite) ControllerDomainServices(c *gc.C) services.DomainServices { - return s.DomainServicesGetter(c, TestingObjectStore{})(s.ControllerModelUUID) + return s.DomainServicesGetter(c, TestingObjectStore{}, TestingLeaseManager{})(s.ControllerModelUUID) } // DefaultModelDomainServices conveniently constructs a domain services for the // default model. func (s *DomainServicesSuite) DefaultModelDomainServices(c *gc.C) services.DomainServices { - return s.DomainServicesGetter(c, TestingObjectStore{})(s.ControllerModelUUID) + return s.DomainServicesGetter(c, TestingObjectStore{}, TestingLeaseManager{})(s.ControllerModelUUID) } // ModelDomainServices conveniently constructs a domain services for the // default model. func (s *DomainServicesSuite) ModelDomainServices(c *gc.C, modelUUID model.UUID) services.DomainServices { - return s.DomainServicesGetter(c, TestingObjectStore{})(modelUUID) + return s.DomainServicesGetter(c, TestingObjectStore{}, TestingLeaseManager{})(modelUUID) } func (s *DomainServicesSuite) SeedControllerConfig(c *gc.C) { @@ -234,8 +235,8 @@ func (s *DomainServicesSuite) SeedModelDatabases(c *gc.C) { // DomainServicesGetter provides an implementation of the DomainServicesGetter // interface to use in tests. This includes the dummy storage registry. -func (s *DomainServicesSuite) DomainServicesGetter(c *gc.C, objectStore coreobjectstore.ObjectStore) DomainServicesGetterFunc { - return s.DomainServicesGetterWithStorageRegistry(c, objectStore, storage.ChainedProviderRegistry{ +func (s *DomainServicesSuite) DomainServicesGetter(c *gc.C, objectStore coreobjectstore.ObjectStore, leaseManager lease.LeaseCheckerWaiter) DomainServicesGetterFunc { + return s.DomainServicesGetterWithStorageRegistry(c, objectStore, leaseManager, storage.ChainedProviderRegistry{ // Using the dummy storage provider for testing purposes isn't // ideal. We should potentially use a mock storage provider // instead. @@ -247,7 +248,7 @@ func (s *DomainServicesSuite) DomainServicesGetter(c *gc.C, objectStore coreobje // DomainServicesGetterWithStorageRegistry provides an implementation of the // DomainServicesGetterWithStorageRegistry interface to use in tests with the // additional storage provider. -func (s *DomainServicesSuite) DomainServicesGetterWithStorageRegistry(c *gc.C, objectStore coreobjectstore.ObjectStore, storageRegistry storage.ProviderRegistry) DomainServicesGetterFunc { +func (s *DomainServicesSuite) DomainServicesGetterWithStorageRegistry(c *gc.C, objectStore coreobjectstore.ObjectStore, leaseManager lease.LeaseCheckerWaiter, storageRegistry storage.ProviderRegistry) DomainServicesGetterFunc { return func(modelUUID coremodel.UUID) services.DomainServices { return domainservicefactory.NewDomainServices( databasetesting.ConstFactory(s.TxnRunner()), @@ -262,6 +263,9 @@ func (s *DomainServicesSuite) DomainServicesGetterWithStorageRegistry(c *gc.C, o return storageRegistry, nil }), sshimporter.NewImporter(&http.Client{}), + modelApplicationLeaseManagerGetter(func() lease.LeaseCheckerWaiter { + return leaseManager + }), clock.WallClock, loggertesting.WrapCheckLog(c), ) @@ -286,6 +290,11 @@ func (s *DomainServicesSuite) NoopObjectStore(c *gc.C) coreobjectstore.ObjectSto return TestingObjectStore{} } +// NoopLeaseManager returns a no-op implementation of the LeaseCheckerWaiter. +func (s *DomainServicesSuite) NoopLeaseManager(c *gc.C) lease.LeaseCheckerWaiter { + return TestingLeaseManager{} +} + // SetUpTest creates the controller and default model unique identifiers if they // have not already been set. Also seeds the initial database with the models. func (s *DomainServicesSuite) SetUpTest(c *gc.C) { @@ -335,6 +344,12 @@ func (s modelStorageRegistryGetter) GetStorageRegistry(ctx context.Context) (sto return s(ctx) } +type modelApplicationLeaseManagerGetter func() lease.LeaseCheckerWaiter + +func (s modelApplicationLeaseManagerGetter) GetLeaseManager() (lease.LeaseCheckerWaiter, error) { + return s(), nil +} + // TestingObjectStore is a testing implementation of the ObjectStore interface. type TestingObjectStore struct{} @@ -359,3 +374,32 @@ func (TestingObjectStore) PutAndCheckHash(ctx context.Context, path string, r io func (TestingObjectStore) Remove(ctx context.Context, path string) error { return nil } + +// TestingLeaseManager is a testing implementation of the LeaseCheckerWaiter +// interface. It returns canned responses for the methods. +type TestingLeaseManager struct{} + +// WaitUntilExpired returns nil when the named lease is no longer held. If +// it returns any error, no reasonable inferences may be made. The supplied +// context can be used to cancel the request; in this case, the method will +// return ErrWaitCancelled. +// The started channel when non-nil is closed when the wait begins. +func (TestingLeaseManager) WaitUntilExpired(ctx context.Context, leaseName string, started chan<- struct{}) error { + close(started) + + return nil +} + +// Token returns a Token that can be interrogated at any time to discover +// whether the supplied lease is currently held by the supplied holder. +func (TestingLeaseManager) Token(leaseName, holderName string) lease.Token { + return TestingLeaseManagerToken{} +} + +// TestingLeaseManagerToken is a testing implementation of the Token interface. +type TestingLeaseManagerToken struct{} + +// Check will always return lease.ErrNotHeld. +func (TestingLeaseManagerToken) Check() error { + return lease.ErrNotHeld +} diff --git a/internal/worker/domainservices/lease_mock_test.go b/internal/worker/domainservices/lease_mock_test.go new file mode 100644 index 00000000000..9b54323ea1d --- /dev/null +++ b/internal/worker/domainservices/lease_mock_test.go @@ -0,0 +1,460 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/juju/juju/core/lease (interfaces: LeaseCheckerWaiter,Manager,ApplicationLeaseManagerGetter,ModelApplicationLeaseManagerGetter) +// +// Generated by this command: +// +// mockgen -typed -package domainservices -destination lease_mock_test.go github.com/juju/juju/core/lease LeaseCheckerWaiter,Manager,ApplicationLeaseManagerGetter,ModelApplicationLeaseManagerGetter +// + +// Package domainservices is a generated GoMock package. +package domainservices + +import ( + context "context" + reflect "reflect" + + lease "github.com/juju/juju/core/lease" + model "github.com/juju/juju/core/model" + gomock "go.uber.org/mock/gomock" +) + +// MockLeaseCheckerWaiter is a mock of LeaseCheckerWaiter interface. +type MockLeaseCheckerWaiter struct { + ctrl *gomock.Controller + recorder *MockLeaseCheckerWaiterMockRecorder +} + +// MockLeaseCheckerWaiterMockRecorder is the mock recorder for MockLeaseCheckerWaiter. +type MockLeaseCheckerWaiterMockRecorder struct { + mock *MockLeaseCheckerWaiter +} + +// NewMockLeaseCheckerWaiter creates a new mock instance. +func NewMockLeaseCheckerWaiter(ctrl *gomock.Controller) *MockLeaseCheckerWaiter { + mock := &MockLeaseCheckerWaiter{ctrl: ctrl} + mock.recorder = &MockLeaseCheckerWaiterMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockLeaseCheckerWaiter) EXPECT() *MockLeaseCheckerWaiterMockRecorder { + return m.recorder +} + +// Token mocks base method. +func (m *MockLeaseCheckerWaiter) Token(arg0, arg1 string) lease.Token { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Token", arg0, arg1) + ret0, _ := ret[0].(lease.Token) + return ret0 +} + +// Token indicates an expected call of Token. +func (mr *MockLeaseCheckerWaiterMockRecorder) Token(arg0, arg1 any) *MockLeaseCheckerWaiterTokenCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Token", reflect.TypeOf((*MockLeaseCheckerWaiter)(nil).Token), arg0, arg1) + return &MockLeaseCheckerWaiterTokenCall{Call: call} +} + +// MockLeaseCheckerWaiterTokenCall wrap *gomock.Call +type MockLeaseCheckerWaiterTokenCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockLeaseCheckerWaiterTokenCall) Return(arg0 lease.Token) *MockLeaseCheckerWaiterTokenCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockLeaseCheckerWaiterTokenCall) Do(f func(string, string) lease.Token) *MockLeaseCheckerWaiterTokenCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockLeaseCheckerWaiterTokenCall) DoAndReturn(f func(string, string) lease.Token) *MockLeaseCheckerWaiterTokenCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// WaitUntilExpired mocks base method. +func (m *MockLeaseCheckerWaiter) WaitUntilExpired(arg0 context.Context, arg1 string, arg2 chan<- struct{}) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WaitUntilExpired", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// WaitUntilExpired indicates an expected call of WaitUntilExpired. +func (mr *MockLeaseCheckerWaiterMockRecorder) WaitUntilExpired(arg0, arg1, arg2 any) *MockLeaseCheckerWaiterWaitUntilExpiredCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WaitUntilExpired", reflect.TypeOf((*MockLeaseCheckerWaiter)(nil).WaitUntilExpired), arg0, arg1, arg2) + return &MockLeaseCheckerWaiterWaitUntilExpiredCall{Call: call} +} + +// MockLeaseCheckerWaiterWaitUntilExpiredCall wrap *gomock.Call +type MockLeaseCheckerWaiterWaitUntilExpiredCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockLeaseCheckerWaiterWaitUntilExpiredCall) Return(arg0 error) *MockLeaseCheckerWaiterWaitUntilExpiredCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockLeaseCheckerWaiterWaitUntilExpiredCall) Do(f func(context.Context, string, chan<- struct{}) error) *MockLeaseCheckerWaiterWaitUntilExpiredCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockLeaseCheckerWaiterWaitUntilExpiredCall) DoAndReturn(f func(context.Context, string, chan<- struct{}) error) *MockLeaseCheckerWaiterWaitUntilExpiredCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// MockManager is a mock of Manager interface. +type MockManager struct { + ctrl *gomock.Controller + recorder *MockManagerMockRecorder +} + +// MockManagerMockRecorder is the mock recorder for MockManager. +type MockManagerMockRecorder struct { + mock *MockManager +} + +// NewMockManager creates a new mock instance. +func NewMockManager(ctrl *gomock.Controller) *MockManager { + mock := &MockManager{ctrl: ctrl} + mock.recorder = &MockManagerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockManager) EXPECT() *MockManagerMockRecorder { + return m.recorder +} + +// Checker mocks base method. +func (m *MockManager) Checker(arg0, arg1 string) (lease.Checker, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Checker", arg0, arg1) + ret0, _ := ret[0].(lease.Checker) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Checker indicates an expected call of Checker. +func (mr *MockManagerMockRecorder) Checker(arg0, arg1 any) *MockManagerCheckerCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Checker", reflect.TypeOf((*MockManager)(nil).Checker), arg0, arg1) + return &MockManagerCheckerCall{Call: call} +} + +// MockManagerCheckerCall wrap *gomock.Call +type MockManagerCheckerCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockManagerCheckerCall) Return(arg0 lease.Checker, arg1 error) *MockManagerCheckerCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockManagerCheckerCall) Do(f func(string, string) (lease.Checker, error)) *MockManagerCheckerCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockManagerCheckerCall) DoAndReturn(f func(string, string) (lease.Checker, error)) *MockManagerCheckerCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// Claimer mocks base method. +func (m *MockManager) Claimer(arg0, arg1 string) (lease.Claimer, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Claimer", arg0, arg1) + ret0, _ := ret[0].(lease.Claimer) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Claimer indicates an expected call of Claimer. +func (mr *MockManagerMockRecorder) Claimer(arg0, arg1 any) *MockManagerClaimerCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Claimer", reflect.TypeOf((*MockManager)(nil).Claimer), arg0, arg1) + return &MockManagerClaimerCall{Call: call} +} + +// MockManagerClaimerCall wrap *gomock.Call +type MockManagerClaimerCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockManagerClaimerCall) Return(arg0 lease.Claimer, arg1 error) *MockManagerClaimerCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockManagerClaimerCall) Do(f func(string, string) (lease.Claimer, error)) *MockManagerClaimerCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockManagerClaimerCall) DoAndReturn(f func(string, string) (lease.Claimer, error)) *MockManagerClaimerCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// Pinner mocks base method. +func (m *MockManager) Pinner(arg0, arg1 string) (lease.Pinner, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Pinner", arg0, arg1) + ret0, _ := ret[0].(lease.Pinner) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Pinner indicates an expected call of Pinner. +func (mr *MockManagerMockRecorder) Pinner(arg0, arg1 any) *MockManagerPinnerCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Pinner", reflect.TypeOf((*MockManager)(nil).Pinner), arg0, arg1) + return &MockManagerPinnerCall{Call: call} +} + +// MockManagerPinnerCall wrap *gomock.Call +type MockManagerPinnerCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockManagerPinnerCall) Return(arg0 lease.Pinner, arg1 error) *MockManagerPinnerCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockManagerPinnerCall) Do(f func(string, string) (lease.Pinner, error)) *MockManagerPinnerCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockManagerPinnerCall) DoAndReturn(f func(string, string) (lease.Pinner, error)) *MockManagerPinnerCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// Reader mocks base method. +func (m *MockManager) Reader(arg0, arg1 string) (lease.Reader, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Reader", arg0, arg1) + ret0, _ := ret[0].(lease.Reader) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Reader indicates an expected call of Reader. +func (mr *MockManagerMockRecorder) Reader(arg0, arg1 any) *MockManagerReaderCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Reader", reflect.TypeOf((*MockManager)(nil).Reader), arg0, arg1) + return &MockManagerReaderCall{Call: call} +} + +// MockManagerReaderCall wrap *gomock.Call +type MockManagerReaderCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockManagerReaderCall) Return(arg0 lease.Reader, arg1 error) *MockManagerReaderCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockManagerReaderCall) Do(f func(string, string) (lease.Reader, error)) *MockManagerReaderCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockManagerReaderCall) DoAndReturn(f func(string, string) (lease.Reader, error)) *MockManagerReaderCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// Revoker mocks base method. +func (m *MockManager) Revoker(arg0, arg1 string) (lease.Revoker, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Revoker", arg0, arg1) + ret0, _ := ret[0].(lease.Revoker) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Revoker indicates an expected call of Revoker. +func (mr *MockManagerMockRecorder) Revoker(arg0, arg1 any) *MockManagerRevokerCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Revoker", reflect.TypeOf((*MockManager)(nil).Revoker), arg0, arg1) + return &MockManagerRevokerCall{Call: call} +} + +// MockManagerRevokerCall wrap *gomock.Call +type MockManagerRevokerCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockManagerRevokerCall) Return(arg0 lease.Revoker, arg1 error) *MockManagerRevokerCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockManagerRevokerCall) Do(f func(string, string) (lease.Revoker, error)) *MockManagerRevokerCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockManagerRevokerCall) DoAndReturn(f func(string, string) (lease.Revoker, error)) *MockManagerRevokerCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// MockApplicationLeaseManagerGetter is a mock of ApplicationLeaseManagerGetter interface. +type MockApplicationLeaseManagerGetter struct { + ctrl *gomock.Controller + recorder *MockApplicationLeaseManagerGetterMockRecorder +} + +// MockApplicationLeaseManagerGetterMockRecorder is the mock recorder for MockApplicationLeaseManagerGetter. +type MockApplicationLeaseManagerGetterMockRecorder struct { + mock *MockApplicationLeaseManagerGetter +} + +// NewMockApplicationLeaseManagerGetter creates a new mock instance. +func NewMockApplicationLeaseManagerGetter(ctrl *gomock.Controller) *MockApplicationLeaseManagerGetter { + mock := &MockApplicationLeaseManagerGetter{ctrl: ctrl} + mock.recorder = &MockApplicationLeaseManagerGetterMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockApplicationLeaseManagerGetter) EXPECT() *MockApplicationLeaseManagerGetterMockRecorder { + return m.recorder +} + +// GetLeaseManager mocks base method. +func (m *MockApplicationLeaseManagerGetter) GetLeaseManager(arg0 model.UUID) (lease.LeaseCheckerWaiter, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLeaseManager", arg0) + ret0, _ := ret[0].(lease.LeaseCheckerWaiter) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetLeaseManager indicates an expected call of GetLeaseManager. +func (mr *MockApplicationLeaseManagerGetterMockRecorder) GetLeaseManager(arg0 any) *MockApplicationLeaseManagerGetterGetLeaseManagerCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLeaseManager", reflect.TypeOf((*MockApplicationLeaseManagerGetter)(nil).GetLeaseManager), arg0) + return &MockApplicationLeaseManagerGetterGetLeaseManagerCall{Call: call} +} + +// MockApplicationLeaseManagerGetterGetLeaseManagerCall wrap *gomock.Call +type MockApplicationLeaseManagerGetterGetLeaseManagerCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockApplicationLeaseManagerGetterGetLeaseManagerCall) Return(arg0 lease.LeaseCheckerWaiter, arg1 error) *MockApplicationLeaseManagerGetterGetLeaseManagerCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockApplicationLeaseManagerGetterGetLeaseManagerCall) Do(f func(model.UUID) (lease.LeaseCheckerWaiter, error)) *MockApplicationLeaseManagerGetterGetLeaseManagerCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockApplicationLeaseManagerGetterGetLeaseManagerCall) DoAndReturn(f func(model.UUID) (lease.LeaseCheckerWaiter, error)) *MockApplicationLeaseManagerGetterGetLeaseManagerCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// MockModelApplicationLeaseManagerGetter is a mock of ModelApplicationLeaseManagerGetter interface. +type MockModelApplicationLeaseManagerGetter struct { + ctrl *gomock.Controller + recorder *MockModelApplicationLeaseManagerGetterMockRecorder +} + +// MockModelApplicationLeaseManagerGetterMockRecorder is the mock recorder for MockModelApplicationLeaseManagerGetter. +type MockModelApplicationLeaseManagerGetterMockRecorder struct { + mock *MockModelApplicationLeaseManagerGetter +} + +// NewMockModelApplicationLeaseManagerGetter creates a new mock instance. +func NewMockModelApplicationLeaseManagerGetter(ctrl *gomock.Controller) *MockModelApplicationLeaseManagerGetter { + mock := &MockModelApplicationLeaseManagerGetter{ctrl: ctrl} + mock.recorder = &MockModelApplicationLeaseManagerGetterMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockModelApplicationLeaseManagerGetter) EXPECT() *MockModelApplicationLeaseManagerGetterMockRecorder { + return m.recorder +} + +// GetLeaseManager mocks base method. +func (m *MockModelApplicationLeaseManagerGetter) GetLeaseManager() (lease.LeaseCheckerWaiter, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLeaseManager") + ret0, _ := ret[0].(lease.LeaseCheckerWaiter) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetLeaseManager indicates an expected call of GetLeaseManager. +func (mr *MockModelApplicationLeaseManagerGetterMockRecorder) GetLeaseManager() *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLeaseManager", reflect.TypeOf((*MockModelApplicationLeaseManagerGetter)(nil).GetLeaseManager)) + return &MockModelApplicationLeaseManagerGetterGetLeaseManagerCall{Call: call} +} + +// MockModelApplicationLeaseManagerGetterGetLeaseManagerCall wrap *gomock.Call +type MockModelApplicationLeaseManagerGetterGetLeaseManagerCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall) Return(arg0 lease.LeaseCheckerWaiter, arg1 error) *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall) Do(f func() (lease.LeaseCheckerWaiter, error)) *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall) DoAndReturn(f func() (lease.LeaseCheckerWaiter, error)) *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { + c.Call = c.Call.DoAndReturn(f) + return c +} diff --git a/internal/worker/domainservices/manifold.go b/internal/worker/domainservices/manifold.go index 91c25a64b3c..625e66a956f 100644 --- a/internal/worker/domainservices/manifold.go +++ b/internal/worker/domainservices/manifold.go @@ -14,6 +14,7 @@ import ( "github.com/juju/juju/core/changestream" coredatabase "github.com/juju/juju/core/database" corehttp "github.com/juju/juju/core/http" + "github.com/juju/juju/core/lease" "github.com/juju/juju/core/logger" coremodel "github.com/juju/juju/core/model" "github.com/juju/juju/core/objectstore" @@ -34,6 +35,7 @@ type ManifoldConfig struct { ObjectStoreName string StorageRegistryName string HTTPClientName string + LeaseManagerName string Logger logger.Logger Clock clock.Clock NewWorker func(Config) (worker.Worker, error) @@ -51,6 +53,7 @@ type DomainServicesGetterFn func( objectstore.ObjectStoreGetter, storage.StorageRegistryGetter, domainservices.PublicKeyImporter, + lease.Manager, clock.Clock, logger.Logger, ) services.DomainServicesGetter @@ -72,6 +75,7 @@ type ModelDomainServicesFn func( objectstore.ModelObjectStoreGetter, storage.ModelStorageRegistryGetter, domainservices.PublicKeyImporter, + lease.ModelApplicationLeaseManagerGetter, clock.Clock, logger.Logger, ) services.ModelDomainServices @@ -96,6 +100,9 @@ func (config ManifoldConfig) Validate() error { if config.HTTPClientName == "" { return errors.NotValidf("empty HTTPClientName") } + if config.LeaseManagerName == "" { + return errors.NotValidf("empty LeaseManagerName") + } if config.NewWorker == nil { return errors.NotValidf("nil NewWorker") } @@ -128,6 +135,7 @@ func Manifold(config ManifoldConfig) dependency.Manifold { config.ObjectStoreName, config.StorageRegistryName, config.HTTPClientName, + config.LeaseManagerName, }, Start: config.start, Output: config.output, @@ -175,6 +183,11 @@ func (config ManifoldConfig) start(ctx context.Context, getter dependency.Getter return nil, errors.Trace(err) } + var leaseManager lease.Manager + if err := getter.Get(config.LeaseManagerName, &leaseManager); err != nil { + return nil, errors.Trace(err) + } + return config.NewWorker(Config{ DBGetter: dbGetter, DBDeleter: dbDeleter, @@ -182,6 +195,7 @@ func (config ManifoldConfig) start(ctx context.Context, getter dependency.Getter ObjectStoreGetter: objectStoreGetter, StorageRegistryGetter: storageRegistryGetter, PublicKeyImporter: sshimporter.NewImporter(sshImporterClient), + LeaseManager: leaseManager, Logger: config.Logger, Clock: config.Clock, NewDomainServicesGetter: config.NewDomainServicesGetter, @@ -236,6 +250,7 @@ func NewProviderTrackerModelDomainServices( objectStore objectstore.ModelObjectStoreGetter, storageRegistry storage.ModelStorageRegistryGetter, publicKeyImporter domainservices.PublicKeyImporter, + leaseManager lease.ModelApplicationLeaseManagerGetter, clock clock.Clock, logger logger.Logger, ) services.ModelDomainServices { @@ -247,6 +262,7 @@ func NewProviderTrackerModelDomainServices( objectStore, storageRegistry, publicKeyImporter, + leaseManager, clock, logger, ) @@ -261,6 +277,7 @@ func NewDomainServicesGetter( objectStoreGetter objectstore.ObjectStoreGetter, storageRegistryGetter storage.StorageRegistryGetter, publicKeyImporter domainservices.PublicKeyImporter, + leaseManager lease.Manager, clock clock.Clock, logger logger.Logger, ) services.DomainServicesGetter { @@ -274,6 +291,7 @@ func NewDomainServicesGetter( objectStoreGetter: objectStoreGetter, storageRegistryGetter: storageRegistryGetter, publicKeyImporter: publicKeyImporter, + leaseManager: leaseManager, } } diff --git a/internal/worker/domainservices/manifold_test.go b/internal/worker/domainservices/manifold_test.go index 091d09e0a88..35aa8328dcb 100644 --- a/internal/worker/domainservices/manifold_test.go +++ b/internal/worker/domainservices/manifold_test.go @@ -18,6 +18,7 @@ import ( "github.com/juju/juju/core/changestream" coredatabase "github.com/juju/juju/core/database" corehttp "github.com/juju/juju/core/http" + "github.com/juju/juju/core/lease" "github.com/juju/juju/core/logger" coremodel "github.com/juju/juju/core/model" "github.com/juju/juju/core/objectstore" @@ -67,6 +68,10 @@ func (s *manifoldSuite) TestValidateConfig(c *gc.C) { cfg.HTTPClientName = "" c.Check(cfg.Validate(), jc.ErrorIs, errors.NotValid) + cfg = s.getConfig() + cfg.LeaseManagerName = "" + c.Check(cfg.Validate(), jc.ErrorIs, errors.NotValid) + cfg = s.getConfig() cfg.NewWorker = nil c.Check(cfg.Validate(), jc.ErrorIs, errors.NotValid) @@ -100,6 +105,7 @@ func (s *manifoldSuite) TestStart(c *gc.C) { "objectstore": s.objectStoreGetter, "storageregistry": s.storageRegistryGetter, "httpclient": s.httpClientGetter, + "leasemanager": s.leaseManager, } manifold := Manifold(ManifoldConfig{ @@ -109,6 +115,7 @@ func (s *manifoldSuite) TestStart(c *gc.C) { ObjectStoreName: "objectstore", StorageRegistryName: "storageregistry", HTTPClientName: "httpclient", + LeaseManagerName: "leasemanager", Logger: s.logger, NewWorker: NewWorker, NewDomainServicesGetter: NewDomainServicesGetter, @@ -134,6 +141,7 @@ func (s *manifoldSuite) TestOutputControllerDomainServices(c *gc.C) { ObjectStoreGetter: s.objectStoreGetter, StorageRegistryGetter: s.storageRegistryGetter, PublicKeyImporter: s.publicKeyImporter, + LeaseManager: s.leaseManager, NewDomainServicesGetter: NewDomainServicesGetter, NewControllerDomainServices: NewControllerDomainServices, NewModelDomainServices: NewProviderTrackerModelDomainServices, @@ -160,6 +168,7 @@ func (s *manifoldSuite) TestOutputDomainServicesGetter(c *gc.C) { ObjectStoreGetter: s.objectStoreGetter, StorageRegistryGetter: s.storageRegistryGetter, PublicKeyImporter: s.publicKeyImporter, + LeaseManager: s.leaseManager, NewDomainServicesGetter: NewDomainServicesGetter, NewControllerDomainServices: NewControllerDomainServices, NewModelDomainServices: NewProviderTrackerModelDomainServices, @@ -186,6 +195,7 @@ func (s *manifoldSuite) TestOutputInvalid(c *gc.C) { ObjectStoreGetter: s.objectStoreGetter, StorageRegistryGetter: s.storageRegistryGetter, PublicKeyImporter: s.publicKeyImporter, + LeaseManager: s.leaseManager, NewDomainServicesGetter: NewDomainServicesGetter, NewControllerDomainServices: NewControllerDomainServices, NewModelDomainServices: NewProviderTrackerModelDomainServices, @@ -213,6 +223,7 @@ func (s *manifoldSuite) TestNewModelDomainServices(c *gc.C) { s.modelObjectStoreGetter, s.modelStorageRegistryGetter, s.publicKeyImporter, + s.modelApplicationLeaseManagerGetter, s.clock, s.logger, ) @@ -229,6 +240,7 @@ func (s *manifoldSuite) TestNewDomainServicesGetter(c *gc.C) { s.objectStoreGetter, s.storageRegistryGetter, s.publicKeyImporter, + s.leaseManager, s.clock, s.logger, ) @@ -246,6 +258,7 @@ func (s *manifoldSuite) getConfig() ManifoldConfig { ObjectStoreName: "objectstore", StorageRegistryName: "storageregistry", HTTPClientName: "httpclient", + LeaseManagerName: "leasemanager", Clock: s.clock, Logger: s.logger, NewWorker: func(Config) (worker.Worker, error) { @@ -265,6 +278,7 @@ func noopDomainServicesGetter( objectstore.ObjectStoreGetter, storage.StorageRegistryGetter, domainservices.PublicKeyImporter, + lease.Manager, clock.Clock, logger.Logger, ) services.DomainServicesGetter { @@ -287,6 +301,7 @@ func noopModelDomainServices( objectstore.ModelObjectStoreGetter, storage.ModelStorageRegistryGetter, domainservices.PublicKeyImporter, + lease.ModelApplicationLeaseManagerGetter, clock.Clock, logger.Logger, ) services.ModelDomainServices { diff --git a/internal/worker/domainservices/package_test.go b/internal/worker/domainservices/package_test.go index 8a8eb3c4256..283eb263bb1 100644 --- a/internal/worker/domainservices/package_test.go +++ b/internal/worker/domainservices/package_test.go @@ -13,6 +13,7 @@ import ( changestream "github.com/juju/juju/core/changestream" coredatabase "github.com/juju/juju/core/database" + "github.com/juju/juju/core/lease" "github.com/juju/juju/core/logger" coremodel "github.com/juju/juju/core/model" "github.com/juju/juju/core/objectstore" @@ -31,6 +32,7 @@ import ( //go:generate go run go.uber.org/mock/mockgen -typed -package domainservices -destination objectstore_mock_test.go github.com/juju/juju/core/objectstore ObjectStore,ObjectStoreGetter,ModelObjectStoreGetter //go:generate go run go.uber.org/mock/mockgen -typed -package domainservices -destination storage_mock_test.go github.com/juju/juju/core/storage StorageRegistryGetter,ModelStorageRegistryGetter //go:generate go run go.uber.org/mock/mockgen -typed -package domainservices -destination http_mock_test.go github.com/juju/juju/core/http HTTPClientGetter,HTTPClient +//go:generate go run go.uber.org/mock/mockgen -typed -package domainservices -destination lease_mock_test.go github.com/juju/juju/core/lease LeaseCheckerWaiter,Manager,ApplicationLeaseManagerGetter,ModelApplicationLeaseManagerGetter func TestPackage(t *testing.T) { gc.TestingT(t) @@ -61,6 +63,10 @@ type baseSuite struct { httpClientGetter *MockHTTPClientGetter httpClient *MockHTTPClient + leaseManager *MockManager + applicationLeaseManagerGetter *MockApplicationLeaseManagerGetter + modelApplicationLeaseManagerGetter *MockModelApplicationLeaseManagerGetter + publicKeyImporter *sshimporter.Importer } @@ -89,6 +95,10 @@ func (s *baseSuite) setupMocks(c *gc.C) *gomock.Controller { s.httpClientGetter = NewMockHTTPClientGetter(ctrl) s.httpClient = NewMockHTTPClient(ctrl) + s.leaseManager = NewMockManager(ctrl) + s.applicationLeaseManagerGetter = NewMockApplicationLeaseManagerGetter(ctrl) + s.modelApplicationLeaseManagerGetter = NewMockModelApplicationLeaseManagerGetter(ctrl) + s.publicKeyImporter = sshimporter.NewImporter(&http.Client{}) return ctrl @@ -103,6 +113,7 @@ func NewModelDomainServices( objectStore objectstore.ModelObjectStoreGetter, storageRegistry storage.ModelStorageRegistryGetter, publicKeyImporter domainservices.PublicKeyImporter, + leaseManager lease.ModelApplicationLeaseManagerGetter, clock clock.Clock, logger logger.Logger, ) services.ModelDomainServices { @@ -114,6 +125,7 @@ func NewModelDomainServices( objectStore, storageRegistry, publicKeyImporter, + leaseManager, clock, logger, ) diff --git a/internal/worker/domainservices/worker.go b/internal/worker/domainservices/worker.go index 414147b3a0a..f1e20024d4d 100644 --- a/internal/worker/domainservices/worker.go +++ b/internal/worker/domainservices/worker.go @@ -13,6 +13,7 @@ import ( "github.com/juju/juju/core/changestream" coredatabase "github.com/juju/juju/core/database" + "github.com/juju/juju/core/lease" "github.com/juju/juju/core/logger" coremodel "github.com/juju/juju/core/model" "github.com/juju/juju/core/objectstore" @@ -40,8 +41,12 @@ type Config struct { // StorageRegistryGetter is used to get storage registry instances. StorageRegistryGetter storage.StorageRegistryGetter + // PublicKeyImporter is used to import public keys. PublicKeyImporter domainservices.PublicKeyImporter + // LeaseManager is used to manage leases. + LeaseManager lease.Manager + // Logger is used to log messages. Logger logger.Logger @@ -73,6 +78,10 @@ func (config Config) Validate() error { if config.PublicKeyImporter == nil { return errors.NotValidf("nil PublicKeyImporter") } + + if config.LeaseManager == nil { + return errors.NotValidf("nil LeaseManager") + } if config.Logger == nil { return errors.NotValidf("nil Logger") } @@ -108,6 +117,7 @@ func NewWorker(config Config) (worker.Worker, error) { config.ObjectStoreGetter, config.StorageRegistryGetter, config.PublicKeyImporter, + config.LeaseManager, config.Clock, config.Logger, ), @@ -173,6 +183,7 @@ type domainServicesGetter struct { objectStoreGetter objectstore.ObjectStoreGetter storageRegistryGetter storage.StorageRegistryGetter publicKeyImporter domainservices.PublicKeyImporter + leaseManager lease.Manager } // ServicesForModel returns the domain services for the given model uuid. @@ -192,6 +203,10 @@ func (s *domainServicesGetter) ServicesForModel(modelUUID coremodel.UUID) servic storageRegistryGetter: s.storageRegistryGetter, }, s.publicKeyImporter, + modelApplicationLeaseManager{ + modelUUID: modelUUID, + manager: s.leaseManager, + }, s.clock, s.logger, ), @@ -224,3 +239,49 @@ type modelStorageRegistryGetter struct { func (s modelStorageRegistryGetter) GetStorageRegistry(ctx context.Context) (internalstorage.ProviderRegistry, error) { return s.storageRegistryGetter.GetStorageRegistry(ctx, s.modelUUID.String()) } + +type modelApplicationLeaseManager struct { + modelUUID coremodel.UUID + manager lease.Manager +} + +// GetLeaseManager returns a lease manager for the given model UUID. +func (s modelApplicationLeaseManager) GetLeaseManager() (lease.LeaseCheckerWaiter, error) { + // TODO (stickupkid): These aren't cheap to make, so we should cache them + // and reuse them where possible. I'm not sure these should be workers, I'd + // be happy with a sync.Pool at minimum though. + claimer, err := s.manager.Claimer(lease.ApplicationLeadershipNamespace, s.modelUUID.String()) + if err != nil { + return nil, errors.Trace(err) + } + + checker, err := s.manager.Checker(lease.ApplicationLeadershipNamespace, s.modelUUID.String()) + if err != nil { + return nil, errors.Trace(err) + } + + return &leaseManager{ + claimer: claimer, + checker: checker, + }, nil +} + +type leaseManager struct { + claimer lease.Claimer + checker lease.Checker +} + +// WaitUntilExpired returns nil when the named lease is no longer held. If +// it returns any error, no reasonable inferences may be made. The supplied +// context can be used to cancel the request; in this case, the method will +// return ErrWaitCancelled. +// The started channel when non-nil is closed when the wait begins. +func (m *leaseManager) WaitUntilExpired(ctx context.Context, leaseName string, started chan<- struct{}) error { + return m.claimer.WaitUntilExpired(ctx, leaseName, started) +} + +// Token returns a Token that can be interrogated at any time to discover +// whether the supplied lease is currently held by the supplied holder. +func (m *leaseManager) Token(leaseName, holderName string) lease.Token { + return m.checker.Token(leaseName, holderName) +} diff --git a/internal/worker/domainservices/worker_test.go b/internal/worker/domainservices/worker_test.go index aafb42374a8..e124a894976 100644 --- a/internal/worker/domainservices/worker_test.go +++ b/internal/worker/domainservices/worker_test.go @@ -13,6 +13,7 @@ import ( "github.com/juju/juju/core/changestream" coredatabase "github.com/juju/juju/core/database" + "github.com/juju/juju/core/lease" "github.com/juju/juju/core/logger" coremodel "github.com/juju/juju/core/model" "github.com/juju/juju/core/objectstore" @@ -54,6 +55,14 @@ func (s *workerSuite) TestValidateConfig(c *gc.C) { cfg.ObjectStoreGetter = nil c.Check(cfg.Validate(), jc.ErrorIs, errors.NotValid) + cfg = s.getConfig() + cfg.StorageRegistryGetter = nil + c.Check(cfg.Validate(), jc.ErrorIs, errors.NotValid) + + cfg = s.getConfig() + cfg.LeaseManager = nil + c.Check(cfg.Validate(), jc.ErrorIs, errors.NotValid) + cfg = s.getConfig() cfg.NewDomainServicesGetter = nil c.Check(cfg.Validate(), jc.ErrorIs, errors.NotValid) @@ -83,6 +92,7 @@ func (s *workerSuite) getConfig() Config { ObjectStoreGetter: s.objectStoreGetter, StorageRegistryGetter: s.storageRegistryGetter, PublicKeyImporter: s.publicKeyImporter, + LeaseManager: s.leaseManager, Clock: s.clock, Logger: s.logger, NewDomainServicesGetter: func( @@ -93,6 +103,7 @@ func (s *workerSuite) getConfig() Config { objectstore.ObjectStoreGetter, storage.StorageRegistryGetter, domainservices.PublicKeyImporter, + lease.Manager, clock.Clock, logger.Logger, ) services.DomainServicesGetter { @@ -113,6 +124,7 @@ func (s *workerSuite) getConfig() Config { objectstore.ModelObjectStoreGetter, storage.ModelStorageRegistryGetter, domainservices.PublicKeyImporter, + lease.ModelApplicationLeaseManagerGetter, clock.Clock, logger.Logger, ) services.ModelDomainServices { diff --git a/juju/testing/apiserver.go b/juju/testing/apiserver.go index e0aa011cecc..a7ee959dc5a 100644 --- a/juju/testing/apiserver.go +++ b/juju/testing/apiserver.go @@ -259,10 +259,10 @@ func (s *ApiServerSuite) setupControllerModel(c *gc.C, controllerCfg controller. domainServices := s.ControllerDomainServices(c) storageServiceGetter := func(modelUUID coremodel.UUID) state.StoragePoolGetter { - return s.DomainServicesGetter(c, s.NoopObjectStore(c)).ServicesForModel(modelUUID).Storage() + return s.DomainServicesGetter(c, s.NoopObjectStore(c), s.NoopLeaseManager(c)).ServicesForModel(modelUUID).Storage() } modelConfigServiceGetter := func(modelUUID coremodel.UUID) stateenvirons.ModelConfigService { - return s.DomainServicesGetter(c, s.NoopObjectStore(c)).ServicesForModel(modelUUID).Config() + return s.DomainServicesGetter(c, s.NoopObjectStore(c), s.NoopLeaseManager(c)).ServicesForModel(modelUUID).Config() } ctrl, err := state.Initialize(state.InitializeParams{ Clock: clock.WallClock, @@ -318,7 +318,7 @@ func (s *ApiServerSuite) setupApiServer(c *gc.C, controllerCfg controller.Config cfg.Mux = s.mux cfg.DBGetter = stubDBGetter{db: stubWatchableDB{TxnRunner: s.TxnRunner()}} cfg.DBDeleter = stubDBDeleter{} - cfg.DomainServicesGetter = s.DomainServicesGetter(c, s.NoopObjectStore(c)) + cfg.DomainServicesGetter = s.DomainServicesGetter(c, s.NoopObjectStore(c), s.NoopLeaseManager(c)) cfg.StatePool = s.controller.StatePool() cfg.PublicDNSName = controllerCfg.AutocertDNSName() @@ -540,7 +540,7 @@ func (s *ApiServerSuite) NewFactory(c *gc.C, modelUUID string) (*factory.Factory st = pooledSt.State } - modelDomainServices := s.DomainServicesGetter(c, s.NoopObjectStore(c)).ServicesForModel(coremodel.UUID(modelUUID)) + modelDomainServices := s.DomainServicesGetter(c, s.NoopObjectStore(c), servicefactorytesting.TestingLeaseManager{}).ServicesForModel(coremodel.UUID(modelUUID)) applicationService := modelDomainServices.Application() return factory.NewFactory(st, s.controller.StatePool(), coretesting.FakeControllerConfig()). WithApplicationService(applicationService), releaser From a5590a803230f6d8dc1748c0ee834a46c2ea8136 Mon Sep 17 00:00:00 2001 From: Simon Richardson Date: Thu, 24 Oct 2024 14:41:14 +0100 Subject: [PATCH 2/4] refactor: use lease manager directly We can use the lease manager directly. The lease service takes a manager so that we can get the LeaseCheckerWaiter based on the model uuid. Considering the model uuid is per domain service scope we can get that without passing the uuid in the domain. --- domain/lease_mock_test.go | 66 +++++++++++++++++++++++++++++++++++-- domain/leaseservice.go | 9 +++-- domain/leaseservice_test.go | 21 +++++------- domain/package_test.go | 2 +- domain/services/model.go | 2 ++ 5 files changed, 81 insertions(+), 19 deletions(-) diff --git a/domain/lease_mock_test.go b/domain/lease_mock_test.go index 7bcddb8a84b..3e1958bbf70 100644 --- a/domain/lease_mock_test.go +++ b/domain/lease_mock_test.go @@ -1,9 +1,9 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/juju/juju/core/lease (interfaces: Token,LeaseCheckerWaiter) +// Source: github.com/juju/juju/core/lease (interfaces: Token,LeaseCheckerWaiter,ModelApplicationLeaseManagerGetter) // // Generated by this command: // -// mockgen -typed -package domain -destination lease_mock_test.go github.com/juju/juju/core/lease Token,LeaseCheckerWaiter +// mockgen -typed -package domain -destination lease_mock_test.go github.com/juju/juju/core/lease Token,LeaseCheckerWaiter,ModelApplicationLeaseManagerGetter // // Package domain is a generated GoMock package. @@ -176,3 +176,65 @@ func (c *MockLeaseCheckerWaiterWaitUntilExpiredCall) DoAndReturn(f func(context. c.Call = c.Call.DoAndReturn(f) return c } + +// MockModelApplicationLeaseManagerGetter is a mock of ModelApplicationLeaseManagerGetter interface. +type MockModelApplicationLeaseManagerGetter struct { + ctrl *gomock.Controller + recorder *MockModelApplicationLeaseManagerGetterMockRecorder +} + +// MockModelApplicationLeaseManagerGetterMockRecorder is the mock recorder for MockModelApplicationLeaseManagerGetter. +type MockModelApplicationLeaseManagerGetterMockRecorder struct { + mock *MockModelApplicationLeaseManagerGetter +} + +// NewMockModelApplicationLeaseManagerGetter creates a new mock instance. +func NewMockModelApplicationLeaseManagerGetter(ctrl *gomock.Controller) *MockModelApplicationLeaseManagerGetter { + mock := &MockModelApplicationLeaseManagerGetter{ctrl: ctrl} + mock.recorder = &MockModelApplicationLeaseManagerGetterMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockModelApplicationLeaseManagerGetter) EXPECT() *MockModelApplicationLeaseManagerGetterMockRecorder { + return m.recorder +} + +// GetLeaseManager mocks base method. +func (m *MockModelApplicationLeaseManagerGetter) GetLeaseManager() (lease.LeaseCheckerWaiter, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLeaseManager") + ret0, _ := ret[0].(lease.LeaseCheckerWaiter) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetLeaseManager indicates an expected call of GetLeaseManager. +func (mr *MockModelApplicationLeaseManagerGetterMockRecorder) GetLeaseManager() *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLeaseManager", reflect.TypeOf((*MockModelApplicationLeaseManagerGetter)(nil).GetLeaseManager)) + return &MockModelApplicationLeaseManagerGetterGetLeaseManagerCall{Call: call} +} + +// MockModelApplicationLeaseManagerGetterGetLeaseManagerCall wrap *gomock.Call +type MockModelApplicationLeaseManagerGetterGetLeaseManagerCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall) Return(arg0 lease.LeaseCheckerWaiter, arg1 error) *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall) Do(f func() (lease.LeaseCheckerWaiter, error)) *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall) DoAndReturn(f func() (lease.LeaseCheckerWaiter, error)) *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { + c.Call = c.Call.DoAndReturn(f) + return c +} diff --git a/domain/leaseservice.go b/domain/leaseservice.go index 29d5129cac0..8b8e8985aea 100644 --- a/domain/leaseservice.go +++ b/domain/leaseservice.go @@ -12,11 +12,11 @@ import ( // LeaseService creates a base service that offers lease capabilities. type LeaseService struct { - leaseChecker func() lease.LeaseCheckerWaiter + leaseChecker lease.ModelApplicationLeaseManagerGetter } // NewLeaseService creates a new LeaseService. -func NewLeaseService(leaseChecker func() lease.LeaseCheckerWaiter) *LeaseService { +func NewLeaseService(leaseChecker lease.ModelApplicationLeaseManagerGetter) *LeaseService { return &LeaseService{ leaseChecker: leaseChecker, } @@ -34,7 +34,10 @@ func (s *LeaseService) WithLease(ctx context.Context, leaseName, holderName stri return internalerrors.Errorf("lease prechecking").Add(ctx.Err()) } - leaseChecker := s.leaseChecker() + leaseChecker, err := s.leaseChecker.GetLeaseManager() + if err != nil { + return internalerrors.Errorf("getting lease manager: %w", err) + } // The leaseCtx will be cancelled when the lease is no longer held by the // lease holder. This may or may not be the same as the holderName for the diff --git a/domain/leaseservice_test.go b/domain/leaseservice_test.go index 4f05a78e149..aca3be77608 100644 --- a/domain/leaseservice_test.go +++ b/domain/leaseservice_test.go @@ -13,13 +13,13 @@ import ( "go.uber.org/mock/gomock" gc "gopkg.in/check.v1" - lease "github.com/juju/juju/core/lease" "github.com/juju/juju/internal/errors" ) type leaseServiceSuite struct { testing.IsolationSuite + modelLeaseManager *MockModelApplicationLeaseManagerGetter leaseCheckerWaiter *MockLeaseCheckerWaiter token *MockToken } @@ -49,9 +49,7 @@ func (s *leaseServiceSuite) TestWithLease(c *gc.C) { s.leaseCheckerWaiter.EXPECT().Token("leaseName", "holderName").Return(s.token) s.token.EXPECT().Check().Return(nil) - service := NewLeaseService(func() lease.LeaseCheckerWaiter { - return s.leaseCheckerWaiter - }) + service := NewLeaseService(s.modelLeaseManager) var called bool err := service.WithLease(context.Background(), "leaseName", "holderName", func(ctx context.Context) error { @@ -70,9 +68,7 @@ func (s *leaseServiceSuite) TestWithLeaseWaitReturnsError(c *gc.C) { return fmt.Errorf("not holding lease") }) - service := NewLeaseService(func() lease.LeaseCheckerWaiter { - return s.leaseCheckerWaiter - }) + service := NewLeaseService(s.modelLeaseManager) var called bool err := service.WithLease(context.Background(), "leaseName", "holderName", func(ctx context.Context) error { @@ -109,9 +105,7 @@ func (s *leaseServiceSuite) TestWithLeaseWaitHasLeaseChange(c *gc.C) { s.leaseCheckerWaiter.EXPECT().Token("leaseName", "holderName").Return(s.token) s.token.EXPECT().Check().Return(nil) - service := NewLeaseService(func() lease.LeaseCheckerWaiter { - return s.leaseCheckerWaiter - }) + service := NewLeaseService(s.modelLeaseManager) // Finish is used to ensure that the lease function has completed and not // left running. @@ -166,9 +160,7 @@ func (s *leaseServiceSuite) TestWithLeaseFailsOnWaitCheck(c *gc.C) { s.leaseCheckerWaiter.EXPECT().Token("leaseName", "holderName").Return(s.token) s.token.EXPECT().Check().Return(errors.Errorf("not holding lease")) - service := NewLeaseService(func() lease.LeaseCheckerWaiter { - return s.leaseCheckerWaiter - }) + service := NewLeaseService(s.modelLeaseManager) // The lease function should be a long running function. @@ -184,8 +176,11 @@ func (s *leaseServiceSuite) TestWithLeaseFailsOnWaitCheck(c *gc.C) { func (s *leaseServiceSuite) setupMocks(c *gc.C) *gomock.Controller { ctrl := gomock.NewController(c) + s.modelLeaseManager = NewMockModelApplicationLeaseManagerGetter(ctrl) s.leaseCheckerWaiter = NewMockLeaseCheckerWaiter(ctrl) s.token = NewMockToken(ctrl) + s.modelLeaseManager.EXPECT().GetLeaseManager().Return(s.leaseCheckerWaiter, nil).AnyTimes() + return ctrl } diff --git a/domain/package_test.go b/domain/package_test.go index ab23bd271da..f55c26a1ecc 100644 --- a/domain/package_test.go +++ b/domain/package_test.go @@ -11,7 +11,7 @@ import ( ) //go:generate go run go.uber.org/mock/mockgen -typed -package domain -destination changestream_mock_test.go github.com/juju/juju/core/changestream Subscription,EventSource -//go:generate go run go.uber.org/mock/mockgen -typed -package domain -destination lease_mock_test.go github.com/juju/juju/core/lease Token,LeaseCheckerWaiter +//go:generate go run go.uber.org/mock/mockgen -typed -package domain -destination lease_mock_test.go github.com/juju/juju/core/lease Token,LeaseCheckerWaiter,ModelApplicationLeaseManagerGetter func TestPackage(t *testing.T) { defer goleak.VerifyNone(t) diff --git a/domain/services/model.go b/domain/services/model.go index 4b75bae8430..e2d8c30f1cb 100644 --- a/domain/services/model.go +++ b/domain/services/model.go @@ -87,6 +87,7 @@ type ModelFactory struct { objectstore objectstore.ModelObjectStoreGetter storageRegistry corestorage.ModelStorageRegistryGetter publicKeyImporter PublicKeyImporter + leaseManager lease.ModelApplicationLeaseManagerGetter } // NewModelFactory returns a new registry which uses the provided modelDB @@ -113,6 +114,7 @@ func NewModelFactory( objectstore: objectStore, storageRegistry: storageRegistry, publicKeyImporter: publicKeyImporter, + leaseManager: leaseManager, } } From 6a67cfe129c29899c8d57ef282343080702babea Mon Sep 17 00:00:00 2001 From: Simon Richardson Date: Thu, 24 Oct 2024 14:51:26 +0100 Subject: [PATCH 3/4] refactor: drop application from the lease manager getter Application is the implementation detail of the model lease manager getter. We could have another implementation that is for singular controllers. The interface shouldn't care. It's just offering out a given type. --- core/lease/lease.go | 11 +-- domain/lease_mock_test.go | 44 +++++----- domain/leaseservice.go | 6 +- domain/leaseservice_test.go | 4 +- domain/package_test.go | 2 +- domain/services/model.go | 4 +- domain/services/service.go | 2 +- .../worker/domainservices/lease_mock_test.go | 84 +++++++++---------- internal/worker/domainservices/manifold.go | 4 +- .../worker/domainservices/manifold_test.go | 4 +- .../worker/domainservices/package_test.go | 14 ++-- internal/worker/domainservices/worker.go | 18 ++-- internal/worker/domainservices/worker_test.go | 2 +- 13 files changed, 101 insertions(+), 98 deletions(-) diff --git a/core/lease/lease.go b/core/lease/lease.go index 77d7c21ce14..a41b0850650 100644 --- a/core/lease/lease.go +++ b/core/lease/lease.go @@ -12,16 +12,17 @@ type LeaseCheckerWaiter interface { Checker } -// ApplicationLeaseManagerGetter is an interface that provides a method to get a -// lease manager for a given application using its UUID. -type ApplicationLeaseManagerGetter interface { +// LeaseManagerGetter is an interface that provides a method to get a lease +// manager for a given lease using its UUID. The lease namespace could be a +// model or an application. +type LeaseManagerGetter interface { // GetLeaseManager returns a lease manager for the given model UUID. GetLeaseManager(model.UUID) (LeaseCheckerWaiter, error) } -// ModelApplicationLeaseManagerGetter is an interface that provides a method to +// ModelLeaseManagerGetter is an interface that provides a method to // get a lease manager in the scope of a model. -type ModelApplicationLeaseManagerGetter interface { +type ModelLeaseManagerGetter interface { // GetLeaseManager returns a lease manager for the given model UUID. GetLeaseManager() (LeaseCheckerWaiter, error) } diff --git a/domain/lease_mock_test.go b/domain/lease_mock_test.go index 3e1958bbf70..ec966225c65 100644 --- a/domain/lease_mock_test.go +++ b/domain/lease_mock_test.go @@ -1,9 +1,9 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/juju/juju/core/lease (interfaces: Token,LeaseCheckerWaiter,ModelApplicationLeaseManagerGetter) +// Source: github.com/juju/juju/core/lease (interfaces: Token,LeaseCheckerWaiter,ModelLeaseManagerGetter) // // Generated by this command: // -// mockgen -typed -package domain -destination lease_mock_test.go github.com/juju/juju/core/lease Token,LeaseCheckerWaiter,ModelApplicationLeaseManagerGetter +// mockgen -typed -package domain -destination lease_mock_test.go github.com/juju/juju/core/lease Token,LeaseCheckerWaiter,ModelLeaseManagerGetter // // Package domain is a generated GoMock package. @@ -177,31 +177,31 @@ func (c *MockLeaseCheckerWaiterWaitUntilExpiredCall) DoAndReturn(f func(context. return c } -// MockModelApplicationLeaseManagerGetter is a mock of ModelApplicationLeaseManagerGetter interface. -type MockModelApplicationLeaseManagerGetter struct { +// MockModelLeaseManagerGetter is a mock of ModelLeaseManagerGetter interface. +type MockModelLeaseManagerGetter struct { ctrl *gomock.Controller - recorder *MockModelApplicationLeaseManagerGetterMockRecorder + recorder *MockModelLeaseManagerGetterMockRecorder } -// MockModelApplicationLeaseManagerGetterMockRecorder is the mock recorder for MockModelApplicationLeaseManagerGetter. -type MockModelApplicationLeaseManagerGetterMockRecorder struct { - mock *MockModelApplicationLeaseManagerGetter +// MockModelLeaseManagerGetterMockRecorder is the mock recorder for MockModelLeaseManagerGetter. +type MockModelLeaseManagerGetterMockRecorder struct { + mock *MockModelLeaseManagerGetter } -// NewMockModelApplicationLeaseManagerGetter creates a new mock instance. -func NewMockModelApplicationLeaseManagerGetter(ctrl *gomock.Controller) *MockModelApplicationLeaseManagerGetter { - mock := &MockModelApplicationLeaseManagerGetter{ctrl: ctrl} - mock.recorder = &MockModelApplicationLeaseManagerGetterMockRecorder{mock} +// NewMockModelLeaseManagerGetter creates a new mock instance. +func NewMockModelLeaseManagerGetter(ctrl *gomock.Controller) *MockModelLeaseManagerGetter { + mock := &MockModelLeaseManagerGetter{ctrl: ctrl} + mock.recorder = &MockModelLeaseManagerGetterMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockModelApplicationLeaseManagerGetter) EXPECT() *MockModelApplicationLeaseManagerGetterMockRecorder { +func (m *MockModelLeaseManagerGetter) EXPECT() *MockModelLeaseManagerGetterMockRecorder { return m.recorder } // GetLeaseManager mocks base method. -func (m *MockModelApplicationLeaseManagerGetter) GetLeaseManager() (lease.LeaseCheckerWaiter, error) { +func (m *MockModelLeaseManagerGetter) GetLeaseManager() (lease.LeaseCheckerWaiter, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetLeaseManager") ret0, _ := ret[0].(lease.LeaseCheckerWaiter) @@ -210,31 +210,31 @@ func (m *MockModelApplicationLeaseManagerGetter) GetLeaseManager() (lease.LeaseC } // GetLeaseManager indicates an expected call of GetLeaseManager. -func (mr *MockModelApplicationLeaseManagerGetterMockRecorder) GetLeaseManager() *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { +func (mr *MockModelLeaseManagerGetterMockRecorder) GetLeaseManager() *MockModelLeaseManagerGetterGetLeaseManagerCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLeaseManager", reflect.TypeOf((*MockModelApplicationLeaseManagerGetter)(nil).GetLeaseManager)) - return &MockModelApplicationLeaseManagerGetterGetLeaseManagerCall{Call: call} + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLeaseManager", reflect.TypeOf((*MockModelLeaseManagerGetter)(nil).GetLeaseManager)) + return &MockModelLeaseManagerGetterGetLeaseManagerCall{Call: call} } -// MockModelApplicationLeaseManagerGetterGetLeaseManagerCall wrap *gomock.Call -type MockModelApplicationLeaseManagerGetterGetLeaseManagerCall struct { +// MockModelLeaseManagerGetterGetLeaseManagerCall wrap *gomock.Call +type MockModelLeaseManagerGetterGetLeaseManagerCall struct { *gomock.Call } // Return rewrite *gomock.Call.Return -func (c *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall) Return(arg0 lease.LeaseCheckerWaiter, arg1 error) *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { +func (c *MockModelLeaseManagerGetterGetLeaseManagerCall) Return(arg0 lease.LeaseCheckerWaiter, arg1 error) *MockModelLeaseManagerGetterGetLeaseManagerCall { c.Call = c.Call.Return(arg0, arg1) return c } // Do rewrite *gomock.Call.Do -func (c *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall) Do(f func() (lease.LeaseCheckerWaiter, error)) *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { +func (c *MockModelLeaseManagerGetterGetLeaseManagerCall) Do(f func() (lease.LeaseCheckerWaiter, error)) *MockModelLeaseManagerGetterGetLeaseManagerCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall) DoAndReturn(f func() (lease.LeaseCheckerWaiter, error)) *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { +func (c *MockModelLeaseManagerGetterGetLeaseManagerCall) DoAndReturn(f func() (lease.LeaseCheckerWaiter, error)) *MockModelLeaseManagerGetterGetLeaseManagerCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/domain/leaseservice.go b/domain/leaseservice.go index 8b8e8985aea..a930476aafa 100644 --- a/domain/leaseservice.go +++ b/domain/leaseservice.go @@ -12,11 +12,11 @@ import ( // LeaseService creates a base service that offers lease capabilities. type LeaseService struct { - leaseChecker lease.ModelApplicationLeaseManagerGetter + leaseChecker lease.ModelLeaseManagerGetter } // NewLeaseService creates a new LeaseService. -func NewLeaseService(leaseChecker lease.ModelApplicationLeaseManagerGetter) *LeaseService { +func NewLeaseService(leaseChecker lease.ModelLeaseManagerGetter) *LeaseService { return &LeaseService{ leaseChecker: leaseChecker, } @@ -31,7 +31,7 @@ func (s *LeaseService) WithLease(ctx context.Context, leaseName, holderName stri // Holding the lease is quite a complex operation, so we need to ensure that // the context is not cancelled before we start the operation. if err := ctx.Err(); err != nil { - return internalerrors.Errorf("lease prechecking").Add(ctx.Err()) + return internalerrors.Errorf("lease pre-checking").Add(ctx.Err()) } leaseChecker, err := s.leaseChecker.GetLeaseManager() diff --git a/domain/leaseservice_test.go b/domain/leaseservice_test.go index aca3be77608..e2a2c0bb3d7 100644 --- a/domain/leaseservice_test.go +++ b/domain/leaseservice_test.go @@ -19,7 +19,7 @@ import ( type leaseServiceSuite struct { testing.IsolationSuite - modelLeaseManager *MockModelApplicationLeaseManagerGetter + modelLeaseManager *MockModelLeaseManagerGetter leaseCheckerWaiter *MockLeaseCheckerWaiter token *MockToken } @@ -176,7 +176,7 @@ func (s *leaseServiceSuite) TestWithLeaseFailsOnWaitCheck(c *gc.C) { func (s *leaseServiceSuite) setupMocks(c *gc.C) *gomock.Controller { ctrl := gomock.NewController(c) - s.modelLeaseManager = NewMockModelApplicationLeaseManagerGetter(ctrl) + s.modelLeaseManager = NewMockModelLeaseManagerGetter(ctrl) s.leaseCheckerWaiter = NewMockLeaseCheckerWaiter(ctrl) s.token = NewMockToken(ctrl) diff --git a/domain/package_test.go b/domain/package_test.go index f55c26a1ecc..b16fc88c364 100644 --- a/domain/package_test.go +++ b/domain/package_test.go @@ -11,7 +11,7 @@ import ( ) //go:generate go run go.uber.org/mock/mockgen -typed -package domain -destination changestream_mock_test.go github.com/juju/juju/core/changestream Subscription,EventSource -//go:generate go run go.uber.org/mock/mockgen -typed -package domain -destination lease_mock_test.go github.com/juju/juju/core/lease Token,LeaseCheckerWaiter,ModelApplicationLeaseManagerGetter +//go:generate go run go.uber.org/mock/mockgen -typed -package domain -destination lease_mock_test.go github.com/juju/juju/core/lease Token,LeaseCheckerWaiter,ModelLeaseManagerGetter func TestPackage(t *testing.T) { defer goleak.VerifyNone(t) diff --git a/domain/services/model.go b/domain/services/model.go index e2d8c30f1cb..57759af5d83 100644 --- a/domain/services/model.go +++ b/domain/services/model.go @@ -87,7 +87,7 @@ type ModelFactory struct { objectstore objectstore.ModelObjectStoreGetter storageRegistry corestorage.ModelStorageRegistryGetter publicKeyImporter PublicKeyImporter - leaseManager lease.ModelApplicationLeaseManagerGetter + leaseManager lease.ModelLeaseManagerGetter } // NewModelFactory returns a new registry which uses the provided modelDB @@ -100,7 +100,7 @@ func NewModelFactory( objectStore objectstore.ModelObjectStoreGetter, storageRegistry corestorage.ModelStorageRegistryGetter, publicKeyImporter PublicKeyImporter, - leaseManager lease.ModelApplicationLeaseManagerGetter, + leaseManager lease.ModelLeaseManagerGetter, clock clock.Clock, logger logger.Logger, ) *ModelFactory { diff --git a/domain/services/service.go b/domain/services/service.go index 20e007cc696..5f5b185c353 100644 --- a/domain/services/service.go +++ b/domain/services/service.go @@ -33,7 +33,7 @@ func NewDomainServices( objectStore objectstore.ModelObjectStoreGetter, storageRegistry storage.ModelStorageRegistryGetter, publicKeyImporter PublicKeyImporter, - leaseManager lease.ModelApplicationLeaseManagerGetter, + leaseManager lease.ModelLeaseManagerGetter, clock clock.Clock, logger logger.Logger, ) *DomainServices { diff --git a/internal/worker/domainservices/lease_mock_test.go b/internal/worker/domainservices/lease_mock_test.go index 9b54323ea1d..14de949af90 100644 --- a/internal/worker/domainservices/lease_mock_test.go +++ b/internal/worker/domainservices/lease_mock_test.go @@ -1,9 +1,9 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/juju/juju/core/lease (interfaces: LeaseCheckerWaiter,Manager,ApplicationLeaseManagerGetter,ModelApplicationLeaseManagerGetter) +// Source: github.com/juju/juju/core/lease (interfaces: LeaseCheckerWaiter,Manager,LeaseManagerGetter,ModelLeaseManagerGetter) // // Generated by this command: // -// mockgen -typed -package domainservices -destination lease_mock_test.go github.com/juju/juju/core/lease LeaseCheckerWaiter,Manager,ApplicationLeaseManagerGetter,ModelApplicationLeaseManagerGetter +// mockgen -typed -package domainservices -destination lease_mock_test.go github.com/juju/juju/core/lease LeaseCheckerWaiter,Manager,LeaseManagerGetter,ModelLeaseManagerGetter // // Package domainservices is a generated GoMock package. @@ -335,31 +335,31 @@ func (c *MockManagerRevokerCall) DoAndReturn(f func(string, string) (lease.Revok return c } -// MockApplicationLeaseManagerGetter is a mock of ApplicationLeaseManagerGetter interface. -type MockApplicationLeaseManagerGetter struct { +// MockLeaseManagerGetter is a mock of LeaseManagerGetter interface. +type MockLeaseManagerGetter struct { ctrl *gomock.Controller - recorder *MockApplicationLeaseManagerGetterMockRecorder + recorder *MockLeaseManagerGetterMockRecorder } -// MockApplicationLeaseManagerGetterMockRecorder is the mock recorder for MockApplicationLeaseManagerGetter. -type MockApplicationLeaseManagerGetterMockRecorder struct { - mock *MockApplicationLeaseManagerGetter +// MockLeaseManagerGetterMockRecorder is the mock recorder for MockLeaseManagerGetter. +type MockLeaseManagerGetterMockRecorder struct { + mock *MockLeaseManagerGetter } -// NewMockApplicationLeaseManagerGetter creates a new mock instance. -func NewMockApplicationLeaseManagerGetter(ctrl *gomock.Controller) *MockApplicationLeaseManagerGetter { - mock := &MockApplicationLeaseManagerGetter{ctrl: ctrl} - mock.recorder = &MockApplicationLeaseManagerGetterMockRecorder{mock} +// NewMockLeaseManagerGetter creates a new mock instance. +func NewMockLeaseManagerGetter(ctrl *gomock.Controller) *MockLeaseManagerGetter { + mock := &MockLeaseManagerGetter{ctrl: ctrl} + mock.recorder = &MockLeaseManagerGetterMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockApplicationLeaseManagerGetter) EXPECT() *MockApplicationLeaseManagerGetterMockRecorder { +func (m *MockLeaseManagerGetter) EXPECT() *MockLeaseManagerGetterMockRecorder { return m.recorder } // GetLeaseManager mocks base method. -func (m *MockApplicationLeaseManagerGetter) GetLeaseManager(arg0 model.UUID) (lease.LeaseCheckerWaiter, error) { +func (m *MockLeaseManagerGetter) GetLeaseManager(arg0 model.UUID) (lease.LeaseCheckerWaiter, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetLeaseManager", arg0) ret0, _ := ret[0].(lease.LeaseCheckerWaiter) @@ -368,60 +368,60 @@ func (m *MockApplicationLeaseManagerGetter) GetLeaseManager(arg0 model.UUID) (le } // GetLeaseManager indicates an expected call of GetLeaseManager. -func (mr *MockApplicationLeaseManagerGetterMockRecorder) GetLeaseManager(arg0 any) *MockApplicationLeaseManagerGetterGetLeaseManagerCall { +func (mr *MockLeaseManagerGetterMockRecorder) GetLeaseManager(arg0 any) *MockLeaseManagerGetterGetLeaseManagerCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLeaseManager", reflect.TypeOf((*MockApplicationLeaseManagerGetter)(nil).GetLeaseManager), arg0) - return &MockApplicationLeaseManagerGetterGetLeaseManagerCall{Call: call} + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLeaseManager", reflect.TypeOf((*MockLeaseManagerGetter)(nil).GetLeaseManager), arg0) + return &MockLeaseManagerGetterGetLeaseManagerCall{Call: call} } -// MockApplicationLeaseManagerGetterGetLeaseManagerCall wrap *gomock.Call -type MockApplicationLeaseManagerGetterGetLeaseManagerCall struct { +// MockLeaseManagerGetterGetLeaseManagerCall wrap *gomock.Call +type MockLeaseManagerGetterGetLeaseManagerCall struct { *gomock.Call } // Return rewrite *gomock.Call.Return -func (c *MockApplicationLeaseManagerGetterGetLeaseManagerCall) Return(arg0 lease.LeaseCheckerWaiter, arg1 error) *MockApplicationLeaseManagerGetterGetLeaseManagerCall { +func (c *MockLeaseManagerGetterGetLeaseManagerCall) Return(arg0 lease.LeaseCheckerWaiter, arg1 error) *MockLeaseManagerGetterGetLeaseManagerCall { c.Call = c.Call.Return(arg0, arg1) return c } // Do rewrite *gomock.Call.Do -func (c *MockApplicationLeaseManagerGetterGetLeaseManagerCall) Do(f func(model.UUID) (lease.LeaseCheckerWaiter, error)) *MockApplicationLeaseManagerGetterGetLeaseManagerCall { +func (c *MockLeaseManagerGetterGetLeaseManagerCall) Do(f func(model.UUID) (lease.LeaseCheckerWaiter, error)) *MockLeaseManagerGetterGetLeaseManagerCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockApplicationLeaseManagerGetterGetLeaseManagerCall) DoAndReturn(f func(model.UUID) (lease.LeaseCheckerWaiter, error)) *MockApplicationLeaseManagerGetterGetLeaseManagerCall { +func (c *MockLeaseManagerGetterGetLeaseManagerCall) DoAndReturn(f func(model.UUID) (lease.LeaseCheckerWaiter, error)) *MockLeaseManagerGetterGetLeaseManagerCall { c.Call = c.Call.DoAndReturn(f) return c } -// MockModelApplicationLeaseManagerGetter is a mock of ModelApplicationLeaseManagerGetter interface. -type MockModelApplicationLeaseManagerGetter struct { +// MockModelLeaseManagerGetter is a mock of ModelLeaseManagerGetter interface. +type MockModelLeaseManagerGetter struct { ctrl *gomock.Controller - recorder *MockModelApplicationLeaseManagerGetterMockRecorder + recorder *MockModelLeaseManagerGetterMockRecorder } -// MockModelApplicationLeaseManagerGetterMockRecorder is the mock recorder for MockModelApplicationLeaseManagerGetter. -type MockModelApplicationLeaseManagerGetterMockRecorder struct { - mock *MockModelApplicationLeaseManagerGetter +// MockModelLeaseManagerGetterMockRecorder is the mock recorder for MockModelLeaseManagerGetter. +type MockModelLeaseManagerGetterMockRecorder struct { + mock *MockModelLeaseManagerGetter } -// NewMockModelApplicationLeaseManagerGetter creates a new mock instance. -func NewMockModelApplicationLeaseManagerGetter(ctrl *gomock.Controller) *MockModelApplicationLeaseManagerGetter { - mock := &MockModelApplicationLeaseManagerGetter{ctrl: ctrl} - mock.recorder = &MockModelApplicationLeaseManagerGetterMockRecorder{mock} +// NewMockModelLeaseManagerGetter creates a new mock instance. +func NewMockModelLeaseManagerGetter(ctrl *gomock.Controller) *MockModelLeaseManagerGetter { + mock := &MockModelLeaseManagerGetter{ctrl: ctrl} + mock.recorder = &MockModelLeaseManagerGetterMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockModelApplicationLeaseManagerGetter) EXPECT() *MockModelApplicationLeaseManagerGetterMockRecorder { +func (m *MockModelLeaseManagerGetter) EXPECT() *MockModelLeaseManagerGetterMockRecorder { return m.recorder } // GetLeaseManager mocks base method. -func (m *MockModelApplicationLeaseManagerGetter) GetLeaseManager() (lease.LeaseCheckerWaiter, error) { +func (m *MockModelLeaseManagerGetter) GetLeaseManager() (lease.LeaseCheckerWaiter, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetLeaseManager") ret0, _ := ret[0].(lease.LeaseCheckerWaiter) @@ -430,31 +430,31 @@ func (m *MockModelApplicationLeaseManagerGetter) GetLeaseManager() (lease.LeaseC } // GetLeaseManager indicates an expected call of GetLeaseManager. -func (mr *MockModelApplicationLeaseManagerGetterMockRecorder) GetLeaseManager() *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { +func (mr *MockModelLeaseManagerGetterMockRecorder) GetLeaseManager() *MockModelLeaseManagerGetterGetLeaseManagerCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLeaseManager", reflect.TypeOf((*MockModelApplicationLeaseManagerGetter)(nil).GetLeaseManager)) - return &MockModelApplicationLeaseManagerGetterGetLeaseManagerCall{Call: call} + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLeaseManager", reflect.TypeOf((*MockModelLeaseManagerGetter)(nil).GetLeaseManager)) + return &MockModelLeaseManagerGetterGetLeaseManagerCall{Call: call} } -// MockModelApplicationLeaseManagerGetterGetLeaseManagerCall wrap *gomock.Call -type MockModelApplicationLeaseManagerGetterGetLeaseManagerCall struct { +// MockModelLeaseManagerGetterGetLeaseManagerCall wrap *gomock.Call +type MockModelLeaseManagerGetterGetLeaseManagerCall struct { *gomock.Call } // Return rewrite *gomock.Call.Return -func (c *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall) Return(arg0 lease.LeaseCheckerWaiter, arg1 error) *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { +func (c *MockModelLeaseManagerGetterGetLeaseManagerCall) Return(arg0 lease.LeaseCheckerWaiter, arg1 error) *MockModelLeaseManagerGetterGetLeaseManagerCall { c.Call = c.Call.Return(arg0, arg1) return c } // Do rewrite *gomock.Call.Do -func (c *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall) Do(f func() (lease.LeaseCheckerWaiter, error)) *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { +func (c *MockModelLeaseManagerGetterGetLeaseManagerCall) Do(f func() (lease.LeaseCheckerWaiter, error)) *MockModelLeaseManagerGetterGetLeaseManagerCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall) DoAndReturn(f func() (lease.LeaseCheckerWaiter, error)) *MockModelApplicationLeaseManagerGetterGetLeaseManagerCall { +func (c *MockModelLeaseManagerGetterGetLeaseManagerCall) DoAndReturn(f func() (lease.LeaseCheckerWaiter, error)) *MockModelLeaseManagerGetterGetLeaseManagerCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/internal/worker/domainservices/manifold.go b/internal/worker/domainservices/manifold.go index 625e66a956f..b8e6b35bad0 100644 --- a/internal/worker/domainservices/manifold.go +++ b/internal/worker/domainservices/manifold.go @@ -75,7 +75,7 @@ type ModelDomainServicesFn func( objectstore.ModelObjectStoreGetter, storage.ModelStorageRegistryGetter, domainservices.PublicKeyImporter, - lease.ModelApplicationLeaseManagerGetter, + lease.ModelLeaseManagerGetter, clock.Clock, logger.Logger, ) services.ModelDomainServices @@ -250,7 +250,7 @@ func NewProviderTrackerModelDomainServices( objectStore objectstore.ModelObjectStoreGetter, storageRegistry storage.ModelStorageRegistryGetter, publicKeyImporter domainservices.PublicKeyImporter, - leaseManager lease.ModelApplicationLeaseManagerGetter, + leaseManager lease.ModelLeaseManagerGetter, clock clock.Clock, logger logger.Logger, ) services.ModelDomainServices { diff --git a/internal/worker/domainservices/manifold_test.go b/internal/worker/domainservices/manifold_test.go index 35aa8328dcb..560b76179e2 100644 --- a/internal/worker/domainservices/manifold_test.go +++ b/internal/worker/domainservices/manifold_test.go @@ -223,7 +223,7 @@ func (s *manifoldSuite) TestNewModelDomainServices(c *gc.C) { s.modelObjectStoreGetter, s.modelStorageRegistryGetter, s.publicKeyImporter, - s.modelApplicationLeaseManagerGetter, + s.modelLeaseManagerGetter, s.clock, s.logger, ) @@ -301,7 +301,7 @@ func noopModelDomainServices( objectstore.ModelObjectStoreGetter, storage.ModelStorageRegistryGetter, domainservices.PublicKeyImporter, - lease.ModelApplicationLeaseManagerGetter, + lease.ModelLeaseManagerGetter, clock.Clock, logger.Logger, ) services.ModelDomainServices { diff --git a/internal/worker/domainservices/package_test.go b/internal/worker/domainservices/package_test.go index 283eb263bb1..d564cad7566 100644 --- a/internal/worker/domainservices/package_test.go +++ b/internal/worker/domainservices/package_test.go @@ -32,7 +32,7 @@ import ( //go:generate go run go.uber.org/mock/mockgen -typed -package domainservices -destination objectstore_mock_test.go github.com/juju/juju/core/objectstore ObjectStore,ObjectStoreGetter,ModelObjectStoreGetter //go:generate go run go.uber.org/mock/mockgen -typed -package domainservices -destination storage_mock_test.go github.com/juju/juju/core/storage StorageRegistryGetter,ModelStorageRegistryGetter //go:generate go run go.uber.org/mock/mockgen -typed -package domainservices -destination http_mock_test.go github.com/juju/juju/core/http HTTPClientGetter,HTTPClient -//go:generate go run go.uber.org/mock/mockgen -typed -package domainservices -destination lease_mock_test.go github.com/juju/juju/core/lease LeaseCheckerWaiter,Manager,ApplicationLeaseManagerGetter,ModelApplicationLeaseManagerGetter +//go:generate go run go.uber.org/mock/mockgen -typed -package domainservices -destination lease_mock_test.go github.com/juju/juju/core/lease LeaseCheckerWaiter,Manager,LeaseManagerGetter,ModelLeaseManagerGetter func TestPackage(t *testing.T) { gc.TestingT(t) @@ -63,9 +63,9 @@ type baseSuite struct { httpClientGetter *MockHTTPClientGetter httpClient *MockHTTPClient - leaseManager *MockManager - applicationLeaseManagerGetter *MockApplicationLeaseManagerGetter - modelApplicationLeaseManagerGetter *MockModelApplicationLeaseManagerGetter + leaseManager *MockManager + leaseManagerGetter *MockLeaseManagerGetter + modelLeaseManagerGetter *MockModelLeaseManagerGetter publicKeyImporter *sshimporter.Importer } @@ -96,8 +96,8 @@ func (s *baseSuite) setupMocks(c *gc.C) *gomock.Controller { s.httpClient = NewMockHTTPClient(ctrl) s.leaseManager = NewMockManager(ctrl) - s.applicationLeaseManagerGetter = NewMockApplicationLeaseManagerGetter(ctrl) - s.modelApplicationLeaseManagerGetter = NewMockModelApplicationLeaseManagerGetter(ctrl) + s.leaseManagerGetter = NewMockLeaseManagerGetter(ctrl) + s.modelLeaseManagerGetter = NewMockModelLeaseManagerGetter(ctrl) s.publicKeyImporter = sshimporter.NewImporter(&http.Client{}) @@ -113,7 +113,7 @@ func NewModelDomainServices( objectStore objectstore.ModelObjectStoreGetter, storageRegistry storage.ModelStorageRegistryGetter, publicKeyImporter domainservices.PublicKeyImporter, - leaseManager lease.ModelApplicationLeaseManagerGetter, + leaseManager lease.ModelLeaseManagerGetter, clock clock.Clock, logger logger.Logger, ) services.ModelDomainServices { diff --git a/internal/worker/domainservices/worker.go b/internal/worker/domainservices/worker.go index f1e20024d4d..82f9d9f9a27 100644 --- a/internal/worker/domainservices/worker.go +++ b/internal/worker/domainservices/worker.go @@ -82,12 +82,6 @@ func (config Config) Validate() error { if config.LeaseManager == nil { return errors.NotValidf("nil LeaseManager") } - if config.Logger == nil { - return errors.NotValidf("nil Logger") - } - if config.Clock == nil { - return errors.NotValidf("nil Clock") - } if config.NewDomainServicesGetter == nil { return errors.NotValidf("nil NewDomainServicesGetter") } @@ -97,6 +91,12 @@ func (config Config) Validate() error { if config.NewModelDomainServices == nil { return errors.NotValidf("nil NewModelDomainServices") } + if config.Logger == nil { + return errors.NotValidf("nil Logger") + } + if config.Clock == nil { + return errors.NotValidf("nil Clock") + } return nil } @@ -240,6 +240,8 @@ func (s modelStorageRegistryGetter) GetStorageRegistry(ctx context.Context) (int return s.storageRegistryGetter.GetStorageRegistry(ctx, s.modelUUID.String()) } +// modelApplicationLeaseManager is a lease manager that is specific to +// an application scope. type modelApplicationLeaseManager struct { modelUUID coremodel.UUID manager lease.Manager @@ -252,12 +254,12 @@ func (s modelApplicationLeaseManager) GetLeaseManager() (lease.LeaseCheckerWaite // be happy with a sync.Pool at minimum though. claimer, err := s.manager.Claimer(lease.ApplicationLeadershipNamespace, s.modelUUID.String()) if err != nil { - return nil, errors.Trace(err) + return nil, errors.Errorf("getting claim lease manager: %w", err) } checker, err := s.manager.Checker(lease.ApplicationLeadershipNamespace, s.modelUUID.String()) if err != nil { - return nil, errors.Trace(err) + return nil, errors.Errorf("getting checker lease manager: %w", err) } return &leaseManager{ diff --git a/internal/worker/domainservices/worker_test.go b/internal/worker/domainservices/worker_test.go index e124a894976..715fbce104c 100644 --- a/internal/worker/domainservices/worker_test.go +++ b/internal/worker/domainservices/worker_test.go @@ -124,7 +124,7 @@ func (s *workerSuite) getConfig() Config { objectstore.ModelObjectStoreGetter, storage.ModelStorageRegistryGetter, domainservices.PublicKeyImporter, - lease.ModelApplicationLeaseManagerGetter, + lease.ModelLeaseManagerGetter, clock.Clock, logger.Logger, ) services.ModelDomainServices { From dc34beb594fc5a5c535cda450fa7543127339458 Mon Sep 17 00:00:00 2001 From: Simon Richardson Date: Fri, 25 Oct 2024 14:44:28 +0100 Subject: [PATCH 4/4] fix: use internal errors package --- apiserver/facades/client/application/application_test.go | 2 +- internal/worker/domainservices/worker.go | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apiserver/facades/client/application/application_test.go b/apiserver/facades/client/application/application_test.go index 8f1743501d8..0a15ea2bd87 100644 --- a/apiserver/facades/client/application/application_test.go +++ b/apiserver/facades/client/application/application_test.go @@ -105,7 +105,7 @@ func (s *applicationSuite) makeAPI(c *gc.C) { Type: model.IAAS, } registry := provider.NewStorageProviderRegistry(env) - domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c)) + domainServicesGetter := s.DomainServicesGetter(c, s.NoopObjectStore(c), s.NoopLeaseManager(c)) storageService := domainServicesGetter.ServicesForModel(model.UUID(st.ModelUUID())).Storage() applicationService := domainServices.Application() diff --git a/internal/worker/domainservices/worker.go b/internal/worker/domainservices/worker.go index 82f9d9f9a27..711cd5f5655 100644 --- a/internal/worker/domainservices/worker.go +++ b/internal/worker/domainservices/worker.go @@ -20,6 +20,7 @@ import ( "github.com/juju/juju/core/providertracker" "github.com/juju/juju/core/storage" domainservices "github.com/juju/juju/domain/services" + internalerrors "github.com/juju/juju/internal/errors" "github.com/juju/juju/internal/services" internalstorage "github.com/juju/juju/internal/storage" ) @@ -254,12 +255,12 @@ func (s modelApplicationLeaseManager) GetLeaseManager() (lease.LeaseCheckerWaite // be happy with a sync.Pool at minimum though. claimer, err := s.manager.Claimer(lease.ApplicationLeadershipNamespace, s.modelUUID.String()) if err != nil { - return nil, errors.Errorf("getting claim lease manager: %w", err) + return nil, internalerrors.Errorf("getting claim lease manager: %w", err) } checker, err := s.manager.Checker(lease.ApplicationLeadershipNamespace, s.modelUUID.String()) if err != nil { - return nil, errors.Errorf("getting checker lease manager: %w", err) + return nil, internalerrors.Errorf("getting checker lease manager: %w", err) } return &leaseManager{