35
35
AuthTypes: []cloud.AuthType{cloud.EmptyAuthType, cloud.UserPassAuthType},
36
36
Regions: []cloud.Region{{Name: "nether", Endpoint: "endpoint"}},
38
creds: map[string]cloud.Credential{
39
"one": cloud.NewEmptyCredential(),
40
"two": cloud.NewCredential(cloud.UserPassAuthType, map[string]string{
38
creds: map[names.CloudCredentialTag]cloud.Credential{
39
names.NewCloudCredentialTag("meep/bruce@local/one"): cloud.NewEmptyCredential(),
40
names.NewCloudCredentialTag("meep/bruce@local/two"): cloud.NewCredential(cloud.UserPassAuthType, map[string]string{
41
41
"username": "admin",
42
42
"password": "adm1n",
71
func (s *cloudSuite) TestCloudDefaults(c *gc.C) {
72
results, err := s.api.CloudDefaults(params.Entities{[]params.Entity{
77
c.Assert(err, jc.ErrorIsNil)
78
s.backend.CheckCallNames(c,
79
"IsControllerAdministrator", // for auth-checking
81
"IsControllerAdministrator", // to get default credential
83
c.Assert(results.Results, gc.HasLen, 3)
84
c.Assert(results.Results[0].Error, jc.DeepEquals, ¶ms.Error{
85
Message: `"machine-0" is not a valid user tag`,
87
c.Assert(results.Results[1].Error, jc.DeepEquals, ¶ms.Error{
88
Message: "permission denied", Code: params.CodeUnauthorized,
90
c.Assert(results.Results[2].Error, gc.IsNil)
91
c.Assert(results.Results[2].Result, jc.DeepEquals, ¶ms.CloudDefaults{
92
CloudTag: "cloud-some-cloud",
93
CloudRegion: "some-region",
98
func (s *cloudSuite) TestCloudDefaultsAdminAccess(c *gc.C) {
99
s.authorizer.Tag = names.NewUserTag("admin@local")
100
results, err := s.api.CloudDefaults(params.Entities{[]params.Entity{
103
c.Assert(err, jc.ErrorIsNil)
104
s.backend.CheckCallNames(c,
105
"IsControllerAdministrator", // for auth-checking
107
"IsControllerAdministrator", // to get default credential
109
c.Assert(results.Results, gc.HasLen, 1)
110
c.Assert(results.Results[0].Error, gc.IsNil)
111
c.Assert(results.Results[0].Result, jc.DeepEquals, ¶ms.CloudDefaults{
112
CloudTag: "cloud-some-cloud",
113
CloudRegion: "some-region",
114
CloudCredential: "some-credential",
71
func (s *cloudSuite) TestDefaultCloud(c *gc.C) {
72
result, err := s.api.DefaultCloud()
73
c.Assert(err, jc.ErrorIsNil)
74
s.backend.CheckCallNames(c, "ControllerModel")
75
c.Assert(result, jc.DeepEquals, params.StringResult{
76
Result: "cloud-some-cloud",
118
80
func (s *cloudSuite) TestCredentials(c *gc.C) {
81
s.authorizer.Tag = names.NewUserTag("bruce@local")
119
82
results, err := s.api.Credentials(params.UserClouds{[]params.UserCloud{{
120
83
UserTag: "machine-0",
121
84
CloudTag: "cloud-meep",
127
90
CloudTag: "cloud-meep",
129
92
c.Assert(err, jc.ErrorIsNil)
130
s.backend.CheckCallNames(c, "IsControllerAdministrator", "CloudCredentials")
93
s.backend.CheckCallNames(c, "ControllerTag", "CloudCredentials")
131
94
s.backend.CheckCall(c, 1, "CloudCredentials", names.NewUserTag("bruce"), "meep")
133
96
c.Assert(results.Results, gc.HasLen, 3)
138
101
Message: "permission denied", Code: params.CodeUnauthorized,
140
103
c.Assert(results.Results[2].Error, gc.IsNil)
141
c.Assert(results.Results[2].Credentials, jc.DeepEquals, map[string]params.CloudCredential{
146
AuthType: "userpass",
147
Attributes: map[string]string{
104
c.Assert(results.Results[2].Result, jc.SameContents, []string{
105
"cloudcred-meep_bruce@local_one",
106
"cloudcred-meep_bruce@local_two",
159
114
CloudTag: "cloud-meep",
161
116
c.Assert(err, jc.ErrorIsNil)
162
s.backend.CheckCallNames(c, "IsControllerAdministrator", "CloudCredentials")
117
s.backend.CheckCallNames(c, "ControllerTag", "CloudCredentials")
163
118
c.Assert(results.Results, gc.HasLen, 1)
164
119
// admin can access others' credentials
165
120
c.Assert(results.Results[0].Error, gc.IsNil)
168
123
func (s *cloudSuite) TestUpdateCredentials(c *gc.C) {
169
results, err := s.api.UpdateCredentials(params.UsersCloudCredentials{[]params.UserCloudCredentials{{
170
UserTag: "machine-0",
171
CloudTag: "cloud-meep",
173
UserTag: "user-admin",
174
CloudTag: "cloud-meep",
176
UserTag: "user-bruce",
177
CloudTag: "cloud-meep",
178
Credentials: map[string]params.CloudCredential{
181
Attributes: map[string]string{"token": "foo:bar:baz"},
184
AuthType: "access-key",
185
Attributes: map[string]string{
124
s.authorizer.Tag = names.NewUserTag("bruce@local")
125
results, err := s.api.UpdateCredentials(params.UpdateCloudCredentials{[]params.UpdateCloudCredential{{
128
Tag: "cloudcred-meep_admin_whatever",
130
Tag: "cloudcred-meep_bruce_three",
131
Credential: params.CloudCredential{
133
Attributes: map[string]string{"token": "foo:bar:baz"},
192
136
c.Assert(err, jc.ErrorIsNil)
193
s.backend.CheckCallNames(c, "IsControllerAdministrator", "UpdateCloudCredentials")
137
s.backend.CheckCallNames(c, "ControllerTag", "UpdateCloudCredential")
194
138
c.Assert(results.Results, gc.HasLen, 3)
195
139
c.Assert(results.Results[0].Error, jc.DeepEquals, ¶ms.Error{
196
Message: `"machine-0" is not a valid user tag`,
140
Message: `"machine-0" is not a valid cloudcred tag`,
198
142
c.Assert(results.Results[1].Error, jc.DeepEquals, ¶ms.Error{
199
143
Message: "permission denied", Code: params.CodeUnauthorized,
201
145
c.Assert(results.Results[2].Error, gc.IsNil)
203
147
s.backend.CheckCall(
204
c, 1, "UpdateCloudCredentials",
205
names.NewUserTag("bruce"),
207
map[string]cloud.Credential{
208
"three": cloud.NewCredential(
209
cloud.OAuth1AuthType,
210
map[string]string{"token": "foo:bar:baz"},
212
"four": cloud.NewCredential(
213
cloud.AccessKeyAuthType,
214
map[string]string{"access-key": "foo", "secret-key": "bar"},
148
c, 1, "UpdateCloudCredential",
149
names.NewCloudCredentialTag("meep/bruce/three"),
151
cloud.OAuth1AuthType,
152
map[string]string{"token": "foo:bar:baz"},
220
157
func (s *cloudSuite) TestUpdateCredentialsAdminAccess(c *gc.C) {
221
158
s.authorizer.Tag = names.NewUserTag("admin@local")
222
results, err := s.api.UpdateCredentials(params.UsersCloudCredentials{[]params.UserCloudCredentials{{
223
UserTag: "user-julia",
224
CloudTag: "cloud-meep",
225
Credentials: map[string]params.CloudCredential{
228
Attributes: map[string]string{"token": "foo:bar:baz"},
159
results, err := s.api.UpdateCredentials(params.UpdateCloudCredentials{[]params.UpdateCloudCredential{{
160
Tag: "cloudcred-meep_julia_three",
161
Credential: params.CloudCredential{
163
Attributes: map[string]string{"token": "foo:bar:baz"},
232
166
c.Assert(err, jc.ErrorIsNil)
233
s.backend.CheckCallNames(c, "IsControllerAdministrator", "UpdateCloudCredentials")
167
s.backend.CheckCallNames(c, "ControllerTag", "UpdateCloudCredential")
234
168
c.Assert(results.Results, gc.HasLen, 1)
235
169
// admin can update others' credentials
236
170
c.Assert(results.Results[0].Error, gc.IsNil)
239
173
type mockBackend struct {
240
174
gitjujutesting.Stub
241
175
cloud cloud.Cloud
242
creds map[string]cloud.Credential
176
creds map[names.CloudCredentialTag]cloud.Credential
245
func (st *mockBackend) IsControllerAdministrator(user names.UserTag) (bool, error) {
246
st.MethodCall(st, "IsControllerAdministrator", user)
179
func (st *mockBackend) IsControllerAdmin(user names.UserTag) (bool, error) {
180
st.MethodCall(st, "IsControllerAdmin", user)
247
181
return user.Canonical() == "admin@local", st.NextErr()
250
184
func (st *mockBackend) ControllerModel() (cloudfacade.Model, error) {
251
185
st.MethodCall(st, "ControllerModel")
252
return &mockModel{"some-cloud", "some-region", "some-credential"}, st.NextErr()
186
credentialTag := names.NewCloudCredentialTag("some-cloud/admin@local/some-credential")
187
return &mockModel{"some-cloud", "some-region", credentialTag}, st.NextErr()
190
func (st *mockBackend) ControllerTag() names.ControllerTag {
191
st.MethodCall(st, "ControllerTag")
192
return names.NewControllerTag("deadbeef-0bad-400d-8000-4b1d0d06f00d")
195
func (st *mockBackend) ModelTag() names.ModelTag {
196
st.MethodCall(st, "ModelTag")
197
return names.NewModelTag("deadbeef-0bad-400d-8000-4b1d0d06f00d")
255
200
func (st *mockBackend) Cloud(name string) (cloud.Cloud, error) {
257
202
return st.cloud, st.NextErr()
260
func (st *mockBackend) CloudCredentials(user names.UserTag, cloudName string) (map[string]cloud.Credential, error) {
205
func (st *mockBackend) CloudCredentials(user names.UserTag, cloudName string) (map[names.CloudCredentialTag]cloud.Credential, error) {
261
206
st.MethodCall(st, "CloudCredentials", user, cloudName)
262
207
return st.creds, st.NextErr()
265
func (st *mockBackend) UpdateCloudCredentials(user names.UserTag, cloudName string, creds map[string]cloud.Credential) error {
266
st.MethodCall(st, "UpdateCloudCredentials", user, cloudName, creds)
210
func (st *mockBackend) UpdateCloudCredential(tag names.CloudCredentialTag, cred cloud.Credential) error {
211
st.MethodCall(st, "UpdateCloudCredential", tag, cred)
267
212
return st.NextErr()