Beispiel #1
0
func (s *RelationerSuite) SetUpTest(c *gc.C) {
	s.JujuConnSuite.SetUpTest(c)
	var err error
	s.svc = s.AddTestingService(c, "u", s.AddTestingCharm(c, "riak"))
	c.Assert(err, gc.IsNil)
	rels, err := s.svc.Relations()
	c.Assert(err, gc.IsNil)
	c.Assert(rels, gc.HasLen, 1)
	s.rel = rels[0]
	_, unit := s.AddRelationUnit(c, "u/0")
	s.dirPath = c.MkDir()
	s.dir, err = relation.ReadStateDir(s.dirPath, s.rel.Id())
	c.Assert(err, gc.IsNil)
	s.hooks = make(chan hook.Info)

	password, err := utils.RandomPassword()
	c.Assert(err, gc.IsNil)
	err = unit.SetPassword(password)
	c.Assert(err, gc.IsNil)
	s.st = s.OpenAPIAs(c, unit.Tag(), password)
	s.uniter = s.st.Uniter()
	c.Assert(s.uniter, gc.NotNil)

	apiUnit, err := s.uniter.Unit(unit.Tag())
	c.Assert(err, gc.IsNil)
	apiRel, err := s.uniter.Relation(s.rel.Tag())
	c.Assert(err, gc.IsNil)
	s.apiRelUnit, err = apiRel.Unit(apiUnit)
	c.Assert(err, gc.IsNil)
}
Beispiel #2
0
func (s *StateDirSuite) TestWrite(c *gc.C) {
	for i, t := range writeTests {
		c.Logf("test %d", i)
		basedir := c.MkDir()
		setUpDir(c, basedir, "123", map[string]string{
			"foo-1": "change-version: 0\n",
			"foo-2": "change-version: 0\n",
		})
		dir, err := relation.ReadStateDir(basedir, 123)
		c.Assert(err, gc.IsNil)
		for i, hi := range t.hooks {
			c.Logf("  hook %d", i)
			if i == len(t.hooks)-1 && t.err != "" {
				err = dir.State().Validate(hi)
				expect := fmt.Sprintf(`inappropriate %q for %q: %s`, hi.Kind, hi.RemoteUnit, t.err)
				c.Assert(err, gc.ErrorMatches, expect)
			} else {
				err = dir.State().Validate(hi)
				c.Assert(err, gc.IsNil)
				err = dir.Write(hi)
				c.Assert(err, gc.IsNil)
				// Check that writing the same change again is OK.
				err = dir.Write(hi)
				c.Assert(err, gc.IsNil)
			}
		}
		members := t.members
		if members == nil && !t.deleted {
			members = defaultMembers
		}
		assertState(c, dir, basedir, 123, members, t.pending, t.deleted)
	}
}
Beispiel #3
0
func (s *StateDirSuite) TestRemove(c *gc.C) {
	basedir := c.MkDir()
	dir, err := relation.ReadStateDir(basedir, 1)
	c.Assert(err, gc.IsNil)
	err = dir.Ensure()
	c.Assert(err, gc.IsNil)
	err = dir.Remove()
	c.Assert(err, gc.IsNil)
	err = dir.Remove()
	c.Assert(err, gc.IsNil)

	setUpDir(c, basedir, "99", map[string]string{
		"foo-1": "change-version: 0\n",
	})
	dir, err = relation.ReadStateDir(basedir, 99)
	c.Assert(err, gc.IsNil)
	err = dir.Remove()
	c.Assert(err, gc.ErrorMatches, ".*: directory not empty")
}
Beispiel #4
0
func (s *StateDirSuite) TestBadRelations(c *gc.C) {
	for i, t := range badRelationsTests {
		c.Logf("test %d", i)
		basedir := c.MkDir()
		reldir := setUpDir(c, basedir, "123", t.contents)
		for _, subdir := range t.subdirs {
			setUpDir(c, reldir, subdir, nil)
		}
		_, err := relation.ReadStateDir(basedir, 123)
		expect := `cannot load relation state from ".*": ` + t.err
		c.Assert(err, gc.ErrorMatches, expect)
	}
}
Beispiel #5
0
func assertState(c *gc.C, dir *relation.StateDir, relsdir string, relationId int, members msi, pending string, deleted bool) {
	expect := &relation.State{
		RelationId:     relationId,
		Members:        map[string]int64(members),
		ChangedPending: pending,
	}
	c.Assert(dir.State(), gc.DeepEquals, expect)
	if deleted {
		_, err := os.Stat(filepath.Join(relsdir, strconv.Itoa(relationId)))
		c.Assert(err, jc.Satisfies, os.IsNotExist)
	} else {
		fresh, err := relation.ReadStateDir(relsdir, relationId)
		c.Assert(err, gc.IsNil)
		c.Assert(fresh.State(), gc.DeepEquals, expect)
	}
}
Beispiel #6
0
func (s *StateDirSuite) TestReadStateDirValid(c *gc.C) {
	basedir := c.MkDir()
	reldir := setUpDir(c, basedir, "123", map[string]string{
		"foo-bar-1":           "change-version: 99\n",
		"foo-bar-1.preparing": "change-version: 100\n",
		"baz-qux-7":           "change-version: 101\nchanged-pending: true\n",
		"nonsensical":         "blah",
		"27":                  "blah",
	})
	setUpDir(c, reldir, "ignored", nil)

	dir, err := relation.ReadStateDir(basedir, 123)
	c.Assert(err, gc.IsNil)
	state := dir.State()
	c.Assert(state.RelationId, gc.Equals, 123)
	c.Assert(msi(state.Members), gc.DeepEquals, msi{"foo-bar/1": 99, "baz-qux/7": 101})
	c.Assert(state.ChangedPending, gc.Equals, "baz-qux/7")
}
Beispiel #7
0
func (s *StateDirSuite) TestReadStateDirEmpty(c *gc.C) {
	basedir := c.MkDir()
	reldir := filepath.Join(basedir, "123")

	dir, err := relation.ReadStateDir(basedir, 123)
	c.Assert(err, gc.IsNil)
	state := dir.State()
	c.Assert(state.RelationId, gc.Equals, 123)
	c.Assert(msi(state.Members), gc.DeepEquals, msi{})
	c.Assert(state.ChangedPending, gc.Equals, "")

	_, err = os.Stat(reldir)
	c.Assert(err, jc.Satisfies, os.IsNotExist)

	err = dir.Ensure()
	c.Assert(err, gc.IsNil)
	fi, err := os.Stat(reldir)
	c.Assert(err, gc.IsNil)
	c.Assert(fi, jc.Satisfies, os.FileInfo.IsDir)
}
Beispiel #8
0
func (s *RelationerImplicitSuite) TestImplicitRelationer(c *gc.C) {
	// Create a relationer for an implicit endpoint (mysql:juju-info).
	mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql"))
	u, err := mysql.AddUnit()
	c.Assert(err, gc.IsNil)
	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
	c.Assert(err, gc.IsNil)
	err = u.AssignToMachine(machine)
	c.Assert(err, gc.IsNil)
	err = machine.SetAddresses(instance.NewAddress("blah", instance.NetworkCloudLocal))
	c.Assert(err, gc.IsNil)
	logging := s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging"))
	eps, err := s.State.InferEndpoints([]string{"logging", "mysql"})
	c.Assert(err, gc.IsNil)
	rel, err := s.State.AddRelation(eps...)
	c.Assert(err, gc.IsNil)
	relsDir := c.MkDir()
	dir, err := relation.ReadStateDir(relsDir, rel.Id())
	c.Assert(err, gc.IsNil)
	hooks := make(chan hook.Info)

	password, err := utils.RandomPassword()
	c.Assert(err, gc.IsNil)
	err = u.SetPassword(password)
	c.Assert(err, gc.IsNil)
	st := s.OpenAPIAs(c, u.Tag(), password)
	uniterState := st.Uniter()
	c.Assert(uniterState, gc.NotNil)

	apiUnit, err := uniterState.Unit(u.Tag())
	c.Assert(err, gc.IsNil)
	apiRel, err := uniterState.Relation(rel.Tag())
	c.Assert(err, gc.IsNil)
	apiRelUnit, err := apiRel.Unit(apiUnit)
	c.Assert(err, gc.IsNil)

	r := uniter.NewRelationer(apiRelUnit, dir, hooks)
	c.Assert(r, jc.Satisfies, (*uniter.Relationer).IsImplicit)

	// Join the relation.
	err = r.Join()
	c.Assert(err, gc.IsNil)
	sub, err := logging.Unit("logging/0")
	c.Assert(err, gc.IsNil)

	// Join the other side; check no hooks are sent.
	r.StartHooks()
	defer func() { c.Assert(r.StopHooks(), gc.IsNil) }()
	subru, err := rel.Unit(sub)
	c.Assert(err, gc.IsNil)
	err = subru.EnterScope(map[string]interface{}{"some": "data"})
	c.Assert(err, gc.IsNil)
	s.State.StartSync()
	select {
	case <-time.After(coretesting.ShortWait):
	case <-hooks:
		c.Fatalf("unexpected hook generated")
	}

	// Set it to Dying; check that the dir is removed immediately.
	err = r.SetDying()
	c.Assert(err, gc.IsNil)
	path := strconv.Itoa(rel.Id())
	ft.Removed{path}.Check(c, relsDir)

	// Check that it left scope, by leaving scope on the other side and destroying
	// the relation.
	err = subru.LeaveScope()
	c.Assert(err, gc.IsNil)
	err = rel.Destroy()
	c.Assert(err, gc.IsNil)
	err = rel.Refresh()
	c.Assert(err, jc.Satisfies, errors.IsNotFound)

	// Verify that no other hooks were sent at any stage.
	select {
	case <-hooks:
		c.Fatalf("unexpected hook generated")
	default:
	}
}