// addRelation causes the unit agent to join the supplied relation, and to // store persistent state in the supplied dir. func (u *Uniter) addRelation(rel *state.Relation, dir *relation.StateDir) error { log.Printf("worker/uniter: joining relation %q", rel) ru, err := rel.Unit(u.unit) if err != nil { return err } r := NewRelationer(ru, dir, u.relationHooks) w := u.unit.Watch() defer watcher.Stop(w, &u.tomb) for { select { case <-u.tomb.Dying(): return tomb.ErrDying case _, ok := <-w.Changes(): if !ok { return watcher.MustErr(w) } if err := r.Join(); err == state.ErrCannotEnterScopeYet { log.Printf("worker/uniter: cannot enter scope for relation %q; waiting for subordinate to be removed", rel) continue } else if err != nil { return err } log.Printf("worker/uniter: joined relation %q", rel) u.relationers[rel.Id()] = r return nil } } panic("unreachable") }
func addRU(c *C, svc *state.Service, rel *state.Relation, principal *state.Unit) (*state.Unit, *state.RelationUnit) { // Given the service svc in the relation rel, add a unit of svc and create // a RelationUnit with rel. If principal is supplied, svc is assumed to be // subordinate and the unit will be created by temporarily entering the // relation's scope as the principal. var u *state.Unit if principal == nil { unit, err := svc.AddUnit() c.Assert(err, IsNil) u = unit } else { origUnits, err := svc.AllUnits() c.Assert(err, IsNil) pru, err := rel.Unit(principal) c.Assert(err, IsNil) err = pru.EnterScope(nil) // to create the subordinate c.Assert(err, IsNil) err = pru.LeaveScope() // to reset to initial expected state c.Assert(err, IsNil) newUnits, err := svc.AllUnits() c.Assert(err, IsNil) for _, unit := range newUnits { found := false for _, old := range origUnits { if unit.Name() == old.Name() { found = true break } } if !found { u = unit break } } c.Assert(u, NotNil) } preventUnitDestroyRemove(c, u) ru, err := rel.Unit(u) c.Assert(err, IsNil) return u, ru }