1206.2.1
by Martin Packman
Add copyright statement at the top of all go files bar thirdparty |
1 |
// Copyright 2012, 2013 Canonical Ltd.
|
2 |
// Licensed under the AGPLv3, see LICENCE file for details.
|
|
3 |
||
525.1.1
by Roger Peppe
mstate: rename to state |
4 |
package state_test |
263.9.3
by Aram Hăvărneanu
mstate: basic relations. |
5 |
|
6 |
import ( |
|
7 |
. "launchpad.net/gocheck" |
|
1408.1.1
by John Arbash Meinel
Start changing the imports of the middle level files. |
8 |
|
263.9.18
by Aram Hăvărneanu
mstate: use RelationScope from charm |
9 |
"launchpad.net/juju-core/charm"
|
1242.1.1
by Ian Booth
Move common errors to erros package and remove dupe NotFoundError struct |
10 |
"launchpad.net/juju-core/errors"
|
525.1.2
by Roger Peppe
remove import aliases |
11 |
"launchpad.net/juju-core/state"
|
1322.1.2
by Roger Peppe
many: use checkers.Satisfies |
12 |
"launchpad.net/juju-core/testing/checkers"
|
263.9.3
by Aram Hăvărneanu
mstate: basic relations. |
13 |
)
|
14 |
||
15 |
type RelationSuite struct { |
|
263.10.1
by Aram Hăvărneanu
mstate: remove UtilSuite. |
16 |
ConnSuite
|
263.9.3
by Aram Hăvărneanu
mstate: basic relations. |
17 |
}
|
18 |
||
19 |
var _ = Suite(&RelationSuite{}) |
|
20 |
||
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
21 |
func (s *RelationSuite) TestAddRelationErrors(c *C) { |
701.3.8
by William Reade
address review |
22 |
wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress")) |
23 |
c.Assert(err, IsNil) |
|
24 |
wordpressEP, err := wordpress.Endpoint("db") |
|
25 |
c.Assert(err, IsNil) |
|
26 |
mysql, err := s.State.AddService("mysql", s.AddTestingCharm(c, "mysql")) |
|
27 |
c.Assert(err, IsNil) |
|
28 |
mysqlEP, err := mysql.Endpoint("server") |
|
701.3.1
by William Reade
service charm replacement; wip |
29 |
c.Assert(err, IsNil) |
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
30 |
riak, err := s.State.AddService("riak", s.AddTestingCharm(c, "riak")) |
31 |
c.Assert(err, IsNil) |
|
32 |
riakEP, err := riak.Endpoint("ring") |
|
33 |
c.Assert(err, IsNil) |
|
263.9.3
by Aram Hăvărneanu
mstate: basic relations. |
34 |
|
701.3.3
by William Reade
still wip, but passing tests |
35 |
// Check we can't add a relation with services that don't exist.
|
976.1.7
by William Reade
rearrange service destruction testing for clarity |
36 |
yoursqlEP := mysqlEP |
37 |
yoursqlEP.ServiceName = "yoursql" |
|
38 |
_, err = s.State.AddRelation(yoursqlEP, wordpressEP) |
|
864.2.1
by William Reade
AddRelation now bothers to check service charms; uniter tests still broken |
39 |
c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db yoursql:server": service "yoursql" does not exist`) |
701.3.8
by William Reade
address review |
40 |
assertNoRelations(c, wordpress) |
41 |
assertNoRelations(c, mysql) |
|
263.9.3
by Aram Hăvărneanu
mstate: basic relations. |
42 |
|
43 |
// Check that interfaces have to match.
|
|
701.3.8
by William Reade
address review |
44 |
msep3 := mysqlEP |
701.3.3
by William Reade
still wip, but passing tests |
45 |
msep3.Interface = "roflcopter" |
701.3.8
by William Reade
address review |
46 |
_, err = s.State.AddRelation(msep3, wordpressEP) |
701.3.3
by William Reade
still wip, but passing tests |
47 |
c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db mysql:server": endpoints do not relate`) |
701.3.8
by William Reade
address review |
48 |
assertNoRelations(c, wordpress) |
49 |
assertNoRelations(c, mysql) |
|
263.9.3
by Aram Hăvărneanu
mstate: basic relations. |
50 |
|
51 |
// Check a variety of surprising endpoint combinations.
|
|
701.3.8
by William Reade
address review |
52 |
_, err = s.State.AddRelation(wordpressEP) |
864.2.1
by William Reade
AddRelation now bothers to check service charms; uniter tests still broken |
53 |
c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db": relation must have two endpoints`) |
701.3.8
by William Reade
address review |
54 |
assertNoRelations(c, wordpress) |
701.3.1
by William Reade
service charm replacement; wip |
55 |
|
701.3.8
by William Reade
address review |
56 |
_, err = s.State.AddRelation(riakEP, wordpressEP) |
701.3.3
by William Reade
still wip, but passing tests |
57 |
c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db riak:ring": endpoints do not relate`) |
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
58 |
assertOneRelation(c, riak, 0, riakEP) |
701.3.8
by William Reade
address review |
59 |
assertNoRelations(c, wordpress) |
701.3.1
by William Reade
service charm replacement; wip |
60 |
|
701.3.8
by William Reade
address review |
61 |
_, err = s.State.AddRelation(riakEP, riakEP) |
701.3.3
by William Reade
still wip, but passing tests |
62 |
c.Assert(err, ErrorMatches, `cannot add relation "riak:ring riak:ring": endpoints do not relate`) |
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
63 |
assertOneRelation(c, riak, 0, riakEP) |
263.9.3
by Aram Hăvărneanu
mstate: basic relations. |
64 |
|
263.9.11
by Aram Hăvărneanu
mstate: upgrade relation API to match state |
65 |
_, err = s.State.AddRelation() |
864.2.1
by William Reade
AddRelation now bothers to check service charms; uniter tests still broken |
66 |
c.Assert(err, ErrorMatches, `cannot add relation "": relation must have two endpoints`) |
701.3.8
by William Reade
address review |
67 |
_, err = s.State.AddRelation(mysqlEP, wordpressEP, riakEP) |
864.2.1
by William Reade
AddRelation now bothers to check service charms; uniter tests still broken |
68 |
c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db mysql:server riak:ring": relation must have two endpoints`) |
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
69 |
assertOneRelation(c, riak, 0, riakEP) |
70 |
assertNoRelations(c, wordpress) |
|
71 |
assertNoRelations(c, mysql) |
|
976.1.7
by William Reade
rearrange service destruction testing for clarity |
72 |
|
73 |
// Check that a relation can't be added to a Dying service.
|
|
74 |
_, err = wordpress.AddUnit() |
|
75 |
c.Assert(err, IsNil) |
|
76 |
err = wordpress.Destroy() |
|
77 |
c.Assert(err, IsNil) |
|
78 |
_, err = s.State.AddRelation(mysqlEP, wordpressEP) |
|
79 |
c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db mysql:server": service "wordpress" is not alive`) |
|
80 |
assertNoRelations(c, wordpress) |
|
81 |
assertNoRelations(c, mysql) |
|
560.1.1
by Gustavo Niemeyer
state: getter methods return NotFoundError |
82 |
}
|
263.9.11
by Aram Hăvărneanu
mstate: upgrade relation API to match state |
83 |
|
661.1.1
by William Reade
new Relation getters on State |
84 |
func (s *RelationSuite) TestRetrieveSuccess(c *C) { |
701.3.8
by William Reade
address review |
85 |
wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress")) |
86 |
c.Assert(err, IsNil) |
|
87 |
wordpressEP, err := wordpress.Endpoint("db") |
|
88 |
c.Assert(err, IsNil) |
|
89 |
mysql, err := s.State.AddService("mysql", s.AddTestingCharm(c, "mysql")) |
|
90 |
c.Assert(err, IsNil) |
|
91 |
mysqlEP, err := mysql.Endpoint("server") |
|
92 |
c.Assert(err, IsNil) |
|
93 |
expect, err := s.State.AddRelation(wordpressEP, mysqlEP) |
|
94 |
c.Assert(err, IsNil) |
|
95 |
rel, err := s.State.EndpointsRelation(wordpressEP, mysqlEP) |
|
661.1.1
by William Reade
new Relation getters on State |
96 |
check := func() { |
97 |
c.Assert(err, IsNil) |
|
98 |
c.Assert(rel.Id(), Equals, expect.Id()) |
|
99 |
c.Assert(rel.String(), Equals, expect.String()) |
|
100 |
}
|
|
101 |
check() |
|
701.3.8
by William Reade
address review |
102 |
rel, err = s.State.EndpointsRelation(mysqlEP, wordpressEP) |
661.1.1
by William Reade
new Relation getters on State |
103 |
check() |
104 |
rel, err = s.State.Relation(expect.Id()) |
|
105 |
check() |
|
106 |
}
|
|
107 |
||
108 |
func (s *RelationSuite) TestRetrieveNotFound(c *C) { |
|
1066.1.3
by Roger Peppe
state: embed charm.Relation in Endpoint |
109 |
subway := state.Endpoint{ |
110 |
ServiceName: "subway", |
|
111 |
Relation: charm.Relation{ |
|
1066.1.4
by Roger Peppe
gofmt |
112 |
Name: "db", |
1066.1.3
by Roger Peppe
state: embed charm.Relation in Endpoint |
113 |
Interface: "mongodb", |
1066.1.4
by Roger Peppe
gofmt |
114 |
Role: charm.RoleRequirer, |
115 |
Scope: charm.ScopeGlobal, |
|
1066.1.3
by Roger Peppe
state: embed charm.Relation in Endpoint |
116 |
},
|
117 |
}
|
|
118 |
mongo := state.Endpoint{ |
|
119 |
ServiceName: "mongo", |
|
120 |
Relation: charm.Relation{ |
|
1066.1.4
by Roger Peppe
gofmt |
121 |
Name: "server", |
1066.1.3
by Roger Peppe
state: embed charm.Relation in Endpoint |
122 |
Interface: "mongodb", |
1066.1.4
by Roger Peppe
gofmt |
123 |
Role: charm.RoleProvider, |
124 |
Scope: charm.ScopeGlobal, |
|
1066.1.3
by Roger Peppe
state: embed charm.Relation in Endpoint |
125 |
},
|
126 |
}
|
|
661.1.1
by William Reade
new Relation getters on State |
127 |
_, err := s.State.EndpointsRelation(subway, mongo) |
694.1.1
by William Reade
endpoints are now sorted as req < pro < peer |
128 |
c.Assert(err, ErrorMatches, `relation "subway:db mongo:server" not found`) |
1322.1.2
by Roger Peppe
many: use checkers.Satisfies |
129 |
c.Assert(err, checkers.Satisfies, errors.IsNotFoundError) |
661.1.1
by William Reade
new Relation getters on State |
130 |
|
131 |
_, err = s.State.Relation(999) |
|
132 |
c.Assert(err, ErrorMatches, `relation 999 not found`) |
|
1322.1.2
by Roger Peppe
many: use checkers.Satisfies |
133 |
c.Assert(err, checkers.Satisfies, errors.IsNotFoundError) |
263.9.3
by Aram Hăvărneanu
mstate: basic relations. |
134 |
}
|
135 |
||
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
136 |
func (s *RelationSuite) TestAddRelation(c *C) { |
137 |
// Add a relation.
|
|
701.3.8
by William Reade
address review |
138 |
wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress")) |
139 |
c.Assert(err, IsNil) |
|
140 |
wordpressEP, err := wordpress.Endpoint("db") |
|
141 |
c.Assert(err, IsNil) |
|
142 |
mysql, err := s.State.AddService("mysql", s.AddTestingCharm(c, "mysql")) |
|
143 |
c.Assert(err, IsNil) |
|
144 |
mysqlEP, err := mysql.Endpoint("server") |
|
145 |
c.Assert(err, IsNil) |
|
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
146 |
_, err = s.State.AddRelation(wordpressEP, mysqlEP) |
147 |
c.Assert(err, IsNil) |
|
148 |
assertOneRelation(c, mysql, 0, mysqlEP, wordpressEP) |
|
149 |
assertOneRelation(c, wordpress, 0, wordpressEP, mysqlEP) |
|
150 |
||
151 |
// Check we cannot re-add the same relation, regardless of endpoint ordering.
|
|
152 |
_, err = s.State.AddRelation(mysqlEP, wordpressEP) |
|
153 |
c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db mysql:server": relation already exists`) |
|
154 |
_, err = s.State.AddRelation(wordpressEP, mysqlEP) |
|
155 |
c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db mysql:server": relation already exists`) |
|
156 |
assertOneRelation(c, mysql, 0, mysqlEP, wordpressEP) |
|
157 |
assertOneRelation(c, wordpress, 0, wordpressEP, mysqlEP) |
|
158 |
}
|
|
159 |
||
1061.3.1
by William Reade
restrict subordinate relations' services' serieses |
160 |
func (s *RelationSuite) TestAddRelationSeriesNeedNotMatch(c *C) { |
161 |
wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress")) |
|
162 |
c.Assert(err, IsNil) |
|
163 |
wordpressEP, err := wordpress.Endpoint("db") |
|
164 |
c.Assert(err, IsNil) |
|
1061.3.3
by William Reade
address review |
165 |
mysql, err := s.State.AddService("mysql", s.AddSeriesCharm(c, "mysql", "otherseries")) |
1061.3.1
by William Reade
restrict subordinate relations' services' serieses |
166 |
c.Assert(err, IsNil) |
167 |
mysqlEP, err := mysql.Endpoint("server") |
|
168 |
c.Assert(err, IsNil) |
|
169 |
_, err = s.State.AddRelation(wordpressEP, mysqlEP) |
|
170 |
c.Assert(err, IsNil) |
|
171 |
assertOneRelation(c, mysql, 0, mysqlEP, wordpressEP) |
|
172 |
assertOneRelation(c, wordpress, 0, wordpressEP, mysqlEP) |
|
173 |
}
|
|
174 |
||
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
175 |
func (s *RelationSuite) TestAddContainerRelation(c *C) { |
176 |
// Add a relation.
|
|
177 |
wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress")) |
|
178 |
c.Assert(err, IsNil) |
|
179 |
wordpressEP, err := wordpress.Endpoint("juju-info") |
|
180 |
c.Assert(err, IsNil) |
|
181 |
logging, err := s.State.AddService("logging", s.AddTestingCharm(c, "logging")) |
|
182 |
c.Assert(err, IsNil) |
|
183 |
loggingEP, err := logging.Endpoint("info") |
|
184 |
c.Assert(err, IsNil) |
|
185 |
_, err = s.State.AddRelation(wordpressEP, loggingEP) |
|
186 |
c.Assert(err, IsNil) |
|
187 |
||
188 |
// Check that the endpoints both have container scope.
|
|
1066.1.3
by Roger Peppe
state: embed charm.Relation in Endpoint |
189 |
wordpressEP.Scope = charm.ScopeContainer |
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
190 |
assertOneRelation(c, logging, 0, loggingEP, wordpressEP) |
191 |
assertOneRelation(c, wordpress, 0, wordpressEP, loggingEP) |
|
192 |
||
193 |
// Check we cannot re-add the same relation, regardless of endpoint ordering.
|
|
194 |
_, err = s.State.AddRelation(loggingEP, wordpressEP) |
|
195 |
c.Assert(err, ErrorMatches, `cannot add relation "logging:info wordpress:juju-info": relation already exists`) |
|
196 |
_, err = s.State.AddRelation(wordpressEP, loggingEP) |
|
197 |
c.Assert(err, ErrorMatches, `cannot add relation "logging:info wordpress:juju-info": relation already exists`) |
|
198 |
assertOneRelation(c, logging, 0, loggingEP, wordpressEP) |
|
199 |
assertOneRelation(c, wordpress, 0, wordpressEP, loggingEP) |
|
200 |
}
|
|
201 |
||
1061.3.1
by William Reade
restrict subordinate relations' services' serieses |
202 |
func (s *RelationSuite) TestAddContainerRelationSeriesMustMatch(c *C) { |
203 |
wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress")) |
|
204 |
c.Assert(err, IsNil) |
|
205 |
wordpressEP, err := wordpress.Endpoint("juju-info") |
|
206 |
c.Assert(err, IsNil) |
|
1061.3.3
by William Reade
address review |
207 |
logging, err := s.State.AddService("logging", s.AddSeriesCharm(c, "logging", "otherseries")) |
1061.3.1
by William Reade
restrict subordinate relations' services' serieses |
208 |
c.Assert(err, IsNil) |
209 |
loggingEP, err := logging.Endpoint("info") |
|
210 |
c.Assert(err, IsNil) |
|
211 |
_, err = s.State.AddRelation(wordpressEP, loggingEP) |
|
212 |
c.Assert(err, ErrorMatches, `cannot add relation "logging:info wordpress:juju-info": principal and subordinate services' series must match`) |
|
213 |
}
|
|
214 |
||
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
215 |
func (s *RelationSuite) TestDestroyRelation(c *C) { |
216 |
wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress")) |
|
217 |
c.Assert(err, IsNil) |
|
218 |
mysql, err := s.State.AddService("mysql", s.AddTestingCharm(c, "mysql")) |
|
219 |
c.Assert(err, IsNil) |
|
220 |
eps, err := s.State.InferEndpoints([]string{"wordpress", "mysql"}) |
|
221 |
c.Assert(err, IsNil) |
|
222 |
rel, err := s.State.AddRelation(eps...) |
|
223 |
c.Assert(err, IsNil) |
|
224 |
||
225 |
// Test that the relation can be destroyed.
|
|
226 |
err = rel.Destroy() |
|
227 |
c.Assert(err, IsNil) |
|
228 |
err = rel.Refresh() |
|
1322.1.2
by Roger Peppe
many: use checkers.Satisfies |
229 |
c.Assert(err, checkers.Satisfies, errors.IsNotFoundError) |
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
230 |
assertNoRelations(c, wordpress) |
231 |
assertNoRelations(c, mysql) |
|
232 |
||
233 |
// Check that a second destroy is a no-op.
|
|
234 |
err = rel.Destroy() |
|
235 |
c.Assert(err, IsNil) |
|
236 |
||
237 |
// Create a new relation and check that refreshing the old does not find
|
|
238 |
// the new.
|
|
239 |
_, err = s.State.AddRelation(eps...) |
|
240 |
c.Assert(err, IsNil) |
|
241 |
err = rel.Refresh() |
|
1322.1.2
by Roger Peppe
many: use checkers.Satisfies |
242 |
c.Assert(err, checkers.Satisfies, errors.IsNotFoundError) |
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
243 |
}
|
244 |
||
245 |
func (s *RelationSuite) TestDestroyPeerRelation(c *C) { |
|
246 |
// Check that a peer relation cannot be destroyed directly.
|
|
247 |
riakch := s.AddTestingCharm(c, "riak") |
|
248 |
riak, err := s.State.AddService("riak", riakch) |
|
249 |
c.Assert(err, IsNil) |
|
250 |
riakEP, err := riak.Endpoint("ring") |
|
251 |
c.Assert(err, IsNil) |
|
252 |
rel := assertOneRelation(c, riak, 0, riakEP) |
|
253 |
err = rel.Destroy() |
|
254 |
c.Assert(err, ErrorMatches, `cannot destroy relation "riak:ring": is a peer relation`) |
|
701.3.8
by William Reade
address review |
255 |
assertOneRelation(c, riak, 0, riakEP) |
263.9.11
by Aram Hăvărneanu
mstate: upgrade relation API to match state |
256 |
|
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
257 |
// Check that it is destroyed when the service is destroyed.
|
258 |
err = riak.Destroy() |
|
263.9.11
by Aram Hăvărneanu
mstate: upgrade relation API to match state |
259 |
c.Assert(err, IsNil) |
701.3.8
by William Reade
address review |
260 |
assertNoRelations(c, riak) |
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
261 |
err = rel.Refresh() |
1322.1.2
by Roger Peppe
many: use checkers.Satisfies |
262 |
c.Assert(err, checkers.Satisfies, errors.IsNotFoundError) |
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
263 |
|
264 |
// Create a new service (and hence a new relation in the background); check
|
|
265 |
// that refreshing the old one does not accidentally get the new one.
|
|
266 |
newriak, err := s.State.AddService("riak", riakch) |
|
509.3.9
by Roger Peppe
state: make removing something non-existent not fail |
267 |
c.Assert(err, IsNil) |
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
268 |
assertOneRelation(c, newriak, 1, riakEP) |
269 |
err = rel.Refresh() |
|
1322.1.2
by Roger Peppe
many: use checkers.Satisfies |
270 |
c.Assert(err, checkers.Satisfies, errors.IsNotFoundError) |
263.9.5
by Aram Hăvărneanu
mstate: port more relation tests. |
271 |
}
|
272 |
||
263.9.3
by Aram Hăvărneanu
mstate: basic relations. |
273 |
func assertNoRelations(c *C, srv *state.Service) { |
274 |
rels, err := srv.Relations() |
|
275 |
c.Assert(err, IsNil) |
|
276 |
c.Assert(rels, HasLen, 0) |
|
277 |
}
|
|
278 |
||
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
279 |
func assertOneRelation(c *C, srv *state.Service, relId int, endpoints ...state.Endpoint) *state.Relation { |
263.9.3
by Aram Hăvărneanu
mstate: basic relations. |
280 |
rels, err := srv.Relations() |
281 |
c.Assert(err, IsNil) |
|
282 |
c.Assert(rels, HasLen, 1) |
|
283 |
rel := rels[0] |
|
284 |
c.Assert(rel.Id(), Equals, relId) |
|
285 |
name := srv.Name() |
|
286 |
expectEp := endpoints[0] |
|
287 |
ep, err := rel.Endpoint(name) |
|
288 |
c.Assert(err, IsNil) |
|
289 |
c.Assert(ep, DeepEquals, expectEp) |
|
290 |
if len(endpoints) == 2 { |
|
291 |
expectEp = endpoints[1] |
|
292 |
}
|
|
293 |
eps, err := rel.RelatedEndpoints(name) |
|
294 |
c.Assert(err, IsNil) |
|
681.2.1
by William Reade
rename RelationEndpoint->Endpoint; extend; test |
295 |
c.Assert(eps, DeepEquals, []state.Endpoint{expectEp}) |
858.4.1
by William Reade
fix peer relation lifecycles (now tied to service); uniter tests not yet fixed |
296 |
return rel |
263.9.3
by Aram Hăvărneanu
mstate: basic relations. |
297 |
}
|