func (s *GitDeployerSuite) TestInstall(c *gc.C) { // Prepare. info := s.bundles.AddCustomBundle(c, corecharm.MustParseURL("cs:s/c-1"), func(path string) { err := ioutil.WriteFile(filepath.Join(path, "some-file"), []byte("hello"), 0644) c.Assert(err, jc.ErrorIsNil) }) err := s.deployer.Stage(info, nil) c.Assert(err, jc.ErrorIsNil) checkCleanup(c, s.deployer) // Install. err = s.deployer.Deploy() c.Assert(err, jc.ErrorIsNil) checkCleanup(c, s.deployer) // Check content. data, err := ioutil.ReadFile(filepath.Join(s.targetPath, "some-file")) c.Assert(err, jc.ErrorIsNil) c.Assert(string(data), gc.Equals, "hello") target := charm.NewGitDir(s.targetPath) url, err := target.ReadCharmURL() c.Assert(err, jc.ErrorIsNil) c.Assert(url, gc.DeepEquals, corecharm.MustParseURL("cs:s/c-1")) lines, err := target.Log() c.Assert(err, jc.ErrorIsNil) c.Assert(lines, gc.HasLen, 2) c.Assert(lines[0], gc.Matches, `[0-9a-f]{7} Deployed charm "cs:s/c-1"\.`) c.Assert(lines[1], gc.Matches, `[0-9a-f]{7} Imported charm "cs:s/c-1"\.`) }
// TestAvailability tests that the charmdir resource is properly checked. func (s *ManifoldSuite) TestAvailability(c *gc.C) { recorder := &dummyRecorder{ charmURL: "cs:wordpress-37", unitTag: "wp/0", isDeclaredMetric: true, } s.PatchValue(collect.NewRecorder, func(_ names.UnitTag, _ context.Paths, _ spool.MetricFactory) (spool.MetricRecorder, error) { return recorder, nil }) s.PatchValue(collect.ReadCharm, func(_ names.UnitTag, _ context.Paths) (*corecharm.URL, map[string]corecharm.Metric, error) { return corecharm.MustParseURL("cs:wordpress-37"), map[string]corecharm.Metric{"pings": corecharm.Metric{Description: "test metric", Type: corecharm.MetricTypeAbsolute}}, nil }) charmdir := &dummyCharmdir{aborted: true} s.resources["charmdir-name"] = dt.StubResource{Output: charmdir} collectEntity, err := collect.NewCollect(s.manifoldConfig, s.resources.Context()) c.Assert(err, jc.ErrorIsNil) err = collectEntity.Do(nil) c.Assert(err, jc.ErrorIsNil) c.Assert(recorder.batches, gc.HasLen, 0) charmdir = &dummyCharmdir{aborted: false} s.resources["charmdir-name"] = dt.StubResource{Output: charmdir} collectEntity, err = collect.NewCollect(s.manifoldConfig, s.resources.Context()) c.Assert(err, jc.ErrorIsNil) err = collectEntity.Do(nil) c.Assert(err, jc.ErrorIsNil) c.Assert(recorder.closed, jc.IsTrue) c.Assert(recorder.batches, gc.HasLen, 1) }
func (s *BundlesDirSuite) AddCharm(c *gc.C) (charm.BundleInfo, *state.Charm, []byte) { curl := corecharm.MustParseURL("cs:quantal/dummy-1") storagePath := "dummy-1" bunpath := testcharms.Repo.CharmArchivePath(c.MkDir(), "dummy") bun, err := corecharm.ReadCharmArchive(bunpath) c.Assert(err, jc.ErrorIsNil) bundata, hash := readHash(c, bunpath) info := state.CharmInfo{ Charm: bun, ID: curl, StoragePath: storagePath, SHA256: hash, } sch, err := s.State.AddCharm(info) c.Assert(err, jc.ErrorIsNil) apiCharm, err := s.uniter.Charm(sch.URL()) c.Assert(err, jc.ErrorIsNil) surlBad, err := url.Parse(s.URL("/some/charm.bundle?bad")) c.Assert(err, jc.ErrorIsNil) surlGood, err := url.Parse(s.URL("/some/charm.bundle?good")) c.Assert(err, jc.ErrorIsNil) mock := &mockArchiveURLCharm{ apiCharm, []*url.URL{surlBad, surlGood}, } return mock, sch, bundata }
// TestJujuUnitsBuiltinMetric tests that the juju-units built-in metric is collected // with a mock implementation of newRecorder. func (s *ManifoldSuite) TestJujuUnitsBuiltinMetric(c *gc.C) { recorder := &dummyRecorder{ charmURL: "cs:wordpress-37", unitTag: "wp/0", isDeclaredMetric: true, } s.PatchValue(collect.NewRecorder, func(_ names.UnitTag, _ context.Paths, _ spool.MetricFactory) (spool.MetricRecorder, error) { return recorder, nil }) s.PatchValue(collect.ReadCharm, func(_ names.UnitTag, _ context.Paths) (*corecharm.URL, map[string]corecharm.Metric, error) { return corecharm.MustParseURL("cs:wordpress-37"), map[string]corecharm.Metric{"pings": corecharm.Metric{Description: "test metric", Type: corecharm.MetricTypeAbsolute}}, nil }) collectEntity, err := collect.NewCollect(s.manifoldConfig, s.resources.Context()) c.Assert(err, jc.ErrorIsNil) err = collectEntity.Do(nil) c.Assert(err, jc.ErrorIsNil) c.Assert(recorder.closed, jc.IsTrue) c.Assert(recorder.batches, gc.HasLen, 1) c.Assert(recorder.batches[0].CharmURL, gc.Equals, "cs:wordpress-37") c.Assert(recorder.batches[0].UnitTag, gc.Equals, "wp/0") c.Assert(recorder.batches[0].Metrics, gc.HasLen, 1) c.Assert(recorder.batches[0].Metrics[0].Key, gc.Equals, "juju-units") c.Assert(recorder.batches[0].Metrics[0].Value, gc.Equals, "1") }
func (s *GitDeployerSuite) TestUpgrade(c *gc.C) { // Install. info1 := s.bundles.AddCustomBundle(c, corecharm.MustParseURL("cs:s/c-1"), func(path string) { err := ioutil.WriteFile(filepath.Join(path, "some-file"), []byte("hello"), 0644) c.Assert(err, jc.ErrorIsNil) err = symlink.New("./some-file", filepath.Join(path, "a-symlink")) c.Assert(err, jc.ErrorIsNil) }) err := s.deployer.Stage(info1, nil) c.Assert(err, jc.ErrorIsNil) err = s.deployer.Deploy() c.Assert(err, jc.ErrorIsNil) // Upgrade. info2 := s.bundles.AddCustomBundle(c, corecharm.MustParseURL("cs:s/c-2"), func(path string) { err := ioutil.WriteFile(filepath.Join(path, "some-file"), []byte("goodbye"), 0644) c.Assert(err, jc.ErrorIsNil) err = ioutil.WriteFile(filepath.Join(path, "a-symlink"), []byte("not any more!"), 0644) c.Assert(err, jc.ErrorIsNil) }) err = s.deployer.Stage(info2, nil) c.Assert(err, jc.ErrorIsNil) checkCleanup(c, s.deployer) err = s.deployer.Deploy() c.Assert(err, jc.ErrorIsNil) checkCleanup(c, s.deployer) // Check content. data, err := ioutil.ReadFile(filepath.Join(s.targetPath, "some-file")) c.Assert(err, jc.ErrorIsNil) c.Assert(string(data), gc.Equals, "goodbye") data, err = ioutil.ReadFile(filepath.Join(s.targetPath, "a-symlink")) c.Assert(err, jc.ErrorIsNil) c.Assert(string(data), gc.Equals, "not any more!") target := charm.NewGitDir(s.targetPath) url, err := target.ReadCharmURL() c.Assert(err, jc.ErrorIsNil) c.Assert(url, gc.DeepEquals, corecharm.MustParseURL("cs:s/c-2")) lines, err := target.Log() c.Assert(err, jc.ErrorIsNil) c.Assert(lines, gc.HasLen, 5) c.Assert(lines[0], gc.Matches, `[0-9a-f]{7} Upgraded charm to "cs:s/c-2".`) }
func (s *BundlesDirSuite) AddCharm(c *gc.C) (charm.BundleInfo, *state.Charm) { curl := corecharm.MustParseURL("cs:quantal/dummy-1") bun := testcharms.Repo.CharmDir("dummy") sch, err := testing.AddCharm(s.State, curl, bun) c.Assert(err, jc.ErrorIsNil) apiCharm, err := s.uniter.Charm(sch.URL()) c.Assert(err, jc.ErrorIsNil) return apiCharm, sch }
func (s *BundlesDirSuite) TestGet(c *gc.C) { basedir := c.MkDir() bunsDir := filepath.Join(basedir, "random", "bundles") downloader := api.NewCharmDownloader(s.st.Client()) d := charm.NewBundlesDir(bunsDir, downloader) checkDownloadsEmpty := func() { files, err := ioutil.ReadDir(filepath.Join(bunsDir, "downloads")) c.Assert(err, jc.ErrorIsNil) c.Check(files, gc.HasLen, 0) } // Check it doesn't get created until it's needed. _, err := os.Stat(bunsDir) c.Assert(err, jc.Satisfies, os.IsNotExist) // Add a charm to state that we can try to get. apiCharm, sch := s.AddCharm(c) // Try to get the charm when the content doesn't match. _, err = d.Read(&fakeBundleInfo{apiCharm, nil, "..."}, nil) c.Check(err, gc.ErrorMatches, regexp.QuoteMeta(`failed to download charm "cs:quantal/dummy-1" from API server: `)+`expected sha256 "...", got ".*"`) checkDownloadsEmpty() // Try to get a charm whose bundle doesn't exist. otherURL := corecharm.MustParseURL("cs:quantal/spam-1") _, err = d.Read(&fakeBundleInfo{apiCharm, otherURL, ""}, nil) c.Check(err, gc.ErrorMatches, regexp.QuoteMeta(`failed to download charm "cs:quantal/spam-1" from API server: `)+`.* not found`) checkDownloadsEmpty() // Get a charm whose bundle exists and whose content matches. ch, err := d.Read(apiCharm, nil) c.Assert(err, jc.ErrorIsNil) assertCharm(c, ch, sch) checkDownloadsEmpty() // Get the same charm again, without preparing a response from the server. ch, err = d.Read(apiCharm, nil) c.Assert(err, jc.ErrorIsNil) assertCharm(c, ch, sch) checkDownloadsEmpty() // Check the abort chan is honoured. err = os.RemoveAll(bunsDir) c.Assert(err, jc.ErrorIsNil) abort := make(chan struct{}) close(abort) ch, err = d.Read(apiCharm, abort) c.Check(ch, gc.IsNil) c.Check(err, gc.ErrorMatches, regexp.QuoteMeta(`failed to download charm "cs:quantal/dummy-1" from API server: download aborted`)) checkDownloadsEmpty() }
func (s *BundlesDirSuite) TestGet(c *gc.C) { basedir := c.MkDir() bunsdir := filepath.Join(basedir, "random", "bundles") downloader := api.NewCharmDownloader(s.st.Client()) d := charm.NewBundlesDir(bunsdir, downloader) // Check it doesn't get created until it's needed. _, err := os.Stat(bunsdir) c.Assert(err, jc.Satisfies, os.IsNotExist) // Add a charm to state that we can try to get. apiCharm, sch := s.AddCharm(c) // Try to get the charm when the content doesn't match. _, err = d.Read(&fakeBundleInfo{apiCharm, nil, "..."}, nil) c.Assert(err, gc.ErrorMatches, regexp.QuoteMeta(`failed to download charm "cs:quantal/dummy-1" from API server: `)+`expected sha256 "...", got ".*"`) // Try to get a charm whose bundle doesn't exist. otherURL := corecharm.MustParseURL("cs:quantal/spam-1") _, err = d.Read(&fakeBundleInfo{apiCharm, otherURL, ""}, nil) c.Assert(err, gc.ErrorMatches, regexp.QuoteMeta(`failed to download charm "cs:quantal/spam-1" from API server: `)+`.* not found`) // Get a charm whose bundle exists and whose content matches. ch, err := d.Read(apiCharm, nil) c.Assert(err, jc.ErrorIsNil) assertCharm(c, ch, sch) // Get the same charm again, without preparing a response from the server. ch, err = d.Read(apiCharm, nil) c.Assert(err, jc.ErrorIsNil) assertCharm(c, ch, sch) // Abort a download. err = os.RemoveAll(bunsdir) c.Assert(err, jc.ErrorIsNil) abort := make(chan struct{}) done := make(chan bool) go func() { ch, err := d.Read(apiCharm, abort) c.Assert(ch, gc.IsNil) c.Assert(err, gc.ErrorMatches, regexp.QuoteMeta(`failed to download charm "cs:quantal/dummy-1" from API server: aborted`)) close(done) }() close(abort) gitjujutesting.Server.Response(500, nil, nil) select { case <-done: case <-time.After(coretesting.LongWait): c.Fatalf("timed out waiting for abort") } }
func (s *NewExecutorSuite) TestNewExecutorNoFile(c *gc.C) { charmURL := corecharm.MustParseURL("cs:quantal/nyancat-323") getInstallCharm := func() (*corecharm.URL, error) { return charmURL, nil } executor, err := operation.NewExecutor(s.path("missing"), getInstallCharm, failAcquireLock) c.Assert(err, jc.ErrorIsNil) c.Assert(executor.State(), gc.DeepEquals, operation.State{ Kind: operation.Install, Step: operation.Queued, CharmURL: charmURL, }) ft.Removed{"missing"}.Check(c, s.basePath) }
// TestNoMetricsDeclared tests that if metrics are not declared, none are // collected, not even builtin. func (s *ManifoldSuite) TestNoMetricsDeclared(c *gc.C) { recorder := &dummyRecorder{ charmURL: "cs:wordpress-37", unitTag: "wp/0", isDeclaredMetric: false, } s.PatchValue(collect.NewRecorder, func(_ names.UnitTag, _ context.Paths, _ spool.MetricFactory) (spool.MetricRecorder, error) { return recorder, nil }) s.PatchValue(collect.ReadCharm, func(_ names.UnitTag, _ context.Paths) (*corecharm.URL, map[string]corecharm.Metric, error) { return corecharm.MustParseURL("cs:wordpress-37"), map[string]corecharm.Metric{}, nil }) collectEntity, err := collect.NewCollect(s.manifoldConfig, s.resources.Context()) c.Assert(err, jc.ErrorIsNil) err = collectEntity.Do(nil) c.Assert(err, jc.ErrorIsNil) c.Assert(recorder.closed, jc.IsTrue) c.Assert(recorder.batches, gc.HasLen, 0) }
// TestCollectWorkerStarts ensures that the manifold correctly sets up the worker. func (s *ManifoldSuite) TestCollectWorkerStarts(c *gc.C) { s.PatchValue(collect.NewRecorder, func(_ names.UnitTag, _ context.Paths, _ spool.MetricFactory) (spool.MetricRecorder, error) { // Return a dummyRecorder here, because otherwise a real one // *might* get instantiated and error out, if the periodic worker // happens to fire before the worker shuts down (as seen in // LP:#1497355). return &dummyRecorder{ charmURL: "cs:ubuntu-1", unitTag: "ubuntu/0", }, nil }) s.PatchValue(collect.ReadCharm, func(_ names.UnitTag, _ context.Paths) (*corecharm.URL, map[string]corecharm.Metric, error) { return corecharm.MustParseURL("cs:ubuntu-1"), map[string]corecharm.Metric{"pings": corecharm.Metric{Description: "test metric", Type: corecharm.MetricTypeAbsolute}}, nil }) worker, err := s.manifold.Start(s.resources.Context()) c.Assert(err, jc.ErrorIsNil) c.Assert(worker, gc.NotNil) worker.Kill() err = worker.Wait() c.Assert(err, jc.ErrorIsNil) }
func (s *FactorySuite) testNewDeployString(c *gc.C, newDeploy newDeploy, expectPrefix string) { op, err := newDeploy(s.factory, corecharm.MustParseURL("cs:quantal/wordpress-1")) c.Check(err, jc.ErrorIsNil) c.Check(op.String(), gc.Equals, expectPrefix+" cs:quantal/wordpress-1") }
func (s *GitDeployerSuite) TestConflictRevertResolve(c *gc.C) { // Install. info1 := s.bundles.AddCustomBundle(c, corecharm.MustParseURL("cs:s/c-1"), func(path string) { err := ioutil.WriteFile(filepath.Join(path, "some-file"), []byte("hello"), 0644) c.Assert(err, jc.ErrorIsNil) }) err := s.deployer.Stage(info1, nil) c.Assert(err, jc.ErrorIsNil) err = s.deployer.Deploy() c.Assert(err, jc.ErrorIsNil) // Mess up target. err = ioutil.WriteFile(filepath.Join(s.targetPath, "some-file"), []byte("mu!"), 0644) c.Assert(err, jc.ErrorIsNil) // Upgrade. info2 := s.bundles.AddCustomBundle(c, corecharm.MustParseURL("cs:s/c-2"), func(path string) { err := ioutil.WriteFile(filepath.Join(path, "some-file"), []byte("goodbye"), 0644) c.Assert(err, jc.ErrorIsNil) }) err = s.deployer.Stage(info2, nil) c.Assert(err, jc.ErrorIsNil) err = s.deployer.Deploy() c.Assert(err, gc.Equals, charm.ErrConflict) checkCleanup(c, s.deployer) // Check state. target := charm.NewGitDir(s.targetPath) conflicted, err := target.Conflicted() c.Assert(err, jc.ErrorIsNil) c.Assert(conflicted, jc.IsTrue) // Revert and check initial content. err = s.deployer.NotifyRevert() c.Assert(err, jc.ErrorIsNil) data, err := ioutil.ReadFile(filepath.Join(s.targetPath, "some-file")) c.Assert(err, jc.ErrorIsNil) c.Assert(string(data), gc.Equals, "mu!") conflicted, err = target.Conflicted() c.Assert(err, jc.ErrorIsNil) c.Assert(conflicted, jc.IsFalse) // Try to upgrade again. err = s.deployer.Deploy() c.Assert(err, gc.Equals, charm.ErrConflict) conflicted, err = target.Conflicted() c.Assert(err, jc.ErrorIsNil) c.Assert(conflicted, jc.IsTrue) checkCleanup(c, s.deployer) // And again. err = s.deployer.Deploy() c.Assert(err, gc.Equals, charm.ErrConflict) conflicted, err = target.Conflicted() c.Assert(err, jc.ErrorIsNil) c.Assert(conflicted, jc.IsTrue) checkCleanup(c, s.deployer) // Manually resolve, and commit. err = ioutil.WriteFile(filepath.Join(target.Path(), "some-file"), []byte("nu!"), 0644) c.Assert(err, jc.ErrorIsNil) err = s.deployer.NotifyResolved() c.Assert(err, jc.ErrorIsNil) conflicted, err = target.Conflicted() c.Assert(err, jc.ErrorIsNil) c.Assert(conflicted, jc.IsFalse) // Try a final upgrade to the same charm and check it doesn't write anything // except the upgrade log line. err = s.deployer.Deploy() c.Assert(err, jc.ErrorIsNil) checkCleanup(c, s.deployer) data, err = ioutil.ReadFile(filepath.Join(target.Path(), "some-file")) c.Assert(err, jc.ErrorIsNil) c.Assert(string(data), gc.Equals, "nu!") conflicted, err = target.Conflicted() c.Assert(err, jc.ErrorIsNil) c.Assert(conflicted, jc.IsFalse) lines, err := target.Log() c.Assert(err, jc.ErrorIsNil) c.Assert(lines[0], gc.Matches, `[0-9a-f]{7} Upgraded charm to "cs:s/c-2".`) }
import ( "io/ioutil" "os" "os/exec" "path/filepath" jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" corecharm "gopkg.in/juju/charm.v6-unstable" "github.com/juju/juju/testing" "github.com/juju/juju/worker/uniter/charm" ) var curl = corecharm.MustParseURL("cs:series/blah-blah-123") type GitDirSuite struct { testing.GitSuite } var _ = gc.Suite(&GitDirSuite{}) func (s *GitDirSuite) TestInitConfig(c *gc.C) { base := c.MkDir() repo := charm.NewGitDir(filepath.Join(base, "repo")) err := repo.Init() c.Assert(err, jc.ErrorIsNil) cmd := exec.Command("git", "config", "--list", "--local") cmd.Dir = repo.Path()
func (s *handlerSuite) SetUpTest(c *gc.C) { s.BaseSuite.SetUpTest(c) s.manifoldConfig = collect.ManifoldConfig{ AgentName: "agent-name", MetricSpoolName: "metric-spool-name", CharmDirName: "charmdir-name", } s.manifold = collect.Manifold(s.manifoldConfig) s.dataDir = c.MkDir() // create unit agent base dir so that hooks can run. err := os.MkdirAll(filepath.Join(s.dataDir, "agents", "unit-u-0"), 0777) c.Assert(err, jc.ErrorIsNil) s.recorder = &dummyRecorder{ charmURL: "local:trusty/metered-1", unitTag: "metered/0", metrics: map[string]corecharm.Metric{ "pings": corecharm.Metric{ Description: "test metric", Type: corecharm.MetricTypeAbsolute, }, "juju-units": corecharm.Metric{}, }, } s.resources = dt.StubResources{ "agent-name": dt.StubResource{Output: &dummyAgent{dataDir: s.dataDir}}, "metric-spool-name": dt.StubResource{Output: &mockMetricFactory{recorder: s.recorder}}, "charmdir-name": dt.StubResource{Output: &dummyCharmdir{aborted: false}}, } s.PatchValue(collect.NewRecorder, func(_ names.UnitTag, _ context.Paths, _ spool.MetricFactory) (spool.MetricRecorder, error) { // Return a dummyRecorder here, because otherwise a real one // *might* get instantiated and error out, if the periodic worker // happens to fire before the worker shuts down (as seen in // LP:#1497355). return &dummyRecorder{ charmURL: "local:trusty/metered-1", unitTag: "metered/0", metrics: map[string]corecharm.Metric{ "pings": corecharm.Metric{ Description: "test metric", Type: corecharm.MetricTypeAbsolute, }, "juju-units": corecharm.Metric{}, }, }, nil }, ) s.PatchValue(collect.ReadCharm, func(_ names.UnitTag, _ context.Paths) (*corecharm.URL, map[string]corecharm.Metric, error) { return corecharm.MustParseURL("local:trusty/metered-1"), map[string]corecharm.Metric{ "pings": corecharm.Metric{Description: "test metric", Type: corecharm.MetricTypeAbsolute}, "juju-units": corecharm.Metric{}, }, nil }, ) s.listener = &mockListener{} s.PatchValue(collect.NewSocketListener, collect.NewSocketListenerFnc(s.listener)) }
func curl(revision int) *corecharm.URL { return corecharm.MustParseURL("cs:quantal/wordpress").WithRevision(revision) }
func charmURL(revision int) *corecharm.URL { baseURL := corecharm.MustParseURL("cs:s/c") return baseURL.WithRevision(revision) }