Exemple #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
}
Exemple #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
}
// 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
}
Exemple #4
0
func writeServerFile(endpointProvider EndpointProvider, ctx *cmd.Context, username, password, outPath string) error {
	outPath = ctx.AbsPath(outPath)
	endpoint, err := endpointProvider.ConnectionEndpoint()
	if err != nil {
		return errors.Trace(err)
	}
	if !names.IsValidUser(username) {
		return errors.Errorf("%q is not a valid username", username)
	}
	outputInfo := modelcmd.ServerFile{
		Username:  username,
		Password:  password,
		Addresses: endpoint.Addresses,
		CACert:    endpoint.CACert,
	}
	yaml, err := cmd.FormatYaml(outputInfo)
	if err != nil {
		return errors.Trace(err)
	}
	if err := ioutil.WriteFile(outPath, yaml, 0644); err != nil {
		return errors.Trace(err)
	}
	serverFileNotify(outPath)
	ctx.Infof("server file written to %s", outPath)
	return nil
}
Exemple #5
0
// SetFlags implements Command.Init.
func (c *useEnvironmentCommand) Init(args []string) error {
	if len(args) == 0 || strings.TrimSpace(args[0]) == "" {
		return errors.New("no environment supplied")
	}

	name, args := args[0], args[1:]

	// First check to see if an owner has been specified.
	bits := strings.SplitN(name, "/", 2)
	switch len(bits) {
	case 1:
		// No user specified
		c.EnvName = bits[0]
	case 2:
		owner := bits[0]
		if names.IsValidUser(owner) {
			c.Owner = owner
		} else {
			return errors.Errorf("%q is not a valid user", owner)
		}
		c.EnvName = bits[1]
	}

	// Environment names can generally be anything, but we take a good
	// stab at trying to determine if the user has specified a UUID
	// instead of a name. For now, we only accept a properly formatted UUID,
	// which means one with dashes in the right place.
	if names.IsValidEnvironment(c.EnvName) {
		c.EnvUUID, c.EnvName = c.EnvName, ""
	}

	return cmd.CheckEmpty(args)
}
Exemple #6
0
func (c *JenvCommand) Init(args []string) error {
	if len(args) == 0 {
		return errors.New("no jenv file provided")
	}

	// Store the path to the jenv file.
	if err := c.jenvFile.Set(args[0]); err != nil {
		return errors.Annotate(err, "invalid jenv path")
	}
	args = args[1:]

	if len(args) > 0 {
		// Store and validate the provided environment name.
		c.envName, args = args[0], args[1:]
		if !names.IsValidUser(c.envName) {
			return errors.Errorf("invalid model name %q", c.envName)
		}
	} else {
		// Retrieve the environment name from the jenv file name.
		base := filepath.Base(c.jenvFile.Path)
		c.envName = base[:len(base)-len(filepath.Ext(base))]
	}

	// No other arguments are expected.
	return cmd.CheckEmpty(args)
}
Exemple #7
0
func (c *createModelCommand) Init(args []string) error {
	if len(args) == 0 {
		return errors.New("model name is required")
	}
	c.Name, args = args[0], args[1:]

	if c.Owner != "" && !names.IsValidUser(c.Owner) {
		return errors.Errorf("%q is not a valid user", c.Owner)
	}

	if c.CredentialSpec != "" {
		parts := strings.Split(c.CredentialSpec, ":")
		if len(parts) < 2 {
			return errors.Errorf("invalid cloud credential %s, expected <cloud>:<credential-name>", c.CredentialSpec)
		}
		c.CloudName = parts[0]
		if cloud, err := common.CloudOrProvider(c.CloudName, cloud.CloudByName); err != nil {
			return errors.Trace(err)
		} else {
			c.CloudType = cloud.Type
		}
		c.CredentialName = parts[1]
	}
	return nil
}
Exemple #8
0
// AddUser adds a user to the state.
func (st *State) AddUser(username, displayName, password, creator string) (*User, error) {
	if !names.IsValidUser(username) {
		return nil, errors.Errorf("invalid user name %q", username)
	}
	salt, err := utils.RandomSalt()
	if err != nil {
		return nil, err
	}
	timestamp := time.Now().Round(time.Second).UTC()
	u := &User{
		st: st,
		doc: userDoc{
			Name:         username,
			DisplayName:  displayName,
			PasswordHash: utils.UserPasswordHash(password, salt),
			PasswordSalt: salt,
			CreatedBy:    creator,
			DateCreated:  timestamp,
		},
	}
	ops := []txn.Op{{
		C:      usersC,
		Id:     username,
		Assert: txn.DocMissing,
		Insert: &u.doc,
	}}
	err = st.runTransaction(ops)
	if err == txn.ErrAborted {
		err = errors.New("user already exists")
	}
	if err != nil {
		return nil, errors.Trace(err)
	}
	return u, nil
}
Exemple #9
0
func validateUser(name string) error {
	if !names.IsValidUser(name) {
		return errors.NotValidf("account name %q", name)
	}
	if tag := names.NewUserTag(name); tag.Id() != tag.Canonical() {
		return errors.NotValidf("unqualified account name %q", name)
	}
	return nil
}
Exemple #10
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) ([]params.Environment, error) {
	var result params.EnvironmentList
	if !names.IsValidUser(user) {
		return nil, fmt.Errorf("invalid user name %q", user)
	}
	entity := params.Entity{names.NewUserTag(user).String()}
	err := c.facade.FacadeCall("ListEnvironments", entity, &result)
	if err != nil {
		return nil, errors.Trace(err)
	}
	return result.Environments, nil
}
Exemple #11
0
// Init initializes the command for running.
func (c *BootstrapCommand) Init(args []string) error {
	if len(c.EnvConfig) == 0 {
		return cmdutil.RequiredError("model-config")
	}
	if c.InstanceId == "" {
		return cmdutil.RequiredError("instance-id")
	}
	if !names.IsValidUser(c.AdminUsername) {
		return errors.Errorf("%q is not a valid username", c.AdminUsername)
	}
	return c.AgentConf.CheckArgs(args)
}
Exemple #12
0
func (c *unshareCommand) Init(args []string) (err error) {
	if len(args) == 0 {
		return errors.New("no users specified")
	}

	for _, arg := range args {
		if !names.IsValidUser(arg) {
			return errors.Errorf("invalid username: %q", arg)
		}
		c.Users = append(c.Users, names.NewUserTag(arg))
	}

	return nil
}
Exemple #13
0
func (c *Client) AddUser(username, displayName, password string) error {
	if !names.IsValidUser(username) {
		return fmt.Errorf("invalid user name %q", username)
	}
	userArgs := usermanager.ModifyUsers{
		Changes: []usermanager.ModifyUser{{Username: username, DisplayName: displayName, Password: password}},
	}
	results := new(params.ErrorResults)
	err := c.facade.FacadeCall("AddUser", userArgs, results)
	if err != nil {
		return errors.Trace(err)
	}
	return results.OneError()
}
Exemple #14
0
func (c *Client) userCall(username string, methodCall string) error {
	if !names.IsValidUser(username) {
		return errors.Errorf("%q is not a valid username", username)
	}
	tag := names.NewUserTag(username)

	var results params.ErrorResults
	args := params.Entities{
		[]params.Entity{{tag.String()}},
	}
	err := c.facade.FacadeCall(methodCall, args, &results)
	if err != nil {
		return errors.Trace(err)
	}
	return results.OneError()
}
Exemple #15
0
// CreateModel creates a new model using the account and
// model config specified in the args.
func (c *Client) CreateModel(owner string, account, config map[string]interface{}) (params.Model, error) {
	var result params.Model
	if !names.IsValidUser(owner) {
		return result, errors.Errorf("invalid owner name %q", owner)
	}
	createArgs := params.ModelCreateArgs{
		OwnerTag: names.NewUserTag(owner).String(),
		Account:  account,
		Config:   config,
	}
	err := c.facade.FacadeCall("CreateModel", createArgs, &result)
	if err != nil {
		return result, errors.Trace(err)
	}
	return result, nil
}
Exemple #16
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
}
Exemple #17
0
func (s *userSuite) TestIsValidUser(c *gc.C) {
	for i, t := range []struct {
		string string
		expect bool
	}{
		{"", false},
		{"bob", true},
		{"Bob", true},
		{"bOB", true},
		{"b^b", false},
		{"bob1", true},
		{"bob-1", true},
		{"bob+1", true},
		{"bob+", false},
		{"+bob", false},
		{"bob.1", true},
		{"1bob", true},
		{"1-bob", true},
		{"1+bob", true},
		{"1.bob", true},
		{"jim.bob+99-1.", false},
		{"a", false},
		{"0foo", true},
		{"foo bar", false},
		{"bar{}", false},
		{"bar+foo", true},
		{"bar_foo", false},
		{"bar!", false},
		{"bar^", false},
		{"bar*", false},
		{"foo=bar", false},
		{"foo?", false},
		{"[bar]", false},
		{"'foo'", false},
		{"%bar", false},
		{"&bar", false},
		{"#1foo", false},
		{"[email protected]", true},
		{"bar@", false},
		{"@local", false},
		{"not/valid", false},
	} {
		c.Logf("test %d: %s", i, t.string)
		c.Assert(names.IsValidUser(t.string), gc.Equals, t.expect, gc.Commentf("%s", t.string))
	}
}
// CreateEnvironment creates a new environment using the account and
// environment config specified in the args.
func (c *Client) CreateEnvironment(owner string, account, config map[string]interface{}) (params.Environment, error) {
	var result params.Environment
	if !names.IsValidUser(owner) {
		return result, errors.Errorf("invalid owner name %q", owner)
	}
	createArgs := params.EnvironmentCreateArgs{
		OwnerTag: names.NewUserTag(owner).String(),
		Account:  account,
		Config:   config,
	}
	err := c.facade.FacadeCall("CreateEnvironment", createArgs, &result)
	if err != nil {
		return result, errors.Trace(err)
	}
	logger.Infof("created environment %s (%s)", result.Name, result.UUID)
	return result, nil
}
Exemple #19
0
// SetPassword changes the password for the specified user.
func (c *Client) SetPassword(username, password string) error {
	if !names.IsValidUser(username) {
		return errors.Errorf("%q is not a valid username", username)
	}
	tag := names.NewUserTag(username)
	args := params.EntityPasswords{
		Changes: []params.EntityPassword{{
			Tag:      tag.String(),
			Password: password}},
	}
	var results params.ErrorResults
	err := c.facade.FacadeCall("SetPassword", args, &results)
	if err != nil {
		return err
	}
	return results.OneError()
}
func (c *CreateEnvironmentCommand) Init(args []string) error {
	if len(args) == 0 {
		return errors.New("environment name is required")
	}
	c.name, args = args[0], args[1:]

	values, err := keyvalues.Parse(args, true)
	if err != nil {
		return err
	}
	c.confValues = values

	if c.owner != "" && !names.IsValidUser(c.owner) {
		return errors.Errorf("%q is not a valid user", c.owner)
	}

	return nil
}
Exemple #21
0
// UserInfo returns information about the specified users.  If no users are
// specified, the call should return all users.  If includeDisabled is set to
// ActiveUsers, only enabled users are returned.
func (c *Client) UserInfo(usernames []string, all IncludeDisabled) ([]params.UserInfo, error) {
	var results params.UserInfoResults
	var entities []params.Entity
	for _, username := range usernames {
		if !names.IsValidUser(username) {
			return nil, errors.Errorf("%q is not a valid username", username)
		}
		tag := names.NewUserTag(username)
		entities = append(entities, params.Entity{Tag: tag.String()})
	}
	args := params.UserInfoRequest{
		Entities:        entities,
		IncludeDisabled: bool(all),
	}
	err := c.facade.FacadeCall("UserInfo", args, &results)
	if err != nil {
		return nil, errors.Trace(err)
	}
	// Only need to look for errors if users were explicitly specified, because
	// if we didn't ask for any, we should get all, and we shouldn't get any
	// errors for listing all.  We care here because we index into the users
	// slice.
	if len(results.Results) == len(usernames) {
		var errorStrings []string
		for i, result := range results.Results {
			if result.Error != nil {
				annotated := errors.Annotate(result.Error, usernames[i])
				errorStrings = append(errorStrings, annotated.Error())
			}
		}
		if len(errorStrings) > 0 {
			return nil, errors.New(strings.Join(errorStrings, ", "))
		}
	}
	info := []params.UserInfo{}
	for i, result := range results.Results {
		if result.Result == nil {
			return nil, errors.Errorf("unexpected nil result at position %d", i)
		}
		info = append(info, *result.Result)
	}
	return info, nil
}
Exemple #22
0
func (c *Client) modifyModelUser(action params.ModelAction, user, access string, modelUUIDs []string) error {
	var args params.ModifyModelAccessRequest

	if !names.IsValidUser(user) {
		return errors.Errorf("invalid username: %q", user)
	}
	userTag := names.NewUserTag(user)

	accessPermission, err := ParseModelAccess(access)
	if err != nil {
		return errors.Trace(err)
	}
	for _, model := range modelUUIDs {
		if !names.IsValidModel(model) {
			return errors.Errorf("invalid model: %q", model)
		}
		modelTag := names.NewModelTag(model)
		args.Changes = append(args.Changes, params.ModifyModelAccess{
			UserTag:  userTag.String(),
			Action:   action,
			Access:   accessPermission,
			ModelTag: modelTag.String(),
		})
	}

	var result params.ErrorResults
	err = c.facade.FacadeCall("ModifyModelAccess", args, &result)
	if err != nil {
		return errors.Trace(err)
	}
	if len(result.Results) != len(args.Changes) {
		return errors.Errorf("expected %d results, got %d", len(args.Changes), len(result.Results))
	}

	for i, r := range result.Results {
		if r.Error != nil && r.Error.Code == params.CodeAlreadyExists {
			logger.Warningf("model %q is already shared with %q", modelUUIDs[i], userTag.Canonical())
			result.Results[i].Error = nil
		}
	}
	return result.Combine()
}
Exemple #23
0
// Validate performs sanity checks on the migration configuration it
// holds.
func (s *ModelMigrationSpec) Validate() error {
	if !names.IsValidModel(s.ModelUUID) {
		return errors.NotValidf("model UUID")
	}
	if !names.IsValidModel(s.TargetControllerUUID) {
		return errors.NotValidf("controller UUID")
	}
	if len(s.TargetAddrs) < 1 {
		return errors.NotValidf("empty target API addresses")
	}
	if s.TargetCACert == "" {
		return errors.NotValidf("empty target CA cert")
	}
	if !names.IsValidUser(s.TargetUser) {
		return errors.NotValidf("target user")
	}
	if s.TargetPassword == "" {
		return errors.NotValidf("empty target password")
	}
	return nil
}
Exemple #24
0
func (c *createModelCommand) Init(args []string) error {
	if len(args) == 0 {
		return errors.New("model name is required")
	}
	c.Name, args = args[0], args[1:]

	values, err := keyvalues.Parse(args, true)
	if err != nil {
		return err
	}
	c.ConfValues = values

	if c.Owner != "" && !names.IsValidUser(c.Owner) {
		return errors.Errorf("%q is not a valid user", c.Owner)
	}

	if c.configParser == nil {
		c.configParser = common.ConformYAML
	}

	return nil
}
Exemple #25
0
// AddIdentity adds an identity to the database.
func (st *State) AddIdentity(name, displayName, password, creator string) (*Identity, error) {
	// The name of the identity happens to match the regex we use to confirm user names.
	// Identities do not have tags, so there is no special function for identities. Given
	// the relationships between users and identities it seems reasonable to use the same
	// validation check.
	if !names.IsValidUser(name) {
		return nil, errors.Errorf("invalid identity name %q", name)
	}
	salt, err := utils.RandomSalt()
	if err != nil {
		return nil, err
	}
	identity := &Identity{
		st: st,
		doc: identityDoc{
			Name:         name,
			DisplayName:  displayName,
			PasswordHash: utils.UserPasswordHash(password, salt),
			PasswordSalt: salt,
			CreatedBy:    creator,
			DateCreated:  nowToTheSecond(),
		},
	}
	ops := []txn.Op{{
		C:      identityCollectionName,
		Id:     name,
		Assert: txn.DocMissing,
		Insert: &identity.doc,
	}}
	err = st.runTransaction(ops)
	if err == txn.ErrAborted {
		err = errors.New("identity already exists")
	}
	if err != nil {
		return nil, errors.Trace(err)
	}
	return identity, nil
}
Exemple #26
0
// Authenticate authenticates the provided entity. If there is no macaroon provided, it will
// return a *DischargeRequiredError containing a macaroon that can be used to grant access.
func (m *ExternalMacaroonAuthenticator) Authenticate(entityFinder EntityFinder, _ names.Tag, req params.LoginRequest) (state.Entity, error) {
	declared, err := m.Service.CheckAny(req.Macaroons, nil, checkers.New(checkers.TimeBefore))
	if _, ok := errors.Cause(err).(*bakery.VerificationError); ok {
		return nil, m.newDischargeRequiredError(err)
	}
	if err != nil {
		return nil, errors.Trace(err)
	}
	username := declared[usernameKey]
	var tag names.UserTag
	if names.IsValidUserName(username) {
		// The name is a local name without an explicit @local suffix.
		// In this case, for compatibility with 3rd parties that don't
		// care to add their own domain, we add an @external domain
		// to ensure there is no confusion between local and external
		// users.
		// TODO(rog) remove this logic when deployed dischargers
		// always add an @ domain.
		tag = names.NewLocalUserTag(username).WithDomain("external")
	} else {
		// We have a name with an explicit domain (or an invalid user name).
		if !names.IsValidUser(username) {
			return nil, errors.Errorf("%q is an invalid user name", username)
		}
		tag = names.NewUserTag(username)
		if tag.IsLocal() {
			return nil, errors.Errorf("external identity provider has provided ostensibly local name %q", username)
		}
	}
	entity, err := entityFinder.FindEntity(tag)
	if errors.IsNotFound(err) {
		return nil, errors.Trace(common.ErrBadCreds)
	} else if err != nil {
		return nil, errors.Trace(err)
	}
	return entity, nil
}
Exemple #27
0
// Run implements Command.Run
func (c *LoginCommand) Run(ctx *cmd.Context) error {
	// TODO(thumper): as we support the user and address
	// change this check here.
	if c.Server.Path == "" {
		return errors.New("no server file specified")
	}

	serverYAML, err := c.Server.Read(ctx)
	if err != nil {
		return errors.Trace(err)
	}

	var serverDetails envcmd.ServerFile
	if err := goyaml.Unmarshal(serverYAML, &serverDetails); err != nil {
		return errors.Trace(err)
	}

	// Construct the api.Info struct from the provided values
	// and attempt to connect to the remote server before we do anything else.
	if !names.IsValidUser(serverDetails.Username) {
		return errors.Errorf("%q is not a valid username", serverDetails.Username)
	}

	userTag := names.NewUserTag(serverDetails.Username)
	if userTag.Provider() != names.LocalProvider {
		// Remove users do not have their passwords stored in Juju
		// so we never attempt to change them.
		c.KeepPassword = true
	}

	info := api.Info{
		Addrs:    serverDetails.Addresses,
		CACert:   serverDetails.CACert,
		Tag:      userTag,
		Password: serverDetails.Password,
	}

	apiState, err := c.apiOpen(&info, api.DefaultDialOpts())
	if err != nil {
		return errors.Trace(err)
	}
	defer apiState.Close()

	// If we get to here, the credentials supplied were sufficient to connect
	// to the Juju System and login. Now we cache the details.
	serverInfo, err := c.cacheConnectionInfo(serverDetails, apiState)
	if err != nil {
		return errors.Trace(err)
	}
	ctx.Infof("cached connection details as system %q", c.Name)

	// If we get to here, we have been able to connect to the API server, and
	// also have been able to write the cached information. Now we can change
	// the user's password to a new randomly generated strong password, and
	// update the cached information knowing that the likelihood of failure is
	// minimal.
	if !c.KeepPassword {
		if err := c.updatePassword(ctx, apiState, userTag, serverInfo); err != nil {
			return errors.Trace(err)
		}
	}

	return errors.Trace(envcmd.SetCurrentSystem(ctx, c.Name))
}
Exemple #28
0
// Validate returns an error if the ModelMigrationSpec contains bad
// data. Nil is returned otherwise.
func (spec *ModelMigrationSpec) Validate() error {
	if !names.IsValidUser(spec.InitiatedBy.Id()) {
		return errors.NotValidf("InitiatedBy")
	}
	return spec.TargetInfo.Validate()
}
Exemple #29
0
Fichier : url.go Projet : bz2/charm
// ParseReference parses the provided charm Reference string into its
// respective structure and the targeted series, if present.
func ParseReference(url string) (Reference, string, error) {
	r := Reference{Schema: "cs"}
	series := ""
	i := strings.Index(url, ":")
	if i >= 0 {
		r.Schema = url[:i]
		i++
	} else {
		i = 0
	}
	// cs: or local:
	if r.Schema != "cs" && r.Schema != "local" {
		return Reference{}, "", fmt.Errorf("charm URL has invalid schema: %q", url)
	}
	parts := strings.Split(url[i:], "/")
	if len(parts) < 1 || len(parts) > 3 {
		return Reference{}, "", fmt.Errorf("charm URL has invalid form: %q", url)
	}

	// ~<username>
	if strings.HasPrefix(parts[0], "~") {
		if r.Schema == "local" {
			return Reference{}, "", fmt.Errorf("local charm URL with user name: %q", url)
		}
		r.User = parts[0][1:]
		if !names.IsValidUser(r.User) {
			return Reference{}, "", fmt.Errorf("charm URL has invalid user name: %q", url)
		}
		parts = parts[1:]
	}

	// <series>
	if len(parts) == 2 {
		series = parts[0]
		if !IsValidSeries(series) {
			return Reference{}, "", fmt.Errorf("charm URL has invalid series: %q", url)
		}
		parts = parts[1:]
	}
	if len(parts) < 1 {
		return Reference{}, "", fmt.Errorf("charm URL without charm name: %q", url)
	}

	// <name>[-<revision>]
	r.Name = parts[0]
	r.Revision = -1
	for i := len(r.Name) - 1; i > 0; i-- {
		c := r.Name[i]
		if c >= '0' && c <= '9' {
			continue
		}
		if c == '-' && i != len(r.Name)-1 {
			var err error
			r.Revision, err = strconv.Atoi(r.Name[i+1:])
			if err != nil {
				panic(err) // We just checked it was right.
			}
			r.Name = r.Name[:i]
		}
		break
	}
	if !IsValidName(r.Name) {
		return Reference{}, "", fmt.Errorf("charm URL has invalid charm name: %q", url)
	}
	return r, series, nil
}
Exemple #30
0
func (c *createModelCommand) Run(ctx *cmd.Context) error {
	client, err := c.getAPI()
	if err != nil {
		return errors.Trace(err)
	}
	defer client.Close()

	store := c.ClientStore()
	controllerName := c.ControllerName()
	accountName, err := store.CurrentAccount(controllerName)
	if err != nil {
		return errors.Trace(err)
	}
	currentAccount, err := store.AccountByName(controllerName, accountName)
	if err != nil {
		return errors.Trace(err)
	}

	modelOwner := currentAccount.User
	if c.Owner != "" {
		if !names.IsValidUser(c.Owner) {
			return errors.Errorf("%q is not a valid user name", c.Owner)
		}
		modelOwner = names.NewUserTag(c.Owner).Canonical()
	}

	serverSkeleton, err := client.ConfigSkeleton(c.CloudType, "")
	if err != nil {
		return errors.Trace(err)
	}

	attrs, err := c.getConfigValues(ctx, serverSkeleton)
	if err != nil {
		return errors.Trace(err)
	}

	accountDetails := map[string]interface{}{}
	if c.CredentialName != "" {
		cred, _, _, err := modelcmd.GetCredentials(
			c.credentialStore, "", c.CredentialName, c.CloudName, c.CloudType,
		)
		if err != nil {
			return errors.Trace(err)
		}
		for k, v := range cred.Attributes() {
			accountDetails[k] = v
		}
	}
	model, err := client.CreateModel(modelOwner, accountDetails, attrs)
	if err != nil {
		return errors.Trace(err)
	}
	if modelOwner == currentAccount.User {
		controllerName := c.ControllerName()
		accountName := c.AccountName()
		if err := store.UpdateModel(controllerName, accountName, c.Name, jujuclient.ModelDetails{
			model.UUID,
		}); err != nil {
			return errors.Trace(err)
		}
		if err := store.SetCurrentModel(controllerName, accountName, c.Name); err != nil {
			return errors.Trace(err)
		}
		ctx.Infof("created model %q", c.Name)
	} else {
		ctx.Infof("created model %q for %q", c.Name, c.Owner)
	}

	return nil
}