func (s *loginSuite) assertRemoteEnvironment(c *gc.C, st api.Connection, expected names.ModelTag) { // Look at what the api thinks it has. tag, err := st.ModelTag() c.Assert(err, jc.ErrorIsNil) c.Assert(tag, gc.Equals, expected) // Look at what the api Client thinks it has. client := st.Client() // ModelUUID looks at the env tag on the api state connection. c.Assert(client.ModelUUID(), gc.Equals, expected.Id()) // ModelInfo calls a remote method that looks up the environment. info, err := client.ModelInfo() c.Assert(err, jc.ErrorIsNil) c.Assert(info.UUID, gc.Equals, expected.Id()) }
func (s *loginSuite) assertRemoteModel(c *gc.C, api api.Connection, expected names.ModelTag) { // Look at what the api thinks it has. tag, ok := api.ModelTag() c.Assert(ok, jc.IsTrue) c.Assert(tag, gc.Equals, expected) // Look at what the api Client thinks it has. client := api.Client() // ModelUUID looks at the env tag on the api state connection. uuid, ok := client.ModelUUID() c.Assert(ok, jc.IsTrue) c.Assert(uuid, gc.Equals, expected.Id()) // The code below is to verify that the API connection is operating on // the expected model. We make a change in state on that model, and // then check that it is picked up by a call to the API. st, err := s.State.ForModel(tag) c.Assert(err, jc.ErrorIsNil) defer st.Close() expectedCons := constraints.MustParse("mem=8G") err = st.SetModelConstraints(expectedCons) c.Assert(err, jc.ErrorIsNil) cons, err := client.GetModelConstraints() c.Assert(err, jc.ErrorIsNil) c.Assert(cons, jc.DeepEquals, expectedCons) }
// maybeSetAgentModelTag tries to update the agent configuration if // it's missing a model tag. It doesn't *really* matter if it fails, // because we can demonstrably connect without it, so we log any // errors encountered and never return any to the client. func maybeSetAgentModelTag(a agent.Agent, conn api.Connection) { if a.CurrentConfig().Model().Id() == "" { err := a.ChangeConfig(func(setter agent.ConfigSetter) error { modelTag, err := conn.ModelTag() if err != nil { return errors.Annotate(err, "no model uuid set on api") } return setter.Migrate(agent.MigrateParams{ Model: modelTag, }) }) if err != nil { logger.Warningf("unable to save model uuid: %v", err) // Not really fatal, just annoying. } } }
// envEndpoint returns "/model/<model-uuid>/<destination>" func envEndpoint(c *gc.C, apiState api.Connection, destination string) string { modelTag, ok := apiState.ModelTag() c.Assert(ok, jc.IsTrue) return path.Join("/model", modelTag.Id(), destination) }
// updateSupportedContainers records in state that a machine can run the specified containers. // It starts a watcher and when a container of a given type is first added to the machine, // the watcher is killed, the machine is set up to be able to start containers of the given type, // and a suitable provisioner is started. func (a *MachineAgent) updateSupportedContainers( runner worker.Runner, st api.Connection, containers []instance.ContainerType, agentConfig agent.Config, ) error { pr := st.Provisioner() tag := agentConfig.Tag().(names.MachineTag) machine, err := pr.Machine(tag) if errors.IsNotFound(err) || err == nil && machine.Life() == params.Dead { return worker.ErrTerminateAgent } if err != nil { return errors.Annotatef(err, "cannot load machine %s from state", tag) } if len(containers) == 0 { if err := machine.SupportsNoContainers(); err != nil { return errors.Annotatef(err, "clearing supported containers for %s", tag) } return nil } if err := machine.SetSupportedContainers(containers...); err != nil { return errors.Annotatef(err, "setting supported containers for %s", tag) } initLock, err := cmdutil.HookExecutionLock(agentConfig.DataDir()) if err != nil { return err } // Start the watcher to fire when a container is first requested on the machine. modelUUID, err := st.ModelTag() if err != nil { return err } watcherName := fmt.Sprintf("%s-container-watcher", machine.Id()) // There may not be a CA certificate private key available, and without // it we can't ensure that other Juju nodes can connect securely, so only // use an image URL getter if there's a private key. var imageURLGetter container.ImageURLGetter if agentConfig.Value(agent.AllowsSecureConnection) == "true" { cfg, err := pr.ModelConfig() if err != nil { return errors.Annotate(err, "unable to get environ config") } imageURLGetter = container.NewImageURLGetter( // Explicitly call the non-named constructor so if anyone // adds additional fields, this fails. container.ImageURLGetterConfig{ ServerRoot: st.Addr(), ModelUUID: modelUUID.Id(), CACert: []byte(agentConfig.CACert()), CloudimgBaseUrl: cfg.CloudImageBaseURL(), Stream: cfg.ImageStream(), ImageDownloadFunc: container.ImageDownloadURL, }) } params := provisioner.ContainerSetupParams{ Runner: runner, WorkerName: watcherName, SupportedContainers: containers, ImageURLGetter: imageURLGetter, Machine: machine, Provisioner: pr, Config: agentConfig, InitLock: initLock, } handler := provisioner.NewContainerSetupHandler(params) a.startWorkerAfterUpgrade(runner, watcherName, func() (worker.Worker, error) { w, err := watcher.NewStringsWorker(watcher.StringsConfig{ Handler: handler, }) if err != nil { return nil, errors.Annotatef(err, "cannot start %s worker", watcherName) } return w, nil }) return nil }
// envEndpoint returns "/model/<model-uuid>/<destination>" func envEndpoint(c *gc.C, apiState api.Connection, destination string) string { modelTag, err := apiState.ModelTag() c.Assert(err, jc.ErrorIsNil) return path.Join("/model", modelTag.Id(), destination) }