~rogpeppe/juju-core/azure

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
}