Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
Already on GitHub? Sign in to your account
Add support for listing resources in state. #3981
Merged
jujubot
merged 13 commits into
juju:feature-resources
from
ericsnowcurrently:resources-state-get-resources
Jan 5, 2016
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
792dfc5
Get resources from state.
ericsnowcurrently 7063503
Enable some tests.
ericsnowcurrently 931aa36
Add doc and mongo support for listing resources.
ericsnowcurrently c4aaf0b
Add persistence support for resources.
ericsnowcurrently 2ea3e58
Register the collection in state.
ericsnowcurrently 45549d2
Expose the resources functionality of state.
ericsnowcurrently 31d4d48
Register state and persistence for the component.
ericsnowcurrently 4865210
Drop a method.
ericsnowcurrently 7f35997
Drop a TODO.
ericsnowcurrently aafebb7
doc.resource() -> doc2resource().
ericsnowcurrently 76bee83
Do not typedef the newResources func.
ericsnowcurrently 17b234c
Use the latest charm repo.
ericsnowcurrently 991a8c9
Drop unused error returns.
ericsnowcurrently
Jump to file or symbol
Failed to load files and symbols.
| @@ -0,0 +1,115 @@ | ||
| +// Copyright 2015 Canonical Ltd. | ||
| +// Licensed under the AGPLv3, see LICENCE file for details. | ||
| + | ||
| +package persistence | ||
| + | ||
| +import ( | ||
| + "fmt" | ||
| + "time" | ||
| + | ||
| + "github.com/juju/errors" | ||
| + charmresource "gopkg.in/juju/charm.v6-unstable/resource" | ||
| + "gopkg.in/mgo.v2/bson" | ||
| + | ||
| + "github.com/juju/juju/resource" | ||
| +) | ||
| + | ||
| +const ( | ||
| + resourcesC = "resources" | ||
| +) | ||
| + | ||
| +// resourceID converts an external resource ID into an internal one. | ||
| +func (p Persistence) resourceID(id, serviceID string) string { | ||
| + return fmt.Sprintf("resource#%s#%s", serviceID, id) | ||
| +} | ||
| + | ||
| +// newResourceDoc generates a doc that represents the given resource. | ||
| +func (p Persistence) newResourcDoc(id, serviceID string, res resource.Resource) *resourceDoc { | ||
| + id = p.resourceID(id, serviceID) | ||
| + | ||
| + return &resourceDoc{ | ||
| + DocID: id, | ||
| + ServiceID: serviceID, | ||
| + | ||
| + Name: res.Name, | ||
| + Type: res.Type.String(), | ||
| + Path: res.Path, | ||
| + Comment: res.Comment, | ||
| + | ||
| + Origin: res.Origin.String(), | ||
| + Revision: res.Revision, | ||
| + Fingerprint: res.Fingerprint.Bytes(), | ||
| + | ||
| + Username: res.Username, | ||
| + Timestamp: res.Timestamp, | ||
| + } | ||
| +} | ||
| + | ||
| +// resources returns the resource docs for the given service. | ||
| +func (p Persistence) resources(serviceID string) ([]resourceDoc, error) { | ||
| + var docs []resourceDoc | ||
| + query := bson.D{{"service-id", serviceID}} | ||
| + if err := p.base.All(resourcesC, query, &docs); err != nil { | ||
| + return nil, errors.Trace(err) | ||
| + } | ||
| + return docs, nil | ||
| +} | ||
| + | ||
| +// resourceDoc is the top-level document for resources. | ||
| +type resourceDoc struct { | ||
| + DocID string `bson:"_id"` | ||
| + EnvUUID string `bson:"env-uuid"` | ||
| + ServiceID string `bson:"service-id"` | ||
| + | ||
| + Name string `bson:"name"` | ||
| + Type string `bson:"type"` | ||
| + Path string `bson:"path"` | ||
| + Comment string `bson:"comment"` | ||
| + | ||
| + Origin string `bson:"origin"` | ||
| + Revision int `bson:"revision"` | ||
| + Fingerprint []byte `bson:"fingerprint"` | ||
| + | ||
| + Username string `bson:"username"` | ||
| + Timestamp time.Time `bson:"timestamp-when-added"` | ||
| +} | ||
| + | ||
| +// doc2resource returns the resource.Resource represented by the doc. | ||
| +func doc2resource(doc resourceDoc) (resource.Resource, error) { | ||
| + var res resource.Resource | ||
| + | ||
| + resType, err := charmresource.ParseType(doc.Type) | ||
| + if err != nil { | ||
| + return res, errors.Annotate(err, "got invalid data from DB") | ||
| + } | ||
| + | ||
| + origin, err := charmresource.ParseOrigin(doc.Origin) | ||
| + if err != nil { | ||
| + return res, errors.Annotate(err, "got invalid data from DB") | ||
| + } | ||
| + | ||
| + fp, err := charmresource.NewFingerprint(doc.Fingerprint) | ||
| + if err != nil { | ||
| + return res, errors.Annotate(err, "got invalid data from DB") | ||
| + } | ||
| + | ||
| + res = resource.Resource{ | ||
| + Resource: charmresource.Resource{ | ||
| + Meta: charmresource.Meta{ | ||
| + Name: doc.Name, | ||
| + Type: resType, | ||
| + Path: doc.Path, | ||
| + Comment: doc.Comment, | ||
| + }, | ||
| + Origin: origin, | ||
| + Revision: doc.Revision, | ||
| + Fingerprint: fp, | ||
| + }, | ||
| + Username: doc.Username, | ||
| + Timestamp: doc.Timestamp, | ||
| + } | ||
| + if err := res.Validate(); err != nil { | ||
| + return res, errors.Annotate(err, "got invalid data from DB") | ||
| + } | ||
| + return res, nil | ||
| +} |
| @@ -0,0 +1,14 @@ | ||
| +// Copyright 2015 Canonical Ltd. | ||
| +// Licensed under the AGPLv3, see LICENCE file for details. | ||
| + | ||
| +package persistence | ||
| + | ||
| +import ( | ||
| + "testing" | ||
| + | ||
| + gc "gopkg.in/check.v1" | ||
| +) | ||
| + | ||
| +func Test(t *testing.T) { | ||
| + gc.TestingT(t) | ||
| +} |
| @@ -0,0 +1,56 @@ | ||
| +// Copyright 2015 Canonical Ltd. | ||
| +// Licensed under the AGPLv3, see LICENCE file for details. | ||
| + | ||
| +package persistence | ||
| + | ||
| +import ( | ||
| + "github.com/juju/errors" | ||
| + "github.com/juju/loggo" | ||
| + | ||
| + "github.com/juju/juju/resource" | ||
| +) | ||
| + | ||
| +var logger = loggo.GetLogger("juju.resource.persistence") | ||
| + | ||
| +// PersistenceBase exposes the core persistence functionality needed | ||
| +// for resources. | ||
| +type PersistenceBase interface { | ||
| + // All populates docs with the list of the documents corresponding | ||
| + // to the provided query. | ||
| + All(collName string, query, docs interface{}) error | ||
| +} | ||
| + | ||
| +// Persistence provides the persistence functionality for the | ||
| +// Juju environment as a whole. | ||
| +type Persistence struct { | ||
| + base PersistenceBase | ||
| +} | ||
| + | ||
| +// NewPersistence wraps the base in a new Persistence. | ||
| +func NewPersistence(base PersistenceBase) *Persistence { | ||
| + return &Persistence{ | ||
| + base: base, | ||
| + } | ||
| +} | ||
| + | ||
| +// ListResources returns the resource data for the given service ID. | ||
| +func (p Persistence) ListResources(serviceID string) ([]resource.Resource, error) { | ||
| + logger.Tracef("listing all resources for service %q", serviceID) | ||
| + | ||
| + // TODO(ericsnow) Ensure that the service is still there? | ||
| + | ||
| + docs, err := p.resources(serviceID) | ||
| + if err != nil { | ||
| + return nil, errors.Trace(err) | ||
| + } | ||
| + | ||
| + var results []resource.Resource | ||
| + for _, doc := range docs { | ||
| + res, err := doc2resource(doc) | ||
| + if err != nil { | ||
| + return nil, errors.Trace(err) | ||
| + } | ||
| + results = append(results, res) | ||
| + } | ||
| + return results, nil | ||
| +} |
Oops, something went wrong.