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 startUniter) step(c *gc.C, ctx *context) { if s.unitTag == "" { s.unitTag = "unit-u-0" } if ctx.uniter != nil { panic("don't start two uniters!") } if ctx.api == nil { panic("API connection not established") } tag, err := names.ParseUnitTag(s.unitTag) if err != nil { panic(err.Error()) } downloader := api.NewCharmDownloader(ctx.apiConn.Client()) locksDir := filepath.Join(ctx.dataDir, "locks") lock, err := fslock.NewLock(locksDir, "uniter-hook-execution", fslock.Defaults()) c.Assert(err, jc.ErrorIsNil) operationExecutor := operation.NewExecutor if s.newExecutorFunc != nil { operationExecutor = s.newExecutorFunc } uniterParams := uniter.UniterParams{ UniterFacade: ctx.api, UnitTag: tag, LeadershipTracker: ctx.leaderTracker, CharmDirGuard: ctx.charmDirGuard, DataDir: ctx.dataDir, Downloader: downloader, MachineLock: lock, UpdateStatusSignal: ctx.updateStatusHookTicker.ReturnTimer, NewOperationExecutor: operationExecutor, Observer: ctx, // TODO(axw) 2015-11-02 #1512191 // update tests that rely on timing to advance clock // appropriately. Clock: clock.WallClock, } ctx.uniter, err = uniter.NewUniter(&uniterParams) c.Assert(err, jc.ErrorIsNil) }
// Manifold returns a dependency manifold that runs a uniter worker, // using the resource names defined in the supplied config. func Manifold(config ManifoldConfig) dependency.Manifold { return dependency.Manifold{ Inputs: []string{ config.AgentName, config.APICallerName, config.LeadershipTrackerName, config.MachineLockName, config.CharmDirName, config.HookRetryStrategyName, }, Start: func(context dependency.Context) (worker.Worker, error) { // Collect all required resources. var agent agent.Agent if err := context.Get(config.AgentName, &agent); err != nil { return nil, err } var apiConn api.Connection if err := context.Get(config.APICallerName, &apiConn); err != nil { // TODO(fwereade): absence of an APICaller shouldn't be the end of // the world -- we ought to return a type that can at least run the // leader-deposed hook -- but that's not done yet. return nil, err } var machineLock *fslock.Lock if err := context.Get(config.MachineLockName, &machineLock); err != nil { return nil, err } var leadershipTracker leadership.Tracker if err := context.Get(config.LeadershipTrackerName, &leadershipTracker); err != nil { return nil, err } var charmDirGuard fortress.Guard if err := context.Get(config.CharmDirName, &charmDirGuard); err != nil { return nil, err } var hookRetryStrategy params.RetryStrategy if err := context.Get(config.HookRetryStrategyName, &hookRetryStrategy); err != nil { return nil, err } downloader := api.NewCharmDownloader(apiConn.Client()) // Configure and start the uniter. config := agent.CurrentConfig() tag := config.Tag() unitTag, ok := tag.(names.UnitTag) if !ok { return nil, errors.Errorf("expected a unit tag, got %v", tag) } uniterFacade := uniter.NewState(apiConn, unitTag) uniter, err := NewUniter(&UniterParams{ UniterFacade: uniterFacade, UnitTag: unitTag, LeadershipTracker: leadershipTracker, DataDir: config.DataDir(), Downloader: downloader, MachineLock: machineLock, CharmDirGuard: charmDirGuard, UpdateStatusSignal: NewUpdateStatusTimer(), HookRetryStrategy: hookRetryStrategy, NewOperationExecutor: operation.NewExecutor, Clock: clock.WallClock, }) if err != nil { return nil, errors.Trace(err) } return uniter, nil }, } }