~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/service/upgradecharm_resources_test.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:
6
6
import (
7
7
        "bytes"
8
8
        "io/ioutil"
 
9
        "net/http/httptest"
9
10
        "path"
 
11
        "sort"
 
12
        "time"
10
13
 
11
14
        jc "github.com/juju/testing/checkers"
12
15
        gc "gopkg.in/check.v1"
 
16
        "gopkg.in/juju/charm.v6-unstable"
13
17
        charmresource "gopkg.in/juju/charm.v6-unstable/resource"
 
18
        "gopkg.in/juju/charmrepo.v2-unstable"
 
19
        "gopkg.in/juju/charmrepo.v2-unstable/csclient"
 
20
        "gopkg.in/juju/charmstore.v5-unstable"
14
21
 
15
22
        "github.com/juju/juju/cmd/juju/service"
16
23
        "github.com/juju/juju/component/all"
 
24
        "github.com/juju/juju/constraints"
17
25
        jujutesting "github.com/juju/juju/juju/testing"
 
26
        "github.com/juju/juju/resource"
 
27
        "github.com/juju/juju/state"
18
28
        "github.com/juju/juju/testcharms"
19
29
        "github.com/juju/juju/testing"
20
30
)
69
79
        c.Assert(err, jc.ErrorIsNil)
70
80
 
71
81
        data := []byte("some-data")
 
82
        fp, err := charmresource.GenerateFingerprint(bytes.NewReader(data))
 
83
        c.Assert(err, jc.ErrorIsNil)
 
84
 
72
85
        resourceFile := path.Join(c.MkDir(), "data.lib")
73
86
        err = ioutil.WriteFile(resourceFile, data, 0644)
74
87
        c.Assert(err, jc.ErrorIsNil)
83
96
        sr, err := resources.ListResources("riak")
84
97
        c.Assert(err, jc.ErrorIsNil)
85
98
 
86
 
        c.Assert(sr.Resources, gc.HasLen, 1)
 
99
        c.Check(sr.Resources, gc.HasLen, 1)
87
100
 
88
 
        c.Assert(sr.Resources[0].ServiceID, gc.Equals, "riak")
 
101
        c.Check(sr.Resources[0].ServiceID, gc.Equals, "riak")
89
102
 
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)
95
 
 
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)
98
108
 
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{
102
112
                        Name:        "data",
103
113
                        Type:        charmresource.TypeFile,
109
119
                Size:        int64(len(data)),
110
120
        })
111
121
}
 
122
 
 
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
 
128
        srv     *httptest.Server
 
129
        client  *csclient.Client
 
130
}
 
131
 
 
132
func (s *charmStoreSuite) SetUpTest(c *gc.C) {
 
133
        s.JujuConnSuite.SetUpTest(c)
 
134
 
 
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",
 
140
        }
 
141
        handler, err := charmstore.NewServer(db, nil, "", params, charmstore.V5)
 
142
        c.Assert(err, jc.ErrorIsNil)
 
143
        s.handler = handler
 
144
        s.srv = httptest.NewServer(handler)
 
145
        s.client = csclient.New(csclient.Params{
 
146
                URL:      s.srv.URL,
 
147
                User:     params.AuthUsername,
 
148
                Password: params.AuthPassword,
 
149
        })
 
150
 
 
151
        service.PatchNewCharmStoreClient(s, s.srv.URL)
 
152
 
 
153
        // Initialize the charm cache dir.
 
154
        s.PatchValue(&charmrepo.CacheDir, c.MkDir())
 
155
 
 
156
        // Point the CLI to the charm store testing server.
 
157
 
 
158
        // Point the Juju API server to the charm store testing server.
 
159
        s.PatchValue(&csclient.ServerURL, s.srv.URL)
 
160
}
 
161
 
 
162
func (s *charmStoreSuite) TearDownTest(c *gc.C) {
 
163
        s.handler.Close()
 
164
        s.srv.Close()
 
165
        s.JujuConnSuite.TearDownTest(c)
 
166
}
 
167
 
 
168
type UpgradeCharmStoreResourceSuite struct {
 
169
        charmStoreSuite
 
170
}
 
171
 
 
172
var _ = gc.Suite(&UpgradeCharmStoreResourceSuite{})
 
173
 
 
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)
 
180
}
 
181
 
 
182
// TODO(ericsnow) Adapt this test to check passing revisions once the
 
183
// charmstore endpoints are implemented.
 
184
 
 
185
func (s *UpgradeCharmStoreResourceSuite) TestDeployStarsaySuccess(c *gc.C) {
 
186
        testcharms.UploadCharm(c, s.client, "trusty/starsay-1", "starsay")
 
187
 
 
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)
 
192
 
 
193
        resourceFile := path.Join(c.MkDir(), "data.xml")
 
194
        err = ioutil.WriteFile(resourceFile, data, 0644)
 
195
        c.Assert(err, jc.ErrorIsNil)
 
196
 
 
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)
 
200
 
 
201
        expectedOutput := `Added charm "cs:trusty/starsay-1" to the model.
 
202
Deploying charm "cs:trusty/starsay-1" with the charm series "trusty".
 
203
`
 
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"},
 
208
        })
 
209
        _, err = s.State.Unit("starsay/0")
 
210
        c.Assert(err, jc.ErrorIsNil)
 
211
 
 
212
        res, err := s.State.Resources()
 
213
        c.Assert(err, jc.ErrorIsNil)
 
214
        svcres, err := res.ListResources("starsay")
 
215
        c.Assert(err, jc.ErrorIsNil)
 
216
 
 
217
        sort.Sort(byname(svcres.Resources))
 
218
 
 
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{}
 
222
 
 
223
        expectedResources := []resource.Resource{
 
224
                {
 
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",
 
231
                                },
 
232
                                Origin:   charmresource.OriginStore,
 
233
                                Revision: -1,
 
234
                        },
 
235
                        ID:        "starsay/install-resource",
 
236
                        ServiceID: "starsay",
 
237
                },
 
238
                {
 
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.",
 
245
                                },
 
246
                                Origin:   charmresource.OriginStore,
 
247
                                Revision: -1,
 
248
                        },
 
249
                        ID:        "starsay/store-resource",
 
250
                        ServiceID: "starsay",
 
251
                },
 
252
                {
 
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?",
 
259
                                },
 
260
                                Origin:      charmresource.OriginUpload,
 
261
                                Revision:    0,
 
262
                                Fingerprint: fp,
 
263
                                Size:        int64(len(data)),
 
264
                        },
 
265
                        ID:        "starsay/upload-resource",
 
266
                        ServiceID: "starsay",
 
267
                        Username:  "admin@local",
 
268
                        // Timestamp is checked above
 
269
                },
 
270
        }
 
271
 
 
272
        c.Check(svcres.Resources, jc.DeepEquals, expectedResources)
 
273
 
 
274
        oldCharmStoreResources := make([]charmresource.Resource, len(svcres.CharmStoreResources))
 
275
        copy(oldCharmStoreResources, svcres.CharmStoreResources)
 
276
 
 
277
        sort.Sort(csbyname(oldCharmStoreResources))
 
278
 
 
279
        testcharms.UploadCharm(c, s.client, "trusty/starsay-2", "starsay")
 
280
 
 
281
        _, err = testing.RunCommand(c, service.NewUpgradeCharmCommand(), "starsay")
 
282
        c.Assert(err, jc.ErrorIsNil)
 
283
 
 
284
        s.assertServicesDeployed(c, map[string]serviceInfo{
 
285
                "starsay": {charm: "cs:trusty/starsay-2"},
 
286
        })
 
287
 
 
288
        res, err = s.State.Resources()
 
289
        c.Assert(err, jc.ErrorIsNil)
 
290
        svcres, err = res.ListResources("starsay")
 
291
        c.Assert(err, jc.ErrorIsNil)
 
292
 
 
293
        sort.Sort(byname(svcres.Resources))
 
294
 
 
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{}
 
298
 
 
299
        // ensure that we haven't overridden the previously uploaded resource.
 
300
        c.Check(svcres.Resources, jc.DeepEquals, expectedResources)
 
301
 
 
302
        sort.Sort(csbyname(svcres.CharmStoreResources))
 
303
        c.Check(oldCharmStoreResources, gc.DeepEquals, svcres.CharmStoreResources)
 
304
}
 
305
 
 
306
type byname []resource.Resource
 
307
 
 
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 }
 
311
 
 
312
type csbyname []charmresource.Resource
 
313
 
 
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 }
 
317
 
 
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()
 
325
        }
 
326
        c.Assert(uploaded, jc.SameContents, ids)
 
327
}
 
328
 
 
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 {
 
339
                        config = nil
 
340
                }
 
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 {
 
346
                        storage = nil
 
347
                }
 
348
                deployed[service.Name()] = serviceInfo{
 
349
                        charm:       charm.String(),
 
350
                        config:      config,
 
351
                        constraints: constraints,
 
352
                        exposed:     service.IsExposed(),
 
353
                        storage:     storage,
 
354
                }
 
355
        }
 
356
        c.Assert(deployed, jc.DeepEquals, info)
 
357
}
 
358
 
 
359
// serviceInfo holds information about a deployed service.
 
360
type serviceInfo struct {
 
361
        charm            string
 
362
        config           charm.Settings
 
363
        constraints      constraints.Value
 
364
        exposed          bool
 
365
        storage          map[string]state.StorageConstraints
 
366
        endpointBindings map[string]string
 
367
}