Пример #1
0
// AddUser creates a new local user in the juju server.
func (c *Client) AddUser(username, displayName, password string) (names.UserTag, error) {
	if !names.IsValidUser(username) {
		return names.UserTag{}, fmt.Errorf("invalid user name %q", username)
	}
	userArgs := params.AddUsers{
		Users: []params.AddUser{{Username: username, DisplayName: displayName, Password: password}},
	}
	var results params.AddUserResults
	err := c.facade.FacadeCall("AddUser", userArgs, &results)
	if err != nil {
		return names.UserTag{}, errors.Trace(err)
	}
	if count := len(results.Results); count != 1 {
		logger.Errorf("expected 1 result, got %#v", results)
		return names.UserTag{}, errors.Errorf("expected 1 result, got %d", count)
	}
	result := results.Results[0]
	if result.Error != nil {
		return names.UserTag{}, errors.Trace(result.Error)
	}
	tag, err := names.ParseUserTag(result.Tag)
	if err != nil {
		return names.UserTag{}, errors.Trace(err)
	}
	logger.Infof("created user %s", result.Tag)
	return tag, nil
}
Пример #2
0
// ListModels returns the models that the specified user
// has access to in the current server.  Only that controller owner
// can list models for any user (at this stage).  Other users
// can only ask about their own models.
func (c *Client) ListModels(user string) ([]base.UserModel, error) {
	var models params.UserModelList
	if !names.IsValidUser(user) {
		return nil, errors.Errorf("invalid user name %q", user)
	}
	entity := params.Entity{names.NewUserTag(user).String()}
	err := c.facade.FacadeCall("ListModels", entity, &models)
	if err != nil {
		return nil, errors.Trace(err)
	}
	result := make([]base.UserModel, len(models.UserModels))
	for i, model := range models.UserModels {
		owner, err := names.ParseUserTag(model.OwnerTag)
		if err != nil {
			return nil, errors.Annotatef(err, "OwnerTag %q at position %d", model.OwnerTag, i)
		}
		result[i] = base.UserModel{
			Name:           model.Name,
			UUID:           model.UUID,
			Owner:          owner.Canonical(),
			LastConnection: model.LastConnection,
		}
	}
	return result, nil
}
Пример #3
0
// UserInfo returns information on a user.
func (api *UserManagerAPI) UserInfo(args params.Entities) (UserInfoResults, error) {
	results := UserInfoResults{
		Results: make([]UserInfoResult, len(args.Entities)),
	}

	for i, userArg := range args.Entities {
		tag, err := names.ParseUserTag(userArg.Tag)
		if err != nil {
			results.Results[0].Error = common.ServerError(err)
			continue
		}
		user, err := api.state.User(tag)
		var result UserInfoResult
		if err != nil {
			if errors.IsNotFound(err) {
				result.Error = common.ServerError(common.ErrPerm)
			} else {
				result.Error = common.ServerError(err)
			}
		} else {
			info := UserInfo{
				Username:       tag.Name(),
				DisplayName:    user.DisplayName(),
				CreatedBy:      user.CreatedBy(),
				DateCreated:    user.DateCreated(),
				LastConnection: user.LastLogin(),
			}
			result.Result = &info
		}
		results.Results[i] = result
	}

	return results, nil
}
Пример #4
0
// ListEnvironments returns the environments that the specified user
// has access to in the current server.  Only that state server owner
// can list environments for any user (at this stage).  Other users
// can only ask about their own environments.
func (c *Client) ListEnvironments(user string) ([]base.UserEnvironment, error) {
	var environments params.UserEnvironmentList
	if !names.IsValidUser(user) {
		return nil, errors.Errorf("invalid user name %q", user)
	}
	entity := params.Entity{names.NewUserTag(user).String()}
	err := c.facade.FacadeCall("ListEnvironments", entity, &environments)
	if err != nil {
		return nil, errors.Trace(err)
	}
	result := make([]base.UserEnvironment, len(environments.UserEnvironments))
	for i, env := range environments.UserEnvironments {
		owner, err := names.ParseUserTag(env.OwnerTag)
		if err != nil {
			return nil, errors.Annotatef(err, "OwnerTag %q at position %d", env.OwnerTag, i)
		}
		result[i] = base.UserEnvironment{
			Name:           env.Name,
			UUID:           env.UUID,
			Owner:          owner.Username(),
			LastConnection: env.LastConnection,
		}
	}
	return result, nil
}
Пример #5
0
// ListEnvironments returns the environments that the specified user
// has access to in the current server.  Only that state server owner
// can list environments for any user (at this stage).  Other users
// can only ask about their own environments.
func (em *EnvironmentManagerAPI) ListEnvironments(user params.Entity) (params.EnvironmentList, error) {
	result := params.EnvironmentList{}

	stateServerEnv, err := em.state.StateServerEnvironment()
	if err != nil {
		return result, errors.Trace(err)
	}
	adminUser := stateServerEnv.Owner()

	userTag, err := names.ParseUserTag(user.Tag)
	if err != nil {
		return result, errors.Trace(err)
	}

	err = em.authCheck(userTag, adminUser)
	if err != nil {
		return result, errors.Trace(err)
	}

	environments, err := em.state.EnvironmentsForUser(userTag)
	if err != nil {
		return result, errors.Trace(err)
	}

	for _, env := range environments {
		result.Environments = append(result.Environments, params.Environment{
			Name:     env.Name(),
			UUID:     env.UUID(),
			OwnerTag: env.Owner().String(),
		})
		logger.Debugf("list env: %s, %s, %s", env.Name(), env.UUID(), env.Owner())
	}

	return result, nil
}
Пример #6
0
// EnvironmentStatus returns a status summary for each environment tag passed in.
func (c *Client) EnvironmentStatus(tags ...names.EnvironTag) ([]base.EnvironmentStatus, error) {
	result := params.EnvironmentStatusResults{}
	envs := make([]params.Entity, len(tags))
	for i, tag := range tags {
		envs[i] = params.Entity{Tag: tag.String()}
	}
	req := params.Entities{
		Entities: envs,
	}
	if err := c.facade.FacadeCall("EnvironmentStatus", req, &result); err != nil {
		return nil, err
	}

	results := make([]base.EnvironmentStatus, len(result.Results))
	for i, r := range result.Results {
		env, err := names.ParseEnvironTag(r.EnvironTag)
		if err != nil {
			return nil, errors.Annotatef(err, "EnvironTag %q at position %d", r.EnvironTag, i)
		}
		owner, err := names.ParseUserTag(r.OwnerTag)
		if err != nil {
			return nil, errors.Annotatef(err, "OwnerTag %q at position %d", r.OwnerTag, i)
		}

		results[i] = base.EnvironmentStatus{
			UUID:               env.Id(),
			Life:               r.Life,
			Owner:              owner.Canonical(),
			HostedMachineCount: r.HostedMachineCount,
			ServiceCount:       r.ServiceCount,
		}

	}
	return results, nil
}
Пример #7
0
// cacheAPIInfo updates the local environment settings (.jenv file)
// with the provided apiInfo, assuming we've just successfully
// connected to the API server.
func cacheAPIInfo(info configstore.EnvironInfo, apiInfo *api.Info) (err error) {
	defer errors.Contextf(&err, "failed to cache API credentials")
	environUUID := ""
	if apiInfo.EnvironTag != "" {
		tag, err := names.ParseEnvironTag(apiInfo.Tag)
		if err != nil {
			return err
		}
		environUUID = tag.Id()
	}
	info.SetAPIEndpoint(configstore.APIEndpoint{
		Addresses:   apiInfo.Addrs,
		CACert:      string(apiInfo.CACert),
		EnvironUUID: environUUID,
	})
	tag, err := names.ParseUserTag(apiInfo.Tag)
	if err != nil {
		return err
	}
	info.SetAPICredentials(configstore.APICredentials{
		User:     tag.Id(),
		Password: apiInfo.Password,
	})
	return info.Write()
}
Пример #8
0
// authenticate parses HTTP basic authentication and authorizes the
// request by looking up the provided tag and password against state.
func (h *httpHandler) authenticate(r *http.Request) error {
	parts := strings.Fields(r.Header.Get("Authorization"))
	if len(parts) != 2 || parts[0] != "Basic" {
		// Invalid header format or no header provided.
		return fmt.Errorf("invalid request format")
	}
	// Challenge is a base64-encoded "tag:pass" string.
	// See RFC 2617, Section 2.
	challenge, err := base64.StdEncoding.DecodeString(parts[1])
	if err != nil {
		return fmt.Errorf("invalid request format")
	}
	tagPass := strings.SplitN(string(challenge), ":", 2)
	if len(tagPass) != 2 {
		return fmt.Errorf("invalid request format")
	}
	// Only allow users, not agents.
	if _, err := names.ParseUserTag(tagPass[0]); err != nil {
		return common.ErrBadCreds
	}
	// Ensure the credentials are correct.
	_, err = checkCreds(h.state, params.Creds{
		AuthTag:  tagPass[0],
		Password: tagPass[1],
	})
	return err
}
Пример #9
0
// ModifyModelAccess changes the model access granted to users.
func (m *ModelManagerAPI) ModifyModelAccess(args params.ModifyModelAccessRequest) (result params.ErrorResults, err error) {
	result = params.ErrorResults{
		Results: make([]params.ErrorResult, len(args.Changes)),
	}
	if len(args.Changes) == 0 {
		return result, nil
	}

	for i, arg := range args.Changes {
		modelAccess, err := FromModelAccessParam(arg.Access)
		if err != nil {
			err = errors.Annotate(err, "could not modify model access")
			result.Results[i].Error = common.ServerError(err)
			continue
		}

		targetUserTag, err := names.ParseUserTag(arg.UserTag)
		if err != nil {
			result.Results[i].Error = common.ServerError(errors.Annotate(err, "could not modify model access"))
			continue
		}
		modelTag, err := names.ParseModelTag(arg.ModelTag)
		if err != nil {
			result.Results[i].Error = common.ServerError(errors.Annotate(err, "could not modify model access"))
			continue
		}

		result.Results[i].Error = common.ServerError(
			ChangeModelAccess(m.state, modelTag, m.apiUser, targetUserTag, arg.Action, modelAccess, m.isAdmin))
	}
	return result, nil
}
Пример #10
0
func (api *UserManagerAPI) getUser(tag string) (*state.User, error) {
	userTag, err := names.ParseUserTag(tag)
	if err != nil {
		return nil, errors.Trace(err)
	}
	user, err := api.state.User(userTag)
	if err != nil {
		return nil, errors.Wrap(err, common.ErrPerm)
	}
	return user, nil
}
Пример #11
0
func (s *userSuite) TestParseUserTag(c *gc.C) {
	for i, t := range parseUserTagTests {
		c.Logf("test %d: %s", i, t.tag)
		got, err := names.ParseUserTag(t.tag)
		if err != nil || t.err != nil {
			c.Check(err, gc.DeepEquals, t.err)
			continue
		}
		c.Check(got, gc.FitsTypeOf, t.expected)
		c.Check(got, gc.Equals, t.expected)
	}
}
Пример #12
0
// TargetInfo implements ModelMigration.
func (mig *modelMigration) TargetInfo() (*migration.TargetInfo, error) {
	authTag, err := names.ParseUserTag(mig.doc.TargetAuthTag)
	if err != nil {
		return nil, errors.Trace(err)
	}
	return &migration.TargetInfo{
		ControllerTag: names.NewModelTag(mig.doc.TargetController),
		Addrs:         mig.doc.TargetAddrs,
		CACert:        mig.doc.TargetCACert,
		AuthTag:       authTag,
		Password:      mig.doc.TargetPassword,
	}, nil
}
Пример #13
0
func (s *Service) ownerTag() (names.UserTag, error) {
	var invalidTag names.UserTag
	var result params.StringResult
	args := params.Entities{
		Entities: []params.Entity{{Tag: s.tag.String()}},
	}
	err := s.st.facade.FacadeCall("GetOwnerTag", args, &result)
	if err != nil {
		return invalidTag, err
	}
	if result.Error != nil {
		return invalidTag, result.Error
	}
	return names.ParseUserTag(result.Result)
}
Пример #14
0
// AddUser creates a new local user in the controller, sharing with that user any specified models.
func (c *Client) AddUser(
	username, displayName, password, access string, modelUUIDs ...string,
) (_ names.UserTag, secretKey []byte, _ error) {
	if !names.IsValidUser(username) {
		return names.UserTag{}, nil, fmt.Errorf("invalid user name %q", username)
	}
	modelTags := make([]string, len(modelUUIDs))
	for i, uuid := range modelUUIDs {
		modelTags[i] = names.NewModelTag(uuid).String()
	}

	var accessPermission params.ModelAccessPermission
	var err error
	if len(modelTags) > 0 {
		accessPermission, err = modelmanager.ParseModelAccess(access)
		if err != nil {
			return names.UserTag{}, nil, errors.Trace(err)
		}
	}

	userArgs := params.AddUsers{
		Users: []params.AddUser{{
			Username:        username,
			DisplayName:     displayName,
			Password:        password,
			SharedModelTags: modelTags,
			ModelAccess:     accessPermission}},
	}
	var results params.AddUserResults
	err = c.facade.FacadeCall("AddUser", userArgs, &results)
	if err != nil {
		return names.UserTag{}, nil, errors.Trace(err)
	}
	if count := len(results.Results); count != 1 {
		logger.Errorf("expected 1 result, got %#v", results)
		return names.UserTag{}, nil, errors.Errorf("expected 1 result, got %d", count)
	}
	result := results.Results[0]
	if result.Error != nil {
		return names.UserTag{}, nil, errors.Trace(result.Error)
	}
	tag, err := names.ParseUserTag(result.Tag)
	if err != nil {
		return names.UserTag{}, nil, errors.Trace(err)
	}
	return tag, result.SecretKey, nil
}
Пример #15
0
func (c *ControllerAPI) initiateOneModelMigration(spec params.ModelMigrationSpec) (string, error) {
	modelTag, err := names.ParseModelTag(spec.ModelTag)
	if err != nil {
		return "", errors.Annotate(err, "model tag")
	}

	// Ensure the model exists.
	if _, err := c.state.GetModel(modelTag); err != nil {
		return "", errors.Annotate(err, "unable to read model")
	}

	// Get State for model.
	hostedState, err := c.state.ForModel(modelTag)
	if err != nil {
		return "", errors.Trace(err)
	}
	defer hostedState.Close()

	// Start the migration.
	targetInfo := spec.TargetInfo

	controllerTag, err := names.ParseModelTag(targetInfo.ControllerTag)
	if err != nil {
		return "", errors.Annotate(err, "controller tag")
	}
	authTag, err := names.ParseUserTag(targetInfo.AuthTag)
	if err != nil {
		return "", errors.Annotate(err, "auth tag")
	}

	args := state.ModelMigrationSpec{
		InitiatedBy: c.apiUser,
		TargetInfo: migration.TargetInfo{
			ControllerTag: controllerTag,
			Addrs:         targetInfo.Addrs,
			CACert:        targetInfo.CACert,
			AuthTag:       authTag,
			Password:      targetInfo.Password,
		},
	}
	mig, err := hostedState.CreateModelMigration(args)
	if err != nil {
		return "", errors.Trace(err)
	}
	return mig.Id(), nil
}
Пример #16
0
func (c *showModelCommand) apiModelInfoToModelInfoMap(modelInfo []params.ModelInfo) (map[string]ModelInfo, error) {
	output := make(map[string]ModelInfo)
	for _, info := range modelInfo {
		tag, err := names.ParseUserTag(info.OwnerTag)
		if err != nil {
			return nil, errors.Trace(err)
		}
		output[info.Name] = ModelInfo{
			UUID:           info.UUID,
			ControllerUUID: info.ControllerUUID,
			Owner:          tag.Id(),
			ProviderType:   info.ProviderType,
			Users:          apiUsersToUserInfoMap(info.Users),
		}
	}
	return output, nil
}
Пример #17
0
func (w *migrationMasterWatcher) loop() error {
	w.newResult = func() interface{} { return new(params.ModelMigrationTargetInfo) }
	w.call = makeWatcherAPICaller(w.caller, "MigrationMasterWatcher", w.id)
	w.commonWatcher.init()
	go w.commonLoop()

	for {
		var data interface{}
		var ok bool

		select {
		case data, ok = <-w.in:
			if !ok {
				// The tomb is already killed with the correct error
				// at this point, so just return.
				return nil
			}
		case <-w.tomb.Dying():
			return nil
		}

		info := data.(*params.ModelMigrationTargetInfo)
		controllerTag, err := names.ParseModelTag(info.ControllerTag)
		if err != nil {
			return errors.Annotatef(err, "unable to parse %q", info.ControllerTag)
		}
		authTag, err := names.ParseUserTag(info.AuthTag)
		if err != nil {
			return errors.Annotatef(err, "unable to parse %q", info.AuthTag)
		}
		outInfo := migration.TargetInfo{
			ControllerTag: controllerTag,
			Addrs:         info.Addrs,
			CACert:        info.CACert,
			AuthTag:       authTag,
			Password:      info.Password,
		}
		select {
		case w.out <- outInfo:
		case <-w.tomb.Dying():
			return nil
		}
	}
}
Пример #18
0
// ModifyModelAccess changes the model access granted to users.
func (em *ModelManagerAPI) ModifyModelAccess(args params.ModifyModelAccessRequest) (result params.ErrorResults, err error) {
	// API user must be a controller admin.
	createdBy, _ := em.authorizer.GetAuthTag().(names.UserTag)
	isAdmin, err := em.state.IsControllerAdministrator(createdBy)
	if err != nil {
		return result, errors.Trace(err)
	}
	if !isAdmin {
		return result, errors.New("only controller admins can grant or revoke model access")
	}

	result = params.ErrorResults{
		Results: make([]params.ErrorResult, len(args.Changes)),
	}
	if len(args.Changes) == 0 {
		return result, nil
	}

	for i, arg := range args.Changes {
		modelAccess, err := FromModelAccessParam(arg.Access)
		if err != nil {
			err = errors.Annotate(err, "could not modify model access")
			result.Results[i].Error = common.ServerError(err)
			continue
		}

		userTagString := arg.UserTag
		user, err := names.ParseUserTag(userTagString)
		if err != nil {
			result.Results[i].Error = common.ServerError(errors.Annotate(err, "could not modify model access"))
			continue
		}
		modelTagString := arg.ModelTag
		model, err := names.ParseModelTag(modelTagString)
		if err != nil {
			result.Results[i].Error = common.ServerError(errors.Annotate(err, "could not modify model access"))
			continue
		}

		result.Results[i].Error = common.ServerError(
			ChangeModelAccess(em.state, model, createdBy, user, arg.Action, modelAccess))
	}
	return result, nil
}
Пример #19
0
func (s *Service) serviceOwnerTag() (names.UserTag, error) {
	var invalidTag names.UserTag
	var results params.StringResults
	args := params.Entities{
		Entities: []params.Entity{{Tag: s.tag.String()}},
	}
	err := s.st.facade.FacadeCall("ServiceOwner", args, &results)
	if err != nil {
		return invalidTag, err
	}
	if len(results.Results) != 1 {
		return invalidTag, fmt.Errorf("expected 1 result, got %d", len(results.Results))
	}
	result := results.Results[0]
	if result.Error != nil {
		return invalidTag, result.Error
	}
	return names.ParseUserTag(result.Result)
}
Пример #20
0
// CreateEnvironment creates a new environment using the account and
// environment config specified in the args.
func (em *EnvironmentManagerAPI) CreateEnvironment(args params.EnvironmentCreateArgs) (params.Environment, error) {
	result := params.Environment{}
	// Get the state server environment first. We need it both for the state
	// server owner and the ability to get the config.
	stateServerEnv, err := em.state.StateServerEnvironment()
	if err != nil {
		return result, errors.Trace(err)
	}
	adminUser := stateServerEnv.Owner()

	ownerTag, err := names.ParseUserTag(args.OwnerTag)
	if err != nil {
		return result, errors.Trace(err)
	}

	// Any user is able to create themselves an environment (until real fine
	// grain permissions are available), and admins (the creator of the state
	// server environment) are able to create environments for other people.
	err = em.authCheck(ownerTag, adminUser)
	if err != nil {
		return result, errors.Trace(err)
	}

	newConfig, err := em.newEnvironmentConfig(args, stateServerEnv)
	if err != nil {
		return result, errors.Trace(err)
	}
	// NOTE: check the agent-version of the config, and if it is > the current
	// version, it is not supported, also check existing tools, and if we don't
	// have tools for that version, also die.
	env, st, err := em.state.NewEnvironment(newConfig, ownerTag)
	if err != nil {
		return result, errors.Annotate(err, "failed to create new environment")
	}
	defer st.Close()

	result.Name = env.Name()
	result.UUID = env.UUID()
	result.OwnerTag = env.Owner().String()

	return result, nil
}
Пример #21
0
// GetMigrationStatus implements Client.
func (c *client) GetMigrationStatus() (MigrationStatus, error) {
	var empty MigrationStatus
	var status params.FullMigrationStatus
	err := c.caller.FacadeCall("GetMigrationStatus", nil, &status)
	if err != nil {
		return empty, errors.Trace(err)
	}

	modelTag, err := names.ParseModelTag(status.Spec.ModelTag)
	if err != nil {
		return empty, errors.Annotatef(err, "parsing model tag")
	}

	phase, ok := migration.ParsePhase(status.Phase)
	if !ok {
		return empty, errors.New("unable to parse phase")
	}

	target := status.Spec.TargetInfo
	controllerTag, err := names.ParseModelTag(target.ControllerTag)
	if err != nil {
		return empty, errors.Annotatef(err, "parsing controller tag")
	}

	authTag, err := names.ParseUserTag(target.AuthTag)
	if err != nil {
		return empty, errors.Annotatef(err, "unable to parse auth tag")
	}

	return MigrationStatus{
		ModelUUID: modelTag.Id(),
		Attempt:   status.Attempt,
		Phase:     phase,
		TargetInfo: migration.TargetInfo{
			ControllerTag: controllerTag,
			Addrs:         target.Addrs,
			CACert:        target.CACert,
			AuthTag:       authTag,
			Password:      target.Password,
		},
	}, nil
}
Пример #22
0
// ListModels returns the models that the specified user
// has access to in the current server.  Only that controller owner
// can list models for any user (at this stage).  Other users
// can only ask about their own models.
func (em *ModelManagerAPI) ListModels(user params.Entity) (params.UserModelList, error) {
	result := params.UserModelList{}

	userTag, err := names.ParseUserTag(user.Tag)
	if err != nil {
		return result, errors.Trace(err)
	}

	err = em.authCheck(userTag)
	if err != nil {
		return result, errors.Trace(err)
	}

	models, err := em.state.ModelsForUser(userTag)
	if err != nil {
		return result, errors.Trace(err)
	}

	for _, model := range models {
		var lastConn *time.Time
		userLastConn, err := model.LastConnection()
		if err != nil {
			if !state.IsNeverConnectedError(err) {
				return result, errors.Trace(err)
			}
		} else {
			lastConn = &userLastConn
		}
		result.UserModels = append(result.UserModels, params.UserModel{
			Model: params.Model{
				Name:     model.Name(),
				UUID:     model.UUID(),
				OwnerTag: model.Owner().String(),
			},
			LastConnection: lastConn,
		})
		logger.Debugf("list models: %s, %s, %s", model.Name(), model.UUID(), model.Owner())
	}

	return result, nil
}
Пример #23
0
// CreateModel creates a new model using the account and
// model config specified in the args.
func (mm *ModelManagerAPI) CreateModel(args params.ModelCreateArgs) (params.Model, error) {
	result := params.Model{}
	// Get the controller model first. We need it both for the state
	// server owner and the ability to get the config.
	controllerModel, err := mm.state.ControllerModel()
	if err != nil {
		return result, errors.Trace(err)
	}

	ownerTag, err := names.ParseUserTag(args.OwnerTag)
	if err != nil {
		return result, errors.Trace(err)
	}

	// Any user is able to create themselves an model (until real fine
	// grain permissions are available), and admins (the creator of the state
	// server model) are able to create models for other people.
	err = mm.authCheck(ownerTag)
	if err != nil {
		return result, errors.Trace(err)
	}

	newConfig, err := mm.newModelConfig(args, controllerModel)
	if err != nil {
		return result, errors.Annotate(err, "failed to create config")
	}
	// NOTE: check the agent-version of the config, and if it is > the current
	// version, it is not supported, also check existing tools, and if we don't
	// have tools for that version, also die.
	model, st, err := mm.state.NewModel(state.ModelArgs{Config: newConfig, Owner: ownerTag})
	if err != nil {
		return result, errors.Annotate(err, "failed to create new model")
	}
	defer st.Close()

	result.Name = model.Name()
	result.UUID = model.UUID()
	result.OwnerTag = model.Owner().String()

	return result, nil
}
Пример #24
0
// ListEnvironments returns the environments that the specified user
// has access to in the current server.  Only that state server owner
// can list environments for any user (at this stage).  Other users
// can only ask about their own environments.
func (em *EnvironmentManagerAPI) ListEnvironments(user params.Entity) (params.UserEnvironmentList, error) {
	result := params.UserEnvironmentList{}

	userTag, err := names.ParseUserTag(user.Tag)
	if err != nil {
		return result, errors.Trace(err)
	}

	err = em.authCheck(userTag)
	if err != nil {
		return result, errors.Trace(err)
	}

	environments, err := em.state.EnvironmentsForUser(userTag)
	if err != nil {
		return result, errors.Trace(err)
	}

	for _, env := range environments {
		var lastConn *time.Time
		userLastConn, err := env.LastConnection()
		if err != nil {
			if !state.IsNeverConnectedError(err) {
				return result, errors.Trace(err)
			}
		} else {
			lastConn = &userLastConn
		}
		result.UserEnvironments = append(result.UserEnvironments, params.UserEnvironment{
			Environment: params.Environment{
				Name:     env.Name(),
				UUID:     env.UUID(),
				OwnerTag: env.Owner().String(),
			},
			LastConnection: lastConn,
		})
		logger.Debugf("list env: %s, %s, %s", env.Name(), env.UUID(), env.Owner())
	}

	return result, nil
}
Пример #25
0
// ShareEnvironment manages allowing and denying the given user(s) access to the environment.
func (c *Client) ShareEnvironment(args params.ModifyEnvironUsers) (result params.ErrorResults, err error) {
	var createdBy names.UserTag
	var ok bool
	if createdBy, ok = c.api.auth.GetAuthTag().(names.UserTag); !ok {
		return result, errors.Errorf("api connection is not through a user")
	}

	result = params.ErrorResults{
		Results: make([]params.ErrorResult, len(args.Changes)),
	}
	if len(args.Changes) == 0 {
		return result, nil
	}

	for i, arg := range args.Changes {
		userTagString := arg.UserTag
		user, err := names.ParseUserTag(userTagString)
		if err != nil {
			result.Results[i].Error = common.ServerError(errors.Annotate(err, "could not share environment"))
			continue
		}
		switch arg.Action {
		case params.AddEnvUser:
			_, err := c.api.stateAccessor.AddEnvironmentUser(
				state.EnvUserSpec{User: user, CreatedBy: createdBy})
			if err != nil {
				err = errors.Annotate(err, "could not share environment")
				result.Results[i].Error = common.ServerError(err)
			}
		case params.RemoveEnvUser:
			err := c.api.stateAccessor.RemoveEnvironmentUser(user)
			if err != nil {
				err = errors.Annotate(err, "could not unshare environment")
				result.Results[i].Error = common.ServerError(err)
			}
		default:
			result.Results[i].Error = common.ServerError(errors.Errorf("unknown action %q", arg.Action))
		}
	}
	return result, nil
}
Пример #26
0
// AllEnvironments allows system administrators to get the list of all the
// environments in the system.
func (c *Client) AllEnvironments() ([]base.UserEnvironment, error) {
	var environments params.UserEnvironmentList
	err := c.facade.FacadeCall("AllEnvironments", nil, &environments)
	if err != nil {
		return nil, errors.Trace(err)
	}
	result := make([]base.UserEnvironment, len(environments.UserEnvironments))
	for i, env := range environments.UserEnvironments {
		owner, err := names.ParseUserTag(env.OwnerTag)
		if err != nil {
			return nil, errors.Annotatef(err, "OwnerTag %q at position %d", env.OwnerTag, i)
		}
		result[i] = base.UserEnvironment{
			Name:           env.Name,
			UUID:           env.UUID,
			Owner:          owner.Username(),
			LastConnection: env.LastConnection,
		}
	}
	return result, nil
}
Пример #27
0
// AllModels allows controller administrators to get the list of all the
// models in the controller.
func (c *Client) AllModels() ([]base.UserModel, error) {
	var models params.UserModelList
	err := c.facade.FacadeCall("AllModels", nil, &models)
	if err != nil {
		return nil, errors.Trace(err)
	}
	result := make([]base.UserModel, len(models.UserModels))
	for i, model := range models.UserModels {
		owner, err := names.ParseUserTag(model.OwnerTag)
		if err != nil {
			return nil, errors.Annotatef(err, "OwnerTag %q at position %d", model.OwnerTag, i)
		}
		result[i] = base.UserModel{
			Name:           model.Name,
			UUID:           model.UUID,
			Owner:          owner.Canonical(),
			LastConnection: model.LastConnection,
		}
	}
	return result, nil
}
Пример #28
0
// ModelInfoFromParams translates a params.ModelInfo to ModelInfo.
func ModelInfoFromParams(info params.ModelInfo, now time.Time) (ModelInfo, error) {
	tag, err := names.ParseUserTag(info.OwnerTag)
	if err != nil {
		return ModelInfo{}, errors.Trace(err)
	}
	status := ModelStatus{
		Current: info.Status.Status,
		Message: info.Status.Info,
	}
	if info.Status.Since != nil {
		status.Since = UserFriendlyDuration(*info.Status.Since, now)
	}
	return ModelInfo{
		Name:           info.Name,
		UUID:           info.UUID,
		ControllerUUID: info.ControllerUUID,
		Owner:          tag.Id(),
		Life:           string(info.Life),
		Status:         status,
		ProviderType:   info.ProviderType,
		Users:          ModelUserInfoFromParams(info.Users, now),
	}, nil
}
Пример #29
0
func (s *userSuite) TestParseUserTag(c *gc.C) {
	for i, t := range []struct {
		tag      string
		expected names.Tag
		err      error
	}{{
		tag: "",
		err: names.InvalidTagError("", ""),
	}, {
		tag:      "user-dave",
		expected: names.NewUserTag("dave"),
	}, {
		tag:      "user-dave@local",
		expected: names.NewUserTag("dave@local"),
	}, {
		tag:      "user-dave@foobar",
		expected: names.NewUserTag("dave@foobar"),
	}, {
		tag: "dave",
		err: names.InvalidTagError("dave", ""),
	}, {
		tag: "unit-dave",
		err: names.InvalidTagError("unit-dave", names.UnitTagKind), // not a valid unit name either
	}, {
		tag: "service-dave",
		err: names.InvalidTagError("service-dave", names.UserTagKind),
	}} {
		c.Logf("test %d: %s", i, t.tag)
		got, err := names.ParseUserTag(t.tag)
		if err != nil || t.err != nil {
			c.Check(err, gc.DeepEquals, t.err)
			continue
		}
		c.Check(got, gc.FitsTypeOf, t.expected)
		c.Check(got, gc.Equals, t.expected)
	}
}
Пример #30
0
func (s *KillSuite) TestControllerStatus(c *gc.C) {
	s.api.allEnvs = []base.UserModel{
		{Name: "admin",
			UUID:  "123",
			Owner: names.NewUserTag("admin").String(),
		}, {Name: "env1",
			UUID:  "456",
			Owner: names.NewUserTag("bob").String(),
		}, {Name: "env2",
			UUID:  "789",
			Owner: names.NewUserTag("jo").String(),
		},
	}

	s.api.envStatus = make(map[string]base.ModelStatus)
	for _, env := range s.api.allEnvs {
		owner, err := names.ParseUserTag(env.Owner)
		c.Assert(err, jc.ErrorIsNil)
		s.api.envStatus[env.UUID] = base.ModelStatus{
			UUID:               env.UUID,
			Life:               params.Dying,
			HostedMachineCount: 2,
			ServiceCount:       1,
			Owner:              owner.Canonical(),
		}
	}

	ctrStatus, envsStatus, err := controller.NewData(s.api, "123")
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(ctrStatus.HostedModelCount, gc.Equals, 2)
	c.Assert(ctrStatus.HostedMachineCount, gc.Equals, 6)
	c.Assert(ctrStatus.ServiceCount, gc.Equals, 3)
	c.Assert(envsStatus, gc.HasLen, 2)

	for i, expected := range []struct {
		Owner              string
		Name               string
		Life               params.Life
		HostedMachineCount int
		ServiceCount       int
	}{
		{
			Owner:              "bob@local",
			Name:               "env1",
			Life:               params.Dying,
			HostedMachineCount: 2,
			ServiceCount:       1,
		}, {
			Owner:              "jo@local",
			Name:               "env2",
			Life:               params.Dying,
			HostedMachineCount: 2,
			ServiceCount:       1,
		},
	} {
		c.Assert(envsStatus[i].Owner, gc.Equals, expected.Owner)
		c.Assert(envsStatus[i].Name, gc.Equals, expected.Name)
		c.Assert(envsStatus[i].Life, gc.Equals, expected.Life)
		c.Assert(envsStatus[i].HostedMachineCount, gc.Equals, expected.HostedMachineCount)
		c.Assert(envsStatus[i].ServiceCount, gc.Equals, expected.ServiceCount)
	}

}