83
96
sr, err := resources.ListResources("riak")
84
97
c.Assert(err, jc.ErrorIsNil)
86
c.Assert(sr.Resources, gc.HasLen, 1)
99
c.Check(sr.Resources, gc.HasLen, 1)
88
c.Assert(sr.Resources[0].ServiceID, gc.Equals, "riak")
101
c.Check(sr.Resources[0].ServiceID, gc.Equals, "riak")
90
103
// Most of this is just a sanity check... this is all tested elsewhere.
91
c.Assert(sr.Resources[0].PendingID, gc.Equals, "")
92
c.Assert(sr.Resources[0].Username, gc.Not(gc.Equals), "")
93
c.Assert(sr.Resources[0].ID, gc.Not(gc.Equals), "")
94
c.Assert(sr.Resources[0].Timestamp.IsZero(), jc.IsFalse)
96
fp, err := charmresource.GenerateFingerprint(bytes.NewReader(data))
97
c.Assert(err, jc.ErrorIsNil)
104
c.Check(sr.Resources[0].PendingID, gc.Equals, "")
105
c.Check(sr.Resources[0].Username, gc.Not(gc.Equals), "")
106
c.Check(sr.Resources[0].ID, gc.Not(gc.Equals), "")
107
c.Check(sr.Resources[0].Timestamp.IsZero(), jc.IsFalse)
99
109
// Ensure we get the data we passed in from the metadata.yaml.
100
c.Assert(sr.Resources[0].Resource, gc.DeepEquals, charmresource.Resource{
110
c.Check(sr.Resources[0].Resource, gc.DeepEquals, charmresource.Resource{
101
111
Meta: charmresource.Meta{
103
113
Type: charmresource.TypeFile,
109
119
Size: int64(len(data)),
123
// charmStoreSuite is a suite fixture that puts the machinery in
124
// place to allow testing code that calls addCharmViaAPI.
125
type charmStoreSuite struct {
126
jujutesting.JujuConnSuite
127
handler charmstore.HTTPCloseHandler
129
client *csclient.Client
132
func (s *charmStoreSuite) SetUpTest(c *gc.C) {
133
s.JujuConnSuite.SetUpTest(c)
135
// Set up the charm store testing server.
136
db := s.Session.DB("juju-testing")
137
params := charmstore.ServerParams{
138
AuthUsername: "test-user",
139
AuthPassword: "test-password",
141
handler, err := charmstore.NewServer(db, nil, "", params, charmstore.V5)
142
c.Assert(err, jc.ErrorIsNil)
144
s.srv = httptest.NewServer(handler)
145
s.client = csclient.New(csclient.Params{
147
User: params.AuthUsername,
148
Password: params.AuthPassword,
151
service.PatchNewCharmStoreClient(s, s.srv.URL)
153
// Initialize the charm cache dir.
154
s.PatchValue(&charmrepo.CacheDir, c.MkDir())
156
// Point the CLI to the charm store testing server.
158
// Point the Juju API server to the charm store testing server.
159
s.PatchValue(&csclient.ServerURL, s.srv.URL)
162
func (s *charmStoreSuite) TearDownTest(c *gc.C) {
165
s.JujuConnSuite.TearDownTest(c)
168
type UpgradeCharmStoreResourceSuite struct {
172
var _ = gc.Suite(&UpgradeCharmStoreResourceSuite{})
174
func (s *UpgradeCharmStoreResourceSuite) SetUpSuite(c *gc.C) {
175
s.charmStoreSuite.SetUpSuite(c)
176
err := all.RegisterForServer()
177
c.Assert(err, jc.ErrorIsNil)
178
err = all.RegisterForClient()
179
c.Assert(err, jc.ErrorIsNil)
182
// TODO(ericsnow) Adapt this test to check passing revisions once the
183
// charmstore endpoints are implemented.
185
func (s *UpgradeCharmStoreResourceSuite) TestDeployStarsaySuccess(c *gc.C) {
186
testcharms.UploadCharm(c, s.client, "trusty/starsay-1", "starsay")
188
// let's make a fake resource file to upload
189
data := []byte("some-data")
190
fp, err := charmresource.GenerateFingerprint(bytes.NewReader(data))
191
c.Assert(err, jc.ErrorIsNil)
193
resourceFile := path.Join(c.MkDir(), "data.xml")
194
err = ioutil.WriteFile(resourceFile, data, 0644)
195
c.Assert(err, jc.ErrorIsNil)
197
ctx, err := testing.RunCommand(c, service.NewDeployCommand(), "trusty/starsay", "--resource", "upload-resource="+resourceFile)
198
c.Assert(err, jc.ErrorIsNil)
199
output := testing.Stderr(ctx)
201
expectedOutput := `Added charm "cs:trusty/starsay-1" to the model.
202
Deploying charm "cs:trusty/starsay-1" with the charm series "trusty".
204
c.Assert(output, gc.Equals, expectedOutput)
205
s.assertCharmsUploaded(c, "cs:trusty/starsay-1")
206
s.assertServicesDeployed(c, map[string]serviceInfo{
207
"starsay": {charm: "cs:trusty/starsay-1"},
209
_, err = s.State.Unit("starsay/0")
210
c.Assert(err, jc.ErrorIsNil)
212
res, err := s.State.Resources()
213
c.Assert(err, jc.ErrorIsNil)
214
svcres, err := res.ListResources("starsay")
215
c.Assert(err, jc.ErrorIsNil)
217
sort.Sort(byname(svcres.Resources))
219
c.Assert(svcres.Resources, gc.HasLen, 3)
220
c.Check(svcres.Resources[2].Timestamp, gc.Not(gc.Equals), time.Time{})
221
svcres.Resources[2].Timestamp = time.Time{}
223
expectedResources := []resource.Resource{
225
Resource: charmresource.Resource{
226
Meta: charmresource.Meta{
227
Name: "install-resource",
228
Type: charmresource.TypeFile,
229
Path: "gotta-have-it.txt",
230
Description: "get things started",
232
Origin: charmresource.OriginStore,
235
ID: "starsay/install-resource",
236
ServiceID: "starsay",
239
Resource: charmresource.Resource{
240
Meta: charmresource.Meta{
241
Name: "store-resource",
242
Type: charmresource.TypeFile,
243
Path: "filename.tgz",
244
Description: "One line that is useful when operators need to push it.",
246
Origin: charmresource.OriginStore,
249
ID: "starsay/store-resource",
250
ServiceID: "starsay",
253
Resource: charmresource.Resource{
254
Meta: charmresource.Meta{
255
Name: "upload-resource",
256
Type: charmresource.TypeFile,
257
Path: "somename.xml",
258
Description: "Who uses xml anymore?",
260
Origin: charmresource.OriginUpload,
263
Size: int64(len(data)),
265
ID: "starsay/upload-resource",
266
ServiceID: "starsay",
267
Username: "admin@local",
268
// Timestamp is checked above
272
c.Check(svcres.Resources, jc.DeepEquals, expectedResources)
274
oldCharmStoreResources := make([]charmresource.Resource, len(svcres.CharmStoreResources))
275
copy(oldCharmStoreResources, svcres.CharmStoreResources)
277
sort.Sort(csbyname(oldCharmStoreResources))
279
testcharms.UploadCharm(c, s.client, "trusty/starsay-2", "starsay")
281
_, err = testing.RunCommand(c, service.NewUpgradeCharmCommand(), "starsay")
282
c.Assert(err, jc.ErrorIsNil)
284
s.assertServicesDeployed(c, map[string]serviceInfo{
285
"starsay": {charm: "cs:trusty/starsay-2"},
288
res, err = s.State.Resources()
289
c.Assert(err, jc.ErrorIsNil)
290
svcres, err = res.ListResources("starsay")
291
c.Assert(err, jc.ErrorIsNil)
293
sort.Sort(byname(svcres.Resources))
295
c.Assert(svcres.Resources, gc.HasLen, 3)
296
c.Check(svcres.Resources[2].Timestamp, gc.Not(gc.Equals), time.Time{})
297
svcres.Resources[2].Timestamp = time.Time{}
299
// ensure that we haven't overridden the previously uploaded resource.
300
c.Check(svcres.Resources, jc.DeepEquals, expectedResources)
302
sort.Sort(csbyname(svcres.CharmStoreResources))
303
c.Check(oldCharmStoreResources, gc.DeepEquals, svcres.CharmStoreResources)
306
type byname []resource.Resource
308
func (b byname) Len() int { return len(b) }
309
func (b byname) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
310
func (b byname) Less(i, j int) bool { return b[i].Name < b[j].Name }
312
type csbyname []charmresource.Resource
314
func (b csbyname) Len() int { return len(b) }
315
func (b csbyname) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
316
func (b csbyname) Less(i, j int) bool { return b[i].Name < b[j].Name }
318
// assertCharmsUploaded checks that the given charm ids have been uploaded.
319
func (s *charmStoreSuite) assertCharmsUploaded(c *gc.C, ids ...string) {
320
charms, err := s.State.AllCharms()
321
c.Assert(err, jc.ErrorIsNil)
322
uploaded := make([]string, len(charms))
323
for i, charm := range charms {
324
uploaded[i] = charm.URL().String()
326
c.Assert(uploaded, jc.SameContents, ids)
329
// assertServicesDeployed checks that the given services have been deployed.
330
func (s *charmStoreSuite) assertServicesDeployed(c *gc.C, info map[string]serviceInfo) {
331
services, err := s.State.AllServices()
332
c.Assert(err, jc.ErrorIsNil)
333
deployed := make(map[string]serviceInfo, len(services))
334
for _, service := range services {
335
charm, _ := service.CharmURL()
336
config, err := service.ConfigSettings()
337
c.Assert(err, jc.ErrorIsNil)
338
if len(config) == 0 {
341
constraints, err := service.Constraints()
342
c.Assert(err, jc.ErrorIsNil)
343
storage, err := service.StorageConstraints()
344
c.Assert(err, jc.ErrorIsNil)
345
if len(storage) == 0 {
348
deployed[service.Name()] = serviceInfo{
349
charm: charm.String(),
351
constraints: constraints,
352
exposed: service.IsExposed(),
356
c.Assert(deployed, jc.DeepEquals, info)
359
// serviceInfo holds information about a deployed service.
360
type serviceInfo struct {
362
config charm.Settings
363
constraints constraints.Value
365
storage map[string]state.StorageConstraints
366
endpointBindings map[string]string