Merge lp:~cmars/juju-core/cs-resolve-notfound-fix into lp:~go-bot/juju-core/trunk

Proposed by Casey Marshall
Status: Merged
Approved by: Casey Marshall
Approved revision: no longer in the source branch.
Merged at revision: 2499
Proposed branch: lp:~cmars/juju-core/cs-resolve-notfound-fix
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 150 lines (+78/-4)
4 files modified
store/server.go (+1/-1)
store/server_test.go (+17/-0)
store/store.go (+5/-3)
store/store_test.go (+55/-0)
To merge this branch: bzr merge lp:~cmars/juju-core/cs-resolve-notfound-fix
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+212991@code.launchpad.net

Commit message

Fixed charm store series resolving issues.

Fixed an issue where trying to resolve series for a charm not found causes an
HTTP 502, needed a nil check.

Fixed an issue where the charm URL regex match for resolving series was
too greedy, causing it to fail to resolve mysql, for example.

Added test cases for the above.

Description of the change

Fixed charm store series resolving issues.

Fixed an issue where trying to resolve series for a charm not found causes an
HTTP 502, needed a nil check.

Fixed an issue where the charm URL regex match for resolving series was
too greedy, causing it to fail to resolve mysql, for example.

Added test cases for the above.

https://codereview.appspot.com/81250043/

To post a comment you must log in.
Revision history for this message
Casey Marshall (cmars) wrote :
Download full text (6.3 KiB)

Reviewers: mp+212991_code.launchpad.net,

Message:
Please take a look.

Description:
Fixed charm store series resolving issues.

Fixed an issue where trying to resolve series for a charm not found
causes an
HTTP 502, needed a nil check.

Fixed an issue where the charm URL regex match for resolving series was
too greedy, causing it to fail to resolve mysql, for example.

Added test cases for the above.

https://code.launchpad.net/~cmars/juju-core/cs-resolve-notfound-fix/+merge/212991

(do not edit description out of merge proposal)

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

Affected files (+80, -4 lines):
   A [revision details]
   M store/server.go
   M store/server_test.go
   M store/store.go
   M store/store_test.go

Index: [revision details]
=== added file '[revision details]'
--- [revision details] 2012-01-01 00:00:00 +0000
+++ [revision details] 2012-01-01 00:00:00 +0000
@@ -0,0 +1,2 @@
+Old revision: tarmac-20140325164440-iqj920tnf1v754dw
+New revision: <email address hidden>

Index: store/server.go
=== modified file 'store/server.go'
--- store/server.go 2014-03-24 15:35:41 +0000
+++ store/server.go 2014-03-25 18:57:36 +0000
@@ -117,7 +117,7 @@
     c.Revision = info.Revision()
     c.Digest = info.Digest()
    } else {
- if err == ErrNotFound {
+ if err == ErrNotFound && curl != nil {
      skey = charmStatsKey(curl, "charm-missing")
     }
     c.Errors = append(c.Errors, err.Error())

Index: store/server_test.go
=== modified file 'store/server_test.go'
--- store/server_test.go 2014-03-20 19:51:05 +0000
+++ store/server_test.go 2014-03-27 05:00:05 +0000
@@ -183,6 +183,23 @@
   s.checkCounterSum(c, []string{"charm-event", "oneiric", "mysql"}, false,
1)
  }

+func (s *StoreSuite) TestSeriesNotFound(c *gc.C) {
+ server, err := store.NewServer(s.store)
+ req, err := http.NewRequest("GET", "/charm-info?charms=cs:not-found", nil)
+ c.Assert(err, gc.IsNil)
+ rec := httptest.NewRecorder()
+ server.ServeHTTP(rec, req)
+ c.Assert(rec.Code, gc.Equals, http.StatusOK)
+
+ expected := map[string]interface{}{"cs:not-found": map[string]interface{}{
+ "revision": float64(0),
+ "errors": []interface{}{"entry not found"}}}
+ obtained := map[string]interface{}{}
+ err = json.NewDecoder(rec.Body).Decode(&obtained)
+ c.Assert(err, gc.IsNil)
+ c.Assert(obtained, gc.DeepEquals, expected)
+}
+
  // checkCounterSum checks that statistics are properly collected.
  // It retries a few times as they are generally collected in background.
  func (s *StoreSuite) checkCounterSum(c *gc.C, key []string, prefix bool,
expected int64) {

Index: store/store.go
=== modified file 'store/store.go'
--- store/store.go 2014-03-21 03:20:40 +0000
+++ store/store.go 2014-03-27 05:00:05 +0000
@@ -738,12 +738,12 @@
   session := s.session.Copy()
   defer session.Close()

- patternURL := &charm.URL{Reference: ref, Series: ".*"}
+ patternURL := &charm.URL{Reference: ref, Series: "[a-z][^/]+"}
   patternURL = patternURL.WithRevision(-1)

   charms := session.Charms()
   q := charms.Find(bson.M{
- "urls": bson.RegEx{Pattern: patternURL.String()},
+ "urls": bson.RegEx{Pattern: fmt.Sprintf("^%s$", patternURL.String())},
...

Read more...

Revision history for this message
William Reade (fwereade) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'store/server.go'
2--- store/server.go 2014-03-24 15:35:41 +0000
3+++ store/server.go 2014-03-27 05:09:20 +0000
4@@ -117,7 +117,7 @@
5 c.Revision = info.Revision()
6 c.Digest = info.Digest()
7 } else {
8- if err == ErrNotFound {
9+ if err == ErrNotFound && curl != nil {
10 skey = charmStatsKey(curl, "charm-missing")
11 }
12 c.Errors = append(c.Errors, err.Error())
13
14=== modified file 'store/server_test.go'
15--- store/server_test.go 2014-03-20 19:51:05 +0000
16+++ store/server_test.go 2014-03-27 05:09:20 +0000
17@@ -183,6 +183,23 @@
18 s.checkCounterSum(c, []string{"charm-event", "oneiric", "mysql"}, false, 1)
19 }
20
21+func (s *StoreSuite) TestSeriesNotFound(c *gc.C) {
22+ server, err := store.NewServer(s.store)
23+ req, err := http.NewRequest("GET", "/charm-info?charms=cs:not-found", nil)
24+ c.Assert(err, gc.IsNil)
25+ rec := httptest.NewRecorder()
26+ server.ServeHTTP(rec, req)
27+ c.Assert(rec.Code, gc.Equals, http.StatusOK)
28+
29+ expected := map[string]interface{}{"cs:not-found": map[string]interface{}{
30+ "revision": float64(0),
31+ "errors": []interface{}{"entry not found"}}}
32+ obtained := map[string]interface{}{}
33+ err = json.NewDecoder(rec.Body).Decode(&obtained)
34+ c.Assert(err, gc.IsNil)
35+ c.Assert(obtained, gc.DeepEquals, expected)
36+}
37+
38 // checkCounterSum checks that statistics are properly collected.
39 // It retries a few times as they are generally collected in background.
40 func (s *StoreSuite) checkCounterSum(c *gc.C, key []string, prefix bool, expected int64) {
41
42=== modified file 'store/store.go'
43--- store/store.go 2014-03-21 03:20:40 +0000
44+++ store/store.go 2014-03-27 05:09:20 +0000
45@@ -738,12 +738,12 @@
46 session := s.session.Copy()
47 defer session.Close()
48
49- patternURL := &charm.URL{Reference: ref, Series: ".*"}
50+ patternURL := &charm.URL{Reference: ref, Series: "[a-z][^/]+"}
51 patternURL = patternURL.WithRevision(-1)
52
53 charms := session.Charms()
54 q := charms.Find(bson.M{
55- "urls": bson.RegEx{Pattern: patternURL.String()},
56+ "urls": bson.RegEx{Pattern: fmt.Sprintf("^%s$", patternURL.String())},
57 })
58 var cdocs []charmDoc
59 err := q.All(&cdocs)
60@@ -755,7 +755,9 @@
61 seriesSet := make(map[string]bool)
62 for _, cdoc := range cdocs {
63 for _, url := range cdoc.URLs {
64- seriesSet[url.Series] = true
65+ if ref == url.Reference {
66+ seriesSet[url.Series] = true
67+ }
68 }
69 }
70
71
72=== modified file 'store/store_test.go'
73--- store/store_test.go 2014-03-21 03:20:40 +0000
74+++ store/store_test.go 2014-03-27 05:09:20 +0000
75@@ -344,6 +344,9 @@
76 {"trusty", "wordpress"},
77 {"volumetric", "wordpress"},
78
79+ {"precise", "mysql"},
80+ {"trusty", "mysqladmin"},
81+
82 {"def", "zebra"},
83 {"zef", "zebra"},
84 }
85@@ -373,6 +376,14 @@
86 c.Check(series[3], gc.Equals, "quantal")
87 c.Check(series[4], gc.Equals, "oneiric")
88
89+ // Ensure that the full charm name matches, not just prefix
90+ ref, _, err = charm.ParseReference("cs:mysql")
91+ c.Assert(err, gc.IsNil)
92+ series, err = s.store.Series(ref)
93+ c.Assert(err, gc.IsNil)
94+ c.Assert(series, gc.HasLen, 1)
95+ c.Check(series[0], gc.Equals, "precise")
96+
97 // No LTS, reverse alphabetical order
98 ref, _, err = charm.ParseReference("cs:zebra")
99 c.Assert(err, gc.IsNil)
100@@ -383,6 +394,50 @@
101 c.Check(series[1], gc.Equals, "def")
102 }
103
104+var mysqlSeriesCharms = []struct {
105+ fakeDigest string
106+ urls []string
107+}{
108+ {"533224069221503992aaa726", []string{"cs:~charmers/oneiric/mysql", "cs:oneiric/mysql"}},
109+ {"533224c79221503992aaa7ea", []string{"cs:~charmers/precise/mysql", "cs:precise/mysql"}},
110+ {"533223a69221503992aaa6be", []string{"cs:~bjornt/trusty/mysql"}},
111+ {"533225b49221503992aaa8e5", []string{"cs:~clint-fewbar/precise/mysql"}},
112+ {"5332261b9221503992aaa96b", []string{"cs:~gandelman-a/precise/mysql"}},
113+ {"533226289221503992aaa97d", []string{"cs:~gandelman-a/quantal/mysql"}},
114+ {"5332264d9221503992aaa9b0", []string{"cs:~hazmat/precise/mysql"}},
115+ {"5332272d9221503992aaaa4d", []string{"cs:~jmit/oneiric/mysql"}},
116+ {"53328a439221503992aaad28", []string{"cs:~landscape/trusty/mysql"}},
117+ {"533228ae9221503992aaab96", []string{"cs:~negronjl/precise/mysql-file-permissions"}},
118+ {"533228f39221503992aaabde", []string{"cs:~openstack-ubuntu-testing/oneiric/mysql"}},
119+ {"533229029221503992aaabed", []string{"cs:~openstack-ubuntu-testing/precise/mysql"}},
120+ {"5332291e9221503992aaac09", []string{"cs:~openstack-ubuntu-testing/quantal/mysql"}},
121+ {"53327f4f9221503992aaad1e", []string{"cs:~tribaal/trusty/mysql"}},
122+}
123+
124+func (s *StoreSuite) TestMysqlSeriesSolver(c *gc.C) {
125+ for _, t := range mysqlSeriesCharms {
126+ var urls []*charm.URL
127+ for _, url := range t.urls {
128+ urls = append(urls, charm.MustParseURL(url))
129+ }
130+
131+ pub, err := s.store.CharmPublisher(urls, t.fakeDigest)
132+ c.Assert(err, gc.IsNil)
133+ c.Assert(pub.Revision(), gc.Equals, 0)
134+
135+ err = pub.Publish(&FakeCharmDir{})
136+ c.Assert(err, gc.IsNil)
137+ }
138+
139+ ref, _, err := charm.ParseReference("cs:mysql")
140+ c.Assert(err, gc.IsNil)
141+ series, err := s.store.Series(ref)
142+ c.Assert(err, gc.IsNil)
143+ c.Assert(series, gc.HasLen, 2)
144+ c.Check(series[0], gc.Equals, "precise")
145+ c.Check(series[1], gc.Equals, "oneiric")
146+}
147+
148 func (s *StoreSuite) TestConflictingUpdate(c *gc.C) {
149 // This test checks that if for whatever reason the locking
150 // safety-net fails, adding two charms in parallel still

Subscribers

People subscribed via source and target branches

to status/vote changes: