~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/gopkg.in/juju/charmstore.v5-unstable/internal/v5/status_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2014 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package v5_test // import "gopkg.in/juju/charmstore.v5-unstable/internal/v5"
 
5
 
 
6
import (
 
7
        "encoding/json"
 
8
        "net/http"
 
9
        "time"
 
10
 
 
11
        jc "github.com/juju/testing/checkers"
 
12
        "github.com/juju/testing/httptesting"
 
13
        "github.com/juju/utils/debugstatus"
 
14
        gc "gopkg.in/check.v1"
 
15
        "gopkg.in/juju/charm.v6-unstable"
 
16
        "gopkg.in/juju/charmrepo.v2-unstable/csclient/params"
 
17
 
 
18
        "gopkg.in/juju/charmstore.v5-unstable/internal/mongodoc"
 
19
        "gopkg.in/juju/charmstore.v5-unstable/internal/router"
 
20
)
 
21
 
 
22
var zeroTimeStr = time.Time{}.Format(time.RFC3339)
 
23
 
 
24
func (s *APISuite) TestStatus(c *gc.C) {
 
25
        for _, id := range []*router.ResolvedURL{
 
26
                newResolvedURL("cs:~charmers/precise/wordpress-2", 2),
 
27
                newResolvedURL("cs:~charmers/precise/wordpress-3", 3),
 
28
                newResolvedURL("cs:~foo/precise/mysql-9", 1),
 
29
                newResolvedURL("cs:~bar/utopic/mysql-10", -1),
 
30
                newResolvedURL("cs:~charmers/bundle/wordpress-simple-3", 3),
 
31
                newResolvedURL("cs:~bar/bundle/wordpress-simple-4", -1),
 
32
        } {
 
33
                if id.URL.Series == "bundle" {
 
34
                        s.addPublicBundleFromRepo(c, id.URL.Name, id, false)
 
35
                } else {
 
36
                        s.addPublicCharmFromRepo(c, id.URL.Name, id)
 
37
                }
 
38
        }
 
39
        now := time.Now()
 
40
        s.PatchValue(&debugstatus.StartTime, now)
 
41
        start := now.Add(-2 * time.Hour)
 
42
        s.addLog(c, &mongodoc.Log{
 
43
                Data:  []byte(`"ingestion started"`),
 
44
                Level: mongodoc.InfoLevel,
 
45
                Type:  mongodoc.IngestionType,
 
46
                Time:  start,
 
47
        })
 
48
        end := now.Add(-1 * time.Hour)
 
49
        s.addLog(c, &mongodoc.Log{
 
50
                Data:  []byte(`"ingestion completed"`),
 
51
                Level: mongodoc.InfoLevel,
 
52
                Type:  mongodoc.IngestionType,
 
53
                Time:  end,
 
54
        })
 
55
        statisticsStart := now.Add(-1*time.Hour - 30*time.Minute)
 
56
        s.addLog(c, &mongodoc.Log{
 
57
                Data:  []byte(`"legacy statistics import started"`),
 
58
                Level: mongodoc.InfoLevel,
 
59
                Type:  mongodoc.LegacyStatisticsType,
 
60
                Time:  statisticsStart,
 
61
        })
 
62
        statisticsEnd := now.Add(-30 * time.Minute)
 
63
        s.addLog(c, &mongodoc.Log{
 
64
                Data:  []byte(`"legacy statistics import completed"`),
 
65
                Level: mongodoc.InfoLevel,
 
66
                Type:  mongodoc.LegacyStatisticsType,
 
67
                Time:  statisticsEnd,
 
68
        })
 
69
        s.AssertDebugStatus(c, true, map[string]params.DebugStatus{
 
70
                "mongo_connected": {
 
71
                        Name:   "MongoDB is connected",
 
72
                        Value:  "Connected",
 
73
                        Passed: true,
 
74
                },
 
75
                "mongo_collections": {
 
76
                        Name:   "MongoDB collections",
 
77
                        Value:  "All required collections exist",
 
78
                        Passed: true,
 
79
                },
 
80
                "elasticsearch": {
 
81
                        Name:   "Elastic search is running",
 
82
                        Value:  "Elastic search is not configured",
 
83
                        Passed: true,
 
84
                },
 
85
                "entities": {
 
86
                        Name:   "Entities in charm store",
 
87
                        Value:  "4 charms; 2 bundles; 4 promulgated",
 
88
                        Passed: true,
 
89
                },
 
90
                "base_entities": {
 
91
                        Name:   "Base entities in charm store",
 
92
                        Value:  "count: 5",
 
93
                        Passed: true,
 
94
                },
 
95
                "server_started": {
 
96
                        Name:   "Server started",
 
97
                        Value:  now.String(),
 
98
                        Passed: true,
 
99
                },
 
100
                "ingestion": {
 
101
                        Name:   "Ingestion",
 
102
                        Value:  "started: " + start.Format(time.RFC3339) + ", completed: " + end.Format(time.RFC3339),
 
103
                        Passed: true,
 
104
                },
 
105
                "legacy_statistics": {
 
106
                        Name:   "Legacy Statistics Load",
 
107
                        Value:  "started: " + statisticsStart.Format(time.RFC3339) + ", completed: " + statisticsEnd.Format(time.RFC3339),
 
108
                        Passed: true,
 
109
                },
 
110
        })
 
111
}
 
112
 
 
113
func (s *APISuite) TestStatusWithoutCorrectCollections(c *gc.C) {
 
114
        s.store.DB.Entities().DropCollection()
 
115
        s.AssertDebugStatus(c, false, map[string]params.DebugStatus{
 
116
                "mongo_collections": {
 
117
                        Name:   "MongoDB collections",
 
118
                        Value:  "Missing collections: [" + s.store.DB.Entities().Name + "]",
 
119
                        Passed: false,
 
120
                },
 
121
        })
 
122
}
 
123
 
 
124
func (s *APISuite) TestStatusWithoutIngestion(c *gc.C) {
 
125
        s.AssertDebugStatus(c, false, map[string]params.DebugStatus{
 
126
                "ingestion": {
 
127
                        Name:   "Ingestion",
 
128
                        Value:  "started: " + zeroTimeStr + ", completed: " + zeroTimeStr,
 
129
                        Passed: false,
 
130
                },
 
131
        })
 
132
}
 
133
 
 
134
func (s *APISuite) TestStatusIngestionStarted(c *gc.C) {
 
135
        now := time.Now()
 
136
        start := now.Add(-1 * time.Hour)
 
137
        s.addLog(c, &mongodoc.Log{
 
138
                Data:  []byte(`"ingestion started"`),
 
139
                Level: mongodoc.InfoLevel,
 
140
                Type:  mongodoc.IngestionType,
 
141
                Time:  start,
 
142
        })
 
143
        s.AssertDebugStatus(c, false, map[string]params.DebugStatus{
 
144
                "ingestion": {
 
145
                        Name:   "Ingestion",
 
146
                        Value:  "started: " + start.Format(time.RFC3339) + ", completed: " + zeroTimeStr,
 
147
                        Passed: false,
 
148
                },
 
149
        })
 
150
}
 
151
 
 
152
func (s *APISuite) TestStatusWithoutLegacyStatistics(c *gc.C) {
 
153
        s.AssertDebugStatus(c, false, map[string]params.DebugStatus{
 
154
                "legacy_statistics": {
 
155
                        Name:   "Legacy Statistics Load",
 
156
                        Value:  "started: " + zeroTimeStr + ", completed: " + zeroTimeStr,
 
157
                        Passed: false,
 
158
                },
 
159
        })
 
160
}
 
161
 
 
162
func (s *APISuite) TestStatusLegacyStatisticsStarted(c *gc.C) {
 
163
        now := time.Now()
 
164
        statisticsStart := now.Add(-1*time.Hour - 30*time.Minute)
 
165
        s.addLog(c, &mongodoc.Log{
 
166
                Data:  []byte(`"legacy statistics import started"`),
 
167
                Level: mongodoc.InfoLevel,
 
168
                Type:  mongodoc.LegacyStatisticsType,
 
169
                Time:  statisticsStart,
 
170
        })
 
171
        s.AssertDebugStatus(c, false, map[string]params.DebugStatus{
 
172
                "legacy_statistics": {
 
173
                        Name:   "Legacy Statistics Load",
 
174
                        Value:  "started: " + statisticsStart.Format(time.RFC3339) + ", completed: " + zeroTimeStr,
 
175
                        Passed: false,
 
176
                },
 
177
        })
 
178
}
 
179
 
 
180
func (s *APISuite) TestStatusLegacyStatisticsMultipleLogs(c *gc.C) {
 
181
        now := time.Now()
 
182
        statisticsStart := now.Add(-1*time.Hour - 30*time.Minute)
 
183
        s.addLog(c, &mongodoc.Log{
 
184
                Data:  []byte(`"legacy statistics import started"`),
 
185
                Level: mongodoc.InfoLevel,
 
186
                Type:  mongodoc.LegacyStatisticsType,
 
187
                Time:  statisticsStart.Add(-1 * time.Hour),
 
188
        })
 
189
        s.addLog(c, &mongodoc.Log{
 
190
                Data:  []byte(`"legacy statistics import started"`),
 
191
                Level: mongodoc.InfoLevel,
 
192
                Type:  mongodoc.LegacyStatisticsType,
 
193
                Time:  statisticsStart,
 
194
        })
 
195
        statisticsEnd := now.Add(-30 * time.Minute)
 
196
        s.addLog(c, &mongodoc.Log{
 
197
                Data:  []byte(`"legacy statistics import completed"`),
 
198
                Level: mongodoc.InfoLevel,
 
199
                Type:  mongodoc.LegacyStatisticsType,
 
200
                Time:  statisticsEnd.Add(-1 * time.Hour),
 
201
        })
 
202
        s.addLog(c, &mongodoc.Log{
 
203
                Data:  []byte(`"legacy statistics import completed"`),
 
204
                Level: mongodoc.InfoLevel,
 
205
                Type:  mongodoc.LegacyStatisticsType,
 
206
                Time:  statisticsEnd,
 
207
        })
 
208
        s.AssertDebugStatus(c, false, map[string]params.DebugStatus{
 
209
                "legacy_statistics": {
 
210
                        Name:   "Legacy Statistics Load",
 
211
                        Value:  "started: " + statisticsStart.Format(time.RFC3339) + ", completed: " + statisticsEnd.Format(time.RFC3339),
 
212
                        Passed: true,
 
213
                },
 
214
        })
 
215
}
 
216
 
 
217
func (s *APISuite) TestStatusBaseEntitiesError(c *gc.C) {
 
218
        // Add a base entity without any corresponding entities.
 
219
        entity := &mongodoc.BaseEntity{
 
220
                URL:  charm.MustParseURL("django"),
 
221
                Name: "django",
 
222
        }
 
223
        err := s.store.DB.BaseEntities().Insert(entity)
 
224
        c.Assert(err, gc.IsNil)
 
225
 
 
226
        s.AssertDebugStatus(c, false, map[string]params.DebugStatus{
 
227
                "base_entities": {
 
228
                        Name:   "Base entities in charm store",
 
229
                        Value:  "count: 1",
 
230
                        Passed: false,
 
231
                },
 
232
        })
 
233
}
 
234
 
 
235
// AssertDebugStatus asserts that the current /debug/status endpoint
 
236
// matches the given status, ignoring status duration.
 
237
// If complete is true, it fails if the results contain
 
238
// keys not mentioned in status.
 
239
func (s *APISuite) AssertDebugStatus(c *gc.C, complete bool, status map[string]params.DebugStatus) {
 
240
        rec := httptesting.DoRequest(c, httptesting.DoRequestParams{
 
241
                Handler: s.srv,
 
242
                URL:     storeURL("debug/status"),
 
243
        })
 
244
        c.Assert(rec.Code, gc.Equals, http.StatusOK, gc.Commentf("body: %s", rec.Body.Bytes()))
 
245
        c.Assert(rec.Header().Get("Content-Type"), gc.Equals, "application/json")
 
246
        var gotStatus map[string]params.DebugStatus
 
247
        err := json.Unmarshal(rec.Body.Bytes(), &gotStatus)
 
248
        c.Assert(err, gc.IsNil)
 
249
        for key, r := range gotStatus {
 
250
                if _, found := status[key]; !complete && !found {
 
251
                        delete(gotStatus, key)
 
252
                        continue
 
253
                }
 
254
                r.Duration = 0
 
255
                gotStatus[key] = r
 
256
        }
 
257
        c.Assert(gotStatus, jc.DeepEquals, status)
 
258
}
 
259
 
 
260
type statusWithElasticSearchSuite struct {
 
261
        commonSuite
 
262
}
 
263
 
 
264
var _ = gc.Suite(&statusWithElasticSearchSuite{})
 
265
 
 
266
func (s *statusWithElasticSearchSuite) SetUpSuite(c *gc.C) {
 
267
        s.enableES = true
 
268
        s.commonSuite.SetUpSuite(c)
 
269
}
 
270
 
 
271
func (s *statusWithElasticSearchSuite) TestStatusWithElasticSearch(c *gc.C) {
 
272
        rec := httptesting.DoRequest(c, httptesting.DoRequestParams{
 
273
                Handler: s.srv,
 
274
                URL:     storeURL("debug/status"),
 
275
        })
 
276
        var results map[string]params.DebugStatus
 
277
        err := json.Unmarshal(rec.Body.Bytes(), &results)
 
278
        c.Assert(err, gc.IsNil)
 
279
        c.Assert(results["elasticsearch"].Name, gc.Equals, "Elastic search is running")
 
280
        c.Assert(results["elasticsearch"].Value, jc.Contains, "cluster_name:")
 
281
}