~juju-qa/ubuntu/yakkety/juju/2.0-rc3-again

« back to all changes in this revision

Viewing changes to src/launchpad.net/juju-core/state/relation_test.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-04-24 22:34:47 UTC
  • Revision ID: package-import@ubuntu.com-20130424223447-f0qdji7ubnyo0s71
Tags: upstream-1.10.0.1
ImportĀ upstreamĀ versionĀ 1.10.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package state_test
 
2
 
 
3
import (
 
4
        . "launchpad.net/gocheck"
 
5
        "launchpad.net/juju-core/charm"
 
6
        "launchpad.net/juju-core/state"
 
7
)
 
8
 
 
9
type RelationSuite struct {
 
10
        ConnSuite
 
11
}
 
12
 
 
13
var _ = Suite(&RelationSuite{})
 
14
 
 
15
func (s *RelationSuite) TestAddRelationErrors(c *C) {
 
16
        wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress"))
 
17
        c.Assert(err, IsNil)
 
18
        wordpressEP, err := wordpress.Endpoint("db")
 
19
        c.Assert(err, IsNil)
 
20
        mysql, err := s.State.AddService("mysql", s.AddTestingCharm(c, "mysql"))
 
21
        c.Assert(err, IsNil)
 
22
        mysqlEP, err := mysql.Endpoint("server")
 
23
        c.Assert(err, IsNil)
 
24
        riak, err := s.State.AddService("riak", s.AddTestingCharm(c, "riak"))
 
25
        c.Assert(err, IsNil)
 
26
        riakEP, err := riak.Endpoint("ring")
 
27
        c.Assert(err, IsNil)
 
28
 
 
29
        // Check we can't add a relation with services that don't exist.
 
30
        yoursqlEP := mysqlEP
 
31
        yoursqlEP.ServiceName = "yoursql"
 
32
        _, err = s.State.AddRelation(yoursqlEP, wordpressEP)
 
33
        c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db yoursql:server": service "yoursql" does not exist`)
 
34
        assertNoRelations(c, wordpress)
 
35
        assertNoRelations(c, mysql)
 
36
 
 
37
        // Check that interfaces have to match.
 
38
        msep3 := mysqlEP
 
39
        msep3.Interface = "roflcopter"
 
40
        _, err = s.State.AddRelation(msep3, wordpressEP)
 
41
        c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db mysql:server": endpoints do not relate`)
 
42
        assertNoRelations(c, wordpress)
 
43
        assertNoRelations(c, mysql)
 
44
 
 
45
        // Check a variety of surprising endpoint combinations.
 
46
        _, err = s.State.AddRelation(wordpressEP)
 
47
        c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db": relation must have two endpoints`)
 
48
        assertNoRelations(c, wordpress)
 
49
 
 
50
        _, err = s.State.AddRelation(riakEP, wordpressEP)
 
51
        c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db riak:ring": endpoints do not relate`)
 
52
        assertOneRelation(c, riak, 0, riakEP)
 
53
        assertNoRelations(c, wordpress)
 
54
 
 
55
        _, err = s.State.AddRelation(riakEP, riakEP)
 
56
        c.Assert(err, ErrorMatches, `cannot add relation "riak:ring riak:ring": endpoints do not relate`)
 
57
        assertOneRelation(c, riak, 0, riakEP)
 
58
 
 
59
        _, err = s.State.AddRelation()
 
60
        c.Assert(err, ErrorMatches, `cannot add relation "": relation must have two endpoints`)
 
61
        _, err = s.State.AddRelation(mysqlEP, wordpressEP, riakEP)
 
62
        c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db mysql:server riak:ring": relation must have two endpoints`)
 
63
        assertOneRelation(c, riak, 0, riakEP)
 
64
        assertNoRelations(c, wordpress)
 
65
        assertNoRelations(c, mysql)
 
66
 
 
67
        // Check that a relation can't be added to a Dying service.
 
68
        _, err = wordpress.AddUnit()
 
69
        c.Assert(err, IsNil)
 
70
        err = wordpress.Destroy()
 
71
        c.Assert(err, IsNil)
 
72
        _, err = s.State.AddRelation(mysqlEP, wordpressEP)
 
73
        c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db mysql:server": service "wordpress" is not alive`)
 
74
        assertNoRelations(c, wordpress)
 
75
        assertNoRelations(c, mysql)
 
76
}
 
77
 
 
78
func (s *RelationSuite) TestRetrieveSuccess(c *C) {
 
79
        wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress"))
 
80
        c.Assert(err, IsNil)
 
81
        wordpressEP, err := wordpress.Endpoint("db")
 
82
        c.Assert(err, IsNil)
 
83
        mysql, err := s.State.AddService("mysql", s.AddTestingCharm(c, "mysql"))
 
84
        c.Assert(err, IsNil)
 
85
        mysqlEP, err := mysql.Endpoint("server")
 
86
        c.Assert(err, IsNil)
 
87
        expect, err := s.State.AddRelation(wordpressEP, mysqlEP)
 
88
        c.Assert(err, IsNil)
 
89
        rel, err := s.State.EndpointsRelation(wordpressEP, mysqlEP)
 
90
        check := func() {
 
91
                c.Assert(err, IsNil)
 
92
                c.Assert(rel.Id(), Equals, expect.Id())
 
93
                c.Assert(rel.String(), Equals, expect.String())
 
94
        }
 
95
        check()
 
96
        rel, err = s.State.EndpointsRelation(mysqlEP, wordpressEP)
 
97
        check()
 
98
        rel, err = s.State.Relation(expect.Id())
 
99
        check()
 
100
}
 
101
 
 
102
func (s *RelationSuite) TestRetrieveNotFound(c *C) {
 
103
        subway := state.Endpoint{
 
104
                ServiceName: "subway",
 
105
                Relation: charm.Relation{
 
106
                        Name:      "db",
 
107
                        Interface: "mongodb",
 
108
                        Role:      charm.RoleRequirer,
 
109
                        Scope:     charm.ScopeGlobal,
 
110
                },
 
111
        }
 
112
        mongo := state.Endpoint{
 
113
                ServiceName: "mongo",
 
114
                Relation: charm.Relation{
 
115
                        Name:      "server",
 
116
                        Interface: "mongodb",
 
117
                        Role:      charm.RoleProvider,
 
118
                        Scope:     charm.ScopeGlobal,
 
119
                },
 
120
        }
 
121
        _, err := s.State.EndpointsRelation(subway, mongo)
 
122
        c.Assert(err, ErrorMatches, `relation "subway:db mongo:server" not found`)
 
123
        c.Assert(state.IsNotFound(err), Equals, true)
 
124
 
 
125
        _, err = s.State.Relation(999)
 
126
        c.Assert(err, ErrorMatches, `relation 999 not found`)
 
127
        c.Assert(state.IsNotFound(err), Equals, true)
 
128
}
 
129
 
 
130
func (s *RelationSuite) TestAddRelation(c *C) {
 
131
        // Add a relation.
 
132
        wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress"))
 
133
        c.Assert(err, IsNil)
 
134
        wordpressEP, err := wordpress.Endpoint("db")
 
135
        c.Assert(err, IsNil)
 
136
        mysql, err := s.State.AddService("mysql", s.AddTestingCharm(c, "mysql"))
 
137
        c.Assert(err, IsNil)
 
138
        mysqlEP, err := mysql.Endpoint("server")
 
139
        c.Assert(err, IsNil)
 
140
        _, err = s.State.AddRelation(wordpressEP, mysqlEP)
 
141
        c.Assert(err, IsNil)
 
142
        assertOneRelation(c, mysql, 0, mysqlEP, wordpressEP)
 
143
        assertOneRelation(c, wordpress, 0, wordpressEP, mysqlEP)
 
144
 
 
145
        // Check we cannot re-add the same relation, regardless of endpoint ordering.
 
146
        _, err = s.State.AddRelation(mysqlEP, wordpressEP)
 
147
        c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db mysql:server": relation already exists`)
 
148
        _, err = s.State.AddRelation(wordpressEP, mysqlEP)
 
149
        c.Assert(err, ErrorMatches, `cannot add relation "wordpress:db mysql:server": relation already exists`)
 
150
        assertOneRelation(c, mysql, 0, mysqlEP, wordpressEP)
 
151
        assertOneRelation(c, wordpress, 0, wordpressEP, mysqlEP)
 
152
}
 
153
 
 
154
func (s *RelationSuite) TestAddRelationSeriesNeedNotMatch(c *C) {
 
155
        wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress"))
 
156
        c.Assert(err, IsNil)
 
157
        wordpressEP, err := wordpress.Endpoint("db")
 
158
        c.Assert(err, IsNil)
 
159
        mysql, err := s.State.AddService("mysql", s.AddSeriesCharm(c, "mysql", "otherseries"))
 
160
        c.Assert(err, IsNil)
 
161
        mysqlEP, err := mysql.Endpoint("server")
 
162
        c.Assert(err, IsNil)
 
163
        _, err = s.State.AddRelation(wordpressEP, mysqlEP)
 
164
        c.Assert(err, IsNil)
 
165
        assertOneRelation(c, mysql, 0, mysqlEP, wordpressEP)
 
166
        assertOneRelation(c, wordpress, 0, wordpressEP, mysqlEP)
 
167
}
 
168
 
 
169
func (s *RelationSuite) TestAddContainerRelation(c *C) {
 
170
        // Add a relation.
 
171
        wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress"))
 
172
        c.Assert(err, IsNil)
 
173
        wordpressEP, err := wordpress.Endpoint("juju-info")
 
174
        c.Assert(err, IsNil)
 
175
        logging, err := s.State.AddService("logging", s.AddTestingCharm(c, "logging"))
 
176
        c.Assert(err, IsNil)
 
177
        loggingEP, err := logging.Endpoint("info")
 
178
        c.Assert(err, IsNil)
 
179
        _, err = s.State.AddRelation(wordpressEP, loggingEP)
 
180
        c.Assert(err, IsNil)
 
181
 
 
182
        // Check that the endpoints both have container scope.
 
183
        wordpressEP.Scope = charm.ScopeContainer
 
184
        assertOneRelation(c, logging, 0, loggingEP, wordpressEP)
 
185
        assertOneRelation(c, wordpress, 0, wordpressEP, loggingEP)
 
186
 
 
187
        // Check we cannot re-add the same relation, regardless of endpoint ordering.
 
188
        _, err = s.State.AddRelation(loggingEP, wordpressEP)
 
189
        c.Assert(err, ErrorMatches, `cannot add relation "logging:info wordpress:juju-info": relation already exists`)
 
190
        _, err = s.State.AddRelation(wordpressEP, loggingEP)
 
191
        c.Assert(err, ErrorMatches, `cannot add relation "logging:info wordpress:juju-info": relation already exists`)
 
192
        assertOneRelation(c, logging, 0, loggingEP, wordpressEP)
 
193
        assertOneRelation(c, wordpress, 0, wordpressEP, loggingEP)
 
194
}
 
195
 
 
196
func (s *RelationSuite) TestAddContainerRelationSeriesMustMatch(c *C) {
 
197
        wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress"))
 
198
        c.Assert(err, IsNil)
 
199
        wordpressEP, err := wordpress.Endpoint("juju-info")
 
200
        c.Assert(err, IsNil)
 
201
        logging, err := s.State.AddService("logging", s.AddSeriesCharm(c, "logging", "otherseries"))
 
202
        c.Assert(err, IsNil)
 
203
        loggingEP, err := logging.Endpoint("info")
 
204
        c.Assert(err, IsNil)
 
205
        _, err = s.State.AddRelation(wordpressEP, loggingEP)
 
206
        c.Assert(err, ErrorMatches, `cannot add relation "logging:info wordpress:juju-info": principal and subordinate services' series must match`)
 
207
}
 
208
 
 
209
func (s *RelationSuite) TestDestroyRelation(c *C) {
 
210
        wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress"))
 
211
        c.Assert(err, IsNil)
 
212
        mysql, err := s.State.AddService("mysql", s.AddTestingCharm(c, "mysql"))
 
213
        c.Assert(err, IsNil)
 
214
        eps, err := s.State.InferEndpoints([]string{"wordpress", "mysql"})
 
215
        c.Assert(err, IsNil)
 
216
        rel, err := s.State.AddRelation(eps...)
 
217
        c.Assert(err, IsNil)
 
218
 
 
219
        // Test that the relation can be destroyed.
 
220
        err = rel.Destroy()
 
221
        c.Assert(err, IsNil)
 
222
        err = rel.Refresh()
 
223
        c.Assert(state.IsNotFound(err), Equals, true)
 
224
        assertNoRelations(c, wordpress)
 
225
        assertNoRelations(c, mysql)
 
226
 
 
227
        // Check that a second destroy is a no-op.
 
228
        err = rel.Destroy()
 
229
        c.Assert(err, IsNil)
 
230
 
 
231
        // Create a new relation and check that refreshing the old does not find
 
232
        // the new.
 
233
        _, err = s.State.AddRelation(eps...)
 
234
        c.Assert(err, IsNil)
 
235
        err = rel.Refresh()
 
236
        c.Assert(state.IsNotFound(err), Equals, true)
 
237
}
 
238
 
 
239
func (s *RelationSuite) TestDestroyPeerRelation(c *C) {
 
240
        // Check that a peer relation cannot be destroyed directly.
 
241
        riakch := s.AddTestingCharm(c, "riak")
 
242
        riak, err := s.State.AddService("riak", riakch)
 
243
        c.Assert(err, IsNil)
 
244
        riakEP, err := riak.Endpoint("ring")
 
245
        c.Assert(err, IsNil)
 
246
        rel := assertOneRelation(c, riak, 0, riakEP)
 
247
        err = rel.Destroy()
 
248
        c.Assert(err, ErrorMatches, `cannot destroy relation "riak:ring": is a peer relation`)
 
249
        assertOneRelation(c, riak, 0, riakEP)
 
250
 
 
251
        // Check that it is destroyed when the service is destroyed.
 
252
        err = riak.Destroy()
 
253
        c.Assert(err, IsNil)
 
254
        assertNoRelations(c, riak)
 
255
        err = rel.Refresh()
 
256
        c.Assert(state.IsNotFound(err), Equals, true)
 
257
 
 
258
        // Create a new service (and hence a new relation in the background); check
 
259
        // that refreshing the old one does not accidentally get the new one.
 
260
        newriak, err := s.State.AddService("riak", riakch)
 
261
        c.Assert(err, IsNil)
 
262
        assertOneRelation(c, newriak, 1, riakEP)
 
263
        err = rel.Refresh()
 
264
        c.Assert(state.IsNotFound(err), Equals, true)
 
265
}
 
266
 
 
267
func assertNoRelations(c *C, srv *state.Service) {
 
268
        rels, err := srv.Relations()
 
269
        c.Assert(err, IsNil)
 
270
        c.Assert(rels, HasLen, 0)
 
271
}
 
272
 
 
273
func assertOneRelation(c *C, srv *state.Service, relId int, endpoints ...state.Endpoint) *state.Relation {
 
274
        rels, err := srv.Relations()
 
275
        c.Assert(err, IsNil)
 
276
        c.Assert(rels, HasLen, 1)
 
277
        rel := rels[0]
 
278
        c.Assert(rel.Id(), Equals, relId)
 
279
        name := srv.Name()
 
280
        expectEp := endpoints[0]
 
281
        ep, err := rel.Endpoint(name)
 
282
        c.Assert(err, IsNil)
 
283
        c.Assert(ep, DeepEquals, expectEp)
 
284
        if len(endpoints) == 2 {
 
285
                expectEp = endpoints[1]
 
286
        }
 
287
        eps, err := rel.RelatedEndpoints(name)
 
288
        c.Assert(err, IsNil)
 
289
        c.Assert(eps, DeepEquals, []state.Endpoint{expectEp})
 
290
        return rel
 
291
}