~juju-qa/ubuntu/xenial/juju/xenial-2.0-beta3

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/cmd/juju/user/add.go

  • Committer: Martin Packman
  • Date: 2016-03-30 19:31:08 UTC
  • mfrom: (1.1.41)
  • Revision ID: martin.packman@canonical.com-20160330193108-h9iz3ak334uk0z5r
Merge new upstream source 2.0~beta3

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
        "encoding/asn1"
8
8
        "encoding/base64"
9
9
        "fmt"
 
10
        "strings"
10
11
 
11
12
        "github.com/juju/cmd"
12
13
        "github.com/juju/errors"
15
16
 
16
17
        "github.com/juju/juju/cmd/juju/block"
17
18
        "github.com/juju/juju/cmd/modelcmd"
 
19
        "github.com/juju/juju/juju/permission"
18
20
        "github.com/juju/juju/jujuclient"
19
21
)
20
22
 
30
32
Examples:
31
33
    # Add user "foobar"
32
34
    juju add-user foobar
33
 
    
34
 
    # Add user and share model.
35
 
    juju add-user foobar --share somemodel
 
35
 
 
36
    # Add user with default (read) access to models "qa" and "prod".
 
37
    juju add-user foobar --models qa,prod
 
38
 
 
39
    # Add user with write access to model "devel".
 
40
    juju add-user foobar --models devel --acl write
36
41
 
37
42
 
38
43
See Also:
42
47
 
43
48
// AddUserAPI defines the usermanager API methods that the add command uses.
44
49
type AddUserAPI interface {
45
 
        AddUser(username, displayName, password string, modelUUIDs ...string) (names.UserTag, []byte, error)
 
50
        AddUser(username, displayName, password, access string, modelUUIDs ...string) (names.UserTag, []byte, error)
46
51
        Close() error
47
52
}
48
53
 
56
61
        api         AddUserAPI
57
62
        User        string
58
63
        DisplayName string
59
 
        ModelName   string
 
64
        ModelNames  string
 
65
        ModelAccess string
60
66
}
61
67
 
62
68
func (c *addCommand) SetFlags(f *gnuflag.FlagSet) {
63
 
        f.StringVar(&c.ModelName, "share", "", "share a model with the new user")
 
69
        f.StringVar(&c.ModelNames, "models", "", "models the new user is granted access to")
 
70
        f.StringVar(&c.ModelAccess, "acl", "read", "access controls")
64
71
}
65
72
 
66
73
// Info implements Command.Info.
67
74
func (c *addCommand) Info() *cmd.Info {
68
75
        return &cmd.Info{
69
76
                Name:    "add-user",
70
 
                Args:    "<username> [<display name>] [--share <model name>]",
71
 
                Purpose: "adds a user to a controller and optionally shares a model",
 
77
                Args:    "<username> [<display name>] [--models <model1> [<m2> .. <mN>] ] [--acl <read|write>]",
 
78
                Purpose: "adds a user to a controller, optionally with access to models",
72
79
                Doc:     useraddCommandDoc,
73
80
        }
74
81
}
78
85
        if len(args) == 0 {
79
86
                return fmt.Errorf("no username supplied")
80
87
        }
 
88
 
 
89
        _, err := permission.ParseModelAccess(c.ModelAccess)
 
90
        if err != nil {
 
91
                return err
 
92
        }
 
93
 
81
94
        c.User, args = args[0], args[1:]
82
95
        if len(args) > 0 {
83
96
                c.DisplayName, args = args[0], args[1:]
97
110
                defer api.Close()
98
111
        }
99
112
 
100
 
        // If we need to share a model, look up the model UUID from the supplied name.
101
 
        var modelUUIDs []string
102
 
        if c.ModelName != "" {
103
 
                store := c.ClientStore()
104
 
                controllerName := c.ControllerName()
105
 
                accountName := c.AccountName()
106
 
                model, err := store.ModelByName(controllerName, accountName, c.ModelName)
107
 
                if errors.IsNotFound(err) {
108
 
                        // The model isn't known locally, so query the models available in the controller.
109
 
                        ctx.Verbosef("model %q not cached locally, refreshing models from controller", c.ModelName)
110
 
                        if err := c.RefreshModels(store, controllerName, accountName); err != nil {
111
 
                                return errors.Annotate(err, "refreshing models")
112
 
                        }
113
 
                        model, err = store.ModelByName(controllerName, accountName, c.ModelName)
114
 
                }
115
 
                if err != nil {
116
 
                        return err
117
 
                }
118
 
                modelUUIDs = []string{model.ModelUUID}
 
113
        var modelNames []string
 
114
        for _, modelArg := range strings.Split(c.ModelNames, ",") {
 
115
                modelArg = strings.TrimSpace(modelArg)
 
116
                if len(modelArg) > 0 {
 
117
                        modelNames = append(modelNames, modelArg)
 
118
                }
 
119
        }
 
120
 
 
121
        // If we need to share a model, look up the model UUIDs from the supplied names.
 
122
        modelUUIDs, err := c.ModelUUIDs(modelNames)
 
123
        if err != nil {
 
124
                return errors.Trace(err)
119
125
        }
120
126
 
121
127
        // Add a user without a password. This will generate a temporary
122
128
        // secret key, which we'll print out for the user to supply to
123
129
        // "juju register".
124
 
        _, secretKey, err := api.AddUser(c.User, c.DisplayName, "", modelUUIDs...)
 
130
        _, secretKey, err := api.AddUser(c.User, c.DisplayName, "", c.ModelAccess, modelUUIDs...)
125
131
        if err != nil {
126
132
                return block.ProcessBlockedError(err, block.BlockChange)
127
133
        }
134
140
        // Generate the base64-encoded string for the user to pass to
135
141
        // "juju register". We marshal the information using ASN.1
136
142
        // to keep the size down, since we need to encode binary data.
137
 
        info, err := c.ConnectionInfo()
 
143
        controllerDetails, err := c.ClientStore().ControllerByName(c.ControllerName())
138
144
        if err != nil {
139
145
                return errors.Trace(err)
140
146
        }
141
147
        registrationInfo := jujuclient.RegistrationInfo{
142
148
                User:      c.User,
143
 
                Addrs:     info.APIEndpoint().Addresses,
 
149
                Addrs:     controllerDetails.APIEndpoints,
144
150
                SecretKey: secretKey,
145
151
        }
146
152
        registrationData, err := asn1.Marshal(registrationInfo)
164
170
        )
165
171
 
166
172
        fmt.Fprintf(ctx.Stdout, "User %q added\n", displayName)
167
 
        if c.ModelName != "" {
168
 
                fmt.Fprintf(ctx.Stdout, "Model  %q is now shared\n", c.ModelName)
 
173
        for _, modelName := range modelNames {
 
174
                fmt.Fprintf(ctx.Stdout, "User %q granted %s access to model %q\n", displayName, c.ModelAccess, modelName)
169
175
        }
170
176
        fmt.Fprintf(ctx.Stdout, "Please send this command to %v:\n", c.User)
171
177
        fmt.Fprintf(ctx.Stdout, "    juju register %s\n",
172
178
                base64RegistrationData,
173
179
        )
 
180
        if len(modelNames) == 0 {
 
181
                fmt.Fprintf(ctx.Stdout, `
 
182
%q has not been granted access to any models. You can use "juju grant" to grant access.
 
183
`, displayName)
 
184
        }
174
185
 
175
186
        return nil
176
187
}