Esempio n. 1
0
func (s *ConverterSuite) TestNewDeployerCreatesGitDeployerOnceStaged(c *gc.C) {
	gitDeployer := charm.NewGitDeployer(s.targetPath, s.dataPath, s.bundles)
	info := s.bundles.AddBundle(c, charmURL(1), mockBundle{})
	err := gitDeployer.Stage(info, nil)
	c.Assert(err, gc.IsNil)

	deployer, err := charm.NewDeployer(s.targetPath, s.dataPath, s.bundles)
	c.Assert(err, gc.IsNil)
	c.Assert(deployer, jc.Satisfies, charm.IsGitDeployer)
}
Esempio n. 2
0
func (s *ConverterSuite) TestConvertGitDeployerBeforeDeploy(c *gc.C) {
	gitDeployer := charm.NewGitDeployer(s.targetPath, s.dataPath, s.bundles)
	info := s.bundles.AddBundle(c, charmURL(1), mockBundle{})
	err := gitDeployer.Stage(info, nil)
	c.Assert(err, gc.IsNil)

	deployer, err := charm.NewDeployer(s.targetPath, s.dataPath, s.bundles)
	c.Assert(err, gc.IsNil)
	err = charm.FixDeployer(&deployer)
	c.Assert(err, gc.IsNil)
	c.Assert(deployer, jc.Satisfies, charm.IsManifestDeployer)
	ft.Removed{"current"}.Check(c, s.dataPath)

	err = deployer.Stage(info, nil)
	c.Assert(err, gc.IsNil)
	err = deployer.Deploy()
	c.Assert(err, gc.IsNil)
	ft.Removed{".git"}.Check(c, s.targetPath)
}
Esempio n. 3
0
func (s *ConverterSuite) TestPathological(c *gc.C) {
	initial := s.bundles.AddCustomBundle(c, charmURL(1), func(path string) {
		ft.File{"common", "initial", 0644}.Create(c, path)
		ft.File{"initial", "blah", 0644}.Create(c, path)
	})
	staged := s.bundles.AddCustomBundle(c, charmURL(2), func(path string) {
		ft.File{"common", "staged", 0644}.Create(c, path)
		ft.File{"user", "badwrong", 0644}.Create(c, path)
	})
	final := s.bundles.AddCustomBundle(c, charmURL(3), func(path string) {
		ft.File{"common", "final", 0644}.Create(c, path)
		ft.File{"final", "blah", 0644}.Create(c, path)
	})

	gitDeployer := charm.NewGitDeployer(s.targetPath, s.dataPath, s.bundles)
	err := gitDeployer.Stage(initial, nil)
	c.Assert(err, gc.IsNil)
	err = gitDeployer.Deploy()
	c.Assert(err, gc.IsNil)

	preserveUser := ft.File{"user", "preserve", 0644}.Create(c, s.targetPath)
	err = gitDeployer.Stage(staged, nil)
	c.Assert(err, gc.IsNil)

	deployer, err := charm.NewDeployer(s.targetPath, s.dataPath, s.bundles)
	c.Assert(err, gc.IsNil)
	err = charm.FixDeployer(&deployer)
	c.Assert(err, gc.IsNil)

	err = deployer.Stage(final, nil)
	c.Assert(err, gc.IsNil)
	err = deployer.Deploy()
	c.Assert(err, gc.IsNil)
	ft.Removed{".git"}.Check(c, s.targetPath)
	ft.Removed{"initial"}.Check(c, s.targetPath)
	ft.Removed{"staged"}.Check(c, s.targetPath)
	ft.File{"common", "final", 0644}.Check(c, s.targetPath)
	preserveUser.Check(c, s.targetPath)
}
Esempio n. 4
0
func (u *Uniter) init(unitTag names.UnitTag) (err error) {
	u.unit, err = u.st.Unit(unitTag)
	if err != nil {
		return err
	}
	if u.unit.Life() == params.Dead {
		// If we started up already dead, we should not progress further. If we
		// become Dead immediately after starting up, we may well complete any
		// operations in progress before detecting it; but that race is fundamental
		// and inescapable, whereas this one is not.
		return worker.ErrTerminateAgent
	}
	if err = u.setupLocks(); err != nil {
		return err
	}
	if err := jujuc.EnsureSymlinks(u.paths.ToolsDir); err != nil {
		return err
	}
	if err := os.MkdirAll(u.paths.State.RelationsDir, 0755); err != nil {
		return errors.Trace(err)
	}
	relations, err := relation.NewRelations(
		u.st, unitTag, u.paths.State.CharmDir,
		u.paths.State.RelationsDir, u.catacomb.Dying(),
	)
	if err != nil {
		return errors.Annotatef(err, "cannot create relations")
	}
	u.relations = relations
	storageAttachments, err := storage.NewAttachments(
		u.st, unitTag, u.paths.State.StorageDir, u.catacomb.Dying(),
	)
	if err != nil {
		return errors.Annotatef(err, "cannot create storage hook source")
	}
	u.storage = storageAttachments
	u.commands = runcommands.NewCommands()
	u.commandChannel = make(chan string)

	deployer, err := charm.NewDeployer(
		u.paths.State.CharmDir,
		u.paths.State.DeployerDir,
		charm.NewBundlesDir(u.paths.State.BundlesDir, u.downloader),
	)
	if err != nil {
		return errors.Annotatef(err, "cannot create deployer")
	}
	u.deployer = &deployerProxy{deployer}
	contextFactory, err := context.NewContextFactory(
		u.st, unitTag, u.leadershipTracker, u.relations.GetInfo, u.storage, u.paths, u.clock,
	)
	if err != nil {
		return err
	}
	runnerFactory, err := runner.NewFactory(
		u.st, u.paths, contextFactory,
	)
	if err != nil {
		return errors.Trace(err)
	}
	u.operationFactory = operation.NewFactory(operation.FactoryParams{
		Deployer:       u.deployer,
		RunnerFactory:  runnerFactory,
		Callbacks:      &operationCallbacks{u},
		Abort:          u.catacomb.Dying(),
		MetricSpoolDir: u.paths.GetMetricsSpoolDir(),
	})

	operationExecutor, err := u.newOperationExecutor(u.paths.State.OperationsFile, u.getServiceCharmURL, u.acquireExecutionLock)
	if err != nil {
		return errors.Trace(err)
	}
	u.operationExecutor = operationExecutor

	logger.Debugf("starting juju-run listener on unix:%s", u.paths.Runtime.JujuRunSocket)
	commandRunner, err := NewChannelCommandRunner(ChannelCommandRunnerConfig{
		Abort:          u.catacomb.Dying(),
		Commands:       u.commands,
		CommandChannel: u.commandChannel,
	})
	if err != nil {
		return errors.Annotate(err, "creating command runner")
	}
	u.runListener, err = NewRunListener(RunListenerConfig{
		SocketPath:    u.paths.Runtime.JujuRunSocket,
		CommandRunner: commandRunner,
	})
	if err != nil {
		return errors.Trace(err)
	}
	rlw := newRunListenerWrapper(u.runListener)
	if err := u.catacomb.Add(rlw); err != nil {
		return errors.Trace(err)
	}
	// The socket needs to have permissions 777 in order for other users to use it.
	if jujuos.HostOS() != jujuos.Windows {
		return os.Chmod(u.paths.Runtime.JujuRunSocket, 0777)
	}
	return nil
}
Esempio n. 5
0
func (s *ConverterSuite) TestNewDeployerCreatesManifestDeployer(c *gc.C) {
	deployer, err := charm.NewDeployer(s.targetPath, s.dataPath, s.bundles)
	c.Assert(err, gc.IsNil)
	c.Assert(deployer, jc.Satisfies, charm.IsManifestDeployer)
}
Esempio n. 6
0
func (u *Uniter) init(unitTag names.UnitTag) (err error) {
	u.unit, err = u.st.Unit(unitTag)
	if err != nil {
		return err
	}
	if u.unit.Life() == params.Dead {
		// If we started up already dead, we should not progress further. If we
		// become Dead immediately after starting up, we may well complete any
		// operations in progress before detecting it; but that race is fundamental
		// and inescapable, whereas this one is not.
		return worker.ErrTerminateAgent
	}
	if err = u.setupLocks(); err != nil {
		return err
	}
	if err := jujuc.EnsureSymlinks(u.paths.ToolsDir); err != nil {
		return err
	}
	if err := os.MkdirAll(u.paths.State.RelationsDir, 0755); err != nil {
		return errors.Trace(err)
	}
	relations, err := newRelations(u.st, unitTag, u.paths, u.tomb.Dying())
	if err != nil {
		return errors.Annotatef(err, "cannot create relations")
	}
	u.relations = relations
	storageAttachments, err := storage.NewAttachments(
		u.st, unitTag, u.paths.State.StorageDir, u.tomb.Dying(),
	)
	if err != nil {
		return errors.Annotatef(err, "cannot create storage hook source")
	}
	u.storage = storageAttachments
	u.addCleanup(storageAttachments.Stop)

	deployer, err := charm.NewDeployer(
		u.paths.State.CharmDir,
		u.paths.State.DeployerDir,
		charm.NewBundlesDir(u.paths.State.BundlesDir),
	)
	if err != nil {
		return errors.Annotatef(err, "cannot create deployer")
	}
	u.deployer = &deployerProxy{deployer}
	contextFactory, err := runner.NewContextFactory(
		u.st, unitTag, u.leadershipTracker, u.relations.GetInfo, u.storage, u.paths,
	)
	if err != nil {
		return err
	}
	runnerFactory, err := runner.NewFactory(
		u.st, u.paths, contextFactory,
	)
	if err != nil {
		return err
	}
	u.operationFactory = operation.NewFactory(operation.FactoryParams{
		Deployer:       u.deployer,
		RunnerFactory:  runnerFactory,
		Callbacks:      &operationCallbacks{u},
		StorageUpdater: u.storage,
		Abort:          u.tomb.Dying(),
		MetricSender:   u.unit,
		MetricSpoolDir: u.paths.GetMetricsSpoolDir(),
	})

	operationExecutor, err := u.newOperationExecutor(u.paths.State.OperationsFile, u.getServiceCharmURL, u.acquireExecutionLock)
	if err != nil {
		return err
	}
	u.operationExecutor = operationExecutor

	logger.Debugf("starting juju-run listener on unix:%s", u.paths.Runtime.JujuRunSocket)
	u.runListener, err = NewRunListener(u, u.paths.Runtime.JujuRunSocket)
	if err != nil {
		return err
	}
	u.addCleanup(func() error {
		// TODO(fwereade): RunListener returns no error on Close. This seems wrong.
		u.runListener.Close()
		return nil
	})
	// The socket needs to have permissions 777 in order for other users to use it.
	if version.Current.OS != version.Windows {
		return os.Chmod(u.paths.Runtime.JujuRunSocket, 0777)
	}
	return nil
}
Esempio n. 7
0
func (u *Uniter) init(unitTag string) (err error) {
	tag, err := names.ParseUnitTag(unitTag)
	if err != nil {
		return err
	}
	u.unit, err = u.st.Unit(tag)
	if err != nil {
		return err
	}
	if u.unit.Life() == params.Dead {
		// If we started up already dead, we should not progress further. If we
		// become Dead immediately after starting up, we may well complete any
		// operations in progress before detecting it; but that race is fundamental
		// and inescapable, whereas this one is not.
		return worker.ErrTerminateAgent
	}
	if err = u.setupLocks(); err != nil {
		return err
	}
	u.toolsDir = tools.ToolsDir(u.dataDir, unitTag)
	if err := EnsureJujucSymlinks(u.toolsDir); err != nil {
		return err
	}
	u.baseDir = filepath.Join(u.dataDir, "agents", unitTag)
	u.relationsDir = filepath.Join(u.baseDir, "state", "relations")
	if err := os.MkdirAll(u.relationsDir, 0755); err != nil {
		return err
	}
	serviceTag, err := names.ParseServiceTag(u.unit.ServiceTag())
	if err != nil {
		return err
	}
	u.service, err = u.st.Service(serviceTag)
	if err != nil {
		return err
	}
	var env *uniter.Environment
	env, err = u.st.Environment()
	if err != nil {
		return err
	}
	u.uuid = env.UUID()
	u.envName = env.Name()

	u.relationers = map[int]*Relationer{}
	u.relationHooks = make(chan hook.Info)
	u.charmPath = filepath.Join(u.baseDir, "charm")
	deployerPath := filepath.Join(u.baseDir, "state", "deployer")
	bundles := charm.NewBundlesDir(filepath.Join(u.baseDir, "state", "bundles"))
	u.deployer, err = charm.NewDeployer(u.charmPath, deployerPath, bundles)
	if err != nil {
		return fmt.Errorf("cannot create deployer: %v", err)
	}
	u.sf = NewStateFile(filepath.Join(u.baseDir, "state", "uniter"))
	u.rand = rand.New(rand.NewSource(time.Now().Unix()))

	// If we start trying to listen for juju-run commands before we have valid
	// relation state, surprising things will come to pass.
	if err := u.restoreRelations(); err != nil {
		return err
	}
	runListenerSocketPath := filepath.Join(u.baseDir, RunListenerFile)
	logger.Debugf("starting juju-run listener on unix:%s", runListenerSocketPath)
	u.runListener, err = NewRunListener(u, runListenerSocketPath)
	if err != nil {
		return err
	}
	// The socket needs to have permissions 777 in order for other users to use it.
	return os.Chmod(runListenerSocketPath, 0777)
}
Esempio n. 8
0
func (u *Uniter) init(unitTag names.UnitTag) (err error) {
	u.unit, err = u.st.Unit(unitTag)
	if err != nil {
		return err
	}
	if u.unit.Life() == params.Dead {
		// If we started up already dead, we should not progress further. If we
		// become Dead immediately after starting up, we may well complete any
		// operations in progress before detecting it; but that race is fundamental
		// and inescapable, whereas this one is not.
		return worker.ErrTerminateAgent
	}
	// If initialising for the first time after deploying, update the status.
	currentStatus, err := u.unit.UnitStatus()
	if err != nil {
		return err
	}
	// TODO(fwereade/wallyworld): we should have an explicit place in the model
	// to tell us when we've hit this point, instead of piggybacking on top of
	// status and/or status history.
	// If the previous status was waiting for machine, we transition to the next step.
	if currentStatus.Status == string(status.Waiting) &&
		(currentStatus.Info == status.MessageWaitForMachine || currentStatus.Info == status.MessageInstallingAgent) {
		if err := u.unit.SetUnitStatus(status.Waiting, status.MessageInitializingAgent, nil); err != nil {
			return errors.Trace(err)
		}
	}
	if err := jujuc.EnsureSymlinks(u.paths.ToolsDir); err != nil {
		return err
	}
	if err := os.MkdirAll(u.paths.State.RelationsDir, 0755); err != nil {
		return errors.Trace(err)
	}
	relations, err := relation.NewRelations(
		u.st, unitTag, u.paths.State.CharmDir,
		u.paths.State.RelationsDir, u.catacomb.Dying(),
	)
	if err != nil {
		return errors.Annotatef(err, "cannot create relations")
	}
	u.relations = relations
	storageAttachments, err := storage.NewAttachments(
		u.st, unitTag, u.paths.State.StorageDir, u.catacomb.Dying(),
	)
	if err != nil {
		return errors.Annotatef(err, "cannot create storage hook source")
	}
	u.storage = storageAttachments
	u.commands = runcommands.NewCommands()
	u.commandChannel = make(chan string)

	deployer, err := charm.NewDeployer(
		u.paths.State.CharmDir,
		u.paths.State.DeployerDir,
		charm.NewBundlesDir(u.paths.State.BundlesDir, u.downloader),
	)
	if err != nil {
		return errors.Annotatef(err, "cannot create deployer")
	}
	contextFactory, err := context.NewContextFactory(
		u.st, unitTag, u.leadershipTracker, u.relations.GetInfo, u.storage, u.paths, u.clock,
	)
	if err != nil {
		return err
	}
	runnerFactory, err := runner.NewFactory(
		u.st, u.paths, contextFactory,
	)
	if err != nil {
		return errors.Trace(err)
	}
	u.operationFactory = operation.NewFactory(operation.FactoryParams{
		Deployer:       deployer,
		RunnerFactory:  runnerFactory,
		Callbacks:      &operationCallbacks{u},
		Abort:          u.catacomb.Dying(),
		MetricSpoolDir: u.paths.GetMetricsSpoolDir(),
	})

	operationExecutor, err := u.newOperationExecutor(u.paths.State.OperationsFile, u.getServiceCharmURL, u.acquireExecutionLock)
	if err != nil {
		return errors.Trace(err)
	}
	u.operationExecutor = operationExecutor

	logger.Debugf("starting juju-run listener on unix:%s", u.paths.Runtime.JujuRunSocket)
	commandRunner, err := NewChannelCommandRunner(ChannelCommandRunnerConfig{
		Abort:          u.catacomb.Dying(),
		Commands:       u.commands,
		CommandChannel: u.commandChannel,
	})
	if err != nil {
		return errors.Annotate(err, "creating command runner")
	}
	u.runListener, err = NewRunListener(RunListenerConfig{
		SocketPath:    u.paths.Runtime.JujuRunSocket,
		CommandRunner: commandRunner,
	})
	if err != nil {
		return errors.Trace(err)
	}
	rlw := newRunListenerWrapper(u.runListener)
	if err := u.catacomb.Add(rlw); err != nil {
		return errors.Trace(err)
	}
	// The socket needs to have permissions 777 in order for other users to use it.
	if jujuos.HostOS() != jujuos.Windows {
		return os.Chmod(u.paths.Runtime.JujuRunSocket, 0777)
	}
	return nil
}