~nskaggs/+junk/xenial-test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package resource

import (
	"github.com/juju/errors"
	"gopkg.in/juju/charm.v6-unstable/resource"
	"gopkg.in/juju/names.v2"
)

// ServiceResources contains the list of resources for the application and all its
// units.
type ServiceResources struct {
	// Resources are the current version of the resource for the application that
	// resource-get will retrieve.
	Resources []Resource

	// CharmStoreResources provides the resource info from the charm
	// store for each of the application's resources. The information from
	// the charm store is current as of the last time the charm store
	// was polled. Each entry here corresponds to the same indexed entry
	// in the Resources field.
	CharmStoreResources []resource.Resource

	// UnitResources reports the currenly-in-use version of resources for each
	// unit.
	UnitResources []UnitResources
}

// Updates returns the list of charm store resources corresponding to
// the application's resources that are out of date. Note that there must be
// a charm store resource for each of the application resources and
// vice-versa. If they are out of sync then an error is returned.
func (sr ServiceResources) Updates() ([]resource.Resource, error) {
	storeResources, err := sr.alignStoreResources()
	if err != nil {
		return nil, errors.Trace(err)
	}

	var updates []resource.Resource
	for i, res := range sr.Resources {
		if res.Origin != resource.OriginStore {
			continue
		}
		csRes := storeResources[i]
		// If the revision is the same then all the other info must be.
		if res.Revision == csRes.Revision {
			continue
		}
		updates = append(updates, csRes)
	}
	return updates, nil
}

func (sr ServiceResources) alignStoreResources() ([]resource.Resource, error) {
	if len(sr.CharmStoreResources) > len(sr.Resources) {
		return nil, errors.Errorf("have more charm store resources than application resources")
	}
	if len(sr.CharmStoreResources) < len(sr.Resources) {
		return nil, errors.Errorf("have fewer charm store resources than application resources")
	}

	var store []resource.Resource
	for _, res := range sr.Resources {
		found := false
		for _, chRes := range sr.CharmStoreResources {
			if chRes.Name == res.Name {
				store = append(store, chRes)
				found = true
				break
			}
		}
		if !found {
			return nil, errors.Errorf("charm store resource %q not found", res.Name)
		}
	}
	return store, nil
}

// UnitResources conains the list of resources used by a unit.
type UnitResources struct {
	// Tag is the tag of the unit.
	Tag names.UnitTag

	// Resources are the resource versions currently in use by this unit.
	Resources []Resource

	// DownloadProgress indicates the number of bytes of the unit's
	// resources, identified by name, that have been downloaded so far
	// by the uniter. This only applies to resources that are currently
	// being downloaded to the unit. All other resources for the unit
	// will not be found in the map.
	DownloadProgress map[string]int64
}