예제 #1
0
func (s *DeployerSuite) TestInstall(c *C) {
	// Install.
	d := charm.NewDeployer(filepath.Join(c.MkDir(), "deployer"))
	bun := s.bundle(c, func(path string) {
		err := ioutil.WriteFile(filepath.Join(path, "some-file"), []byte("hello"), 0644)
		c.Assert(err, IsNil)
	})
	err := d.Stage(bun, corecharm.MustParseURL("cs:s/c-1"))
	c.Assert(err, IsNil)
	target := charm.NewGitDir(filepath.Join(c.MkDir(), "target"))
	err = d.Deploy(target)
	c.Assert(err, IsNil)

	// Check content.
	data, err := ioutil.ReadFile(filepath.Join(target.Path(), "some-file"))
	c.Assert(err, IsNil)
	c.Assert(string(data), Equals, "hello")
	url, err := charm.ReadCharmURL(target)
	c.Assert(err, IsNil)
	c.Assert(url, DeepEquals, corecharm.MustParseURL("cs:s/c-1"))
	lines, err := target.Log()
	c.Assert(err, IsNil)
	c.Assert(lines, HasLen, 2)
	c.Assert(lines[0], Matches, `[0-9a-f]{7} Deployed charm "cs:s/c-1".`)
	c.Assert(lines[1], Matches, `[0-9a-f]{7} Imported charm "cs:s/c-1" from ".*".`)
}
예제 #2
0
// ModeAbide is the Uniter's usual steady state. It watches for and responds to:
// * service configuration changes
// * charm upgrade requests
// * relation changes
// * unit death
func ModeAbide(u *Uniter) (next Mode, err error) {
	defer modeContext("ModeAbide", &err)()
	if u.s.Op != Continue {
		return nil, fmt.Errorf("insane uniter state: %#v", u.s)
	}
	if err = u.unit.SetStatus(state.UnitStarted, ""); err != nil {
		return nil, err
	}
	url, err := charm.ReadCharmURL(u.charm)
	if err != nil {
		return nil, err
	}
	u.f.WantUpgradeEvent(url, false)
	for _, r := range u.relationers {
		r.StartHooks()
	}
	defer func() {
		for _, r := range u.relationers {
			if e := r.StopHooks(); e != nil && err == nil {
				err = e
			}
		}
	}()
	select {
	case <-u.f.UnitDying():
		return modeAbideDyingLoop(u)
	default:
	}
	return modeAbideAliveLoop(u)
}
예제 #3
0
func (s *GitDirSuite) TestAddCommitPullRevert(c *C) {
	target := charm.NewGitDir(c.MkDir())
	err := target.Init()
	c.Assert(err, IsNil)
	err = ioutil.WriteFile(filepath.Join(target.Path(), "initial"), []byte("initial"), 0644)
	c.Assert(err, IsNil)
	err = charm.WriteCharmURL(target, curl)
	c.Assert(err, IsNil)
	err = target.AddAll()
	c.Assert(err, IsNil)
	dirty, err := target.Dirty()
	c.Assert(err, IsNil)
	c.Assert(dirty, Equals, true)
	err = target.Commitf("initial")
	c.Assert(err, IsNil)
	dirty, err = target.Dirty()
	c.Assert(err, IsNil)
	c.Assert(dirty, Equals, false)

	source := newRepo(c)
	err = target.Pull(source)
	c.Assert(err, IsNil)
	url, err := charm.ReadCharmURL(target)
	c.Assert(err, IsNil)
	c.Assert(url, DeepEquals, curl)
	fi, err := os.Stat(filepath.Join(target.Path(), "some-dir"))
	c.Assert(err, IsNil)
	c.Assert(fi, checkers.Satisfies, os.FileInfo.IsDir)
	data, err := ioutil.ReadFile(filepath.Join(target.Path(), "some-file"))
	c.Assert(err, IsNil)
	c.Assert(string(data), Equals, "hello")
	dirty, err = target.Dirty()
	c.Assert(err, IsNil)
	c.Assert(dirty, Equals, false)

	err = ioutil.WriteFile(filepath.Join(target.Path(), "another-file"), []byte("blah"), 0644)
	c.Assert(err, IsNil)
	dirty, err = target.Dirty()
	c.Assert(err, IsNil)
	c.Assert(dirty, Equals, true)
	err = source.AddAll()
	c.Assert(err, IsNil)
	dirty, err = target.Dirty()
	c.Assert(err, IsNil)
	c.Assert(dirty, Equals, true)

	err = target.Revert()
	c.Assert(err, IsNil)
	_, err = os.Stat(filepath.Join(target.Path(), "some-file"))
	c.Assert(err, checkers.Satisfies, os.IsNotExist)
	_, err = os.Stat(filepath.Join(target.Path(), "some-dir"))
	c.Assert(err, checkers.Satisfies, os.IsNotExist)
	data, err = ioutil.ReadFile(filepath.Join(target.Path(), "initial"))
	c.Assert(err, IsNil)
	c.Assert(string(data), Equals, "initial")
	dirty, err = target.Dirty()
	c.Assert(err, IsNil)
	c.Assert(dirty, Equals, false)
}
예제 #4
0
// ModeHookError is responsible for watching and responding to:
// * user resolution of hook errors
// * charm upgrade requests
func ModeHookError(u *Uniter) (next Mode, err error) {
	defer modeContext("ModeHookError", &err)()
	if u.s.Op != RunHook || u.s.OpStep != Pending {
		return nil, fmt.Errorf("insane uniter state: %#v", u.s)
	}
	msg := fmt.Sprintf("hook failed: %q", u.s.Hook.Kind)
	if err = u.unit.SetStatus(state.UnitError, msg); err != nil {
		return nil, err
	}
	url, err := charm.ReadCharmURL(u.charm)
	if err != nil {
		return nil, err
	}
	u.f.WantResolvedEvent()
	u.f.WantUpgradeEvent(url, true)
	for {
		select {
		case <-u.tomb.Dying():
			return nil, tomb.ErrDying
		case rm := <-u.f.ResolvedEvents():
			switch rm {
			case state.ResolvedRetryHooks:
				err = u.runHook(*u.s.Hook)
			case state.ResolvedNoHooks:
				err = u.commitHook(*u.s.Hook)
			default:
				return nil, fmt.Errorf("unknown resolved mode %q", rm)
			}
			if e := u.unit.ClearResolved(); e != nil {
				return nil, e
			}
			if err == errHookFailed {
				continue
			} else if err != nil {
				return nil, err
			}
			return ModeContinue, nil
		case upgrade := <-u.f.UpgradeEvents():
			return ModeUpgrading(upgrade), nil
		}
	}
	panic("unreachable")
}
예제 #5
0
func (s *DeployerSuite) TestUpgrade(c *C) {
	// Install.
	d := charm.NewDeployer(filepath.Join(c.MkDir(), "deployer"))
	bun1 := s.bundle(c, func(path string) {
		err := ioutil.WriteFile(filepath.Join(path, "some-file"), []byte("hello"), 0644)
		c.Assert(err, IsNil)
		err = os.Symlink("./some-file", filepath.Join(path, "a-symlink"))
		c.Assert(err, IsNil)
	})
	err := d.Stage(bun1, corecharm.MustParseURL("cs:s/c-1"))
	c.Assert(err, IsNil)
	target := charm.NewGitDir(filepath.Join(c.MkDir(), "target"))
	err = d.Deploy(target)
	c.Assert(err, IsNil)

	// Upgrade.
	bun2 := s.bundle(c, func(path string) {
		err := ioutil.WriteFile(filepath.Join(path, "some-file"), []byte("goodbye"), 0644)
		c.Assert(err, IsNil)
		err = ioutil.WriteFile(filepath.Join(path, "a-symlink"), []byte("not any more!"), 0644)
		c.Assert(err, IsNil)
	})
	err = d.Stage(bun2, corecharm.MustParseURL("cs:s/c-2"))
	c.Assert(err, IsNil)
	err = d.Deploy(target)
	c.Assert(err, IsNil)

	// Check content.
	data, err := ioutil.ReadFile(filepath.Join(target.Path(), "some-file"))
	c.Assert(err, IsNil)
	c.Assert(string(data), Equals, "goodbye")
	data, err = ioutil.ReadFile(filepath.Join(target.Path(), "a-symlink"))
	c.Assert(err, IsNil)
	c.Assert(string(data), Equals, "not any more!")
	url, err := charm.ReadCharmURL(target)
	c.Assert(err, IsNil)
	c.Assert(url, DeepEquals, corecharm.MustParseURL("cs:s/c-2"))
	lines, err := target.Log()
	c.Assert(err, IsNil)
	c.Assert(lines, HasLen, 5)
	c.Assert(lines[0], Matches, `[0-9a-f]{7} Upgraded charm to "cs:s/c-2".`)
}
예제 #6
0
func (s *GitDirSuite) TestCreate(c *C) {
	base := c.MkDir()
	repo := charm.NewGitDir(filepath.Join(base, "repo"))
	exists, err := repo.Exists()
	c.Assert(err, IsNil)
	c.Assert(exists, Equals, false)

	err = ioutil.WriteFile(repo.Path(), nil, 0644)
	c.Assert(err, IsNil)
	_, err = repo.Exists()
	c.Assert(err, ErrorMatches, `".*/repo" is not a directory`)
	err = os.Remove(repo.Path())
	c.Assert(err, IsNil)

	err = os.Chmod(base, 0555)
	c.Assert(err, IsNil)
	defer os.Chmod(base, 0755)
	err = repo.Init()
	c.Assert(err, ErrorMatches, ".* permission denied")
	exists, err = repo.Exists()
	c.Assert(err, IsNil)
	c.Assert(exists, Equals, false)

	err = os.Chmod(base, 0755)
	c.Assert(err, IsNil)
	err = repo.Init()
	c.Assert(err, IsNil)
	exists, err = repo.Exists()
	c.Assert(err, IsNil)
	c.Assert(exists, Equals, true)

	_, err = charm.ReadCharmURL(repo)
	c.Assert(err, checkers.Satisfies, os.IsNotExist)

	err = repo.Init()
	c.Assert(err, IsNil)
}