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

« back to all changes in this revision

Viewing changes to src/gopkg.in/juju/charm.v6-unstable/bundledata.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
        "fmt"
8
8
        "io"
9
9
        "io/ioutil"
 
10
        "os"
 
11
        "path/filepath"
10
12
        "regexp"
11
13
        "sort"
12
14
        "strconv"
66
68
        // use for the given service.
67
69
        Charm string
68
70
 
 
71
        // Series is the series to use when deploying a local charm,
 
72
        // if the charm does not specify a default or the default
 
73
        // is not the desired value.
 
74
        // Series is not compatible with charm store charms where
 
75
        // the series is specified in the URL.
 
76
        Series string `yaml:",omitempty" json:",omitempty"`
 
77
 
 
78
        // Resources is the set of resource revisions to deploy for the
 
79
        // service. Bundles only support charm store resources and not ones
 
80
        // that were uploaded to the controller.
 
81
        Resources map[string]int `yaml:",omitempty" json:",omitempty"`
 
82
 
69
83
        // NumUnits holds the number of units of the
70
84
        // service that will be deployed.
71
85
        //
178
192
}
179
193
 
180
194
type bundleDataVerifier struct {
181
 
        bd *BundleData
 
195
        // bundleDir is the directory containing the bundle file
 
196
        bundleDir string
 
197
        bd        *BundleData
182
198
 
183
199
        // machines holds the reference counts of all machines
184
200
        // as referred to by placement directives.
217
233
        return req
218
234
}
219
235
 
 
236
// VerifyLocal verifies that a local bundle file is consistent.
 
237
// A local bundle file may contain references to charms which are
 
238
// referred to by a directory, either relative or absolute.
 
239
//
 
240
// bundleDir is used to construct the full path for charms specified
 
241
// using a relative directory path. The charm path is therefore expected
 
242
// to be relative to the bundle.yaml file.
 
243
func (bd *BundleData) VerifyLocal(
 
244
        bundleDir string,
 
245
        verifyConstraints func(c string) error,
 
246
        verifyStorage func(s string) error,
 
247
) error {
 
248
        return bd.verifyBundle(bundleDir, verifyConstraints, verifyStorage, nil)
 
249
}
 
250
 
220
251
// Verify is a convenience method that calls VerifyWithCharms
221
252
// with a nil charms map.
222
253
func (bd *BundleData) Verify(
252
283
        verifyStorage func(s string) error,
253
284
        charms map[string]Charm,
254
285
) error {
 
286
        return bd.verifyBundle("", verifyConstraints, verifyStorage, charms)
 
287
}
 
288
 
 
289
func (bd *BundleData) verifyBundle(
 
290
        bundleDir string,
 
291
        verifyConstraints func(c string) error,
 
292
        verifyStorage func(s string) error,
 
293
        charms map[string]Charm,
 
294
) error {
255
295
        if verifyConstraints == nil {
256
296
                verifyConstraints = func(string) error {
257
297
                        return nil
263
303
                }
264
304
        }
265
305
        verifier := &bundleDataVerifier{
 
306
                bundleDir:         bundleDir,
266
307
                verifyConstraints: verifyConstraints,
267
308
                verifyStorage:     verifyStorage,
268
309
                bd:                bd,
319
360
                return
320
361
        }
321
362
        for name, svc := range verifier.bd.Services {
322
 
                if _, err := ParseURL(svc.Charm); err != nil {
 
363
                if svc.Charm == "" {
 
364
                        verifier.addErrorf("empty charm path")
 
365
                }
 
366
                // Charm may be a local directory or a charm URL.
 
367
                var curl *URL
 
368
                var err error
 
369
                if strings.HasPrefix(svc.Charm, ".") || filepath.IsAbs(svc.Charm) {
 
370
                        charmPath := svc.Charm
 
371
                        if !filepath.IsAbs(charmPath) {
 
372
                                charmPath = filepath.Join(verifier.bundleDir, charmPath)
 
373
                        }
 
374
                        if _, err := os.Stat(charmPath); err != nil {
 
375
                                if os.IsNotExist(err) {
 
376
                                        verifier.addErrorf("charm path in service %q does not exist: %v", name, charmPath)
 
377
                                } else {
 
378
                                        verifier.addErrorf("invalid charm path in service %q: %v", name, err)
 
379
                                }
 
380
                        }
 
381
                } else if curl, err = ParseURL(svc.Charm); err != nil {
323
382
                        verifier.addErrorf("invalid charm URL in service %q: %v", name, err)
324
383
                }
 
384
 
 
385
                // Check the series.
 
386
                if curl != nil && curl.Series != "" && svc.Series != "" && curl.Series != svc.Series {
 
387
                        verifier.addErrorf("the charm URL for service %q has a series which does not match, please remove the series from the URL", name)
 
388
                }
 
389
                if svc.Series != "" && !IsValidSeries(svc.Series) {
 
390
                        verifier.addErrorf("service %q declares an invalid series %q", name, svc.Series)
 
391
                }
 
392
 
325
393
                if err := verifier.verifyConstraints(svc.Constraints); err != nil {
326
394
                        verifier.addErrorf("invalid constraints %q in service %q: %v", svc.Constraints, name, err)
327
395
                }
347
415
                                verifier.addErrorf("service %q refers to non-existent charm %q", name, svc.Charm)
348
416
                        }
349
417
                }
 
418
                for resName := range svc.Resources {
 
419
                        if resName == "" {
 
420
                                verifier.addErrorf("missing resource name on service %q", name)
 
421
                        }
 
422
                        // We do not check the revisions because all values
 
423
                        // are allowed.
 
424
                }
350
425
                if svc.NumUnits < 0 {
351
426
                        verifier.addErrorf("negative number of units specified on service %q", name)
352
427
                } else if len(svc.To) > svc.NumUnits {
467
542
                        continue
468
543
                }
469
544
                for endpoint, space := range svc.EndpointBindings {
470
 
                        _, matchedProvides := charm.Meta().Provides[endpoint]
471
 
                        _, matchedRequires := charm.Meta().Requires[endpoint]
472
 
                        _, matchedPeers := charm.Meta().Peers[endpoint]
 
545
                        _, isInProvides := charm.Meta().Provides[endpoint]
 
546
                        _, isInRequires := charm.Meta().Requires[endpoint]
 
547
                        _, isInPeers := charm.Meta().Peers[endpoint]
 
548
                        _, isInExtraBindings := charm.Meta().ExtraBindings[endpoint]
473
549
 
474
 
                        if !(matchedProvides || matchedRequires || matchedPeers) {
 
550
                        if !(isInProvides || isInRequires || isInPeers || isInExtraBindings) {
475
551
                                verifier.addErrorf(
476
552
                                        "service %q wants to bind endpoint %q to space %q, "+
477
553
                                                "but the endpoint is not defined by the charm",