Permalink
Browse files

State upgrade step: Add EnvUUID to charm docs.

Add an upgrade step to add the environment uuid to charm docs. Update
doc struct, call sites and tests respectively.
  • Loading branch information...
1 parent a1a74d5 commit 45f84f50a1c790e1789f383f3d24ca34e7a85989 @waigani waigani committed Oct 28, 2014
Showing with 76 additions and 28 deletions.
  1. +3 −1 state/charm.go
  2. +1 −1 state/export_test.go
  3. +24 −17 state/state.go
  4. +6 −7 state/state_test.go
  5. +1 −1 state/unit.go
  6. +7 −1 state/upgrades.go
  7. +27 −0 state/upgrades_test.go
  8. +6 −0 upgrades/steps121.go
  9. +1 −0 upgrades/steps121_test.go
View
@@ -11,7 +11,9 @@ import (
// charmDoc represents the internal state of a charm in MongoDB.
type charmDoc struct {
- URL *charm.URL `bson:"_id"`
+ DocID string `bson:"_id"`
+ URL *charm.URL `bson:"url"`
+ EnvUUID string `bson:"env-uuid"`
Meta *charm.Meta
Config *charm.Config
Actions *charm.Actions
View
@@ -133,7 +133,7 @@ func addCharm(c *gc.C, st *State, series string, ch charm.Charm) *Charm {
func SetCharmBundleURL(c *gc.C, st *State, curl *charm.URL, bundleURL string) {
ops := []txn.Op{{
C: charmsC,
- Id: curl.String(),
+ Id: st.docID(curl.String()),
Assert: txn.DocExists,
Update: bson.D{{"$set", bson.D{{"bundleurl", bundleURL}}}},
}}
View
@@ -665,10 +665,12 @@ func (st *State) AddCharm(ch charm.Charm, curl *charm.URL, storagePath, bundleSh
charms, closer := st.getCollection(charmsC)
defer closer()
- err = charms.Find(bson.D{{"_id", curl.String()}, {"placeholder", true}}).One(&existing)
+ err = charms.Find(bson.D{{"_id", st.docID(curl.String())}, {"placeholder", true}}).One(&existing)
if err == mgo.ErrNotFound {
cdoc := &charmDoc{
+ DocID: st.docID(curl.String()),
URL: curl,
+ EnvUUID: st.EnvironTag().Id(),
Meta: ch.Meta(),
Config: ch.Config(),
Actions: ch.Actions(),
@@ -707,7 +709,7 @@ func (st *State) Charm(curl *charm.URL) (*Charm, error) {
cdoc := &charmDoc{}
what := bson.D{
- {"_id", curl},
+ {"_id", st.docID(curl.String())},
{"placeholder", bson.D{{"$ne", true}}},
{"pendingupload", bson.D{{"$ne", true}}},
}
@@ -731,7 +733,7 @@ func (st *State) LatestPlaceholderCharm(curl *charm.URL) (*Charm, error) {
defer closer()
noRevURL := curl.WithRevision(-1)
- curlRegex := "^" + regexp.QuoteMeta(noRevURL.String())
+ curlRegex := "^" + regexp.QuoteMeta(st.docID(noRevURL.String()))
var docs []charmDoc
err := charms.Find(bson.D{{"_id", bson.D{{"$regex", curlRegex}}}, {"placeholder", true}}).All(&docs)
if err != nil {
@@ -766,15 +768,15 @@ func (st *State) PrepareLocalCharmUpload(curl *charm.URL) (chosenUrl *charm.URL,
}
// Get a regex with the charm URL and no revision.
noRevURL := curl.WithRevision(-1)
- curlRegex := "^" + regexp.QuoteMeta(noRevURL.String())
+ curlRegex := "^" + regexp.QuoteMeta(st.docID(noRevURL.String()))
charms, closer := st.getCollection(charmsC)
defer closer()
buildTxn := func(attempt int) ([]txn.Op, error) {
// Find the highest revision of that charm in state.
var docs []charmDoc
- err = charms.Find(bson.D{{"_id", bson.D{{"$regex", curlRegex}}}}).Select(bson.D{{"_id", 1}}).All(&docs)
+ err = charms.Find(bson.D{{"_id", bson.D{{"$regex", curlRegex}}}}).Select(bson.D{{"_id", 1}, {"url", 1}}).All(&docs)
if err != nil {
return nil, errors.Trace(err)
}
@@ -795,12 +797,14 @@ func (st *State) PrepareLocalCharmUpload(curl *charm.URL) (chosenUrl *charm.URL,
chosenUrl = curl.WithRevision(chosenRevision)
uploadedCharm := &charmDoc{
+ DocID: st.docID(chosenUrl.String()),
+ EnvUUID: st.EnvironTag().Id(),
URL: chosenUrl,
PendingUpload: true,
}
ops := []txn.Op{{
C: charmsC,
- Id: uploadedCharm.URL,
+ Id: uploadedCharm.DocID,
Assert: txn.DocMissing,
Insert: uploadedCharm,
}}
@@ -839,7 +843,7 @@ func (st *State) PrepareStoreCharmUpload(curl *charm.URL) (*Charm, error) {
)
buildTxn := func(attempt int) ([]txn.Op, error) {
// Find an uploaded or pending charm with the given exact curl.
- err := charms.FindId(curl).One(&uploadedCharm)
+ err := charms.FindId(st.docID(curl.String())).One(&uploadedCharm)
if err != nil && err != mgo.ErrNotFound {
return nil, errors.Trace(err)
} else if err == nil && !uploadedCharm.Placeholder {
@@ -850,6 +854,8 @@ func (st *State) PrepareStoreCharmUpload(curl *charm.URL) (*Charm, error) {
} else if err == mgo.ErrNotFound {
// Prepare the pending charm document for insertion.
uploadedCharm = charmDoc{
+ DocID: st.docID(curl.String()),
+ EnvUUID: st.EnvironTag().Id(),
URL: curl,
PendingUpload: true,
Placeholder: false,
@@ -863,7 +869,7 @@ func (st *State) PrepareStoreCharmUpload(curl *charm.URL) (*Charm, error) {
// changed yet.
ops = []txn.Op{{
C: charmsC,
- Id: curl,
+ Id: uploadedCharm.DocID,
Assert: bson.D{
{"bundlesha256", ""},
{"pendingupload", false},
@@ -881,7 +887,7 @@ func (st *State) PrepareStoreCharmUpload(curl *charm.URL) (*Charm, error) {
// No charm document with this curl yet, insert it.
ops = []txn.Op{{
C: charmsC,
- Id: curl,
+ Id: uploadedCharm.DocID,
Assert: txn.DocMissing,
Insert: uploadedCharm,
}}
@@ -916,7 +922,7 @@ func (st *State) AddStoreCharmPlaceholder(curl *charm.URL) (err error) {
buildTxn := func(attempt int) ([]txn.Op, error) {
// See if the charm already exists in state and exit early if that's the case.
var doc charmDoc
- err := charms.Find(bson.D{{"_id", curl.String()}}).Select(bson.D{{"_id", 1}}).One(&doc)
+ err := charms.Find(bson.D{{"_id", st.docID(curl.String())}}).Select(bson.D{{"_id", 1}}).One(&doc)
if err != nil && err != mgo.ErrNotFound {
return nil, errors.Trace(err)
}
@@ -931,12 +937,14 @@ func (st *State) AddStoreCharmPlaceholder(curl *charm.URL) (err error) {
}
// Add the new charm doc.
placeholderCharm := &charmDoc{
+ DocID: st.docID(curl.String()),
+ EnvUUID: st.EnvironTag().Id(),
URL: curl,
Placeholder: true,
}
ops = append(ops, txn.Op{
C: charmsC,
- Id: placeholderCharm.URL.String(),
+ Id: placeholderCharm.DocID,
Assert: txn.DocMissing,
Insert: placeholderCharm,
})
@@ -950,14 +958,13 @@ func (st *State) AddStoreCharmPlaceholder(curl *charm.URL) (err error) {
func (st *State) deleteOldPlaceholderCharmsOps(curl *charm.URL) ([]txn.Op, error) {
// Get a regex with the charm URL and no revision.
noRevURL := curl.WithRevision(-1)
- curlRegex := "^" + regexp.QuoteMeta(noRevURL.String())
-
+ curlRegex := "^" + regexp.QuoteMeta(st.docID(noRevURL.String()))
charms, closer := st.getCollection(charmsC)
defer closer()
var docs []charmDoc
err := charms.Find(
- bson.D{{"_id", bson.D{{"$regex", curlRegex}}}, {"placeholder", true}}).Select(bson.D{{"_id", 1}}).All(&docs)
+ bson.D{{"_id", bson.D{{"$regex", curlRegex}}}, {"placeholder", true}}).Select(bson.D{{"_id", 1}, {"url", 1}}).All(&docs)
if err != nil {
return nil, errors.Trace(err)
}
@@ -968,7 +975,7 @@ func (st *State) deleteOldPlaceholderCharmsOps(curl *charm.URL) ([]txn.Op, error
}
ops = append(ops, txn.Op{
C: charmsC,
- Id: doc.URL.String(),
+ Id: doc.DocID,
Assert: stillPlaceholder,
Remove: true,
})
@@ -1015,7 +1022,7 @@ func (st *State) UpdateUploadedCharm(ch charm.Charm, curl *charm.URL, storagePat
defer closer()
doc := &charmDoc{}
- err := charms.FindId(curl).One(&doc)
+ err := charms.FindId(st.docID(curl.String())).One(&doc)
if err == mgo.ErrNotFound {
return nil, errors.NotFoundf("charm %q", curl)
}
@@ -1055,7 +1062,7 @@ func (st *State) updateCharmDoc(
}}}
ops := []txn.Op{{
C: charmsC,
- Id: curl,
+ Id: st.docID(curl.String()),
Assert: preReq,
Update: updateFields,
}}
View
@@ -213,7 +213,7 @@ func (s *StateSuite) TestAddCharm(c *gc.C) {
c.Assert(dummy.URL().String(), gc.Equals, curl.String())
doc := state.CharmDoc{}
- err = s.charms.FindId(curl).One(&doc)
+ err = s.charms.FindId(state.DocID(s.State, curl.String())).One(&doc)
c.Assert(err, gc.IsNil)
c.Logf("%#v", doc)
c.Assert(doc.URL, gc.DeepEquals, curl)
@@ -238,7 +238,7 @@ func (s *StateSuite) TestAddCharmUpdatesPlaceholder(c *gc.C) {
// Charm doc has been updated.
var docs []state.CharmDoc
- err = s.charms.FindId(curl).All(&docs)
+ err = s.charms.FindId(state.DocID(s.State, curl.String())).All(&docs)
c.Assert(err, gc.IsNil)
c.Assert(docs, gc.HasLen, 1)
c.Assert(docs[0].URL, gc.DeepEquals, curl)
@@ -253,7 +253,7 @@ func (s *StateSuite) assertPendingCharmExists(c *gc.C, curl *charm.URL) {
// Find charm directly and verify only the charm URL and
// PendingUpload are set.
doc := state.CharmDoc{}
- err := s.charms.FindId(curl).One(&doc)
+ err := s.charms.FindId(state.DocID(s.State, curl.String())).One(&doc)
c.Assert(err, gc.IsNil)
c.Logf("%#v", doc)
c.Assert(doc.URL, gc.DeepEquals, curl)
@@ -283,7 +283,6 @@ func (s *StateSuite) TestPrepareLocalCharmUpload(c *gc.C) {
curl, err = s.State.PrepareLocalCharmUpload(testCurl)
c.Assert(err, gc.IsNil)
c.Assert(curl, gc.DeepEquals, testCurl)
-
s.assertPendingCharmExists(c, curl)
// Try adding it again with the same revision and ensure it gets bumped.
@@ -343,7 +342,7 @@ func (s *StateSuite) TestPrepareStoreCharmUpload(c *gc.C) {
c.Assert(err, gc.IsNil)
},
After: func() {
- err := s.charms.RemoveId(curl)
+ err := s.charms.RemoveId(state.DocID(s.State, curl.String()))
c.Assert(err, gc.IsNil)
},
}
@@ -353,7 +352,7 @@ func (s *StateSuite) TestPrepareStoreCharmUpload(c *gc.C) {
c.Assert(err, gc.IsNil)
},
After: func() {
- err := s.charms.UpdateId(curl, bson.D{{"$set", bson.D{
+ err := s.charms.UpdateId(state.DocID(s.State, curl.String()), bson.D{{"$set", bson.D{
{"bundlesha256", "fake"}},
}})
c.Assert(err, gc.IsNil)
@@ -442,7 +441,7 @@ func (s *StateSuite) assertPlaceholderCharmExists(c *gc.C, curl *charm.URL) {
// Find charm directly and verify only the charm URL and
// Placeholder are set.
doc := state.CharmDoc{}
- err := s.charms.FindId(curl).One(&doc)
+ err := s.charms.FindId(state.DocID(s.State, curl.String())).One(&doc)
c.Assert(err, gc.IsNil)
c.Assert(doc.URL, gc.DeepEquals, curl)
c.Assert(doc.PendingUpload, jc.IsFalse)
View
@@ -856,7 +856,7 @@ func (u *Unit) SetCharmURL(curl *charm.URL) (err error) {
// Already set
return nil, jujutxn.ErrNoOperations
}
- if count, err := charms.FindId(curl).Count(); err != nil {
+ if count, err := charms.FindId(u.st.docID(curl.String())).Count(); err != nil {
return nil, err
} else if count < 1 {
return nil, fmt.Errorf("unknown charm url %q", curl)
View
@@ -456,7 +456,7 @@ func AddCharmStoragePaths(st *State, storagePaths map[*charm.URL]string) error {
upgradesLogger.Debugf("adding storage path %q to %s", storagePath, curl)
op := txn.Op{
C: charmsC,
- Id: curl.String(),
+ Id: st.docID(curl.String()),
Assert: txn.DocExists,
Update: bson.D{
{"$set", bson.D{{"storagepath", storagePath}}},
@@ -517,6 +517,12 @@ func AddEnvUUIDToMachines(st *State) error {
return addEnvUUIDToEntityCollection(st, machinesC, "machineid")
}
+// AddEnvUUIDToCharms prepends the environment UUID to the ID of
+// all charm docs and adds new "env-uuid" field.
+func AddEnvUUIDToCharms(st *State) error {
+ return addEnvUUIDToEntityCollection(st, charmsC, "url")
+}
+
// AddEnvUUIDToReboots prepends the environment UUID to the ID of
// all reboot docs and adds new "env-uuid" field.
func AddEnvUUIDToReboots(st *State) error {
View
@@ -325,6 +325,33 @@ func (s *upgradesSuite) TestAddEnvUUIDToRebootsIdempotent(c *gc.C) {
s.checkAddEnvUUIDToCollectionIdempotent(c, AddEnvUUIDToReboots, rebootC)
}
+func (s *upgradesSuite) TestAddEnvUUIDToCharms(c *gc.C) {
+ coll, closer, newIDs := s.checkAddEnvUUIDToCollection(c, AddEnvUUIDToCharms, charmsC,
+ bson.M{
+ "_id": "local:series/dummy-1",
+ "bundlesha256": "series-dummy-1-sha256",
+ },
+ bson.M{
+ "_id": "local:anotherseries/dummy-2",
+ "bundlesha256": "anotherseries-dummy-2-sha256",
+ },
+ )
+ defer closer()
+
+ var newDoc charmDoc
+ s.FindId(c, coll, newIDs[0], &newDoc)
+ c.Assert(newDoc.URL.String(), gc.Equals, "local:series/dummy-1")
+ c.Assert(newDoc.BundleSha256, gc.Equals, "series-dummy-1-sha256")
+
+ s.FindId(c, coll, newIDs[1], &newDoc)
+ c.Assert(newDoc.URL.String(), gc.Equals, "local:anotherseries/dummy-2")
+ c.Assert(newDoc.BundleSha256, gc.Equals, "anotherseries-dummy-2-sha256")
+}
+
+func (s *upgradesSuite) TestAddEnvUUIDToCharmsIdempotent(c *gc.C) {
+ s.checkAddEnvUUIDToCollectionIdempotent(c, AddEnvUUIDToCharms, charmsC)
+}
+
func (s *upgradesSuite) TestAddEnvUUIDToInstanceData(c *gc.C) {
coll, closer, newIDs := s.checkAddEnvUUIDToCollection(c, AddEnvUUIDToInstanceData, instanceDataC,
bson.M{
View
@@ -124,6 +124,12 @@ func stepsFor121a3() []Step {
run: func(context Context) error {
return state.AddEnvUUIDToReboots(context.State())
},
+ }, &upgradeStep{
+ description: "prepend the environment UUID to the ID of all charm docs",
+ targets: []Target{DatabaseMaster},
+ run: func(context Context) error {
+ return state.AddEnvUUIDToCharms(context.State())
+ },
},
}
}
@@ -45,6 +45,7 @@ func (s *steps121Suite) TestStepsFor121a3(c *gc.C) {
"prepend the environment UUID to the ID of all instanceData docs",
"prepend the environment UUID to the ID of all containerRef docs",
"prepend the environment UUID to the ID of all reboot docs",
+ "prepend the environment UUID to the ID of all charm docs",
}
assertSteps(c, version.MustParse("1.21-alpha3"), expectedSteps)
}

0 comments on commit 45f84f5

Please sign in to comment.