~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/resource/cmd/deploy_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2015 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package cmd
 
5
 
 
6
import (
 
7
        "bytes"
 
8
        "io"
 
9
        "os"
 
10
 
 
11
        "github.com/juju/errors"
 
12
        "github.com/juju/testing"
 
13
        jc "github.com/juju/testing/checkers"
 
14
        gc "gopkg.in/check.v1"
 
15
        "gopkg.in/juju/charm.v6-unstable"
 
16
        charmresource "gopkg.in/juju/charm.v6-unstable/resource"
 
17
        "gopkg.in/macaroon.v1"
 
18
 
 
19
        "github.com/juju/juju/charmstore"
 
20
)
 
21
 
 
22
type DeploySuite struct {
 
23
        testing.IsolationSuite
 
24
 
 
25
        stub *testing.Stub
 
26
}
 
27
 
 
28
var _ = gc.Suite(&DeploySuite{})
 
29
 
 
30
func (s *DeploySuite) SetUpTest(c *gc.C) {
 
31
        s.IsolationSuite.SetUpTest(c)
 
32
 
 
33
        s.stub = &testing.Stub{}
 
34
}
 
35
 
 
36
func (s DeploySuite) TestDeployResourcesWithoutFiles(c *gc.C) {
 
37
        deps := uploadDeps{s.stub, rsc{&bytes.Buffer{}}}
 
38
        cURL := charm.MustParseURL("cs:~a-user/trusty/spam-5")
 
39
        chID := charmstore.CharmID{
 
40
                URL: cURL,
 
41
        }
 
42
        csMac := &macaroon.Macaroon{}
 
43
        resources := map[string]charmresource.Meta{
 
44
                "store-tarball": {
 
45
                        Name: "store-tarball",
 
46
                        Type: charmresource.TypeFile,
 
47
                        Path: "store.tgz",
 
48
                },
 
49
                "store-zip": {
 
50
                        Name: "store-zip",
 
51
                        Type: charmresource.TypeFile,
 
52
                        Path: "store.zip",
 
53
                },
 
54
        }
 
55
 
 
56
        ids, err := DeployResources(DeployResourcesArgs{
 
57
                ApplicationID:      "mysql",
 
58
                CharmID:            chID,
 
59
                CharmStoreMacaroon: csMac,
 
60
                Filenames:          nil,
 
61
                Client:             deps,
 
62
                ResourcesMeta:      resources,
 
63
        })
 
64
        c.Assert(err, jc.ErrorIsNil)
 
65
 
 
66
        c.Check(ids, gc.DeepEquals, map[string]string{
 
67
                "store-tarball": "id-store-tarball",
 
68
                "store-zip":     "id-store-zip",
 
69
        })
 
70
 
 
71
        s.stub.CheckCallNames(c, "AddPendingResources")
 
72
        s.stub.CheckCall(c, 0, "AddPendingResources", "mysql", chID, csMac, []charmresource.Resource{{
 
73
                Meta:     resources["store-tarball"],
 
74
                Origin:   charmresource.OriginStore,
 
75
                Revision: -1,
 
76
        }, {
 
77
                Meta:     resources["store-zip"],
 
78
                Origin:   charmresource.OriginStore,
 
79
                Revision: -1,
 
80
        }})
 
81
}
 
82
 
 
83
func (s DeploySuite) TestUploadFilesOnly(c *gc.C) {
 
84
        deps := uploadDeps{s.stub, rsc{&bytes.Buffer{}}}
 
85
        cURL := charm.MustParseURL("cs:~a-user/trusty/spam-5")
 
86
        chID := charmstore.CharmID{
 
87
                URL: cURL,
 
88
        }
 
89
        csMac := &macaroon.Macaroon{}
 
90
        du := deployUploader{
 
91
                applicationID: "mysql",
 
92
                chID:          chID,
 
93
                csMac:         csMac,
 
94
                client:        deps,
 
95
                resources: map[string]charmresource.Meta{
 
96
                        "upload": {
 
97
                                Name: "upload",
 
98
                                Type: charmresource.TypeFile,
 
99
                                Path: "upload",
 
100
                        },
 
101
                        "store": {
 
102
                                Name: "store",
 
103
                                Type: charmresource.TypeFile,
 
104
                                Path: "store",
 
105
                        },
 
106
                },
 
107
                osOpen: deps.Open,
 
108
                osStat: deps.Stat,
 
109
        }
 
110
 
 
111
        files := map[string]string{
 
112
                "upload": "foobar.txt",
 
113
        }
 
114
        revisions := map[string]int{}
 
115
        ids, err := du.upload(files, revisions)
 
116
        c.Assert(err, jc.ErrorIsNil)
 
117
        c.Check(ids, gc.DeepEquals, map[string]string{
 
118
                "upload": "id-upload",
 
119
                "store":  "id-store",
 
120
        })
 
121
 
 
122
        s.stub.CheckCallNames(c, "Stat", "AddPendingResources", "Open", "AddPendingResource")
 
123
        expectedStore := []charmresource.Resource{
 
124
                {
 
125
                        Meta:     du.resources["store"],
 
126
                        Origin:   charmresource.OriginStore,
 
127
                        Revision: -1,
 
128
                },
 
129
        }
 
130
        s.stub.CheckCall(c, 1, "AddPendingResources", "mysql", chID, csMac, expectedStore)
 
131
        s.stub.CheckCall(c, 2, "Open", "foobar.txt")
 
132
 
 
133
        expectedUpload := charmresource.Resource{
 
134
                Meta:   du.resources["upload"],
 
135
                Origin: charmresource.OriginUpload,
 
136
        }
 
137
        s.stub.CheckCall(c, 3, "AddPendingResource", "mysql", expectedUpload, "foobar.txt", deps.ReadSeekCloser)
 
138
}
 
139
 
 
140
func (s DeploySuite) TestUploadRevisionsOnly(c *gc.C) {
 
141
        deps := uploadDeps{s.stub, rsc{&bytes.Buffer{}}}
 
142
        cURL := charm.MustParseURL("cs:~a-user/trusty/spam-5")
 
143
        chID := charmstore.CharmID{
 
144
                URL: cURL,
 
145
        }
 
146
        csMac := &macaroon.Macaroon{}
 
147
        du := deployUploader{
 
148
                applicationID: "mysql",
 
149
                chID:          chID,
 
150
                csMac:         csMac,
 
151
                client:        deps,
 
152
                resources: map[string]charmresource.Meta{
 
153
                        "upload": {
 
154
                                Name: "upload",
 
155
                                Type: charmresource.TypeFile,
 
156
                                Path: "upload",
 
157
                        },
 
158
                        "store": {
 
159
                                Name: "store",
 
160
                                Type: charmresource.TypeFile,
 
161
                                Path: "store",
 
162
                        },
 
163
                },
 
164
                osOpen: deps.Open,
 
165
                osStat: deps.Stat,
 
166
        }
 
167
 
 
168
        files := map[string]string{}
 
169
        revisions := map[string]int{
 
170
                "store": 3,
 
171
        }
 
172
        ids, err := du.upload(files, revisions)
 
173
        c.Assert(err, jc.ErrorIsNil)
 
174
        c.Check(ids, gc.DeepEquals, map[string]string{
 
175
                "upload": "id-upload",
 
176
                "store":  "id-store",
 
177
        })
 
178
 
 
179
        s.stub.CheckCallNames(c, "AddPendingResources")
 
180
        expectedStore := []charmresource.Resource{{
 
181
                Meta:     du.resources["store"],
 
182
                Origin:   charmresource.OriginStore,
 
183
                Revision: 3,
 
184
        }, {
 
185
                Meta:     du.resources["upload"],
 
186
                Origin:   charmresource.OriginStore,
 
187
                Revision: -1,
 
188
        }}
 
189
        s.stub.CheckCall(c, 0, "AddPendingResources", "mysql", chID, csMac, expectedStore)
 
190
}
 
191
 
 
192
func (s DeploySuite) TestUploadFilesAndRevisions(c *gc.C) {
 
193
        deps := uploadDeps{s.stub, rsc{&bytes.Buffer{}}}
 
194
        cURL := charm.MustParseURL("cs:~a-user/trusty/spam-5")
 
195
        chID := charmstore.CharmID{
 
196
                URL: cURL,
 
197
        }
 
198
        csMac := &macaroon.Macaroon{}
 
199
        du := deployUploader{
 
200
                applicationID: "mysql",
 
201
                chID:          chID,
 
202
                csMac:         csMac,
 
203
                client:        deps,
 
204
                resources: map[string]charmresource.Meta{
 
205
                        "upload": {
 
206
                                Name: "upload",
 
207
                                Type: charmresource.TypeFile,
 
208
                                Path: "upload",
 
209
                        },
 
210
                        "store": {
 
211
                                Name: "store",
 
212
                                Type: charmresource.TypeFile,
 
213
                                Path: "store",
 
214
                        },
 
215
                },
 
216
                osOpen: deps.Open,
 
217
                osStat: deps.Stat,
 
218
        }
 
219
 
 
220
        files := map[string]string{
 
221
                "upload": "foobar.txt",
 
222
        }
 
223
        revisions := map[string]int{
 
224
                "store": 3,
 
225
        }
 
226
        ids, err := du.upload(files, revisions)
 
227
        c.Assert(err, jc.ErrorIsNil)
 
228
        c.Check(ids, gc.DeepEquals, map[string]string{
 
229
                "upload": "id-upload",
 
230
                "store":  "id-store",
 
231
        })
 
232
 
 
233
        s.stub.CheckCallNames(c, "Stat", "AddPendingResources", "Open", "AddPendingResource")
 
234
        expectedStore := []charmresource.Resource{
 
235
                {
 
236
                        Meta:     du.resources["store"],
 
237
                        Origin:   charmresource.OriginStore,
 
238
                        Revision: 3,
 
239
                },
 
240
        }
 
241
        s.stub.CheckCall(c, 1, "AddPendingResources", "mysql", chID, csMac, expectedStore)
 
242
        s.stub.CheckCall(c, 2, "Open", "foobar.txt")
 
243
 
 
244
        expectedUpload := charmresource.Resource{
 
245
                Meta:   du.resources["upload"],
 
246
                Origin: charmresource.OriginUpload,
 
247
        }
 
248
        s.stub.CheckCall(c, 3, "AddPendingResource", "mysql", expectedUpload, "foobar.txt", deps.ReadSeekCloser)
 
249
}
 
250
 
 
251
func (s DeploySuite) TestUploadUnexpectedResourceFile(c *gc.C) {
 
252
        deps := uploadDeps{s.stub, rsc{&bytes.Buffer{}}}
 
253
        du := deployUploader{
 
254
                applicationID: "mysql",
 
255
                client:        deps,
 
256
                resources: map[string]charmresource.Meta{
 
257
                        "res1": {
 
258
                                Name: "res1",
 
259
                                Type: charmresource.TypeFile,
 
260
                                Path: "path",
 
261
                        },
 
262
                },
 
263
                osOpen: deps.Open,
 
264
                osStat: deps.Stat,
 
265
        }
 
266
 
 
267
        files := map[string]string{"some bad resource": "foobar.txt"}
 
268
        revisions := map[string]int{}
 
269
        _, err := du.upload(files, revisions)
 
270
        c.Check(err, gc.ErrorMatches, `unrecognized resource "some bad resource"`)
 
271
 
 
272
        s.stub.CheckNoCalls(c)
 
273
}
 
274
 
 
275
func (s DeploySuite) TestUploadUnexpectedResourceRevision(c *gc.C) {
 
276
        deps := uploadDeps{s.stub, rsc{&bytes.Buffer{}}}
 
277
        du := deployUploader{
 
278
                applicationID: "mysql",
 
279
                client:        deps,
 
280
                resources: map[string]charmresource.Meta{
 
281
                        "res1": {
 
282
                                Name: "res1",
 
283
                                Type: charmresource.TypeFile,
 
284
                                Path: "path",
 
285
                        },
 
286
                },
 
287
                osOpen: deps.Open,
 
288
                osStat: deps.Stat,
 
289
        }
 
290
 
 
291
        files := map[string]string{}
 
292
        revisions := map[string]int{"some bad resource": 2}
 
293
        _, err := du.upload(files, revisions)
 
294
        c.Check(err, gc.ErrorMatches, `unrecognized resource "some bad resource"`)
 
295
 
 
296
        s.stub.CheckNoCalls(c)
 
297
}
 
298
 
 
299
func (s DeploySuite) TestMissingResource(c *gc.C) {
 
300
        deps := uploadDeps{s.stub, rsc{&bytes.Buffer{}}}
 
301
        du := deployUploader{
 
302
                applicationID: "mysql",
 
303
                client:        deps,
 
304
                resources: map[string]charmresource.Meta{
 
305
                        "res1": {
 
306
                                Name: "res1",
 
307
                                Type: charmresource.TypeFile,
 
308
                                Path: "path",
 
309
                        },
 
310
                },
 
311
                osOpen: deps.Open,
 
312
                osStat: deps.Stat,
 
313
        }
 
314
 
 
315
        // set the error that will be returned by os.Stat
 
316
        s.stub.SetErrors(os.ErrNotExist)
 
317
 
 
318
        files := map[string]string{"res1": "foobar.txt"}
 
319
        revisions := map[string]int{}
 
320
        _, err := du.upload(files, revisions)
 
321
        c.Check(err, gc.ErrorMatches, `file for resource "res1".*`)
 
322
        c.Check(errors.Cause(err), jc.Satisfies, os.IsNotExist)
 
323
}
 
324
 
 
325
type uploadDeps struct {
 
326
        stub           *testing.Stub
 
327
        ReadSeekCloser ReadSeekCloser
 
328
}
 
329
 
 
330
func (s uploadDeps) AddPendingResources(applicationID string, charmID charmstore.CharmID, csMac *macaroon.Macaroon, resources []charmresource.Resource) (ids []string, err error) {
 
331
        charmresource.Sort(resources)
 
332
        s.stub.AddCall("AddPendingResources", applicationID, charmID, csMac, resources)
 
333
        if err := s.stub.NextErr(); err != nil {
 
334
                return nil, err
 
335
        }
 
336
        ids = make([]string, len(resources))
 
337
        for i, res := range resources {
 
338
                ids[i] = "id-" + res.Name
 
339
        }
 
340
        return ids, nil
 
341
}
 
342
 
 
343
func (s uploadDeps) AddPendingResource(applicationID string, resource charmresource.Resource, filename string, r io.ReadSeeker) (id string, err error) {
 
344
        s.stub.AddCall("AddPendingResource", applicationID, resource, filename, r)
 
345
        if err := s.stub.NextErr(); err != nil {
 
346
                return "", err
 
347
        }
 
348
        return "id-" + resource.Name, nil
 
349
}
 
350
 
 
351
func (s uploadDeps) Open(name string) (ReadSeekCloser, error) {
 
352
        s.stub.AddCall("Open", name)
 
353
        if err := s.stub.NextErr(); err != nil {
 
354
                return nil, err
 
355
        }
 
356
        return s.ReadSeekCloser, nil
 
357
}
 
358
 
 
359
func (s uploadDeps) Stat(name string) error {
 
360
        s.stub.AddCall("Stat", name)
 
361
        return s.stub.NextErr()
 
362
}
 
363
 
 
364
type rsc struct {
 
365
        *bytes.Buffer
 
366
}
 
367
 
 
368
func (rsc) Close() error {
 
369
        return nil
 
370
}
 
371
func (rsc) Seek(offset int64, whence int) (int64, error) {
 
372
        return 0, nil
 
373
}