Beispiel #1
0
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)
}
Beispiel #2
0
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")
	}
}
Beispiel #3
0
// 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)
}
Beispiel #4
0
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)
}
Beispiel #5
0
// 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)
}
Beispiel #6
0
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")
	}
}