func (s *BootstrapSuite) TestAutoSyncLocalSource(c *gc.C) { sourceDir := createToolsSource(c, vAll) s.PatchValue(&jujuversion.Current, version.MustParse("1.2.0")) series.SetLatestLtsForTesting("trusty") resetJujuXDGDataHome(c) // Bootstrap the controller with the valid source. // The bootstrapping has to show no error, because the tools // are automatically synchronized. _, err := coretesting.RunCommand( c, s.newBootstrapCommand(), "--metadata-source", sourceDir, "devcontroller", "dummy-cloud/region-1", ) c.Assert(err, jc.ErrorIsNil) p, err := environs.Provider("dummy") c.Assert(err, jc.ErrorIsNil) cfg, err := modelcmd.NewGetBootstrapConfigFunc(s.store)("devcontroller") c.Assert(err, jc.ErrorIsNil) env, err := p.PrepareForBootstrap(envtesting.BootstrapContext(c), cfg) c.Assert(err, jc.ErrorIsNil) // Now check the available tools which are the 1.2.0 envtools. checkTools(c, env, v120All) }
func (s *NewAPIClientSuite) TestWithSlowInfoConnect(c *gc.C) { c.Skip("wallyworld - this is a dumb test relying on an arbitary 50ms delay to pass") s.PatchValue(&jujuversion.Current, coretesting.FakeVersionNumber) _, store := s.bootstrapModel(c) setEndpointAddressAndHostname(c, store, "0.1.2.3", "infoapi.invalid") infoOpenedState := mockedAPIState(noFlags) infoEndpointOpened := make(chan struct{}) cfgOpenedState := mockedAPIState(noFlags) // On a sample run with no delay, the logic took 45ms to run, so // we make the delay slightly more than that, so that if the // logic doesn't delay at all, the test will fail reasonably consistently. s.PatchValue(juju.ProviderConnectDelay, 50*time.Millisecond) apiOpen := func(info *api.Info, opts api.DialOpts) (api.Connection, error) { if info.Addrs[0] == "0.1.2.3" { infoEndpointOpened <- struct{}{} return infoOpenedState, nil } return cfgOpenedState, nil } stateClosed := make(chan api.Connection) infoOpenedState.close = func(st api.Connection) error { stateClosed <- st return nil } cfgOpenedState.close = infoOpenedState.close startTime := time.Now() st, err := newAPIConnectionFromNames(c, "local.my-controller", "admin@local", "only", store, apiOpen, modelcmd.NewGetBootstrapConfigFunc(store), ) c.Assert(err, jc.ErrorIsNil) // The connection logic should wait for some time before opening // the API from the configuration. c.Assert(time.Since(startTime), jc.GreaterThan, *juju.ProviderConnectDelay) c.Assert(st, gc.Equals, cfgOpenedState) select { case <-infoEndpointOpened: case <-time.After(coretesting.LongWait): c.Errorf("api never opened via info") } // Check that the ignored state was closed. select { case st := <-stateClosed: c.Assert(st, gc.Equals, infoOpenedState) case <-time.After(coretesting.LongWait): c.Errorf("timed out waiting for state to be closed") } }
// getEnviron returns the environ for the specified controller, or // mocked out environ for testing. func (c *restoreCommand) getEnviron(controllerName string, meta *params.BackupsMetadataResult) (environs.Environ, error) { // TODO(axw) delete this and -b in 2.0-beta2. We will update bootstrap // with a flag to specify a restore file. When we do that, we'll need // to extract the CA cert from the backup, and we'll need to reset the // password after restore so the admin user can login. // We also need to store things like the admin-secret, controller // certificate etc with the backup. store := c.ClientStore() cfg, err := modelcmd.NewGetBootstrapConfigFunc(store)(controllerName) if err != nil { return nil, errors.Annotate(err, "cannot restore from a machine other than the one used to bootstrap") } // Reset current model to admin so first bootstrap succeeds. err = store.SetCurrentModel(controllerName, environs.AdminUser, "admin") if err != nil { return nil, errors.Trace(err) } // Get the local admin user so we can use the password as the admin secret. var adminSecret string account, err := store.AccountByName(controllerName, environs.AdminUser) if err == nil { adminSecret = account.Password } else if errors.IsNotFound(err) { // No relevant local admin user so generate a new secret. buf := make([]byte, 16) if _, err := io.ReadFull(rand.Reader, buf); err != nil { return nil, errors.Annotate(err, "generating new admin secret") } adminSecret = fmt.Sprintf("%x", buf) } else { return nil, errors.Trace(err) } // Turn on safe mode so that the newly bootstrapped instance // will not destroy all the instances it does not know about. // Also set the admin secret and ca cert info. cfg, err = cfg.Apply(map[string]interface{}{ "provisioner-safe-mode": true, "admin-secret": adminSecret, "ca-private-key": meta.CAPrivateKey, "ca-cert": meta.CACert, }) if err != nil { return nil, errors.Annotatef(err, "cannot enable provisioner-safe-mode") } return environs.New(cfg) }
func (c *imageMetadataCommandBase) prepare(context *cmd.Context) (environs.Environ, error) { // NOTE(axw) this is a work-around for the TODO below. This // means that the command will only work if you've bootstrapped // the specified environment. cfg, err := modelcmd.NewGetBootstrapConfigFunc(c.ClientStore())(c.ControllerName()) if err != nil { return nil, errors.Trace(err) } // TODO(axw) we'll need to revise the metadata commands to work // without preparing an environment. They should take the same // format as bootstrap, i.e. cloud/region, and we'll use that to // identify region and endpoint info that we need. Not sure what // we'll do about simplestreams.MetadataValidator yet. Probably // move it to the EnvironProvider interface. return environs.New(cfg) }
// getControllerEnviron returns the Environ for the controller model. // // getControllerEnviron gets the information required to get the // Environ by first checking the config store, then querying the // API if the information is not in the store. func (c *destroyCommandBase) getControllerEnviron( store jujuclient.ClientStore, controllerName string, sysAPI destroyControllerAPI, ) (_ environs.Environ, err error) { cfg, err := modelcmd.NewGetBootstrapConfigFunc(store)(controllerName) if errors.IsNotFound(err) { if sysAPI == nil { return nil, errors.New( "unable to get bootstrap information from client store or API", ) } bootstrapConfig, err := sysAPI.ModelConfig() if err != nil { return nil, errors.Annotate(err, "getting bootstrap config from API") } cfg, err = config.New(config.NoDefaults, bootstrapConfig) if err != nil { return nil, errors.Trace(err) } } else if err != nil { return nil, errors.Annotate(err, "getting bootstrap config from client store") } return environs.New(cfg) }
func (s *NewAPIClientSuite) TestWithSlowConfigConnect(c *gc.C) { s.PatchValue(&jujuversion.Current, coretesting.FakeVersionNumber) _, store := s.bootstrapModel(c) setEndpointAddressAndHostname(c, store, "0.1.2.3", "infoapi.invalid") infoOpenedState := mockedAPIState(noFlags) infoEndpointOpened := make(chan struct{}) cfgOpenedState := mockedAPIState(noFlags) cfgEndpointOpened := make(chan struct{}) s.PatchValue(juju.ProviderConnectDelay, 0*time.Second) apiOpen := func(info *api.Info, opts api.DialOpts) (api.Connection, error) { if info.Addrs[0] == "0.1.2.3" { infoEndpointOpened <- struct{}{} <-infoEndpointOpened return infoOpenedState, nil } cfgEndpointOpened <- struct{}{} <-cfgEndpointOpened return cfgOpenedState, nil } stateClosed := make(chan api.Connection) infoOpenedState.close = func(st api.Connection) error { stateClosed <- st return nil } cfgOpenedState.close = infoOpenedState.close done := make(chan struct{}) go func() { st, err := newAPIConnectionFromNames(c, "local.my-controller", "admin@local", "only", store, apiOpen, modelcmd.NewGetBootstrapConfigFunc(store), ) c.Check(err, jc.ErrorIsNil) c.Check(st, gc.Equals, infoOpenedState) close(done) }() // Check that we're trying to connect to both endpoints: select { case <-infoEndpointOpened: case <-time.After(coretesting.LongWait): c.Fatalf("api never opened via info") } select { case <-cfgEndpointOpened: case <-time.After(coretesting.LongWait): c.Fatalf("api never opened via config") } // Let the info endpoint open go ahead and // check that the NewAPIFromStore call returns. infoEndpointOpened <- struct{}{} select { case <-done: case <-time.After(coretesting.LongWait): c.Errorf("timed out opening API") } // Let the config endpoint open go ahead and // check that its state is closed. cfgEndpointOpened <- struct{}{} select { case st := <-stateClosed: c.Assert(st, gc.Equals, cfgOpenedState) case <-time.After(coretesting.LongWait): c.Errorf("timed out waiting for state to be closed") } }