// AddCharm adds the ch charm with curl to the state. bundleURL must // be set to a URL where the bundle for ch may be downloaded from. On // success the newly added charm state is returned. func (st *State) AddCharm(ch charm.Charm, curl *charm.URL, bundleURL *url.URL, bundleSha256 string) (stch *Charm, err error) { // The charm may already exist in state as a placeholder, so we // check for that situation and update the existing charm record // if necessary, otherwise add a new record. var existing charmDoc err = st.charms.Find(bson.D{{"_id", curl.String()}, {"placeholder", true}}).One(&existing) if err == mgo.ErrNotFound { cdoc := &charmDoc{ URL: curl, Meta: ch.Meta(), Config: ch.Config(), Actions: ch.Actions(), BundleURL: bundleURL, BundleSha256: bundleSha256, } err = st.charms.Insert(cdoc) if err != nil { return nil, fmt.Errorf("cannot add charm %q: %v", curl, err) } return newCharm(st, cdoc) } else if err != nil { return nil, err } return st.updateCharmDoc(ch, curl, bundleURL, bundleSha256, stillPlaceholder) }
func checkDummy(c *gc.C, f charm.Charm, path string) { c.Assert(f.Revision(), gc.Equals, 1) c.Assert(f.Meta().Name, gc.Equals, "dummy") c.Assert(f.Config().Options["title"].Default, gc.Equals, "My Title") c.Assert(f.Actions(), gc.DeepEquals, &charm.Actions{ map[string]charm.ActionSpec{ "snapshot": charm.ActionSpec{ Description: "Take a snapshot of the database.", Params: map[string]interface{}{ "outfile": map[string]interface{}{ "description": "The file to write out to.", "type": "string", "default": "foo.bz2", }}}}}) switch f := f.(type) { case *charm.Bundle: c.Assert(f.Path, gc.Equals, path) case *charm.Dir: c.Assert(f.Path, gc.Equals, path) } }
// updateCharmDoc updates the charm with specified URL with the given // data, and resets the placeholder and pendingupdate flags. If the // charm is no longer a placeholder or pending (depending on preReq), // it returns ErrCharmRevisionAlreadyModified. func (st *State) updateCharmDoc( ch charm.Charm, curl *charm.URL, bundleURL *url.URL, bundleSha256 string, preReq interface{}) (*Charm, error) { updateFields := bson.D{{"$set", bson.D{ {"meta", ch.Meta()}, {"config", ch.Config()}, {"actions", ch.Actions()}, {"bundleurl", bundleURL}, {"bundlesha256", bundleSha256}, {"pendingupload", false}, {"placeholder", false}, }}} ops := []txn.Op{{ C: st.charms.Name, Id: curl, Assert: preReq, Update: updateFields, }} if err := st.runTransaction(ops); err != nil { return nil, onAbort(err, ErrCharmRevisionAlreadyModified) } return st.Charm(curl) }