diff --git a/apiserver/admin.go b/apiserver/admin.go index 3542e5477c6..06f93cfe3e8 100644 --- a/apiserver/admin.go +++ b/apiserver/admin.go @@ -20,7 +20,6 @@ import ( "github.com/juju/juju/apiserver/facade" "github.com/juju/juju/apiserver/observer" "github.com/juju/juju/core/auditlog" - "github.com/juju/juju/core/database" "github.com/juju/juju/core/network" "github.com/juju/juju/core/permission" "github.com/juju/juju/core/pinger" @@ -463,7 +462,7 @@ func (a *admin) checkUserPermissions(authInfo authentication.AuthInfo, controlle // The best option might be to round up all of these special case // "everyone@external" checks and push them into either the permission // delegator or the service itself. - accessService := a.srv.shared.serviceFactoryGetter.FactoryForModel(database.ControllerNS).Access() + accessService := a.srv.shared.serviceFactoryGetter.FactoryForModel(a.srv.shared.controllerModelID).Access() everyoneGroupUser, err := accessService.ReadUserAccessForTarget( context.TODO(), common.EveryoneTagName, diff --git a/apiserver/apiserver.go b/apiserver/apiserver.go index 4b255c9f6de..f0a691b3e76 100644 --- a/apiserver/apiserver.go +++ b/apiserver/apiserver.go @@ -46,6 +46,7 @@ import ( "github.com/juju/juju/core/database" "github.com/juju/juju/core/lease" corelogger "github.com/juju/juju/core/logger" + "github.com/juju/juju/core/model" "github.com/juju/juju/core/objectstore" "github.com/juju/juju/core/presence" "github.com/juju/juju/core/resources" @@ -164,6 +165,9 @@ type ServerConfig struct { // ControllerUUID is the controller unique identifier. ControllerUUID string + // ControllerModelID is the ID for the controller model. + ControllerModelID model.UUID + // LocalMacaroonAuthenticator is the request authenticator used for verifying // local user macaroons. LocalMacaroonAuthenticator macaroon.LocalMacaroonAuthenticator @@ -266,6 +270,9 @@ func (c ServerConfig) Validate() error { if c.ControllerUUID == "" { return errors.NotValidf("missing ControllerUUID") } + if c.ControllerModelID == "" { + return errors.NotValidf("missing ControllerModelID") + } if c.LocalMacaroonAuthenticator == nil { return errors.NotValidf("missing local macaroon authenticator") } @@ -337,7 +344,7 @@ func NewServer(ctx context.Context, cfg ServerConfig) (*Server, error) { const readyTimeout = time.Second * 30 func newServer(ctx context.Context, cfg ServerConfig) (_ *Server, err error) { - controllerServiceFactory := cfg.ServiceFactoryGetter.FactoryForModel(database.ControllerNS) + controllerServiceFactory := cfg.ServiceFactoryGetter.FactoryForModel(cfg.ControllerModelID) controllerConfigService := controllerServiceFactory.ControllerConfig() controllerConfig, err := controllerConfigService.ControllerConfig(ctx) if err != nil { @@ -358,6 +365,7 @@ func newServer(ctx context.Context, cfg ServerConfig) (_ *Server, err error) { presence: cfg.Presence, leaseManager: cfg.LeaseManager, controllerUUID: cfg.ControllerUUID, + controllerModelID: cfg.ControllerModelID, controllerConfig: controllerConfig, logger: internallogger.GetLogger("juju.apiserver"), charmhubHTTPClient: cfg.CharmhubHTTPClient, @@ -1107,7 +1115,7 @@ func (srv *Server) apiHandler(w http.ResponseWriter, req *http.Request) { if err := srv.serveConn( srv.tomb.Context(req.Context()), conn, - modelUUID, + model.UUID(modelUUID), connectionID, apiObserver, req.Host, @@ -1120,7 +1128,7 @@ func (srv *Server) apiHandler(w http.ResponseWriter, req *http.Request) { func (srv *Server) serveConn( ctx context.Context, wsConn *websocket.Conn, - modelUUID string, + modelID model.UUID, connectionID uint64, apiObserver observer.Observer, host string, @@ -1129,33 +1137,27 @@ func (srv *Server) serveConn( recorderFactory := observer.NewRecorderFactory(apiObserver, nil, observer.NoCaptureArgs) conn := rpc.NewConn(codec, recorderFactory) - modelService := srv.shared.serviceFactoryGetter.FactoryForModel(database.ControllerNS).Model() - // Note that we don't overwrite modelUUID here because // newAPIHandler treats an empty modelUUID as signifying // the API version used. - resolvedModelUUID := modelUUID - if modelUUID == "" { - info, err := modelService.ControllerModel(ctx) - if err != nil { - return errors.Trace(err) - } - resolvedModelUUID = info.UUID.String() + resolvedModelID := modelID + if resolvedModelID == "" { + resolvedModelID = srv.shared.controllerModelID } tracer, err := srv.shared.tracerGetter.GetTracer( ctx, - coretrace.Namespace("apiserver", resolvedModelUUID), + coretrace.Namespace("apiserver", resolvedModelID.String()), ) if err != nil { - logger.Infof("failed to get tracer for model %q: %v", modelUUID, err) + logger.Infof("failed to get tracer for model %q: %v", resolvedModelID, err) tracer = coretrace.NoopTracer{} } // Grab the object store for the model. - objectStore, err := srv.shared.objectStoreGetter.GetObjectStore(ctx, resolvedModelUUID) + objectStore, err := srv.shared.objectStoreGetter.GetObjectStore(ctx, resolvedModelID.String()) if err != nil { - return errors.Annotatef(err, "getting object store for model %q", resolvedModelUUID) + return errors.Annotatef(err, "getting object store for model %q", resolvedModelID) } // Grab the object store for the controller, this is primarily used for @@ -1165,10 +1167,10 @@ func (srv *Server) serveConn( return errors.Annotatef(err, "getting controller object store") } - serviceFactory := srv.shared.serviceFactoryGetter.FactoryForModel(resolvedModelUUID) + serviceFactory := srv.shared.serviceFactoryGetter.FactoryForModel(resolvedModelID) var handler *apiHandler - st, err := srv.shared.statePool.Get(resolvedModelUUID) + st, err := srv.shared.statePool.Get(resolvedModelID.String()) if err == nil { defer st.Release() handler, err = newAPIHandler( @@ -1182,13 +1184,13 @@ func (srv *Server) serveConn( objectStore, srv.shared.objectStoreGetter, controllerObjectStore, - modelUUID, + modelID, connectionID, host, ) } if errors.Is(err, errors.NotFound) { - err = fmt.Errorf("%w: %q", apiservererrors.UnknownModelError, resolvedModelUUID) + err = fmt.Errorf("%w: %q", apiservererrors.UnknownModelError, resolvedModelID) } if err != nil { diff --git a/apiserver/embeddedcli.go b/apiserver/embeddedcli.go index fd429995dee..80fac991a2c 100644 --- a/apiserver/embeddedcli.go +++ b/apiserver/embeddedcli.go @@ -21,7 +21,6 @@ import ( apiservererrors "github.com/juju/juju/apiserver/errors" "github.com/juju/juju/apiserver/httpcontext" "github.com/juju/juju/apiserver/websocket" - "github.com/juju/juju/core/database" corelogger "github.com/juju/juju/core/logger" "github.com/juju/juju/core/model" "github.com/juju/juju/internal/featureflag" @@ -161,7 +160,7 @@ func (h *embeddedCLIHandler) runEmbeddedCommands( // TODO (stickupkid): This is actually terrible. We should refactor // this out, so we can just pass an interface the handler, that hides // all of this nonsense. - controllerServiceFactory := h.ctxt.srv.shared.serviceFactoryGetter.FactoryForModel(database.ControllerNS) + controllerServiceFactory := h.ctxt.srv.shared.serviceFactoryGetter.FactoryForModel(h.ctxt.srv.shared.controllerModelID) controllerConfigService := controllerServiceFactory.ControllerConfig() // Make a pipe to stream the stdout/stderr of the commands. diff --git a/apiserver/export_test.go b/apiserver/export_test.go index 21186695664..dc9ce127128 100644 --- a/apiserver/export_test.go +++ b/apiserver/export_test.go @@ -20,6 +20,7 @@ import ( "github.com/juju/juju/apiserver/facade" "github.com/juju/juju/apiserver/stateauthenticator" "github.com/juju/juju/controller" + "github.com/juju/juju/core/model" "github.com/juju/juju/core/objectstore" "github.com/juju/juju/core/permission" coretrace "github.com/juju/juju/core/trace" @@ -140,7 +141,7 @@ func TestingAPIHandler(c *gc.C, pool *state.StatePool, st *state.State, sf servi }, tag: names.NewMachineTag("0"), } - h, err := newAPIHandler(context.Background(), srv, st, nil, sf, nil, coretrace.NoopTracer{}, nil, nil, nil, st.ModelUUID(), 6543, "testing.invalid:1234") + h, err := newAPIHandler(context.Background(), srv, st, nil, sf, nil, coretrace.NoopTracer{}, nil, nil, nil, model.UUID(st.ModelUUID()), 6543, "testing.invalid:1234") c.Assert(err, jc.ErrorIsNil) return h, h.Resources() @@ -148,7 +149,7 @@ func TestingAPIHandler(c *gc.C, pool *state.StatePool, st *state.State, sf servi type StubServiceFactoryGetter struct{} -func (s *StubServiceFactoryGetter) FactoryForModel(string) servicefactory.ServiceFactory { +func (s *StubServiceFactoryGetter) FactoryForModel(model.UUID) servicefactory.ServiceFactory { return nil } diff --git a/apiserver/facades/agent/provisioner/provisioner_test.go b/apiserver/facades/agent/provisioner/provisioner_test.go index 3b545892093..43bb0e1a602 100644 --- a/apiserver/facades/agent/provisioner/provisioner_test.go +++ b/apiserver/facades/agent/provisioner/provisioner_test.go @@ -27,6 +27,7 @@ import ( "github.com/juju/juju/controller" "github.com/juju/juju/core/constraints" "github.com/juju/juju/core/instance" + "github.com/juju/juju/core/model" "github.com/juju/juju/core/network" "github.com/juju/juju/core/status" "github.com/juju/juju/environs/config" @@ -1304,7 +1305,7 @@ func (s *withoutControllerSuite) TestSetInstanceInfo(c *gc.C) { serviceFactoryGetter := s.ServiceFactoryGetter(c) st := s.ControllerModel(c).State() - storageService := serviceFactoryGetter.FactoryForModel(st.ModelUUID()).Storage(registry) + storageService := serviceFactoryGetter.FactoryForModel(model.UUID(st.ModelUUID())).Storage(registry) err := storageService.CreateStoragePool(context.Background(), "static-pool", "static", map[string]any{"foo": "bar"}) c.Assert(err, jc.ErrorIsNil) err = s.ControllerModel(c).UpdateModelConfig(s.ConfigSchemaSourceGetter(c), map[string]any{ diff --git a/apiserver/facades/agent/provisioner/provisioninginfo_test.go b/apiserver/facades/agent/provisioner/provisioninginfo_test.go index 7f1e2c377f6..8b776c067b8 100644 --- a/apiserver/facades/agent/provisioner/provisioninginfo_test.go +++ b/apiserver/facades/agent/provisioner/provisioninginfo_test.go @@ -36,7 +36,7 @@ func (s *withoutControllerSuite) TestProvisioningInfoWithStorage(c *gc.C) { serviceFactoryGetter := s.ServiceFactoryGetter(c) st := s.ControllerModel(c).State() - storageService := serviceFactoryGetter.FactoryForModel(st.ModelUUID()).Storage(registry) + storageService := serviceFactoryGetter.FactoryForModel(model.UUID(st.ModelUUID())).Storage(registry) err := storageService.CreateStoragePool(context.Background(), "static-pool", "static", map[string]any{"foo": "bar"}) c.Assert(err, jc.ErrorIsNil) @@ -140,7 +140,7 @@ func (s *withoutControllerSuite) TestProvisioningInfoRootDiskVolume(c *gc.C) { serviceFactoryGetter := s.ServiceFactoryGetter(c) st := s.ControllerModel(c).State() - storageService := serviceFactoryGetter.FactoryForModel(st.ModelUUID()).Storage(registry) + storageService := serviceFactoryGetter.FactoryForModel(model.UUID(st.ModelUUID())).Storage(registry) err := storageService.CreateStoragePool(context.Background(), "static-pool", "static", map[string]any{"foo": "bar"}) c.Assert(err, jc.ErrorIsNil) template := state.MachineTemplate{ diff --git a/apiserver/facades/agent/storageprovisioner/storageprovisioner_caas_test.go b/apiserver/facades/agent/storageprovisioner/storageprovisioner_caas_test.go index 77c871a00d8..6f00868c1f3 100644 --- a/apiserver/facades/agent/storageprovisioner/storageprovisioner_caas_test.go +++ b/apiserver/facades/agent/storageprovisioner/storageprovisioner_caas_test.go @@ -19,6 +19,7 @@ import ( "github.com/juju/juju/caas/kubernetes/provider" k8stesting "github.com/juju/juju/caas/kubernetes/provider/testing" "github.com/juju/juju/core/life" + "github.com/juju/juju/core/model" loggertesting "github.com/juju/juju/internal/logger/testing" "github.com/juju/juju/rpc/params" "github.com/juju/juju/state" @@ -61,7 +62,7 @@ func (s *caasProvisionerSuite) SetUpTest(c *gc.C) { c.Assert(err, jc.ErrorIsNil) registry := stateenvirons.NewStorageProviderRegistry(broker) serviceFactoryGetter := s.ServiceFactoryGetter(c) - storageService := serviceFactoryGetter.FactoryForModel(s.st.ModelUUID()).Storage(registry) + storageService := serviceFactoryGetter.FactoryForModel(model.UUID(s.st.ModelUUID())).Storage(registry) s.authorizer = &apiservertesting.FakeAuthorizer{ Tag: names.NewMachineTag("0"), diff --git a/apiserver/facades/agent/storageprovisioner/storageprovisioner_iaas_test.go b/apiserver/facades/agent/storageprovisioner/storageprovisioner_iaas_test.go index 7b0a0da5695..0e1fdd813bc 100644 --- a/apiserver/facades/agent/storageprovisioner/storageprovisioner_iaas_test.go +++ b/apiserver/facades/agent/storageprovisioner/storageprovisioner_iaas_test.go @@ -23,6 +23,7 @@ import ( "github.com/juju/juju/core/blockdevice" "github.com/juju/juju/core/instance" "github.com/juju/juju/core/life" + "github.com/juju/juju/core/model" "github.com/juju/juju/core/objectstore" "github.com/juju/juju/core/watcher/watchertest" "github.com/juju/juju/environs" @@ -70,7 +71,7 @@ func (s *iaasProvisionerSuite) newApi(c *gc.C, blockDeviceService storageprovisi registry := stateenvirons.NewStorageProviderRegistry(env) s.st = s.ControllerModel(c).State() serviceFactoryGetter := s.ServiceFactoryGetter(c) - storageService := serviceFactoryGetter.FactoryForModel(s.st.ModelUUID()).Storage(registry) + storageService := serviceFactoryGetter.FactoryForModel(model.UUID(s.st.ModelUUID())).Storage(registry) s.authorizer = &apiservertesting.FakeAuthorizer{ Tag: names.NewMachineTag("0"), diff --git a/apiserver/facades/client/application/application_test.go b/apiserver/facades/client/application/application_test.go index 46f8041128d..bed0435516e 100644 --- a/apiserver/facades/client/application/application_test.go +++ b/apiserver/facades/client/application/application_test.go @@ -85,7 +85,7 @@ func (s *applicationSuite) makeAPI(c *gc.C) *application.APIBase { st := s.ControllerModel(c).State() storageAccess, err := application.GetStorageState(st) c.Assert(err, jc.ErrorIsNil) - model, err := st.Model() + m, err := st.Model() c.Assert(err, jc.ErrorIsNil) blockChecker := common.NewBlockChecker(st) @@ -101,7 +101,7 @@ func (s *applicationSuite) makeAPI(c *gc.C) *application.APIBase { registry := stateenvirons.NewStorageProviderRegistry(env) serviceFactoryGetter := s.ServiceFactoryGetter(c) - storageService := serviceFactoryGetter.FactoryForModel(st.ModelUUID()).Storage(registry) + storageService := serviceFactoryGetter.FactoryForModel(model.UUID(st.ModelUUID())).Storage(registry) api, err := application.NewAPIBase( application.GetState(st, env), nil, @@ -111,7 +111,7 @@ func (s *applicationSuite) makeAPI(c *gc.C) *application.APIBase { nil, nil, blockChecker, - application.GetModel(model), + application.GetModel(m), serviceFactory.Cloud(), serviceFactory.Credential(), serviceFactory.Machine(), diff --git a/apiserver/facades/client/controller/controller_test.go b/apiserver/facades/client/controller/controller_test.go index 622a947fb48..c3d9236ca0a 100644 --- a/apiserver/facades/client/controller/controller_test.go +++ b/apiserver/facades/client/controller/controller_test.go @@ -86,7 +86,7 @@ func (s *controllerSuite) SetUpTest(c *gc.C) { s.StateSuite.ControllerConfig = controllerCfg s.StateSuite.SetUpTest(c) s.ServiceFactorySuite.SetUpTest(c) - jujujujutesting.SeedDatabase(c, s.ControllerSuite.TxnRunner(), s.ServiceFactoryGetter(c)(s.ControllerModelUUID.String()), controllerCfg) + jujujujutesting.SeedDatabase(c, s.ControllerSuite.TxnRunner(), s.ServiceFactoryGetter(c)(s.ControllerModelUUID), controllerCfg) s.hub = pubsub.NewStructuredHub(nil) diff --git a/apiserver/facades/controller/migrationtarget/servicefactory_mock_test.go b/apiserver/facades/controller/migrationtarget/servicefactory_mock_test.go index 5e42a671b69..9694dfba1e9 100644 --- a/apiserver/facades/controller/migrationtarget/servicefactory_mock_test.go +++ b/apiserver/facades/controller/migrationtarget/servicefactory_mock_test.go @@ -12,6 +12,7 @@ package migrationtarget_test import ( reflect "reflect" + model "github.com/juju/juju/core/model" service "github.com/juju/juju/domain/access/service" service0 "github.com/juju/juju/domain/annotation/service" service1 "github.com/juju/juju/domain/application/service" @@ -65,7 +66,7 @@ func (m *MockServiceFactoryGetter) EXPECT() *MockServiceFactoryGetterMockRecorde } // FactoryForModel mocks base method. -func (m *MockServiceFactoryGetter) FactoryForModel(arg0 string) servicefactory.ServiceFactory { +func (m *MockServiceFactoryGetter) FactoryForModel(arg0 model.UUID) servicefactory.ServiceFactory { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "FactoryForModel", arg0) ret0, _ := ret[0].(servicefactory.ServiceFactory) @@ -91,13 +92,13 @@ func (c *MockServiceFactoryGetterFactoryForModelCall) Return(arg0 servicefactory } // Do rewrite *gomock.Call.Do -func (c *MockServiceFactoryGetterFactoryForModelCall) Do(f func(string) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { +func (c *MockServiceFactoryGetterFactoryForModelCall) Do(f func(model.UUID) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockServiceFactoryGetterFactoryForModelCall) DoAndReturn(f func(string) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { +func (c *MockServiceFactoryGetterFactoryForModelCall) DoAndReturn(f func(model.UUID) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/apiserver/introspection.go b/apiserver/introspection.go index 8f833e78fb8..f8c81aaa34d 100644 --- a/apiserver/introspection.go +++ b/apiserver/introspection.go @@ -11,7 +11,6 @@ import ( "github.com/juju/names/v5" "github.com/juju/juju/apiserver/common" - "github.com/juju/juju/core/database" "github.com/juju/juju/core/permission" "github.com/juju/juju/rpc/params" ) @@ -45,7 +44,7 @@ func (h introspectionHandler) checkAuth(r *http.Request) error { // or "read" access on the controller model, can // access these endpoints. - accessService := h.ctx.srv.shared.serviceFactoryGetter.FactoryForModel(database.ControllerNS).Access() + accessService := h.ctx.srv.shared.serviceFactoryGetter.FactoryForModel(h.ctx.srv.shared.controllerModelID).Access() userPermission := func(subject names.UserTag, target names.Tag) (permission.Access, error) { var pID permission.ID diff --git a/apiserver/registration.go b/apiserver/registration.go index 0e9ed522357..b15220bbb4e 100644 --- a/apiserver/registration.go +++ b/apiserver/registration.go @@ -19,6 +19,7 @@ import ( coremacaroon "github.com/juju/juju/core/macaroon" usererrors "github.com/juju/juju/domain/access/errors" "github.com/juju/juju/environs" + "github.com/juju/juju/internal/servicefactory" "github.com/juju/juju/rpc/params" "github.com/juju/juju/state" "github.com/juju/juju/state/stateenvirons" @@ -51,7 +52,8 @@ func (h *registerUserHandler) ServeHTTP(w http.ResponseWriter, req *http.Request // TODO (stickupkid): Remove this nonsense, we should be able to get the // service factory from the handler. - serviceFactory := h.ctxt.srv.shared.serviceFactoryGetter.FactoryForModel(st.ModelUUID()) + var serviceFactory servicefactory.ControllerServiceFactory + serviceFactory = h.ctxt.srv.shared.serviceFactoryGetter.FactoryForModel(h.ctxt.srv.shared.controllerModelID) userTag, response, err := h.processPost( req, st.State, diff --git a/apiserver/root.go b/apiserver/root.go index 1aff588b038..2686b1f0807 100644 --- a/apiserver/root.go +++ b/apiserver/root.go @@ -137,7 +137,7 @@ func newAPIHandler( objectStore objectstore.ObjectStore, objectStoreGetter objectstore.ObjectStoreGetter, controllerObjectStore objectstore.ObjectStore, - modelUUID string, + modelID model.UUID, connectionID uint64, serverHost string, ) (*apiHandler, error) { @@ -174,7 +174,7 @@ func newAPIHandler( watcherRegistry: registry, shared: srv.shared, rpcConn: rpcConn, - modelUUID: modelUUID, + modelUUID: modelID.String(), connectionID: connectionID, serverHost: serverHost, } @@ -985,7 +985,7 @@ func (ctx *facadeContext) migrationScope(modelUUID string) modelmigration.Scope // ServiceFactoryForModel returns the services factory for a given // model uuid. func (ctx *facadeContext) ServiceFactoryForModel(uuid model.UUID) servicefactory.ServiceFactory { - return ctx.r.serviceFactoryGetter.FactoryForModel(uuid.String()) + return ctx.r.serviceFactoryGetter.FactoryForModel(uuid) } // ObjectStoreForModel returns the object store for a given model uuid. diff --git a/apiserver/shared.go b/apiserver/shared.go index f7bffcc6046..be7536429e3 100644 --- a/apiserver/shared.go +++ b/apiserver/shared.go @@ -17,6 +17,7 @@ import ( "github.com/juju/juju/core/database" "github.com/juju/juju/core/lease" corelogger "github.com/juju/juju/core/logger" + "github.com/juju/juju/core/model" "github.com/juju/juju/core/objectstore" "github.com/juju/juju/core/presence" "github.com/juju/juju/internal/pubsub/controller" @@ -74,6 +75,9 @@ type sharedServerContext struct { controllerConfig jujucontroller.Config features set.Strings + // controllerModelID is the ID of the controller model. + controllerModelID model.UUID + machineTag names.Tag dataDir string logDir string @@ -87,6 +91,7 @@ type sharedServerConfig struct { presence presence.Recorder leaseManager lease.Manager controllerUUID string + controllerModelID model.UUID controllerConfig jujucontroller.Config logger corelogger.Logger charmhubHTTPClient facade.HTTPClient @@ -151,6 +156,7 @@ func newSharedServerContext(config sharedServerConfig) (*sharedServerContext, er leaseManager: config.leaseManager, logger: config.logger, controllerUUID: config.controllerUUID, + controllerModelID: config.controllerModelID, controllerConfig: config.controllerConfig, charmhubHTTPClient: config.charmhubHTTPClient, dbGetter: config.dbGetter, diff --git a/apiserver/shared_test.go b/apiserver/shared_test.go index 5d611927893..11c9c59e3e3 100644 --- a/apiserver/shared_test.go +++ b/apiserver/shared_test.go @@ -14,6 +14,7 @@ import ( gc "gopkg.in/check.v1" corecontroller "github.com/juju/juju/controller" + "github.com/juju/juju/core/model" "github.com/juju/juju/core/presence" loggertesting "github.com/juju/juju/internal/logger/testing" "github.com/juju/juju/internal/pubsub/controller" @@ -54,6 +55,7 @@ func (s *sharedServerContextSuite) SetUpTest(c *gc.C) { dataDir: c.MkDir(), logDir: c.MkDir(), controllerUUID: testing.ControllerTag.Id(), + controllerModelID: model.UUID(testing.ModelTag.Id()), } } diff --git a/apiserver/tools.go b/apiserver/tools.go index 6e191de573d..5310b154abf 100644 --- a/apiserver/tools.go +++ b/apiserver/tools.go @@ -20,6 +20,7 @@ import ( "github.com/juju/juju/apiserver/common" "github.com/juju/juju/apiserver/httpcontext" + coremodel "github.com/juju/juju/core/model" "github.com/juju/juju/core/objectstore" "github.com/juju/juju/environs" "github.com/juju/juju/environs/simplestreams" @@ -235,7 +236,7 @@ func (h *toolsDownloadHandler) fetchAndCacheTools( } newEnviron := stateenvirons.GetNewEnvironFunc(environs.New) - serviceFactory := h.ctxt.srv.shared.serviceFactoryGetter.FactoryForModel(st.ModelUUID()) + serviceFactory := h.ctxt.srv.shared.serviceFactoryGetter.FactoryForModel(coremodel.UUID(st.ModelUUID())) env, err := newEnviron(model, serviceFactory.Cloud(), serviceFactory.Credential()) if err != nil { return err diff --git a/cmd/jujud-controller/agent/bootstrap.go b/cmd/jujud-controller/agent/bootstrap.go index 48824b606fb..65c47b4523f 100644 --- a/cmd/jujud-controller/agent/bootstrap.go +++ b/cmd/jujud-controller/agent/bootstrap.go @@ -34,6 +34,7 @@ import ( "github.com/juju/juju/core/arch" "github.com/juju/juju/core/credential" "github.com/juju/juju/core/instance" + "github.com/juju/juju/core/model" "github.com/juju/juju/core/network" coreos "github.com/juju/juju/core/os" coreuser "github.com/juju/juju/core/user" @@ -397,7 +398,7 @@ func (c *BootstrapCommand) Run(ctx *cmd.Context) error { cloudGetter{cloud: &args.ControllerCloud}, credentialGetter{cred: args.ControllerCloudCredential}, // We don't need the storage service at bootstrap. - func(modelUUID string, registry storage.ProviderRegistry) state.StoragePoolGetter { + func(modelUUID model.UUID, registry storage.ProviderRegistry) state.StoragePoolGetter { return noopStoragePoolGetter{} }, ), diff --git a/cmd/jujud-controller/agent/machine.go b/cmd/jujud-controller/agent/machine.go index e7080ae4d19..a6a9e718c88 100644 --- a/cmd/jujud-controller/agent/machine.go +++ b/cmd/jujud-controller/agent/machine.go @@ -1136,7 +1136,7 @@ func openStatePool( ControllerTag: agentConfig.Controller(), ControllerModelTag: agentConfig.Model(), MongoSession: session, - NewPolicy: stateenvirons.GetNewPolicyFunc(cloudService, credService, func(modelUUID string, registry storage.ProviderRegistry) state.StoragePoolGetter { + NewPolicy: stateenvirons.GetNewPolicyFunc(cloudService, credService, func(modelUUID coremodel.UUID, registry storage.ProviderRegistry) state.StoragePoolGetter { return serviceFactoryGetter.FactoryForModel(modelUUID).Storage(registry) }), RunTransactionObserver: runTransactionObserver, diff --git a/cmd/jujud-controller/agent/machine/manifolds.go b/cmd/jujud-controller/agent/machine/manifolds.go index 96370cfea3d..ce1d69f3f74 100644 --- a/cmd/jujud-controller/agent/machine/manifolds.go +++ b/cmd/jujud-controller/agent/machine/manifolds.go @@ -671,6 +671,7 @@ func commonManifolds(config ManifoldsConfig) dependency.Manifolds { Hub: config.CentralHub, Presence: config.PresenceRecorder, GetControllerConfigService: apiserver.GetControllerConfigService, + GetModelService: apiserver.GetModelService, NewWorker: apiserver.NewWorker, NewMetricsCollector: apiserver.NewMetricsCollector, })), diff --git a/domain/servicefactory/testing/service.go b/domain/servicefactory/testing/service.go index a5ed68de97a..a29a51dde5a 100644 --- a/domain/servicefactory/testing/service.go +++ b/domain/servicefactory/testing/service.go @@ -4,6 +4,7 @@ package testing import ( + "github.com/juju/juju/core/model" accessservice "github.com/juju/juju/domain/access/service" annotationservice "github.com/juju/juju/domain/annotation/service" applicationservice "github.com/juju/juju/domain/application/service" @@ -155,7 +156,7 @@ func (s *TestingServiceFactory) Macaroon() *macaroonservice.Service { // FactoryForModel returns a service factory for the given model uuid. // This will late bind the model service factory to the actual service factory. -func (s *TestingServiceFactory) FactoryForModel(modelUUID string) servicefactory.ServiceFactory { +func (s *TestingServiceFactory) FactoryForModel(modelID model.UUID) servicefactory.ServiceFactory { return s } diff --git a/domain/servicefactory/testing/suite.go b/domain/servicefactory/testing/suite.go index fb05abb7453..c20815fe9be 100644 --- a/domain/servicefactory/testing/suite.go +++ b/domain/servicefactory/testing/suite.go @@ -76,13 +76,13 @@ func (s stubDBDeleter) DeleteDB(namespace string) error { // ControllerServiceFactory conveniently constructs a service factory for the // controller model. func (s *ServiceFactorySuite) ControllerServiceFactory(c *gc.C) servicefactory.ServiceFactory { - return s.ServiceFactoryGetter(c)(string(s.ControllerModelUUID)) + return s.ServiceFactoryGetter(c)(s.ControllerModelUUID) } // DefaultModelServiceFactory conveniently constructs a service factory for the // default model. func (s *ServiceFactorySuite) DefaultModelServiceFactory(c *gc.C) servicefactory.ServiceFactory { - return s.ServiceFactoryGetter(c)(string(s.ControllerModelUUID)) + return s.ServiceFactoryGetter(c)(s.ControllerModelUUID) } func (s *ServiceFactorySuite) SeedAdminUser(c *gc.C) { @@ -191,11 +191,11 @@ func (s *ServiceFactorySuite) SeedModelDatabases(c *gc.C) { // ServiceFactoryGetter provides an implementation of the ServiceFactoryGetter // interface to use in tests. func (s *ServiceFactorySuite) ServiceFactoryGetter(c *gc.C) ServiceFactoryGetterFunc { - return func(modelUUID string) servicefactory.ServiceFactory { + return func(modelUUID coremodel.UUID) servicefactory.ServiceFactory { return domainservicefactory.NewServiceFactory( databasetesting.ConstFactory(s.TxnRunner()), - coremodel.UUID(modelUUID), - databasetesting.ConstFactory(s.ModelTxnRunner(c, modelUUID)), + modelUUID, + databasetesting.ConstFactory(s.ModelTxnRunner(c, modelUUID.String())), stubDBDeleter{DB: s.DB()}, s.ProviderTracker, loggertesting.WrapCheckLog(c), @@ -220,9 +220,9 @@ func (s *ServiceFactorySuite) SetUpTest(c *gc.C) { // ServiceFactoryGetterFunc is a convenience type for translating a getter // function into the ServiceFactoryGetter interface. -type ServiceFactoryGetterFunc func(string) servicefactory.ServiceFactory +type ServiceFactoryGetterFunc func(coremodel.UUID) servicefactory.ServiceFactory // FactoryForModel implements the ServiceFactoryGetter interface. -func (s ServiceFactoryGetterFunc) FactoryForModel(modelUUID string) servicefactory.ServiceFactory { +func (s ServiceFactoryGetterFunc) FactoryForModel(modelUUID coremodel.UUID) servicefactory.ServiceFactory { return s(modelUUID) } diff --git a/internal/migration/migration.go b/internal/migration/migration.go index 582447d5d5f..d1092691b84 100644 --- a/internal/migration/migration.go +++ b/internal/migration/migration.go @@ -176,7 +176,7 @@ func (i *ModelImporter) ImportModel(ctx context.Context, bytes []byte) (*state.M modelUUID := coremodel.UUID(model.Tag().Id()) - serviceFactory := i.serviceFactoryGetter.FactoryForModel(modelUUID.String()) + serviceFactory := i.serviceFactoryGetter.FactoryForModel(modelUUID) configSchemaSource := i.configSchemaSourceProvider(serviceFactory.Cloud()) dbModel, dbState, err := i.legacyStateImporter.Import(model, ctrlConfig, configSchemaSource) if err != nil { diff --git a/internal/migration/servicefactory_mock_test.go b/internal/migration/servicefactory_mock_test.go index f541edeeeee..b42958fdb01 100644 --- a/internal/migration/servicefactory_mock_test.go +++ b/internal/migration/servicefactory_mock_test.go @@ -12,6 +12,7 @@ package migration_test import ( reflect "reflect" + model "github.com/juju/juju/core/model" service "github.com/juju/juju/domain/access/service" service0 "github.com/juju/juju/domain/annotation/service" service1 "github.com/juju/juju/domain/application/service" @@ -65,7 +66,7 @@ func (m *MockServiceFactoryGetter) EXPECT() *MockServiceFactoryGetterMockRecorde } // FactoryForModel mocks base method. -func (m *MockServiceFactoryGetter) FactoryForModel(arg0 string) servicefactory.ServiceFactory { +func (m *MockServiceFactoryGetter) FactoryForModel(arg0 model.UUID) servicefactory.ServiceFactory { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "FactoryForModel", arg0) ret0, _ := ret[0].(servicefactory.ServiceFactory) @@ -91,13 +92,13 @@ func (c *MockServiceFactoryGetterFactoryForModelCall) Return(arg0 servicefactory } // Do rewrite *gomock.Call.Do -func (c *MockServiceFactoryGetterFactoryForModelCall) Do(f func(string) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { +func (c *MockServiceFactoryGetterFactoryForModelCall) Do(f func(model.UUID) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockServiceFactoryGetterFactoryForModelCall) DoAndReturn(f func(string) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { +func (c *MockServiceFactoryGetterFactoryForModelCall) DoAndReturn(f func(model.UUID) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/internal/servicefactory/interface.go b/internal/servicefactory/interface.go index dc05ced62a8..78ed8c7e65b 100644 --- a/internal/servicefactory/interface.go +++ b/internal/servicefactory/interface.go @@ -4,6 +4,7 @@ package servicefactory import ( + "github.com/juju/juju/core/model" accessservice "github.com/juju/juju/domain/access/service" annotationService "github.com/juju/juju/domain/annotation/service" applicationservice "github.com/juju/juju/domain/application/service" @@ -110,7 +111,7 @@ type ServiceFactory interface { // model. type ServiceFactoryGetter interface { // FactoryForModel returns a ServiceFactory for the given model. - FactoryForModel(modelUUID string) ServiceFactory + FactoryForModel(modelID model.UUID) ServiceFactory } // ProviderServiceFactory provides access to the services required by the diff --git a/internal/worker/apiserver/controllerconfig_mock_test.go b/internal/worker/apiserver/controllerconfig_mock_test.go index 5bca130bac7..ac80668ceb5 100644 --- a/internal/worker/apiserver/controllerconfig_mock_test.go +++ b/internal/worker/apiserver/controllerconfig_mock_test.go @@ -1,9 +1,9 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/juju/juju/internal/worker/apiserver (interfaces: ControllerConfigService) +// Source: github.com/juju/juju/internal/worker/apiserver (interfaces: ControllerConfigService,ModelService) // // Generated by this command: // -// mockgen -typed -package apiserver_test -destination controllerconfig_mock_test.go github.com/juju/juju/internal/worker/apiserver ControllerConfigService +// mockgen -typed -package apiserver_test -destination controllerconfig_mock_test.go github.com/juju/juju/internal/worker/apiserver ControllerConfigService,ModelService // // Package apiserver_test is a generated GoMock package. @@ -14,6 +14,7 @@ import ( reflect "reflect" controller "github.com/juju/juju/controller" + model "github.com/juju/juju/core/model" gomock "go.uber.org/mock/gomock" ) @@ -78,3 +79,65 @@ func (c *MockControllerConfigServiceControllerConfigCall) DoAndReturn(f func(con c.Call = c.Call.DoAndReturn(f) return c } + +// MockModelService is a mock of ModelService interface. +type MockModelService struct { + ctrl *gomock.Controller + recorder *MockModelServiceMockRecorder +} + +// MockModelServiceMockRecorder is the mock recorder for MockModelService. +type MockModelServiceMockRecorder struct { + mock *MockModelService +} + +// NewMockModelService creates a new mock instance. +func NewMockModelService(ctrl *gomock.Controller) *MockModelService { + mock := &MockModelService{ctrl: ctrl} + mock.recorder = &MockModelServiceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockModelService) EXPECT() *MockModelServiceMockRecorder { + return m.recorder +} + +// ControllerModel mocks base method. +func (m *MockModelService) ControllerModel(arg0 context.Context) (model.Model, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ControllerModel", arg0) + ret0, _ := ret[0].(model.Model) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ControllerModel indicates an expected call of ControllerModel. +func (mr *MockModelServiceMockRecorder) ControllerModel(arg0 any) *MockModelServiceControllerModelCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ControllerModel", reflect.TypeOf((*MockModelService)(nil).ControllerModel), arg0) + return &MockModelServiceControllerModelCall{Call: call} +} + +// MockModelServiceControllerModelCall wrap *gomock.Call +type MockModelServiceControllerModelCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockModelServiceControllerModelCall) Return(arg0 model.Model, arg1 error) *MockModelServiceControllerModelCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockModelServiceControllerModelCall) Do(f func(context.Context) (model.Model, error)) *MockModelServiceControllerModelCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockModelServiceControllerModelCall) DoAndReturn(f func(context.Context) (model.Model, error)) *MockModelServiceControllerModelCall { + c.Call = c.Call.DoAndReturn(f) + return c +} diff --git a/internal/worker/apiserver/manifold.go b/internal/worker/apiserver/manifold.go index f99963144a7..20cc3db32bd 100644 --- a/internal/worker/apiserver/manifold.go +++ b/internal/worker/apiserver/manifold.go @@ -21,7 +21,6 @@ import ( "github.com/juju/juju/apiserver/apiserverhttp" "github.com/juju/juju/apiserver/authentication/macaroon" "github.com/juju/juju/cmd/juju/commands" - jujucontroller "github.com/juju/juju/controller" "github.com/juju/juju/core/auditlog" "github.com/juju/juju/core/changestream" "github.com/juju/juju/core/database" @@ -38,23 +37,28 @@ import ( "github.com/juju/juju/jujuclient" ) -// GetControllerConfigServiceFunc is a helper function that gets a service from -// the manifold. +// GetControllerConfigServiceFunc is a helper function that gets a +// [ControllerConfigService] from the manifold. type GetControllerConfigServiceFunc func(getter dependency.Getter, name string) (ControllerConfigService, error) -// GetControllerConfigService is a helper function that gets a service from the -// manifold. +// GetControllerConfigService is a helper function that gets a +// [ControllerConfigService] from the manifold. func GetControllerConfigService(getter dependency.Getter, name string) (ControllerConfigService, error) { return coredependency.GetDependencyByName(getter, name, func(factory servicefactory.ControllerServiceFactory) ControllerConfigService { return factory.ControllerConfig() }) } -// ControllerConfigService is the interface that the worker uses to get the -// controller configuration. -type ControllerConfigService interface { - // ControllerConfig returns the current controller configuration. - ControllerConfig(context.Context) (jujucontroller.Config, error) +// GetModelServiceFunc is a helper function that gets a [ModelService] from the +// manifold. +type GetModelServiceFunc func(getter dependency.Getter, name string) (ModelService, error) + +// GetModelService is a helper function that gets a [ModelService] from the +// manifold. +func GetModelService(getter dependency.Getter, name string) (ModelService, error) { + return coredependency.GetDependencyByName(getter, name, func(factory servicefactory.ControllerServiceFactory) ModelService { + return factory.Model() + }) } // ManifoldConfig holds the information necessary to run an apiserver @@ -81,6 +85,7 @@ type ManifoldConfig struct { Hub *pubsub.StructuredHub Presence presence.Recorder GetControllerConfigService GetControllerConfigServiceFunc + GetModelService GetModelServiceFunc NewWorker func(context.Context, Config) (worker.Worker, error) NewMetricsCollector func() *apiserver.Collector @@ -154,6 +159,9 @@ func (config ManifoldConfig) Validate() error { if config.GetControllerConfigService == nil { return errors.NotValidf("nil GetControllerConfigService") } + if config.GetModelService == nil { + return errors.NotValidf("nil GetModelService") + } return nil } @@ -269,6 +277,11 @@ func (config ManifoldConfig) start(ctx context.Context, getter dependency.Getter return nil, errors.Trace(err) } + modelService, err := config.GetModelService(getter, config.ServiceFactoryName) + if err != nil { + return nil, errors.Trace(err) + } + // Register the metrics collector against the prometheus register. metricsCollector := config.NewMetricsCollector() if err := config.PrometheusRegisterer.Register(metricsCollector); err != nil { @@ -310,6 +323,7 @@ func (config ManifoldConfig) start(ctx context.Context, getter dependency.Getter TracerGetter: tracerGetter, ObjectStoreGetter: objectStoreGetter, ControllerConfigService: controllerConfigService, + ModelService: modelService, }) if err != nil { // Ensure we clean up the resources we've registered with. This includes diff --git a/internal/worker/apiserver/manifold_test.go b/internal/worker/apiserver/manifold_test.go index 0730d4ba156..de35e24e393 100644 --- a/internal/worker/apiserver/manifold_test.go +++ b/internal/worker/apiserver/manifold_test.go @@ -30,6 +30,7 @@ import ( "github.com/juju/juju/core/auditlog" "github.com/juju/juju/core/changestream" corelogger "github.com/juju/juju/core/logger" + "github.com/juju/juju/core/model" "github.com/juju/juju/core/objectstore" "github.com/juju/juju/core/presence" "github.com/juju/juju/internal/servicefactory" @@ -64,6 +65,7 @@ type ManifoldSuite struct { dbDeleter stubDBDeleter serviceFactoryGetter *stubServiceFactoryGetter controllerConfigService *MockControllerConfigService + modelService *MockModelService tracerGetter stubTracerGetter objectStoreGetter stubObjectStoreGetter @@ -92,6 +94,7 @@ func (s *ManifoldSuite) SetUpTest(c *gc.C) { s.serviceFactoryGetter = &stubServiceFactoryGetter{} s.dbDeleter = stubDBDeleter{} s.controllerConfigService = NewMockControllerConfigService(ctrl) + s.modelService = NewMockModelService(ctrl) s.getter = s.newGetter(nil) s.manifold = apiserver.Manifold(apiserver.ManifoldConfig{ @@ -117,6 +120,9 @@ func (s *ManifoldSuite) SetUpTest(c *gc.C) { GetControllerConfigService: func(getter dependency.Getter, name string) (apiserver.ControllerConfigService, error) { return s.controllerConfigService, nil }, + GetModelService: func(getter dependency.Getter, name string) (apiserver.ModelService, error) { + return s.modelService, nil + }, NewWorker: s.newWorker, NewMetricsCollector: s.newMetricsCollector, }) @@ -243,6 +249,7 @@ func (s *ManifoldSuite) TestStart(c *gc.C) { TracerGetter: s.tracerGetter, ObjectStoreGetter: s.objectStoreGetter, ControllerConfigService: s.controllerConfigService, + ModelService: s.modelService, }) } @@ -408,7 +415,7 @@ type stubServiceFactoryGetter struct { servicefactory.ServiceFactoryGetter } -func (s *stubServiceFactoryGetter) FactoryForModel(modelUUID string) servicefactory.ServiceFactory { +func (s *stubServiceFactoryGetter) FactoryForModel(model.UUID) servicefactory.ServiceFactory { return nil } diff --git a/internal/worker/apiserver/package_test.go b/internal/worker/apiserver/package_test.go index bed10db50ce..0715a1cf8f5 100644 --- a/internal/worker/apiserver/package_test.go +++ b/internal/worker/apiserver/package_test.go @@ -9,7 +9,7 @@ import ( gc "gopkg.in/check.v1" ) -//go:generate go run go.uber.org/mock/mockgen -typed -package apiserver_test -destination controllerconfig_mock_test.go github.com/juju/juju/internal/worker/apiserver ControllerConfigService +//go:generate go run go.uber.org/mock/mockgen -typed -package apiserver_test -destination controllerconfig_mock_test.go github.com/juju/juju/internal/worker/apiserver ControllerConfigService,ModelService //go:generate go run go.uber.org/mock/mockgen -typed -package apiserver_test -destination service_mock_test.go github.com/juju/juju/internal/servicefactory ServiceFactoryGetter func TestPackage(t *testing.T) { diff --git a/internal/worker/apiserver/service.go b/internal/worker/apiserver/service.go new file mode 100644 index 00000000000..72c8fe5e6b3 --- /dev/null +++ b/internal/worker/apiserver/service.go @@ -0,0 +1,24 @@ +// Copyright 2024 Canonical Ltd. +// Licensed under the AGPLv3, see LICENCE file for details. + +package apiserver + +import ( + "context" + + "github.com/juju/juju/controller" + "github.com/juju/juju/core/model" +) + +// ControllerConfigService is the interface that the worker uses to get the +// controller configuration. +type ControllerConfigService interface { + // ControllerConfig returns the current controller configuration. + ControllerConfig(context.Context) (controller.Config, error) +} + +// ModelService is the interface that the worker uses to get model information. +type ModelService interface { + // ControllerModel returns information for the controller model. + ControllerModel(context.Context) (model.Model, error) +} diff --git a/internal/worker/apiserver/service_mock_test.go b/internal/worker/apiserver/service_mock_test.go index e77813d12f1..d4351565226 100644 --- a/internal/worker/apiserver/service_mock_test.go +++ b/internal/worker/apiserver/service_mock_test.go @@ -12,6 +12,7 @@ package apiserver_test import ( reflect "reflect" + model "github.com/juju/juju/core/model" servicefactory "github.com/juju/juju/internal/servicefactory" gomock "go.uber.org/mock/gomock" ) @@ -40,7 +41,7 @@ func (m *MockServiceFactoryGetter) EXPECT() *MockServiceFactoryGetterMockRecorde } // FactoryForModel mocks base method. -func (m *MockServiceFactoryGetter) FactoryForModel(arg0 string) servicefactory.ServiceFactory { +func (m *MockServiceFactoryGetter) FactoryForModel(arg0 model.UUID) servicefactory.ServiceFactory { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "FactoryForModel", arg0) ret0, _ := ret[0].(servicefactory.ServiceFactory) @@ -66,13 +67,13 @@ func (c *MockServiceFactoryGetterFactoryForModelCall) Return(arg0 servicefactory } // Do rewrite *gomock.Call.Do -func (c *MockServiceFactoryGetterFactoryForModelCall) Do(f func(string) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { +func (c *MockServiceFactoryGetterFactoryForModelCall) Do(f func(model.UUID) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockServiceFactoryGetterFactoryForModelCall) DoAndReturn(f func(string) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { +func (c *MockServiceFactoryGetterFactoryForModelCall) DoAndReturn(f func(model.UUID) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/internal/worker/apiserver/worker.go b/internal/worker/apiserver/worker.go index b54f5602418..c6c7cc5cbff 100644 --- a/internal/worker/apiserver/worker.go +++ b/internal/worker/apiserver/worker.go @@ -57,6 +57,7 @@ type Config struct { TracerGetter trace.TracerGetter ObjectStoreGetter objectstore.ObjectStoreGetter ControllerConfigService ControllerConfigService + ModelService ModelService } type HTTPClient interface { @@ -126,6 +127,12 @@ func (config Config) Validate() error { if config.ObjectStoreGetter == nil { return errors.NotValidf("nil ObjectStoreGetter") } + if config.ControllerConfigService == nil { + return errors.NotValidf("nil ControllerConfigService") + } + if config.ModelService == nil { + return errors.NotValidf("nil ModelService") + } return nil } @@ -145,6 +152,11 @@ func NewWorker(ctx context.Context, config Config) (worker.Worker, error) { return nil, errors.Annotate(err, "getting controller config") } + controllerModel, err := config.ModelService.ControllerModel(ctx) + if err != nil { + return nil, errors.Annotate(err, "getting controller model information") + } + observerFactory, err := newObserverFn( config.AgentConfig, config.Clock, @@ -170,6 +182,7 @@ func NewWorker(ctx context.Context, config Config) (worker.Worker, error) { Presence: config.Presence, Mux: config.Mux, ControllerUUID: controllerConfig.ControllerUUID(), + ControllerModelID: controllerModel.UUID, LocalMacaroonAuthenticator: config.LocalMacaroonAuthenticator, JWTAuthenticator: jwtAuthenticator, UpgradeComplete: config.UpgradeComplete, diff --git a/internal/worker/apiserver/worker_state_test.go b/internal/worker/apiserver/worker_state_test.go index be2625b3354..eed3f2dee6d 100644 --- a/internal/worker/apiserver/worker_state_test.go +++ b/internal/worker/apiserver/worker_state_test.go @@ -130,5 +130,6 @@ func (s *WorkerStateSuite) TestStart(c *gc.C) { TracerGetter: s.tracerGetter, ObjectStoreGetter: s.objectStoreGetter, ControllerUUID: s.controllerUUID, + ControllerModelID: s.controllerModelID, }) } diff --git a/internal/worker/apiserver/worker_test.go b/internal/worker/apiserver/worker_test.go index ce3830309c2..8468d663044 100644 --- a/internal/worker/apiserver/worker_test.go +++ b/internal/worker/apiserver/worker_test.go @@ -22,6 +22,8 @@ import ( "github.com/juju/juju/controller" "github.com/juju/juju/core/lease" corelogger "github.com/juju/juju/core/logger" + "github.com/juju/juju/core/model" + modeltesting "github.com/juju/juju/core/model/testing" "github.com/juju/juju/core/presence" "github.com/juju/juju/internal/worker/apiserver" "github.com/juju/juju/state" @@ -47,8 +49,10 @@ type workerFixture struct { tracerGetter stubTracerGetter objectStoreGetter stubObjectStoreGetter controllerConfigService *MockControllerConfigService + modelService *MockModelService serviceFactoryGetter *MockServiceFactoryGetter controllerUUID string + controllerModelID model.UUID } func (s *workerFixture) SetUpTest(c *gc.C) { @@ -71,8 +75,10 @@ func (s *workerFixture) SetUpTest(c *gc.C) { s.logSink = &mockModelLogger{} s.charmhubHTTPClient = &http.Client{} s.controllerConfigService = NewMockControllerConfigService(ctrl) + s.modelService = NewMockModelService(ctrl) s.serviceFactoryGetter = NewMockServiceFactoryGetter(ctrl) s.controllerUUID = coretesting.ControllerTag.Id() + s.controllerModelID = modeltesting.GenModelUUID(c) s.stub.ResetCalls() s.config = apiserver.Config{ @@ -93,6 +99,7 @@ func (s *workerFixture) SetUpTest(c *gc.C) { DBGetter: s.dbGetter, DBDeleter: s.dbDeleter, ControllerConfigService: s.controllerConfigService, + ModelService: s.modelService, ServiceFactoryGetter: s.serviceFactoryGetter, TracerGetter: s.tracerGetter, ObjectStoreGetter: s.objectStoreGetter, diff --git a/internal/worker/bootstrap/manifold.go b/internal/worker/bootstrap/manifold.go index 1d604babb28..3bbfc63cce1 100644 --- a/internal/worker/bootstrap/manifold.go +++ b/internal/worker/bootstrap/manifold.go @@ -19,6 +19,7 @@ import ( "github.com/juju/juju/core/flags" "github.com/juju/juju/core/instance" "github.com/juju/juju/core/logger" + "github.com/juju/juju/core/model" "github.com/juju/juju/core/network" "github.com/juju/juju/core/objectstore" "github.com/juju/juju/core/user" @@ -324,7 +325,7 @@ func Manifold(config ManifoldConfig) dependency.Manifold { _ = stTracker.Done() return nil, errors.Trace(err) } - modelServiceFactory := serviceFactoryGetter.FactoryForModel(systemState.ModelUUID()) + modelServiceFactory := serviceFactoryGetter.FactoryForModel(model.UUID(systemState.ModelUUID())) // TODO (stickupkid): This should be removed once we get rid of // the policy and move it into the service factory. diff --git a/internal/worker/modelworkermanager/modelworkermanager.go b/internal/worker/modelworkermanager/modelworkermanager.go index 2c3c35ce08b..64f51c191f6 100644 --- a/internal/worker/modelworkermanager/modelworkermanager.go +++ b/internal/worker/modelworkermanager/modelworkermanager.go @@ -20,6 +20,7 @@ import ( "github.com/juju/juju/controller" "github.com/juju/juju/core/database" corelogger "github.com/juju/juju/core/logger" + "github.com/juju/juju/core/model" "github.com/juju/juju/internal/pki" "github.com/juju/juju/internal/servicefactory" "github.com/juju/juju/state" @@ -283,7 +284,7 @@ func (m *modelWorkerManager) starter(cfg NewModelConfig) func() (worker.Worker, // Get the provider service factory for the model. cfg.ProviderServiceFactoryGetter = m.config.ProviderServiceFactoryGetter - cfg.ServiceFactory = m.config.ServiceFactoryGetter.FactoryForModel(modelUUID) + cfg.ServiceFactory = m.config.ServiceFactoryGetter.FactoryForModel(model.UUID(modelUUID)) // Get the controller config for the model worker so that we correctly // handle the case where the controller config changes between model diff --git a/internal/worker/objectstore/manifold.go b/internal/worker/objectstore/manifold.go index 4cd52466dfc..cea7a2887f6 100644 --- a/internal/worker/objectstore/manifold.go +++ b/internal/worker/objectstore/manifold.go @@ -18,6 +18,7 @@ import ( coredependency "github.com/juju/juju/core/dependency" "github.com/juju/juju/core/lease" "github.com/juju/juju/core/logger" + "github.com/juju/juju/core/model" coreobjectstore "github.com/juju/juju/core/objectstore" "github.com/juju/juju/internal/objectstore" "github.com/juju/juju/internal/servicefactory" @@ -29,7 +30,7 @@ import ( // MetadataService for a given model UUID. type MetadataServiceGetter interface { // For returns the MetadataService for the given model UUID. - ForModelUUID(string) MetadataService + ForModelUUID(model.UUID) MetadataService } // ModelClaimGetter is the interface that is used to get a model claimer. @@ -237,7 +238,7 @@ type modelMetadataServiceGetter struct { } // ForModelUUID returns the MetadataService for the given model UUID. -func (s modelMetadataServiceGetter) ForModelUUID(modelUUID string) MetadataService { +func (s modelMetadataServiceGetter) ForModelUUID(modelUUID model.UUID) MetadataService { return modelMetadataService{factory: s.factoryGetter.FactoryForModel(modelUUID)} } diff --git a/internal/worker/objectstore/manifold_test.go b/internal/worker/objectstore/manifold_test.go index c3be83901f1..8832ae9700f 100644 --- a/internal/worker/objectstore/manifold_test.go +++ b/internal/worker/objectstore/manifold_test.go @@ -11,9 +11,10 @@ import ( "github.com/juju/worker/v4/dependency" dependencytesting "github.com/juju/worker/v4/dependency/testing" "github.com/juju/worker/v4/workertest" - gomock "go.uber.org/mock/gomock" + "go.uber.org/mock/gomock" gc "gopkg.in/check.v1" + "github.com/juju/juju/core/model" "github.com/juju/juju/core/objectstore" "github.com/juju/juju/core/trace" controllerconfigservice "github.com/juju/juju/domain/controllerconfig/service" @@ -137,7 +138,7 @@ type stubServiceFactoryGetter struct { servicefactory.ServiceFactoryGetter } -func (s *stubServiceFactoryGetter) FactoryForModel(modelUUID string) servicefactory.ServiceFactory { +func (s *stubServiceFactoryGetter) FactoryForModel(model.UUID) servicefactory.ServiceFactory { return &stubServiceFactory{} } diff --git a/internal/worker/objectstore/objectstore_mock_test.go b/internal/worker/objectstore/objectstore_mock_test.go index b432e59143b..3236a6752bf 100644 --- a/internal/worker/objectstore/objectstore_mock_test.go +++ b/internal/worker/objectstore/objectstore_mock_test.go @@ -15,6 +15,7 @@ import ( reflect "reflect" controller "github.com/juju/juju/controller" + model "github.com/juju/juju/core/model" objectstore "github.com/juju/juju/core/objectstore" objectstore0 "github.com/juju/juju/internal/objectstore" gomock "go.uber.org/mock/gomock" @@ -295,7 +296,7 @@ func (m *MockMetadataServiceGetter) EXPECT() *MockMetadataServiceGetterMockRecor } // ForModelUUID mocks base method. -func (m *MockMetadataServiceGetter) ForModelUUID(arg0 string) MetadataService { +func (m *MockMetadataServiceGetter) ForModelUUID(arg0 model.UUID) MetadataService { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ForModelUUID", arg0) ret0, _ := ret[0].(MetadataService) @@ -321,13 +322,13 @@ func (c *MockMetadataServiceGetterForModelUUIDCall) Return(arg0 MetadataService) } // Do rewrite *gomock.Call.Do -func (c *MockMetadataServiceGetterForModelUUIDCall) Do(f func(string) MetadataService) *MockMetadataServiceGetterForModelUUIDCall { +func (c *MockMetadataServiceGetterForModelUUIDCall) Do(f func(model.UUID) MetadataService) *MockMetadataServiceGetterForModelUUIDCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockMetadataServiceGetterForModelUUIDCall) DoAndReturn(f func(string) MetadataService) *MockMetadataServiceGetterForModelUUIDCall { +func (c *MockMetadataServiceGetterForModelUUIDCall) DoAndReturn(f func(model.UUID) MetadataService) *MockMetadataServiceGetterForModelUUIDCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/internal/worker/objectstore/worker.go b/internal/worker/objectstore/worker.go index 4045afab53a..c015e5e1e7b 100644 --- a/internal/worker/objectstore/worker.go +++ b/internal/worker/objectstore/worker.go @@ -15,6 +15,7 @@ import ( "github.com/juju/juju/core/database" "github.com/juju/juju/core/logger" + "github.com/juju/juju/core/model" coreobjectstore "github.com/juju/juju/core/objectstore" coretrace "github.com/juju/juju/core/trace" internalobjectstore "github.com/juju/juju/internal/objectstore" @@ -279,7 +280,7 @@ func (w *objectStoreWorker) initObjectStore(namespace string) error { if namespace == database.ControllerNS { metadataService = w.cfg.ControllerMetadataService } else { - metadataService = w.cfg.ModelMetadataServiceGetter.ForModelUUID(namespace) + metadataService = w.cfg.ModelMetadataServiceGetter.ForModelUUID(model.UUID(namespace)) } objectStore, err := w.cfg.NewObjectStoreWorker( diff --git a/internal/worker/servicefactory/servicefactory_mock_test.go b/internal/worker/servicefactory/servicefactory_mock_test.go index 479db4af8f0..40a9eb0e01e 100644 --- a/internal/worker/servicefactory/servicefactory_mock_test.go +++ b/internal/worker/servicefactory/servicefactory_mock_test.go @@ -12,6 +12,7 @@ package servicefactory import ( reflect "reflect" + model "github.com/juju/juju/core/model" service "github.com/juju/juju/domain/access/service" service0 "github.com/juju/juju/domain/annotation/service" service1 "github.com/juju/juju/domain/application/service" @@ -2110,7 +2111,7 @@ func (m *MockServiceFactoryGetter) EXPECT() *MockServiceFactoryGetterMockRecorde } // FactoryForModel mocks base method. -func (m *MockServiceFactoryGetter) FactoryForModel(arg0 string) servicefactory.ServiceFactory { +func (m *MockServiceFactoryGetter) FactoryForModel(arg0 model.UUID) servicefactory.ServiceFactory { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "FactoryForModel", arg0) ret0, _ := ret[0].(servicefactory.ServiceFactory) @@ -2136,13 +2137,13 @@ func (c *MockServiceFactoryGetterFactoryForModelCall) Return(arg0 servicefactory } // Do rewrite *gomock.Call.Do -func (c *MockServiceFactoryGetterFactoryForModelCall) Do(f func(string) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { +func (c *MockServiceFactoryGetterFactoryForModelCall) Do(f func(model.UUID) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockServiceFactoryGetterFactoryForModelCall) DoAndReturn(f func(string) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { +func (c *MockServiceFactoryGetterFactoryForModelCall) DoAndReturn(f func(model.UUID) servicefactory.ServiceFactory) *MockServiceFactoryGetterFactoryForModelCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/internal/worker/servicefactory/worker.go b/internal/worker/servicefactory/worker.go index 4ab17a43d60..c7f24f569a9 100644 --- a/internal/worker/servicefactory/worker.go +++ b/internal/worker/servicefactory/worker.go @@ -141,11 +141,11 @@ type serviceFactoryGetter struct { // FactoryForModel returns a service factory for the given model uuid. // This will late bind the model service factory to the actual service factory. -func (s *serviceFactoryGetter) FactoryForModel(modelUUID string) servicefactory.ServiceFactory { +func (s *serviceFactoryGetter) FactoryForModel(modelUUID coremodel.UUID) servicefactory.ServiceFactory { return &serviceFactory{ ControllerServiceFactory: s.ctrlFactory, ModelServiceFactory: s.newModelServiceFactory( - coremodel.UUID(modelUUID), s.dbGetter, + modelUUID, s.dbGetter, s.providerFactory, s.logger, ), diff --git a/juju/testing/apiserver.go b/juju/testing/apiserver.go index b0d25eeb1e8..af466ee2220 100644 --- a/juju/testing/apiserver.go +++ b/juju/testing/apiserver.go @@ -281,7 +281,7 @@ func (s *ApiServerSuite) setupControllerModel(c *gc.C, controllerCfg controller. CloudName: DefaultCloud.Name, MongoSession: session, AdminPassword: AdminSecret, - NewPolicy: stateenvirons.GetNewPolicyFunc(serviceFactory.Cloud(), serviceFactory.Credential(), func(modelUUID string, registry storage.ProviderRegistry) state.StoragePoolGetter { + NewPolicy: stateenvirons.GetNewPolicyFunc(serviceFactory.Cloud(), serviceFactory.Credential(), func(modelUUID coremodel.UUID, registry storage.ProviderRegistry) state.StoragePoolGetter { return s.ServiceFactoryGetter(c).FactoryForModel(modelUUID).Storage(registry) }), }, environs.ProviderConfigSchemaSource(serviceFactory.Cloud())) @@ -541,7 +541,7 @@ func (s *ApiServerSuite) NewFactory(c *gc.C, modelUUID string) (*factory.Factory c.Assert(err, jc.ErrorIsNil) } - modelServiceFactory := s.ServiceFactoryGetter(c).FactoryForModel(modelUUID) + modelServiceFactory := s.ServiceFactoryGetter(c).FactoryForModel(coremodel.UUID(modelUUID)) var registry storage.ProviderRegistry if model.Type() == state.ModelTypeIAAS { registry = storage.ChainedProviderRegistry{ @@ -674,6 +674,7 @@ func DefaultServerConfig(c *gc.C, testclock clock.Clock) apiserver.ServerConfig LocalMacaroonAuthenticator: &mockAuthenticator{}, GetAuditConfig: func() auditlog.Config { return auditlog.Config{} }, ControllerUUID: coretesting.ControllerTag.Id(), + ControllerModelID: coremodel.UUID(coretesting.ModelTag.Id()), } } @@ -707,7 +708,7 @@ type stubObjectStoreGetter struct { } func (s *stubObjectStoreGetter) GetObjectStore(ctx context.Context, namespace string) (objectstore.ObjectStore, error) { - serviceFactory := s.serviceFactoryGetter.FactoryForModel(namespace) + serviceFactory := s.serviceFactoryGetter.FactoryForModel(coremodel.UUID(namespace)) return internalobjectstore.ObjectStoreFactory(ctx, internalobjectstore.DefaultBackendType(), diff --git a/state/stateenvirons/policy.go b/state/stateenvirons/policy.go index 4ee97a994bc..cdbf33ab48b 100644 --- a/state/stateenvirons/policy.go +++ b/state/stateenvirons/policy.go @@ -11,6 +11,7 @@ import ( "github.com/juju/juju/caas" "github.com/juju/juju/core/constraints" + coremodel "github.com/juju/juju/core/model" "github.com/juju/juju/environs" "github.com/juju/juju/environs/config" "github.com/juju/juju/environs/envcontext" @@ -39,7 +40,7 @@ type deployChecker interface { environs.ConstraintsChecker } -type storageServiceGetter func(modelUUID string, registry storage.ProviderRegistry) state.StoragePoolGetter +type storageServiceGetter func(modelUUID coremodel.UUID, registry storage.ProviderRegistry) state.StoragePoolGetter // GetNewPolicyFunc returns a state.NewPolicyFunc that will return // a state.Policy implemented in terms of either environs.Environ @@ -142,7 +143,7 @@ func (p *environStatePolicy) StorageServices() (state.StoragePoolGetter, storage if err != nil { return nil, nil, errors.Trace(err) } - storageService := p.storageServiceGetter(model.UUID(), registry) + storageService := p.storageServiceGetter(coremodel.UUID(model.UUID()), registry) return storageService, registry, nil }