Exemple #1
0
// InitiateModelMigration attempts to start a migration for the
// specified model, returning the migration's ID.
//
// The API server supports starting multiple migrations in one request
// but we don't need that at the client side yet (and may never) so
// this call just supports starting one migration at a time.
func (c *Client) InitiateModelMigration(spec ModelMigrationSpec) (string, error) {
	if err := spec.Validate(); err != nil {
		return "", errors.Trace(err)
	}
	args := params.InitiateModelMigrationArgs{
		Specs: []params.ModelMigrationSpec{{
			ModelTag: names.NewModelTag(spec.ModelUUID).String(),
			TargetInfo: params.ModelMigrationTargetInfo{
				ControllerTag: names.NewModelTag(spec.TargetControllerUUID).String(),
				Addrs:         spec.TargetAddrs,
				CACert:        spec.TargetCACert,
				AuthTag:       names.NewUserTag(spec.TargetUser).String(),
				Password:      spec.TargetPassword,
			},
		}},
	}
	response := params.InitiateModelMigrationResults{}
	if err := c.facade.FacadeCall("InitiateModelMigration", args, &response); err != nil {
		return "", errors.Trace(err)
	}
	if len(response.Results) != 1 {
		return "", errors.New("unexpected number of results returned")
	}
	result := response.Results[0]
	if result.Error != nil {
		return "", errors.Trace(result.Error)
	}
	return result.Id, nil
}
Exemple #2
0
func (s *apiclientSuite) TestOpenHonorsModelTag(c *gc.C) {
	info := s.APIInfo(c)

	// TODO(jam): 2014-06-05 http://pad.lv/1326802
	// we want to test this eventually, but for now s.APIInfo uses
	// conn.StateInfo() which doesn't know about ModelTag.
	// c.Check(info.ModelTag, gc.Equals, env.Tag())
	// c.Assert(info.ModelTag, gc.Not(gc.Equals), "")

	// We start by ensuring we have an invalid tag, and Open should fail.
	info.ModelTag = names.NewModelTag("bad-tag")
	_, err := api.Open(info, api.DialOpts{})
	c.Assert(errors.Cause(err), gc.DeepEquals, &rpc.RequestError{
		Message: `unknown model: "bad-tag"`,
		Code:    "not found",
	})
	c.Check(params.ErrCode(err), gc.Equals, params.CodeNotFound)

	// Now set it to the right tag, and we should succeed.
	info.ModelTag = s.State.ModelTag()
	st, err := api.Open(info, api.DialOpts{})
	c.Assert(err, jc.ErrorIsNil)
	st.Close()

	// Backwards compatibility, we should succeed if we do not set an
	// model tag
	info.ModelTag = names.NewModelTag("")
	st, err = api.Open(info, api.DialOpts{})
	c.Assert(err, jc.ErrorIsNil)
	st.Close()
}
Exemple #3
0
func (s *clientSuite) TestOpenUsesEnvironUUIDPaths(c *gc.C) {
	info := s.APIInfo(c)
	// Backwards compatibility, passing ModelTag = "" should just work
	info.ModelTag = names.NewModelTag("")
	apistate, err := api.Open(info, api.DialOpts{})
	c.Assert(err, jc.ErrorIsNil)
	apistate.Close()

	// Passing in the correct model UUID should also work
	environ, err := s.State.Model()
	c.Assert(err, jc.ErrorIsNil)
	info.ModelTag = environ.ModelTag()
	apistate, err = api.Open(info, api.DialOpts{})
	c.Assert(err, jc.ErrorIsNil)
	apistate.Close()

	// Passing in a bad model UUID should fail with a known error
	info.ModelTag = names.NewModelTag("dead-beef-123456")
	apistate, err = api.Open(info, api.DialOpts{})
	c.Assert(errors.Cause(err), gc.DeepEquals, &rpc.RequestError{
		Message: `unknown model: "dead-beef-123456"`,
		Code:    "not found",
	})
	c.Check(err, jc.Satisfies, params.IsCodeNotFound)
	c.Assert(apistate, gc.IsNil)
}
Exemple #4
0
func (*tagsSuite) TestResourceTagsUUID(c *gc.C) {
	testResourceTags(c, testing.ModelTag, names.NewModelTag(""), nil, map[string]string{
		"juju-model-uuid":      testing.ModelTag.Id(),
		"juju-controller-uuid": "",
	})
	testResourceTags(c, names.NewModelTag(""), testing.ModelTag, nil, map[string]string{
		"juju-model-uuid":      "",
		"juju-controller-uuid": testing.ModelTag.Id(),
	})
}
Exemple #5
0
// InstanceTags returns the minimum set of tags that should be set on a
// machine instance, if the provider supports them.
func InstanceTags(cfg *config.Config, jobs []multiwatcher.MachineJob) map[string]string {
	instanceTags := tags.ResourceTags(
		names.NewModelTag(cfg.UUID()),
		names.NewModelTag(cfg.ControllerUUID()),
		cfg,
	)
	if multiwatcher.AnyJobNeedsState(jobs...) {
		instanceTags[tags.JujuIsController] = "true"
	}
	return instanceTags
}
Exemple #6
0
func (s *PresenceSuite) setup(c *gc.C, key string) (*presence.Watcher, *presence.Pinger, <-chan presence.Change) {
	uuid, err := utils.NewUUID()
	c.Assert(err, jc.ErrorIsNil)
	modelUUID := uuid.String()

	w := presence.NewWatcher(s.presence, names.NewModelTag(modelUUID))
	p := presence.NewPinger(s.presence, names.NewModelTag(modelUUID), key)

	ch := make(chan presence.Change)
	w.Watch(key, ch)
	assertChange(c, ch, presence.Change{key, false})
	return w, p, ch
}
Exemple #7
0
// initResourceGroup creates and initialises a resource group for this
// environment. The resource group will have a storage account and a
// subnet associated with it (but not necessarily contained within:
// see subnet creation).
func (env *azureEnviron) initResourceGroup() (*config.Config, error) {
	location := env.config.location
	tags := tags.ResourceTags(
		names.NewModelTag(env.config.Config.UUID()),
		names.NewModelTag(env.config.Config.ControllerUUID()),
		env.config,
	)
	resourceGroupsClient := resources.GroupsClient{env.resources}

	logger.Debugf("creating resource group %q", env.resourceGroup)
	_, err := resourceGroupsClient.CreateOrUpdate(env.resourceGroup, resources.Group{
		Location: to.StringPtr(location),
		Tags:     toTagsPtr(tags),
	})
	if err != nil {
		return nil, errors.Annotate(err, "creating resource group")
	}

	// Create an internal network for all VMs in the
	// resource group to connect to.
	vnetPtr, err := createInternalVirtualNetwork(
		env.network, env.resourceGroup, location, tags,
	)
	if err != nil {
		return nil, errors.Annotate(err, "creating virtual network")
	}

	_, err = createInternalSubnet(
		env.network, env.resourceGroup, vnetPtr, location, tags,
	)
	if err != nil {
		return nil, errors.Annotate(err, "creating subnet")
	}

	// Create a storage account for the resource group.
	storageAccountsClient := storage.AccountsClient{env.storage}
	storageAccountName, storageAccountKey, err := createStorageAccount(
		storageAccountsClient, env.config.storageAccountType,
		env.resourceGroup, location, tags,
		env.provider.config.StorageAccountNameGenerator,
	)
	if err != nil {
		return nil, errors.Annotate(err, "creating storage account")
	}
	return env.config.Config.Apply(map[string]interface{}{
		configAttrStorageAccount:    storageAccountName,
		configAttrStorageAccountKey: storageAccountKey,
	})
}
Exemple #8
0
// storageTags returns the tags that should be set on a volume or filesystem,
// if the provider supports them.
func storageTags(
	storageInstance state.StorageInstance,
	cfg *config.Config,
) (map[string]string, error) {
	storageTags := tags.ResourceTags(
		names.NewModelTag(cfg.UUID()),
		names.NewModelTag(cfg.ControllerUUID()),
		cfg,
	)
	if storageInstance != nil {
		storageTags[tags.JujuStorageInstance] = storageInstance.Tag().Id()
		storageTags[tags.JujuStorageOwner] = storageInstance.Owner().Id()
	}
	return storageTags, nil
}
Exemple #9
0
func (s *ModelMigrationSuite) SetUpTest(c *gc.C) {
	s.ConnSuite.SetUpTest(c)
	s.clock = coretesting.NewClock(time.Now().Truncate(time.Second))
	s.PatchValue(&state.GetClock, func() clock.Clock {
		return s.clock
	})

	// Create a hosted model to migrate.
	s.State2 = s.Factory.MakeModel(c, nil)
	s.AddCleanup(func(*gc.C) { s.State2.Close() })

	targetControllerTag := names.NewModelTag(utils.MustNewUUID().String())

	// Plausible migration arguments to test with.
	s.stdSpec = state.ModelMigrationSpec{
		InitiatedBy: names.NewUserTag("admin"),
		TargetInfo: migration.TargetInfo{
			ControllerTag: targetControllerTag,
			Addrs:         []string{"1.2.3.4:5555", "4.3.2.1:6666"},
			CACert:        "cert",
			AuthTag:       names.NewUserTag("user"),
			Password:      "******",
		},
	}
}
Exemple #10
0
func (s *ClientSuite) TestActivate(c *gc.C) {
	client, stub := s.getClientAndStub(c)

	uuid := "fake"
	err := client.Activate(uuid)
	s.AssertModelCall(c, stub, names.NewModelTag(uuid), "Activate", err)
}
Exemple #11
0
// newState returns a new State that uses the given environment.
// The environment must have already been bootstrapped.
func newState(environ environs.Environ, mongoInfo *mongo.MongoInfo) (*state.State, error) {
	config := environ.Config()
	password := config.AdminSecret()
	if password == "" {
		return nil, fmt.Errorf("cannot connect without admin-secret")
	}
	modelTag := names.NewModelTag(config.UUID())

	mongoInfo.Password = password
	opts := mongo.DefaultDialOpts()
	st, err := state.Open(modelTag, mongoInfo, opts, environs.NewStatePolicy())
	if errors.IsUnauthorized(errors.Cause(err)) {
		// We try for a while because we might succeed in
		// connecting to mongo before the state has been
		// initialized and the initial password set.
		for a := redialStrategy.Start(); a.Next(); {
			st, err = state.Open(modelTag, mongoInfo, opts, environs.NewStatePolicy())
			if !errors.IsUnauthorized(errors.Cause(err)) {
				break
			}
		}
		if err != nil {
			return nil, err
		}
	} else if err != nil {
		return nil, err
	}
	if err := updateSecrets(environ, st); err != nil {
		st.Close()
		return nil, fmt.Errorf("unable to push secrets: %v", err)
	}
	return st, nil
}
Exemple #12
0
// APIInfo returns an api.Info for the environment. The result is populated
// with addresses and CA certificate, but no tag or password.
func APIInfo(env Environ) (*api.Info, error) {
	instanceIds, err := env.ControllerInstances()
	if err != nil {
		return nil, err
	}
	logger.Debugf("ControllerInstances returned: %v", instanceIds)
	addrs, err := waitAnyInstanceAddresses(env, instanceIds)
	if err != nil {
		return nil, err
	}
	defaultSpaceAddr, ok := network.SelectAddressBySpace(addrs, network.DefaultSpace)
	if ok {
		addrs = []network.Address{defaultSpaceAddr}
		logger.Debugf("selected %q as API address in space %q", defaultSpaceAddr.Value, network.DefaultSpace)
	} else {
		logger.Warningf("using all API addresses (cannot pick by space %q): %+v", network.DefaultSpace, addrs)
	}
	config := env.Config()
	cert, hasCert := config.CACert()
	if !hasCert {
		return nil, errors.New("config has no CACert")
	}
	apiPort := config.APIPort()
	apiAddrs := network.HostPortsToStrings(
		network.AddressesWithPort(addrs, apiPort),
	)
	uuid, uuidSet := config.UUID()
	if !uuidSet {
		return nil, errors.New("config has no UUID")
	}
	modelTag := names.NewModelTag(uuid)
	apiInfo := &api.Info{Addrs: apiAddrs, CACert: cert, ModelTag: modelTag}
	return apiInfo, nil
}
Exemple #13
0
func (s *Suite) TestMigration(c *gc.C) {
	masterClient := newStubMasterClient(s.stub)
	w := migrationmaster.New(masterClient)

	// Trigger migration.
	masterClient.watcher.changes <- migration.TargetInfo{
		ControllerTag: names.NewModelTag("uuid"),
		Addrs:         []string{"1.2.3.4:5"},
		CACert:        "cert",
		AuthTag:       names.NewUserTag("admin"),
		Password:      "******",
	}

	// This error is temporary while migrationmaster is a WIP.
	runWorkerAndWait(c, w, "migration seen and aborted")

	// Observe that the migration was seen, the model exported, an API
	// connection to the target controller was made, the model was
	// imported and then the migration aborted.
	s.stub.CheckCalls(c, []jujutesting.StubCall{
		{"masterClient.Watch", nil},
		{"masterClient.Export", nil},
		{"apiOpen", []interface{}{&api.Info{
			Addrs:    []string{"1.2.3.4:5"},
			CACert:   "cert",
			Tag:      names.NewUserTag("admin"),
			Password: "******",
		}, api.DefaultDialOpts()}},
		{"APICall:MigrationTarget.Import",
			[]interface{}{params.SerializedModel{Bytes: fakeSerializedModel}}},
		{"masterClient.SetPhase", []interface{}{migration.ABORT}},
		{"Connection.Close", nil},
	})
}
Exemple #14
0
func (c *modelsCommand) getModelInfo(userModels []base.UserModel) ([]params.ModelInfo, error) {
	client, err := c.getModelManagerAPI()
	if err != nil {
		return nil, errors.Trace(err)
	}
	defer client.Close()

	tags := make([]names.ModelTag, len(userModels))
	for i, m := range userModels {
		tags[i] = names.NewModelTag(m.UUID)
	}
	results, err := client.ModelInfo(tags)
	if err != nil {
		return nil, errors.Trace(err)
	}

	info := make([]params.ModelInfo, len(tags))
	for i, result := range results {
		if result.Error != nil {
			if params.IsCodeUnauthorized(result.Error) {
				// If we get this, then the model was removed
				// between the initial listing and the call
				// to query its details.
				continue
			}
			return nil, errors.Annotatef(
				result.Error, "getting model %s (%q) info",
				userModels[i].UUID, userModels[i].Name,
			)
		}
		info[i] = *result.Result
	}
	return info, nil
}
Exemple #15
0
// ModelsForUser returns a list of models that the user
// is able to access.
func (st *State) ModelsForUser(user names.UserTag) ([]*UserModel, error) {
	// Since there are no groups at this stage, the simplest way to get all
	// the models that a particular user can see is to look through the
	// model user collection. A raw collection is required to support
	// queries across multiple models.
	modelUsers, userCloser := st.getRawCollection(modelUsersC)
	defer userCloser()

	// TODO: consider adding an index to the modelUsers collection on the username.
	var userSlice []modelUserDoc
	err := modelUsers.Find(bson.D{{"user", user.Canonical()}}).Select(bson.D{{"model-uuid", 1}, {"_id", 1}}).All(&userSlice)
	if err != nil {
		return nil, err
	}

	var result []*UserModel
	for _, doc := range userSlice {
		modelTag := names.NewModelTag(doc.ModelUUID)
		env, err := st.GetModel(modelTag)
		if err != nil {
			return nil, errors.Trace(err)
		}

		result = append(result, &UserModel{Model: env, User: user})
	}

	return result, nil
}
Exemple #16
0
// Run implements Command.Run.
func (c *showModelCommand) Run(ctx *cmd.Context) (err error) {
	api, err := c.getAPI()
	if err != nil {
		return err
	}
	defer api.Close()

	store := c.ClientStore()
	modelDetails, err := store.ModelByName(
		c.ControllerName(),
		c.AccountName(),
		c.ModelName(),
	)
	if err != nil {
		return errors.Annotate(err, "getting model details")
	}

	modelTag := names.NewModelTag(modelDetails.ModelUUID)
	results, err := api.ModelInfo([]names.ModelTag{modelTag})
	if err != nil {
		return err
	}
	if results[0].Error != nil {
		return results[0].Error
	}
	infoMap, err := c.apiModelInfoToModelInfoMap([]params.ModelInfo{*results[0].Result})
	if err != nil {
		return errors.Trace(err)
	}
	return c.out.Write(ctx, infoMap)
}
Exemple #17
0
func (s *controllerSuite) TestAllModels(c *gc.C) {
	admin := s.Factory.MakeUser(c, &factory.UserParams{Name: "foobar"})

	s.Factory.MakeModel(c, &factory.ModelParams{
		Name: "owned", Owner: admin.UserTag()}).Close()
	remoteUserTag := names.NewUserTag("user@remote")
	st := s.Factory.MakeModel(c, &factory.ModelParams{
		Name: "user", Owner: remoteUserTag})
	defer st.Close()
	st.AddModelUser(state.ModelUserSpec{
		User:        admin.UserTag(),
		CreatedBy:   remoteUserTag,
		DisplayName: "Foo Bar"})

	s.Factory.MakeModel(c, &factory.ModelParams{
		Name: "no-access", Owner: remoteUserTag}).Close()

	response, err := s.controller.AllModels()
	c.Assert(err, jc.ErrorIsNil)
	// The results are sorted.
	expected := []string{"dummymodel", "no-access", "owned", "user"}
	var obtained []string
	for _, env := range response.UserModels {
		obtained = append(obtained, env.Name)
		stateEnv, err := s.State.GetModel(names.NewModelTag(env.UUID))
		c.Assert(err, jc.ErrorIsNil)
		s.checkEnvironmentMatches(c, env.Model, stateEnv)
	}
	c.Assert(obtained, jc.DeepEquals, expected)
}
Exemple #18
0
// apiInfoConnect looks for endpoint on the given environment and
// tries to connect to it, sending the result on the returned channel.
func apiInfoConnect(info configstore.EnvironInfo, apiOpen api.OpenFunc, stop <-chan struct{}, bClient *httpbakery.Client) (api.Connection, error) {
	endpoint := info.APIEndpoint()
	if info == nil || len(endpoint.Addresses) == 0 {
		return nil, &infoConnectError{fmt.Errorf("no cached addresses")}
	}
	logger.Infof("connecting to API addresses: %v", endpoint.Addresses)
	var modelTag names.ModelTag
	if names.IsValidModel(endpoint.ModelUUID) {
		modelTag = names.NewModelTag(endpoint.ModelUUID)
	}

	apiInfo := &api.Info{
		Addrs:    endpoint.Addresses,
		CACert:   endpoint.CACert,
		Tag:      environInfoUserTag(info),
		Password: info.APICredentials().Password,
		ModelTag: modelTag,
	}
	if apiInfo.Tag == nil {
		apiInfo.UseMacaroons = true
	}

	dialOpts := api.DefaultDialOpts()
	dialOpts.BakeryClient = bClient

	st, err := apiOpen(apiInfo, dialOpts)
	if err != nil {
		return nil, &infoConnectError{err}
	}
	return st, nil
}
Exemple #19
0
func (c *MigrateCommand) exportModel(ctx *cmd.Context, st *state.State) error {
	ctx.Infof("\nexport %s", c.modelUUID)

	// first make sure the uuid is good enough
	tag := names.NewModelTag(c.modelUUID)
	_, err := st.GetModel(tag)
	if err != nil {
		return errors.Trace(err)
	}

	modelState, err := st.ForModel(tag)
	if err != nil {
		return errors.Trace(err)
	}
	defer modelState.Close()

	model, err := modelState.Export()
	if err != nil {
		return errors.Trace(err)
	}

	bytes, err := yaml.Marshal(model)
	if err != nil {
		return errors.Trace(err)
	}

	ctx.Stdout.Write(bytes)
	return nil
}
Exemple #20
0
// APIInfo returns an api.Info for the environment. The result is populated
// with addresses and CA certificate, but no tag or password.
func APIInfo(env Environ) (*api.Info, error) {
	instanceIds, err := env.ControllerInstances()
	if err != nil {
		return nil, err
	}
	logger.Debugf("ControllerInstances returned: %v", instanceIds)
	addrs, err := waitAnyInstanceAddresses(env, instanceIds)
	if err != nil {
		return nil, err
	}
	config := env.Config()
	cert, hasCert := config.CACert()
	if !hasCert {
		return nil, errors.New("config has no CACert")
	}
	apiPort := config.APIPort()
	apiAddrs := network.HostPortsToStrings(
		network.AddressesWithPort(addrs, apiPort),
	)
	uuid, uuidSet := config.UUID()
	if !uuidSet {
		return nil, errors.New("config has no UUID")
	}
	modelTag := names.NewModelTag(uuid)
	apiInfo := &api.Info{Addrs: apiAddrs, CACert: cert, ModelTag: modelTag}
	return apiInfo, nil
}
Exemple #21
0
func (s *PresenceSuite) SetUpSuite(c *gc.C) {
	s.BaseSuite.SetUpSuite(c)
	s.MgoSuite.SetUpSuite(c)
	uuid, err := utils.NewUUID()
	c.Assert(err, jc.ErrorIsNil)
	s.modelTag = names.NewModelTag(uuid.String())
}
Exemple #22
0
// validateModelUUID is the common validator for the various
// apiserver components that need to check for a valid model
// UUID.  An empty modelUUID means that the connection has come in at
// the root of the URL space and refers to the controller
// model.
//
// It returns the validated model UUID.
func validateModelUUID(args validateArgs) (string, error) {
	ssState := args.statePool.SystemState()
	if args.modelUUID == "" {
		// We allow the modelUUID to be empty for 2 cases
		// 1) Compatibility with older clients
		// 2) TODO: server a limited API at the root (empty modelUUID)
		//    with just the user manager and model manager
		//    if the connection comes over a sufficiently up to date
		//    login command.
		if args.strict {
			return "", errors.Trace(common.UnknownModelError(args.modelUUID))
		}
		logger.Debugf("validate model uuid: empty modelUUID")
		return ssState.ModelUUID(), nil
	}
	if args.modelUUID == ssState.ModelUUID() {
		logger.Debugf("validate model uuid: controller model - %s", args.modelUUID)
		return args.modelUUID, nil
	}
	if args.controllerModelOnly {
		return "", errors.Unauthorizedf("requested model %q is not the controller model", args.modelUUID)
	}
	if !names.IsValidModel(args.modelUUID) {
		return "", errors.Trace(common.UnknownModelError(args.modelUUID))
	}
	modelTag := names.NewModelTag(args.modelUUID)
	if _, err := ssState.GetModel(modelTag); err != nil {
		return "", errors.Wrap(err, common.UnknownModelError(args.modelUUID))
	}
	logger.Debugf("validate model uuid: %s", args.modelUUID)
	return args.modelUUID, nil
}
Exemple #23
0
// NewAPIAuthenticator gets the state and api info once from the
// provisioner API.
func NewAPIAuthenticator(st *apiprovisioner.State) (AuthenticationProvider, error) {
	stateAddresses, err := st.StateAddresses()
	if err != nil {
		return nil, errors.Trace(err)
	}
	apiAddresses, err := st.APIAddresses()
	if err != nil {
		return nil, errors.Trace(err)
	}
	caCert, err := st.CACert()
	if err != nil {
		return nil, errors.Trace(err)
	}
	modelUUID, err := st.ModelUUID()
	if err != nil {
		return nil, errors.Trace(err)
	}
	stateInfo := &mongo.MongoInfo{
		Info: mongo.Info{
			Addrs:  stateAddresses,
			CACert: caCert,
		},
	}
	apiInfo := &api.Info{
		Addrs:    apiAddresses,
		CACert:   caCert,
		ModelTag: names.NewModelTag(modelUUID),
	}
	return &simpleAuth{stateInfo, apiInfo}, nil
}
func (s *macaroonLoginSuite) SetUpTest(c *gc.C) {
	s.MacaroonSuite.SetUpTest(c)
	s.MacaroonSuite.AddModelUser(c, testUser)

	s.controllerName = "my-controller"
	s.accountName = "my@account"
	s.modelName = "my-model"
	modelTag := names.NewModelTag(s.State.ModelUUID())
	apiInfo := s.APIInfo(c)

	s.store = jujuclienttesting.NewMemStore()
	s.store.Controllers[s.controllerName] = jujuclient.ControllerDetails{
		APIEndpoints:   apiInfo.Addrs,
		ControllerUUID: apiInfo.ModelTag.Id(),
		CACert:         apiInfo.CACert,
	}
	s.store.Accounts[s.controllerName] = &jujuclient.ControllerAccounts{
		Accounts: map[string]jujuclient.AccountDetails{
			// Empty password forces use of macaroons.
			s.accountName: {User: s.accountName},
		},
		CurrentAccount: s.accountName,
	}
	s.store.Models[s.controllerName] = jujuclient.ControllerAccountModels{
		AccountModels: map[string]*jujuclient.AccountModels{
			s.accountName: {
				Models: map[string]jujuclient.ModelDetails{
					s.modelName: {modelTag.Id()},
				},
			},
		},
	}
}
Exemple #25
0
func (s *migrationWatcherSuite) TestWatch(c *gc.C) {
	// Create a state server
	m, password := s.Factory.MakeMachineReturningPassword(c, &factory.MachineParams{
		Jobs:  []state.MachineJob{state.JobManageModel},
		Nonce: "noncey",
	})

	// Create a model to migrate.
	hostedState := s.Factory.MakeModel(c, nil)

	// Connect as a state server to the hosted environment.
	apiInfo := s.APIInfo(c)
	apiInfo.Tag = m.Tag()
	apiInfo.Password = password
	apiInfo.ModelTag = hostedState.ModelTag()
	apiInfo.Nonce = "noncey"

	apiConn, err := api.Open(apiInfo, api.DialOpts{})
	c.Assert(err, jc.ErrorIsNil)
	defer apiConn.Close()

	// Start watching for a migration.
	client := migrationmaster.NewClient(apiConn)
	w, err := client.Watch()
	c.Assert(err, jc.ErrorIsNil)
	defer func() {
		c.Assert(worker.Stop(w), jc.ErrorIsNil)
	}()

	// Should be no initial events.
	select {
	case _, ok := <-w.Changes():
		c.Fatalf("watcher sent unexpected change: (_, %v)", ok)
	case <-time.After(coretesting.ShortWait):
	}

	// Now create a migration.
	targetInfo := migration.TargetInfo{
		ControllerTag: names.NewModelTag(utils.MustNewUUID().String()),
		Addrs:         []string{"1.2.3.4:5"},
		CACert:        "trust me I'm an authority",
		AuthTag:       names.NewUserTag("dog"),
		Password:      "******",
	}
	_, err = hostedState.CreateModelMigration(state.ModelMigrationSpec{
		InitiatedBy: names.NewUserTag("someone"),
		TargetInfo:  targetInfo,
	})
	c.Assert(err, jc.ErrorIsNil)

	// Event with correct target details should be emitted.
	select {
	case reportedTargetInfo, ok := <-w.Changes():
		c.Assert(ok, jc.IsTrue)
		c.Assert(reportedTargetInfo, jc.DeepEquals, targetInfo)
	case <-time.After(coretesting.LongWait):
		c.Fatalf("watcher didn't emit an event")
	}
}
Exemple #26
0
// NewModel creates a new model with its own UUID and
// prepares it for use. Model and State instances for the new
// model are returned.
//
// The controller model's UUID is attached to the new
// model's document. Having the server UUIDs stored with each
// model document means that we have a way to represent external
// models, perhaps for future use around cross model
// relations.
func (st *State) NewModel(cfg *config.Config, owner names.UserTag) (_ *Model, _ *State, err error) {
	if owner.IsLocal() {
		if _, err := st.User(owner); err != nil {
			return nil, nil, errors.Annotate(err, "cannot create model")
		}
	}

	ssEnv, err := st.ControllerModel()
	if err != nil {
		return nil, nil, errors.Annotate(err, "could not load controller model")
	}

	uuid := cfg.UUID()
	newState, err := st.ForModel(names.NewModelTag(uuid))
	if err != nil {
		return nil, nil, errors.Annotate(err, "could not create state for new model")
	}
	defer func() {
		if err != nil {
			newState.Close()
		}
	}()

	ops, err := newState.envSetupOps(cfg, uuid, ssEnv.UUID(), owner)
	if err != nil {
		return nil, nil, errors.Annotate(err, "failed to create new model")
	}
	err = newState.runTransaction(ops)
	if err == txn.ErrAborted {

		// We have a  unique key restriction on the "owner" and "name" fields,
		// which will cause the insert to fail if there is another record with
		// the same "owner" and "name" in the collection. If the txn is
		// aborted, check if it is due to the unique key restriction.
		models, closer := st.getCollection(modelsC)
		defer closer()
		envCount, countErr := models.Find(bson.D{
			{"owner", owner.Canonical()},
			{"name", cfg.Name()}},
		).Count()
		if countErr != nil {
			err = errors.Trace(countErr)
		} else if envCount > 0 {
			err = errors.AlreadyExistsf("model %q for %s", cfg.Name(), owner.Canonical())
		} else {
			err = errors.New("model already exists")
		}
	}
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	newEnv, err := newState.Model()
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	return newEnv, newState, nil
}
Exemple #27
0
// InstanceTags returns the minimum set of tags that should be set on a
// machine instance, if the provider supports them.
func InstanceTags(cfg *config.Config, jobs []multiwatcher.MachineJob) map[string]string {
	uuid, _ := cfg.UUID()
	instanceTags := tags.ResourceTags(names.NewModelTag(uuid), cfg)
	if multiwatcher.AnyJobNeedsState(jobs...) {
		instanceTags[tags.JujuStateServer] = "true"
	}
	return instanceTags
}
Exemple #28
0
// APIInfo is part of the agent.Config interface. This implementation always
// replaces the target model tag with the configured model tag.
func (c *modelAgentConfig) APIInfo() (*api.Info, bool) {
	info, ok := c.Config.APIInfo()
	if !ok {
		return nil, false
	}
	info.ModelTag = names.NewModelTag(c.uuid)
	return info, true
}
Exemple #29
0
func (s *apiclientSuite) TestConnectWebsocketToRoot(c *gc.C) {
	info := s.APIInfo(c)
	info.ModelTag = names.NewModelTag("")
	conn, _, err := api.ConnectWebsocket(info, api.DialOpts{})
	c.Assert(err, jc.ErrorIsNil)
	defer conn.Close()
	assertConnAddrForRoot(c, conn, info.Addrs[0])
}
Exemple #30
0
func (s *modelManagerSuite) TestGrantMissingModelFails(c *gc.C) {
	s.setAPIUser(c, s.AdminUserTag(c))
	user := s.Factory.MakeModelUser(c, nil)
	model := names.NewModelTag("17e4bd2d-3e08-4f3d-b945-087be7ebdce4")
	err := s.grant(c, user.UserTag(), params.ModelReadAccess, model)
	expectedErr := `model not found`
	c.Assert(err, gc.ErrorMatches, expectedErr)
}