func (s *LocalRepoSuite) TestMultipleVersions(c *gc.C) { charmURL := charm.MustParseURL("local:quantal/upgrade") s.addDir("upgrade1") rev, err := charm.Latest(s.repo, charmURL) c.Assert(err, gc.IsNil) c.Assert(rev, gc.Equals, 1) ch, err := s.repo.Get(charmURL) c.Assert(err, gc.IsNil) c.Assert(ch.Revision(), gc.Equals, 1) s.addDir("upgrade2") rev, err = charm.Latest(s.repo, charmURL) c.Assert(err, gc.IsNil) c.Assert(rev, gc.Equals, 2) ch, err = s.repo.Get(charmURL) c.Assert(err, gc.IsNil) c.Assert(ch.Revision(), gc.Equals, 2) revCharmURL := charmURL.WithRevision(1) rev, err = charm.Latest(s.repo, revCharmURL) c.Assert(err, gc.IsNil) c.Assert(rev, gc.Equals, 2) ch, err = s.repo.Get(revCharmURL) c.Assert(err, gc.IsNil) c.Assert(ch.Revision(), gc.Equals, 1) badRevCharmURL := charmURL.WithRevision(33) rev, err = charm.Latest(s.repo, badRevCharmURL) c.Assert(err, gc.IsNil) c.Assert(rev, gc.Equals, 2) _, err = s.repo.Get(badRevCharmURL) s.checkNotFoundErr(c, err, badRevCharmURL) }
func (s *LocalRepoSuite) TestMissingRepo(c *gc.C) { c.Assert(os.RemoveAll(s.repo.Path), gc.IsNil) _, err := charm.Latest(s.repo, charm.MustParseURL("local:quantal/zebra")) c.Assert(err, gc.ErrorMatches, `no repository found at ".*"`) _, err = s.repo.Get(charm.MustParseURL("local:quantal/zebra")) c.Assert(err, gc.ErrorMatches, `no repository found at ".*"`) c.Assert(ioutil.WriteFile(s.repo.Path, nil, 0666), gc.IsNil) _, err = charm.Latest(s.repo, charm.MustParseURL("local:quantal/zebra")) c.Assert(err, gc.ErrorMatches, `no repository found at ".*"`) _, err = s.repo.Get(charm.MustParseURL("local:quantal/zebra")) c.Assert(err, gc.ErrorMatches, `no repository found at ".*"`) }
// addCharmViaAPI calls the appropriate client API calls to add the // given charm URL to state. Also displays the charm URL of the added // charm on stdout. func addCharmViaAPI(client *api.Client, ctx *cmd.Context, curl *charm.URL, repo charm.Repository) (*charm.URL, error) { if curl.Revision < 0 { latest, err := charm.Latest(repo, curl) if err != nil { return nil, err } curl = curl.WithRevision(latest) } switch curl.Schema { case "local": ch, err := repo.Get(curl) if err != nil { return nil, err } stateCurl, err := client.AddLocalCharm(curl, ch) if err != nil { return nil, err } curl = stateCurl case "cs": err := client.AddCharm(curl) if err != nil { return nil, err } default: return nil, fmt.Errorf("unsupported charm URL schema: %q", curl.Schema) } ctx.Infof("Added charm %q to the environment.", curl) return curl, nil }
// PutCharm uploads the given charm to provider storage, and adds a // state.Charm to the state. The charm is not uploaded if a charm with // the same URL already exists in the state. // If bumpRevision is true, the charm must be a local directory, // and the revision number will be incremented before pushing. func (conn *Conn) PutCharm(curl *charm.URL, repo charm.Repository, bumpRevision bool) (*state.Charm, error) { if curl.Revision == -1 { rev, err := charm.Latest(repo, curl) if err != nil { return nil, fmt.Errorf("cannot get latest charm revision: %v", err) } curl = curl.WithRevision(rev) } ch, err := repo.Get(curl) if err != nil { return nil, fmt.Errorf("cannot get charm: %v", err) } if bumpRevision { chd, ok := ch.(*charm.Dir) if !ok { return nil, fmt.Errorf("cannot increment revision of charm %q: not a directory", curl) } if err = chd.SetDiskRevision(chd.Revision() + 1); err != nil { return nil, fmt.Errorf("cannot increment revision of charm %q: %v", curl, err) } curl = curl.WithRevision(chd.Revision()) } if sch, err := conn.State.Charm(curl); err == nil { return sch, nil } return conn.addCharm(curl, ch) }
func (s *StoreSuite) TestError(c *gc.C) { charmURL := charm.MustParseURL("cs:series/borken") expect := `charm info errors for "cs:series/borken": badness` _, err := charm.Latest(s.store, charmURL) c.Assert(err, gc.ErrorMatches, expect) _, err = s.store.Get(charmURL) c.Assert(err, gc.ErrorMatches, expect) }
func (s *StoreSuite) TestMissing(c *gc.C) { charmURL := charm.MustParseURL("cs:series/missing") expect := `charm not found: cs:series/missing` _, err := charm.Latest(s.store, charmURL) c.Assert(err, gc.ErrorMatches, expect) _, err = s.store.Get(charmURL) c.Assert(err, gc.ErrorMatches, expect) }
func (s *LocalRepoSuite) TestBundle(c *gc.C) { charmURL := charm.MustParseURL("local:quantal/dummy") s.addBundle("dummy") rev, err := charm.Latest(s.repo, charmURL) c.Assert(err, gc.IsNil) c.Assert(rev, gc.Equals, 1) ch, err := s.repo.Get(charmURL) c.Assert(err, gc.IsNil) c.Assert(ch.Revision(), gc.Equals, 1) }
func (s *StoreSuite) TestWarning(c *gc.C) { charmURL := charm.MustParseURL("cs:series/unwise") expect := `.* WARNING juju.charm charm store reports for "cs:series/unwise": foolishness` + "\n" r, err := charm.Latest(s.store, charmURL) c.Assert(r, gc.Equals, 23) c.Assert(err, gc.IsNil) c.Assert(c.GetTestLog(), gc.Matches, expect) ch, err := s.store.Get(charmURL) c.Assert(ch, gc.NotNil) c.Assert(err, gc.IsNil) c.Assert(c.GetTestLog(), gc.Matches, expect+expect) }
func (s *LocalRepoSuite) TestMissingCharm(c *gc.C) { for i, str := range []string{ "local:quantal/zebra", "local:badseries/zebra", } { c.Logf("test %d: %s", i, str) charmURL := charm.MustParseURL(str) _, err := charm.Latest(s.repo, charmURL) s.checkNotFoundErr(c, err, charmURL) _, err = s.repo.Get(charmURL) s.checkNotFoundErr(c, err, charmURL) } }
func (s *LocalRepoSuite) TestIgnoresUnpromisingNames(c *gc.C) { err := ioutil.WriteFile(filepath.Join(s.seriesPath, "blah.notacharm"), nil, 0666) c.Assert(err, gc.IsNil) err = os.Mkdir(filepath.Join(s.seriesPath, ".blah"), 0666) c.Assert(err, gc.IsNil) renameSibling(c, s.addDir("dummy"), ".dummy") renameSibling(c, s.addBundle("dummy"), "dummy.notacharm") charmURL := charm.MustParseURL("local:quantal/dummy") _, err = s.repo.Get(charmURL) s.checkNotFoundErr(c, err, charmURL) _, err = charm.Latest(s.repo, charmURL) s.checkNotFoundErr(c, err, charmURL) c.Assert(c.GetTestLog(), gc.Equals, "") }
// Run connects to the specified environment and starts the charm // upgrade process. func (c *UpgradeCharmCommand) Run(ctx *cmd.Context) error { client, err := juju.NewAPIClientFromName(c.EnvName) if err != nil { return err } defer client.Close() oldURL, err := client.ServiceGetCharmURL(c.ServiceName) if err != nil { return err } attrs, err := client.EnvironmentGet() if err != nil { return err } conf, err := config.New(config.NoDefaults, attrs) if err != nil { return err } var newURL *charm.URL if c.SwitchURL != "" { newURL, err = resolveCharmURL(c.SwitchURL, client, conf) if err != nil { return err } } else { // No new URL specified, but revision might have been. newURL = oldURL.WithRevision(c.Revision) } repo, err := charm.InferRepository(newURL.Reference, ctx.AbsPath(c.RepoPath)) if err != nil { return err } repo = config.SpecializeCharmRepo(repo, conf) // If no explicit revision was set with either SwitchURL // or Revision flags, discover the latest. explicitRevision := true if newURL.Revision == -1 { explicitRevision = false latest, err := charm.Latest(repo, newURL) if err != nil { return err } newURL = newURL.WithRevision(latest) } if *newURL == *oldURL { if explicitRevision { return fmt.Errorf("already running specified charm %q", newURL) } else if newURL.Schema == "cs" { // No point in trying to upgrade a charm store charm when // we just determined that's the latest revision // available. return fmt.Errorf("already running latest charm %q", newURL) } } addedURL, err := addCharmViaAPI(client, ctx, newURL, repo) if err != nil { return err } return client.ServiceSetCharm(c.ServiceName, addedURL.String(), c.Force) }