Merge lp:~dimitern/juju-core/103-relation-entity-tags into lp:~go-bot/juju-core/trunk

Proposed by Dimiter Naydenov
Status: Merged
Approved by: Dimiter Naydenov
Approved revision: no longer in the source branch.
Merged at revision: 1661
Proposed branch: lp:~dimitern/juju-core/103-relation-entity-tags
Merge into: lp:~go-bot/juju-core/trunk
Prerequisite: lp:~dimitern/juju-core/102-state-endpoint-refactoring
Diff against target: 277 lines (+124/-23)
7 files modified
names/relation.go (+24/-0)
names/relation_test.go (+36/-0)
names/tag.go (+18/-15)
names/tag_test.go (+9/-3)
state/relation.go (+7/-0)
state/state.go (+9/-0)
state/state_test.go (+21/-5)
To merge this branch: bzr merge lp:~dimitern/juju-core/103-relation-entity-tags
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+180157@code.launchpad.net

Commit message

state: Make Relation an Entity

This adds relation tags to the names package. The
format is "relation-<id>", where <id> is the relation's
numeric id.
It also adds a Tag() method on the relation, and a few
other necessary modifications to make state.Relation
objects behave like other entities. This is needed for
the uniter API facade, so relations can be used as
params and results.

https://codereview.appspot.com/12748044/

R=gz, rogpeppe

Description of the change

state: Make Relation an Entity

This adds relation tags to the names package. The
format is "relation-<id>", where <id> is the relation's
numeric id.
It also adds a Tag() method on the relation, and a few
other necessary modifications to make state.Relation
objects behave like other entities. This is needed for
the uniter API facade, so relations can be used as
params and results.

https://codereview.appspot.com/12748044/

To post a comment you must log in.
Revision history for this message
Dimiter Naydenov (dimitern) wrote :

Reviewers: mp+180157_code.launchpad.net,

Message:
Please take a look.

Description:
state: Make Relation an Entity

This adds relation tags to the names package. The
format is "relation-<id>", where <id> is the relation's
numeric id.
It also adds a Tag() method on the relation, and a few
other necessary modifications to make state.Relation
objects behave like other entities. This is needed for
the uniter API facade, so relations can be used as
params and results.

https://code.launchpad.net/~dimitern/juju-core/103-relation-entity-tags/+merge/180157

Requires:
https://code.launchpad.net/~dimitern/juju-core/102-state-endpoint-refactoring/+merge/180141

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/12748044/

Affected files:
   A [revision details]
   A names/relation.go
   A names/relation_test.go
   M names/tag.go
   M names/tag_test.go
   M state/relation.go
   M state/state.go
   M state/state_test.go

Revision history for this message
Roger Peppe (rogpeppe) wrote :

LGTM with some extra tests.

https://codereview.appspot.com/12748044/diff/1/names/relation.go
File names/relation.go (right):

https://codereview.appspot.com/12748044/diff/1/names/relation.go#newcode18
names/relation.go:18: func RelationTag(relationId string) string {
if !IsRelation(relationId) {
    panic(fmt.Sprintf("%q is not a valid relation id", relationId))
}

https://codereview.appspot.com/12748044/diff/1/state/relation.go
File state/relation.go (right):

https://codereview.appspot.com/12748044/diff/1/state/relation.go#newcode66
state/relation.go:66: func (r *Relation) Tag() string {
This should have a test.

https://codereview.appspot.com/12748044/diff/1/state/state_test.go
File state/state_test.go (right):

https://codereview.appspot.com/12748044/diff/1/state/state_test.go#newcode1438
state/state_test.go:1438: tag: "service-ser-vice2",
We need a relation tag test here.

https://codereview.appspot.com/12748044/

Revision history for this message
Dimiter Naydenov (dimitern) wrote :

Please take a look.

https://codereview.appspot.com/12748044/diff/1/names/relation.go
File names/relation.go (right):

https://codereview.appspot.com/12748044/diff/1/names/relation.go#newcode18
names/relation.go:18: func RelationTag(relationId string) string {
On 2013/08/14 15:02:49, rog wrote:
> if !IsRelation(relationId) {
> panic(fmt.Sprintf("%q is not a valid relation id", relationId))
> }

Done.

https://codereview.appspot.com/12748044/diff/1/state/relation.go
File state/relation.go (right):

https://codereview.appspot.com/12748044/diff/1/state/relation.go#newcode66
state/relation.go:66: func (r *Relation) Tag() string {
On 2013/08/14 15:02:49, rog wrote:
> This should have a test.

Done.

https://codereview.appspot.com/12748044/diff/1/state/state_test.go
File state/state_test.go (right):

https://codereview.appspot.com/12748044/diff/1/state/state_test.go#newcode1438
state/state_test.go:1438: tag: "service-ser-vice2",
On 2013/08/14 15:02:49, rog wrote:
> We need a relation tag test here.

Done.

https://codereview.appspot.com/12748044/

Revision history for this message
Martin Packman (gz) wrote :

LGTM.

https://codereview.appspot.com/12748044/diff/5002/names/relation_test.go
File names/relation_test.go (right):

https://codereview.appspot.com/12748044/diff/5002/names/relation_test.go#newcode16
names/relation_test.go:16: var relationIdTests = []struct {
Okay, so this is a case where I like the table test style.

https://codereview.appspot.com/12748044/diff/5002/state/state.go
File state/state.go (right):

https://codereview.appspot.com/12748044/diff/5002/state/state.go#newcode498
state/state.go:498: return nil, errors.NotFoundf("relation %s", id)
If the conversion fails, is that really a not found rather than an
invalid situation?

Is there a test exercising this branch?

https://codereview.appspot.com/12748044/

Revision history for this message
Dimiter Naydenov (dimitern) wrote :

Please take a look.

https://codereview.appspot.com/12748044/diff/5002/names/relation_test.go
File names/relation_test.go (right):

https://codereview.appspot.com/12748044/diff/5002/names/relation_test.go#newcode16
names/relation_test.go:16: var relationIdTests = []struct {
On 2013/08/14 15:54:56, gz wrote:
> Okay, so this is a case where I like the table test style.

Yeah!

https://codereview.appspot.com/12748044/diff/5002/state/state.go
File state/state.go (right):

https://codereview.appspot.com/12748044/diff/5002/state/state.go#newcode498
state/state.go:498: return nil, errors.NotFoundf("relation %s", id)
On 2013/08/14 15:54:56, gz wrote:
> If the conversion fails, is that really a not found rather than an
invalid
> situation?

> Is there a test exercising this branch?

I'll add a test, thanks. And the point is: there won't be a relation
with an invalid id anyway, so it's NotFoundError. It will also help
later in the API when we convert NotFoundErrors to ErrPerm.

https://codereview.appspot.com/12748044/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'names/relation.go'
2--- names/relation.go 1970-01-01 00:00:00 +0000
3+++ names/relation.go 2013-08-14 16:01:40 +0000
4@@ -0,0 +1,24 @@
5+// Copyright 2013 Canonical Ltd.
6+// Licensed under the AGPLv3, see LICENCE file for details.
7+
8+package names
9+
10+import (
11+ "fmt"
12+ "regexp"
13+)
14+
15+var validRelation = regexp.MustCompile("^" + NumberSnippet + "$")
16+
17+// IsRelation returns whether id is a valid relation id.
18+func IsRelation(id string) bool {
19+ return validRelation.MatchString(id)
20+}
21+
22+// RelationTag returns the tag for the relation with the given id.
23+func RelationTag(relationId string) string {
24+ if !IsRelation(relationId) {
25+ panic(fmt.Sprintf("%q is not a valid relation id", relationId))
26+ }
27+ return makeTag(RelationTagKind, relationId)
28+}
29
30=== added file 'names/relation_test.go'
31--- names/relation_test.go 1970-01-01 00:00:00 +0000
32+++ names/relation_test.go 2013-08-14 16:01:40 +0000
33@@ -0,0 +1,36 @@
34+// Copyright 2013 Canonical Ltd.
35+// Licensed under the AGPLv3, see LICENCE file for details.
36+
37+package names_test
38+
39+import (
40+ gc "launchpad.net/gocheck"
41+
42+ "launchpad.net/juju-core/names"
43+)
44+
45+type relationSuite struct{}
46+
47+var _ = gc.Suite(&relationSuite{})
48+
49+var relationIdTests = []struct {
50+ pattern string
51+ valid bool
52+}{
53+ {pattern: "", valid: false},
54+ {pattern: "foo", valid: false},
55+ {pattern: "foo42", valid: false},
56+ {pattern: "42", valid: true},
57+ {pattern: "0", valid: true},
58+ {pattern: "%not", valid: false},
59+ {pattern: "42also-not", valid: false},
60+ {pattern: "042", valid: false},
61+ {pattern: "0x42", valid: false},
62+}
63+
64+func (s *relationSuite) TestRelationIdFormats(c *gc.C) {
65+ for i, test := range relationIdTests {
66+ c.Logf("test %d: %q", i, test.pattern)
67+ c.Assert(names.IsRelation(test.pattern), gc.Equals, test.valid)
68+ }
69+}
70
71=== modified file 'names/tag.go'
72--- names/tag.go 2013-08-07 14:21:04 +0000
73+++ names/tag.go 2013-08-14 16:01:40 +0000
74@@ -9,19 +9,21 @@
75 )
76
77 const (
78- UnitTagKind = "unit"
79- MachineTagKind = "machine"
80- ServiceTagKind = "service"
81- EnvironTagKind = "environment"
82- UserTagKind = "user"
83+ UnitTagKind = "unit"
84+ MachineTagKind = "machine"
85+ ServiceTagKind = "service"
86+ EnvironTagKind = "environment"
87+ UserTagKind = "user"
88+ RelationTagKind = "relation"
89 )
90
91 var validKinds = map[string]bool{
92- UnitTagKind: true,
93- MachineTagKind: true,
94- ServiceTagKind: true,
95- EnvironTagKind: true,
96- UserTagKind: true,
97+ UnitTagKind: true,
98+ MachineTagKind: true,
99+ ServiceTagKind: true,
100+ EnvironTagKind: true,
101+ UserTagKind: true,
102+ RelationTagKind: true,
103 }
104
105 var tagSuffixToId = map[string]func(string) string{
106@@ -30,11 +32,12 @@
107 }
108
109 var verifyId = map[string]func(string) bool{
110- UnitTagKind: IsUnit,
111- MachineTagKind: IsMachine,
112- ServiceTagKind: IsService,
113- UserTagKind: IsUser,
114- EnvironTagKind: IsEnvironment,
115+ UnitTagKind: IsUnit,
116+ MachineTagKind: IsMachine,
117+ ServiceTagKind: IsService,
118+ UserTagKind: IsUser,
119+ EnvironTagKind: IsEnvironment,
120+ RelationTagKind: IsRelation,
121 }
122
123 // TagKind returns one of the *TagKind constants for the given tag, or
124
125=== modified file 'names/tag_test.go'
126--- names/tag_test.go 2013-08-07 14:21:04 +0000
127+++ names/tag_test.go 2013-08-14 16:01:40 +0000
128@@ -23,6 +23,7 @@
129 {tag: "service-foo", kind: names.ServiceTagKind},
130 {tag: "environment-42", kind: names.EnvironTagKind},
131 {tag: "user-admin", kind: names.UserTagKind},
132+ {tag: "relation-42", kind: names.RelationTagKind},
133 {tag: "foo", err: `"foo" is not a valid tag`},
134 {tag: "unit", err: `"unit" is not a valid tag`},
135 }
136@@ -95,6 +96,10 @@
137 expectKind: names.EnvironTagKind,
138 resultId: "foo",
139 }, {
140+ tag: "relation-42",
141+ expectKind: names.RelationTagKind,
142+ resultId: "42",
143+}, {
144 tag: "environment-/",
145 expectKind: names.EnvironTagKind,
146 resultErr: `"environment-/" is not a valid environment tag`,
147@@ -113,9 +118,10 @@
148 }}
149
150 var makeTag = map[string]func(id string) string{
151- names.MachineTagKind: names.MachineTag,
152- names.UnitTagKind: names.UnitTag,
153- names.ServiceTagKind: names.ServiceTag,
154+ names.MachineTagKind: names.MachineTag,
155+ names.UnitTagKind: names.UnitTag,
156+ names.ServiceTagKind: names.ServiceTag,
157+ names.RelationTagKind: names.RelationTag,
158 // TODO(rog) environment and user, when they have Tag functions.
159 }
160
161
162=== modified file 'state/relation.go'
163--- state/relation.go 2013-07-09 10:32:23 +0000
164+++ state/relation.go 2013-08-14 16:01:40 +0000
165@@ -15,6 +15,7 @@
166
167 "launchpad.net/juju-core/charm"
168 errors "launchpad.net/juju-core/errors"
169+ "launchpad.net/juju-core/names"
170 "launchpad.net/juju-core/utils"
171 )
172
173@@ -60,6 +61,12 @@
174 return r.doc.Key
175 }
176
177+// Tag returns a name identifying the relation that is safe to use
178+// as a file name.
179+func (r *Relation) Tag() string {
180+ return names.RelationTag(strconv.Itoa(r.doc.Id))
181+}
182+
183 // Refresh refreshes the contents of the relation from the underlying
184 // state. It returns an error that satisfies IsNotFound if the relation has been
185 // removed.
186
187=== modified file 'state/state.go'
188--- state/state.go 2013-08-07 14:23:50 +0000
189+++ state/state.go 2013-08-14 16:01:40 +0000
190@@ -492,6 +492,12 @@
191 return nil, errors.NotFoundf("environment %q", id)
192 }
193 return st.Environment()
194+ case names.RelationTagKind:
195+ relId, err := strconv.Atoi(id)
196+ if err != nil {
197+ return nil, errors.NotFoundf("relation %s", id)
198+ }
199+ return st.Relation(relId)
200 }
201 return nil, err
202 }
203@@ -512,6 +518,8 @@
204 coll = st.units.Name
205 case names.UserTagKind:
206 coll = st.users.Name
207+ case names.RelationTagKind:
208+ coll = st.relations.Name
209 default:
210 return "", "", fmt.Errorf("%q is not a valid collection tag", tag)
211 }
212@@ -1181,6 +1189,7 @@
213 's': names.ServiceTagKind + "-",
214 'u': names.UnitTagKind + "-",
215 'e': names.EnvironTagKind + "-",
216+ 'r': names.RelationTagKind + "-",
217 }
218
219 func tagForGlobalKey(key string) (string, bool) {
220
221=== modified file 'state/state_test.go'
222--- state/state_test.go 2013-08-08 17:56:28 +0000
223+++ state/state_test.go 2013-08-14 16:01:40 +0000
224@@ -1412,6 +1412,12 @@
225 tag: "unit-123",
226 err: `"unit-123" is not a valid unit tag`,
227 }, {
228+ tag: "relation-blah",
229+ err: `"relation-blah" is not a valid relation tag`,
230+}, {
231+ tag: "relation-42",
232+ err: "relation 42 not found",
233+}, {
234 tag: "unit-foo",
235 err: `"unit-foo" is not a valid unit tag`,
236 }, {
237@@ -1437,6 +1443,8 @@
238 }, {
239 tag: "service-ser-vice2",
240 }, {
241+ tag: "relation-0",
242+}, {
243 tag: "unit-ser-vice2-0",
244 }, {
245 tag: "user-arble",
246@@ -1445,11 +1453,12 @@
247 }}
248
249 var entityTypes = map[string]interface{}{
250- names.UserTagKind: (*state.User)(nil),
251- names.EnvironTagKind: (*state.Environment)(nil),
252- names.ServiceTagKind: (*state.Service)(nil),
253- names.UnitTagKind: (*state.Unit)(nil),
254- names.MachineTagKind: (*state.Machine)(nil),
255+ names.UserTagKind: (*state.User)(nil),
256+ names.EnvironTagKind: (*state.Environment)(nil),
257+ names.ServiceTagKind: (*state.Service)(nil),
258+ names.UnitTagKind: (*state.Unit)(nil),
259+ names.MachineTagKind: (*state.Machine)(nil),
260+ names.RelationTagKind: (*state.Relation)(nil),
261 }
262
263 func (s *StateSuite) TestFindEntity(c *gc.C) {
264@@ -1461,6 +1470,13 @@
265 c.Assert(err, gc.IsNil)
266 _, err = s.State.AddUser("arble", "pass")
267 c.Assert(err, gc.IsNil)
268+ _, err = s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress"))
269+ c.Assert(err, gc.IsNil)
270+ eps, err := s.State.InferEndpoints([]string{"wordpress", "ser-vice2"})
271+ c.Assert(err, gc.IsNil)
272+ rel, err := s.State.AddRelation(eps...)
273+ c.Assert(err, gc.IsNil)
274+ c.Assert(rel.Id(), gc.Equals, 0)
275
276 for i, test := range findEntityTests {
277 c.Logf("test %d: %q", i, test.tag)

Subscribers

People subscribed via source and target branches

to status/vote changes: