Merge lp:~pedronis/ubuntu-push/fixes-to-wily into lp:ubuntu-push

Proposed by Samuele Pedroni
Status: Merged
Approved by: Samuele Pedroni
Approved revision: 150
Merged at revision: 149
Proposed branch: lp:~pedronis/ubuntu-push/fixes-to-wily
Merge into: lp:ubuntu-push
Diff against target: 705 lines (+257/-136)
9 files modified
client/service/postal.go (+0/-2)
messaging/cmessaging/cmessaging.go (+0/-1)
messaging/messaging.go (+32/-49)
messaging/messaging_test.go (+102/-50)
server/acceptance/acceptanceclient.go (+6/-1)
server/acceptance/cmd/acceptanceclient.go (+1/-1)
server/acceptance/kit/api.go (+41/-7)
server/acceptance/kit/cliloop.go (+73/-23)
ubuntu-push-client.go (+2/-2)
To merge this branch: bzr merge lp:~pedronis/ubuntu-push/fixes-to-wily
Reviewer Review Type Date Requested Status
Samuele Pedroni Approve
Review via email: mp+268067@code.launchpad.net

Commit message

* address lp:1451510 aggressively finding gone notifications in Tags()
* truncate runtime.Stack result to size, otherwise we log \x00s or old stuff

Description of the change

bring in recent fixes, mainly addressing lp:1451510

To post a comment you must log in.
Revision history for this message
Samuele Pedroni (pedronis) :
review: Approve
150. By Samuele Pedroni

revert rules

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'client/service/postal.go'
2--- client/service/postal.go 2015-03-05 14:09:54 +0000
3+++ client/service/postal.go 2015-08-14 14:03:06 +0000
4@@ -53,7 +53,6 @@
5 Presenter
6 GetCh() chan *reply.MMActionReply
7 RemoveNotification(string, bool)
8- StartCleanupLoop()
9 Tags(*click.AppId) []string
10 Clear(*click.AppId, ...string) int
11 }
12@@ -187,7 +186,6 @@
13
14 go svc.consumeHelperResults(svc.HelperPool.Start())
15 go svc.handleActions(actionsCh, svc.messagingMenu.GetCh())
16- svc.messagingMenu.StartCleanupLoop()
17 return nil
18 }
19
20
21=== modified file 'messaging/cmessaging/cmessaging.go'
22--- messaging/cmessaging/cmessaging.go 2014-08-07 10:20:35 +0000
23+++ messaging/cmessaging/cmessaging.go 2015-08-14 14:03:06 +0000
24@@ -44,7 +44,6 @@
25 Actions []string
26 App *click.AppId
27 Tag string
28- Gone bool
29 }
30
31 func gchar(s string) *C.gchar {
32
33=== modified file 'messaging/messaging.go'
34--- messaging/messaging.go 2015-01-22 09:52:07 +0000
35+++ messaging/messaging.go 2015-08-14 14:03:06 +0000
36@@ -31,23 +31,19 @@
37 "launchpad.net/ubuntu-push/messaging/reply"
38 )
39
40-var cleanupLoopDuration = 5 * time.Minute
41-
42 type MessagingMenu struct {
43- Log logger.Logger
44- Ch chan *reply.MMActionReply
45- notifications map[string]*cmessaging.Payload // keep a ref to the Payload used in the MMU callback
46- lock sync.RWMutex
47- stopCleanupLoopCh chan bool
48- ticker *time.Ticker
49- tickerCh <-chan time.Time
50+ Log logger.Logger
51+ Ch chan *reply.MMActionReply
52+ notifications map[string]*cmessaging.Payload // keep a ref to the Payload used in the MMU callback
53+ lock sync.RWMutex
54+ lastCleanupTime time.Time
55 }
56
57+type cleanUp func()
58+
59 // New returns a new MessagingMenu
60 func New(log logger.Logger) *MessagingMenu {
61- ticker := time.NewTicker(cleanupLoopDuration)
62- stopCh := make(chan bool)
63- return &MessagingMenu{Log: log, Ch: make(chan *reply.MMActionReply), notifications: make(map[string]*cmessaging.Payload), ticker: ticker, tickerCh: ticker.C, stopCleanupLoopCh: stopCh}
64+ return &MessagingMenu{Log: log, Ch: make(chan *reply.MMActionReply), notifications: make(map[string]*cmessaging.Payload)}
65 }
66
67 var cAddNotification = cmessaging.AddNotification
68@@ -59,12 +55,23 @@
69 return mmu.Ch
70 }
71
72-func (mmu *MessagingMenu) addNotification(app *click.AppId, notificationId string, tag string, card *launch_helper.Card, actions []string) {
73+func (mmu *MessagingMenu) addNotification(app *click.AppId, notificationId string, tag string, card *launch_helper.Card, actions []string, testingCleanUpFunction cleanUp) {
74 mmu.lock.Lock()
75 defer mmu.lock.Unlock()
76 payload := &cmessaging.Payload{Ch: mmu.Ch, Actions: actions, App: app, Tag: tag}
77 mmu.notifications[notificationId] = payload
78 cAddNotification(app.DesktopId(), notificationId, card, payload)
79+
80+ // Clean up our internal notifications store if it holds more than 20 messages (and apparently nobody ever calls Tags())
81+ if len(mmu.notifications) > 20 && time.Since(mmu.lastCleanupTime).Minutes() > 10 {
82+ mmu.lastCleanupTime = time.Now()
83+ if testingCleanUpFunction == nil {
84+ go mmu.cleanUpNotifications()
85+ } else {
86+ testingCleanUpFunction() // Has to implement the asynchronous part itself
87+ }
88+
89+ }
90 }
91
92 func (mmu *MessagingMenu) RemoveNotification(notificationId string, fromUI bool) {
93@@ -77,53 +84,28 @@
94 }
95 }
96
97-// cleanupNotifications remove notifications that were cleared from the messaging menu
98 func (mmu *MessagingMenu) cleanUpNotifications() {
99 mmu.lock.Lock()
100 defer mmu.lock.Unlock()
101+ mmu.doCleanUpNotifications()
102+}
103+
104+// doCleanupNotifications removes notifications that were cleared from the messaging menu
105+func (mmu *MessagingMenu) doCleanUpNotifications() {
106 for nid, payload := range mmu.notifications {
107- if payload.Gone {
108- // sweep
109+ if !cNotificationExists(payload.App.DesktopId(), nid) {
110 delete(mmu.notifications, nid)
111- // don't check the mmu for this nid
112- continue
113- }
114- exists := cNotificationExists(payload.App.DesktopId(), nid)
115- if !exists {
116- // mark
117- payload.Gone = true
118 }
119 }
120 }
121
122-func (mmu *MessagingMenu) StartCleanupLoop() {
123- mmu.doStartCleanupLoop(mmu.cleanUpNotifications)
124-}
125-
126-func (mmu *MessagingMenu) doStartCleanupLoop(cleanupFunc func()) {
127- go func() {
128- for {
129- select {
130- case <-mmu.tickerCh:
131- cleanupFunc()
132- case <-mmu.stopCleanupLoopCh:
133- mmu.ticker.Stop()
134- mmu.Log.Debugf("CleanupLoop stopped.")
135- return
136- }
137- }
138- }()
139-}
140-
141-func (mmu *MessagingMenu) StopCleanupLoop() {
142- mmu.stopCleanupLoopCh <- true
143-}
144-
145 func (mmu *MessagingMenu) Tags(app *click.AppId) []string {
146 orig := app.Original()
147 tags := []string(nil)
148- mmu.lock.RLock()
149- defer mmu.lock.RUnlock()
150+ mmu.lock.Lock()
151+ defer mmu.lock.Unlock()
152+ mmu.lastCleanupTime = time.Now()
153+ mmu.doCleanUpNotifications()
154 for _, payload := range mmu.notifications {
155 if payload.App.Original() == orig {
156 tags = append(tags, payload.Tag)
157@@ -156,6 +138,7 @@
158 for _, nid := range nids {
159 mmu.RemoveNotification(nid, true)
160 }
161+ mmu.cleanUpNotifications()
162
163 return len(nids)
164 }
165@@ -190,7 +173,7 @@
166
167 mmu.Log.Debugf("[%s] creating notification centre entry for %s (summary: %s)", nid, app.Base(), card.Summary)
168
169- mmu.addNotification(app, nid, notification.Tag, card, actions)
170+ mmu.addNotification(app, nid, notification.Tag, card, actions, nil)
171
172 return true
173 }
174
175=== modified file 'messaging/messaging_test.go'
176--- messaging/messaging_test.go 2014-11-25 18:33:24 +0000
177+++ messaging/messaging_test.go 2015-08-14 14:03:06 +0000
178@@ -18,6 +18,8 @@
179
180 import (
181 "sort"
182+ "strconv"
183+ "sync"
184 "time"
185
186 . "launchpad.net/gocheck"
187@@ -48,8 +50,6 @@
188 cRemoveNotification = func(a, n string) {
189 ms.log.Debugf("REMOVE: app: %s, not: %s", a, n)
190 }
191- // just in case
192- cNotificationExists = nil
193 }
194
195 func (ms *MessagingSuite) TearDownSuite(c *C) {
196@@ -61,6 +61,8 @@
197 func (ms *MessagingSuite) SetUpTest(c *C) {
198 ms.log = helpers.NewTestLogger(c, "debug")
199 ms.app = clickhelp.MustParseAppId("com.example.test_test_0")
200+ // just in case
201+ cNotificationExists = nil
202 }
203
204 func (ms *MessagingSuite) TestPresentPresents(c *C) {
205@@ -135,11 +137,23 @@
206 return &launch_helper.Notification{Card: &card, Tag: s}
207 }
208
209+ existsCount := 0
210+ // patch cNotificationExists to return true
211+ cNotificationExists = func(did string, nid string) bool {
212+ existsCount++
213+ return true
214+ }
215+
216 c.Check(mmu.Tags(ms.app), IsNil)
217 c.Assert(mmu.Present(ms.app, "notif1", f("one")), Equals, true)
218 ms.checkTags(c, mmu.Tags(ms.app), []string{"one"})
219+ c.Check(existsCount, Equals, 1)
220+ existsCount = 0
221+
222 c.Assert(mmu.Present(ms.app, "notif2", f("")), Equals, true)
223 ms.checkTags(c, mmu.Tags(ms.app), []string{"one", ""})
224+ c.Check(existsCount, Equals, 2)
225+
226 // and an empty notification doesn't count
227 c.Assert(mmu.Present(ms.app, "notif3", &launch_helper.Notification{Tag: "X"}), Equals, false)
228 ms.checkTags(c, mmu.Tags(ms.app), []string{"one", ""})
229@@ -172,6 +186,12 @@
230 c.Assert(f(app3, "notif6", "one", true), Equals, true)
231 c.Assert(f(app3, "notif7", "", true), Equals, true)
232
233+ // patch cNotificationExists to return true in order to make sure that messages
234+ // do not get deleted by the doCleanUpTags() call in the Tags() function
235+ cNotificationExists = func(did string, nid string) bool {
236+ return true
237+ }
238+
239 // that is:
240 // app 1: "one", "two", "";
241 // app 2: "one", "two";
242@@ -223,7 +243,7 @@
243 mmu := New(ms.log)
244 card := launch_helper.Card{Summary: "ehlo", Persist: true, Actions: []string{"action-1"}}
245 actions := []string{"{\"app\":\"com.example.test_test_0\",\"act\":\"action-1\",\"nid\":\"notif-id\"}", "action-1"}
246- mmu.addNotification(ms.app, "notif-id", "a-tag", &card, actions)
247+ mmu.addNotification(ms.app, "notif-id", "a-tag", &card, actions, nil)
248
249 // check it's there
250 payload, ok := mmu.notifications["notif-id"]
251@@ -242,7 +262,7 @@
252 mmu := New(ms.log)
253 card := launch_helper.Card{Summary: "ehlo", Persist: true, Actions: []string{"action-1"}}
254 actions := []string{"{\"app\":\"com.example.test_test_0\",\"act\":\"action-1\",\"nid\":\"notif-id\"}", "action-1"}
255- mmu.addNotification(ms.app, "notif-id", "a-tag", &card, actions)
256+ mmu.addNotification(ms.app, "notif-id", "a-tag", &card, actions, nil)
257
258 // check it's there
259 _, ok := mmu.notifications["notif-id"]
260@@ -261,13 +281,13 @@
261 mmu := New(ms.log)
262 card := launch_helper.Card{Summary: "ehlo", Persist: true, Actions: []string{"action-1"}}
263 actions := []string{"{\"app\":\"com.example.test_test_0\",\"act\":\"action-1\",\"nid\":\"notif-id\"}", "action-1"}
264- mmu.addNotification(ms.app, "notif-id", "", &card, actions)
265+ mmu.addNotification(ms.app, "notif-id", "", &card, actions, nil)
266
267 // check it's there
268 _, ok := mmu.notifications["notif-id"]
269 c.Check(ok, Equals, true)
270
271- // patch cnotificationexists to return true
272+ // patch cNotificationExists to return true
273 cNotificationExists = func(did string, nid string) bool {
274 return true
275 }
276@@ -276,62 +296,94 @@
277 // check it's still there
278 _, ok = mmu.notifications["notif-id"]
279 c.Check(ok, Equals, true)
280- // patch cnotificationexists to return false
281+
282+ // patch cNotificationExists to return false
283 cNotificationExists = func(did string, nid string) bool {
284 return false
285 }
286- // mark the notification
287- mmu.cleanUpNotifications()
288- // check it's gone
289- _, ok = mmu.notifications["notif-id"]
290- c.Check(ok, Equals, true)
291- // sweep the notification
292+ // remove the notification
293 mmu.cleanUpNotifications()
294 // check it's gone
295 _, ok = mmu.notifications["notif-id"]
296 c.Check(ok, Equals, false)
297 }
298
299-func (ms *MessagingSuite) TestCleanupLoop(c *C) {
300- mmu := New(ms.log)
301- tickerCh := make(chan time.Time)
302- mmu.tickerCh = tickerCh
303- cleanupCh := make(chan bool)
304- cleanupFunc := func() {
305- cleanupCh <- true
306- }
307- // start the cleanup loop
308- mmu.doStartCleanupLoop(cleanupFunc)
309- // mark
310- tickerCh <- time.Now()
311- // check it was called
312- <-cleanupCh
313- // stop the loop and check that it's actually stopped.
314- mmu.StopCleanupLoop()
315- c.Check(ms.log.Captured(), Matches, "(?s).*DEBUG CleanupLoop stopped.*")
316-}
317-
318-func (ms *MessagingSuite) TestStartCleanupLoop(c *C) {
319- mmu := New(ms.log)
320- tickerCh := make(chan time.Time)
321- mmu.tickerCh = tickerCh
322- card := launch_helper.Card{Summary: "ehlo", Persist: true, Actions: []string{"action-1"}}
323- actions := []string{"{\"app\":\"com.example.test_test_0\",\"act\":\"action-1\",\"nid\":\"notif-id\"}", "action-1"}
324- mmu.addNotification(ms.app, "notif-id", "", &card, actions)
325- // patch cnotificationexists to return true and signal when it's called
326- notifExistsCh := make(chan bool)
327+func (ms *MessagingSuite) TestCleanupInAddNotification(c *C) {
328+ mmu := New(ms.log)
329+
330+ var wg sync.WaitGroup
331+
332+ var cleanUpAsynchronously = func() {
333+ wg.Add(1)
334+ go func() {
335+ defer wg.Done()
336+ mmu.cleanUpNotifications()
337+ }()
338+ }
339+
340+ showNotification := func(number int) {
341+ action := "action-" + strconv.Itoa(number)
342+ notificationId := "notif-id-" + strconv.Itoa(number)
343+ card := launch_helper.Card{Summary: "ehlo", Persist: true, Actions: []string{action}}
344+ actions := []string{"{\"app\":\"com.example.test_test_0\",\"act\":\"" + action + "\",\"nid\":\"" + notificationId + "\"}", action}
345+ mmu.addNotification(ms.app, notificationId, "", &card, actions, cleanUpAsynchronously)
346+ }
347+
348+ // Add 20 notifications
349+ for i := 0; i < 20; i++ {
350+ showNotification(i)
351+ }
352+
353+ // wait for the cleanup goroutine in addNotification to finish in case it gets called (which it shouldn't!)
354+ wg.Wait()
355+
356+ // check that we have got 20 notifications
357+ c.Check(mmu.notifications, HasLen, 20)
358+
359+ // patch cNotificationExists to return true
360 cNotificationExists = func(did string, nid string) bool {
361- notifExistsCh <- true
362 return true
363 }
364- // statr the cleanup loop
365- mmu.StartCleanupLoop()
366- // mark
367- tickerCh <- time.Now()
368- // check it's there, and marked
369- <-notifExistsCh
370- // stop the loop
371- mmu.StopCleanupLoop()
372+
373+ // adding another notification should not remove the current ones
374+ showNotification(21)
375+
376+ // wait for the cleanup goroutine in addNotification to finish in case it gets called (which it shouldn't!)
377+ wg.Wait()
378+
379+ // check we that have 21 notifications now
380+ c.Check(mmu.notifications, HasLen, 21)
381+
382+ // patch cNotificationExists to return false for all but the next one we are going to add
383+ cNotificationExists = func(did string, nid string) bool {
384+ return nid == "notif-id-22"
385+ }
386+
387+ // adding another notification should not remove the current ones as mmu.lastCleanupTime is too recent
388+ showNotification(22)
389+
390+ // wait for the cleanup goroutine in addNotification to finish in case it gets called (which it shouldn't!)
391+ wg.Wait()
392+
393+ // check we that have got 22 notifications now
394+ c.Check(mmu.notifications, HasLen, 22)
395+
396+ // set back the lastCleanupTime to 11 minutes ago
397+ mmu.lastCleanupTime = mmu.lastCleanupTime.Add(-11 * time.Minute)
398+
399+ // patch cNotificationExists to return false for all but the next one we are going to add
400+ cNotificationExists = func(did string, nid string) bool {
401+ return nid == "notif-id-23"
402+ }
403+
404+ // adding another notification should remove all previous ones now
405+ showNotification(23)
406+
407+ // wait for the cleanup goroutine in addNotification to finish
408+ wg.Wait()
409+
410+ // check that all notifications except the last one have been removed
411+ c.Check(mmu.notifications, HasLen, 1)
412 }
413
414 func (ms *MessagingSuite) TestGetCh(c *C) {
415
416=== modified file 'server/acceptance/acceptanceclient.go'
417--- server/acceptance/acceptanceclient.go 2015-04-16 12:16:51 +0000
418+++ server/acceptance/acceptanceclient.go 2015-08-14 14:03:06 +0000
419@@ -49,6 +49,8 @@
420 cookie string
421 cookieLock sync.RWMutex
422 ReportSetParams bool
423+ DontClose bool
424+ SlowStart time.Duration
425 // connection
426 Connection net.Conn
427 }
428@@ -101,7 +103,10 @@
429 // Run the session with the server, emits a stream of events.
430 func (sess *ClientSession) Run(events chan<- string) error {
431 conn := sess.Connection
432- defer conn.Close()
433+ if !sess.DontClose {
434+ defer conn.Close()
435+ }
436+ time.Sleep(sess.SlowStart)
437 conn.SetDeadline(time.Now().Add(sess.ExchangeTimeout))
438 _, err := conn.Write(wireVersionBytes)
439 if err != nil {
440
441=== modified file 'server/acceptance/cmd/acceptanceclient.go'
442--- server/acceptance/cmd/acceptanceclient.go 2014-08-20 19:48:59 +0000
443+++ server/acceptance/cmd/acceptanceclient.go 2015-08-14 14:03:06 +0000
444@@ -36,7 +36,7 @@
445 kit.Defaults["auth_helper"] = ""
446 kit.Defaults["wait_for"] = ""
447 cfg := &configuration{}
448- kit.CliLoop(cfg, &cfg.Configuration, func(session *acceptance.ClientSession, cfgDir string) {
449+ kit.CliLoop(cfg, &cfg.Configuration, func(session *acceptance.ClientSession, apiCli *kit.APIClient, cfgDir string) {
450 log.Printf("with: %#v", session)
451 }, func(url string) string {
452 if cfg.AuthHelper == "" {
453
454=== modified file 'server/acceptance/kit/api.go'
455--- server/acceptance/kit/api.go 2015-04-16 12:16:51 +0000
456+++ server/acceptance/kit/api.go 2015-08-14 14:03:06 +0000
457@@ -23,8 +23,10 @@
458 "crypto/tls"
459 "encoding/json"
460 "errors"
461+ "io"
462 "io/ioutil"
463 "net/http"
464+ "net/url"
465 )
466
467 // APIClient helps making api requests.
468@@ -56,6 +58,20 @@
469
470 var ErrNOk = errors.New("not ok")
471
472+func readBody(respBody io.ReadCloser) (map[string]interface{}, error) {
473+ defer respBody.Close()
474+ body, err := ioutil.ReadAll(respBody)
475+ if err != nil {
476+ return nil, err
477+ }
478+ var res map[string]interface{}
479+ err = json.Unmarshal(body, &res)
480+ if err != nil {
481+ return nil, &APIError{err.Error(), body}
482+ }
483+ return res, nil
484+}
485+
486 // Post a API request.
487 func (api *APIClient) PostRequest(path string, message interface{}) (map[string]interface{}, error) {
488 packedMessage, err := json.Marshal(message)
489@@ -77,18 +93,36 @@
490 if err != nil {
491 return nil, err
492 }
493- defer resp.Body.Close()
494- body, err := ioutil.ReadAll(resp.Body)
495+ res, err := readBody(resp.Body)
496 if err != nil {
497 return nil, err
498 }
499- var res map[string]interface{}
500- err = json.Unmarshal(body, &res)
501- if err != nil {
502- return nil, &APIError{err.Error(), body}
503- }
504+
505 if ok, _ := res["ok"].(bool); !ok {
506 return res, ErrNOk
507 }
508 return res, nil
509 }
510+
511+// Get resource from API endpoint.
512+func (api *APIClient) GetRequest(path string, params map[string]string) (map[string]interface{}, error) {
513+ apiURL := api.ServerAPIURL + path
514+ if len(params) != 0 {
515+ vals := url.Values{}
516+ for k, v := range params {
517+ vals.Set(k, v)
518+ }
519+ apiURL += "?" + vals.Encode()
520+ }
521+ request, _ := http.NewRequest("GET", apiURL, nil)
522+
523+ resp, err := api.httpClient.Do(request)
524+ if err != nil {
525+ return nil, err
526+ }
527+ res, err := readBody(resp.Body)
528+ if err != nil {
529+ return nil, err
530+ }
531+ return res, nil
532+}
533
534=== modified file 'server/acceptance/kit/cliloop.go'
535--- server/acceptance/kit/cliloop.go 2015-04-15 15:35:12 +0000
536+++ server/acceptance/kit/cliloop.go 2015-08-14 14:03:06 +0000
537@@ -17,6 +17,7 @@
538 package kit
539
540 import (
541+ "crypto/tls"
542 "flag"
543 "fmt"
544 "log"
545@@ -26,6 +27,8 @@
546 "strings"
547 "time"
548
549+ "launchpad.net/ubuntu-push/external/murmur3"
550+
551 "launchpad.net/ubuntu-push/config"
552 "launchpad.net/ubuntu-push/server/acceptance"
553 )
554@@ -34,11 +37,15 @@
555 // session configuration
556 ExchangeTimeout config.ConfigTimeDuration `json:"exchange_timeout"`
557 // server connection config
558- Target string `json:"target"`
559+ Target string `json:"target" help:"production|staging - picks defaults"`
560 Addr config.ConfigHostPort `json:"addr"`
561+ Vnode string `json:"vnode" help:"vnode postfix to make up a targeting device-id"`
562 CertPEMFile string `json:"cert_pem_file"`
563 Insecure bool `json:"insecure" help:"disable checking of server certificate and hostname"`
564 Domain string `json:"domain" help:"domain for tls connect"`
565+ // api config
566+ APIURL string `json:"api" help:"api url"`
567+ APICertPEMFile string `json:"api_cert_pem_file"`
568 // run timeout
569 RunTimeout config.ConfigTimeDuration `json:"run_timeout"`
570 // flags
571@@ -66,22 +73,25 @@
572 var (
573 Name = "acceptanceclient"
574 Defaults = map[string]interface{}{
575- "target": "",
576- "addr": ":0",
577- "exchange_timeout": "5s",
578- "cert_pem_file": "",
579- "insecure": false,
580- "domain": "",
581- "run_timeout": "0s",
582- "reportPings": true,
583- "model": "?",
584- "imageChannel": "?",
585- "buildNumber": -1,
586+ "target": "",
587+ "addr": ":0",
588+ "vnode": "",
589+ "exchange_timeout": "5s",
590+ "cert_pem_file": "",
591+ "insecure": false,
592+ "domain": "",
593+ "run_timeout": "0s",
594+ "reportPings": true,
595+ "model": "?",
596+ "imageChannel": "?",
597+ "buildNumber": -1,
598+ "api": "",
599+ "api_cert_pem_file": "",
600 }
601 )
602
603 // CliLoop parses command line arguments and runs a client loop.
604-func CliLoop(totalCfg interface{}, cfg *Configuration, onSetup func(sess *acceptance.ClientSession, cfgDir string), auth func(string) string, waitFor func() string, onConnect func()) {
605+func CliLoop(totalCfg interface{}, cfg *Configuration, onSetup func(sess *acceptance.ClientSession, apiCli *APIClient, cfgDir string), auth func(string) string, waitFor func() string, onConnect func()) {
606 flag.Usage = func() {
607 fmt.Fprintf(os.Stderr, "Usage: %s [options] <device id>\n", Name)
608 flag.PrintDefaults()
609@@ -95,31 +105,71 @@
610 if err != nil {
611 log.Fatalf("reading config: %v", err)
612 }
613- narg := flag.NArg()
614- switch {
615- case narg < 1:
616- missingArg("device-id")
617+ deviceId := ""
618+ if cfg.Vnode != "" {
619+ if cfg.Addr == ":0" {
620+ log.Fatalf("-vnode needs -addr specified")
621+ }
622+ deviceId = cfg.Addr.HostPort() + "|" + cfg.Vnode
623+ log.Printf("using device-id: %q", deviceId)
624+ } else {
625+ narg := flag.NArg()
626+ switch {
627+ case narg < 1:
628+ missingArg("device-id")
629+ }
630+ deviceId = flag.Arg(0)
631+ }
632+ cfgDir := filepath.Dir(flag.Lookup("cfg@").Value.String())
633+ // setup api
634+ apiCli := &APIClient{}
635+ var apiTLSConfig *tls.Config
636+ if cfg.APICertPEMFile != "" || cfg.Insecure {
637+ var err error
638+ apiTLSConfig, err = MakeTLSConfig("", cfg.Insecure,
639+ cfg.APICertPEMFile, cfgDir)
640+ if err != nil {
641+ log.Fatalf("api tls config: %v", err)
642+ }
643+ }
644+ apiCli.SetupClient(apiTLSConfig, true, 1)
645+ if cfg.APIURL == "" {
646+ apiCli.ServerAPIURL = cfg.PickByTarget("api",
647+ "https://push.ubuntu.com",
648+ "https://push.staging.ubuntu.com")
649+ } else {
650+ apiCli.ServerAPIURL = cfg.APIURL
651 }
652 addr := ""
653+ domain := ""
654 if cfg.Addr == ":0" {
655- addr = cfg.PickByTarget("addr", "push-delivery.ubuntu.com:443",
656- "push-delivery.staging.ubuntu.com:443")
657+ hash := murmur3.Sum64([]byte(deviceId))
658+ hosts, err := apiCli.GetRequest("/delivery-hosts",
659+ map[string]string{
660+ "h": fmt.Sprintf("%x", hash),
661+ })
662+ if err != nil {
663+ log.Fatalf("querying hosts: %v", err)
664+ }
665+ addr = hosts["hosts"].([]interface{})[0].(string)
666+ domain = hosts["domain"].(string)
667+ log.Printf("using: %s %s", addr, domain)
668 } else {
669 addr = cfg.Addr.HostPort()
670+ domain = cfg.Domain
671 }
672 session := &acceptance.ClientSession{
673 ExchangeTimeout: cfg.ExchangeTimeout.TimeDuration(),
674 ServerAddr: addr,
675- DeviceId: flag.Arg(0),
676+ DeviceId: deviceId,
677 // flags
678 Model: cfg.DeviceModel,
679 ImageChannel: cfg.ImageChannel,
680 BuildNumber: cfg.BuildNumber,
681 ReportPings: cfg.ReportPings,
682 }
683- cfgDir := filepath.Dir(flag.Lookup("cfg@").Value.String())
684- onSetup(session, cfgDir)
685- session.TLSConfig, err = MakeTLSConfig(cfg.Domain, cfg.Insecure, cfg.CertPEMFile, cfgDir)
686+ onSetup(session, apiCli, cfgDir)
687+ session.TLSConfig, err = MakeTLSConfig(domain, cfg.Insecure, cfg.CertPEMFile, cfgDir)
688 if err != nil {
689 log.Fatalf("tls config: %v", err)
690 }
691
692=== modified file 'ubuntu-push-client.go'
693--- ubuntu-push-client.go 2015-01-21 21:31:39 +0000
694+++ ubuntu-push-client.go 2015-08-14 14:03:06 +0000
695@@ -35,8 +35,8 @@
696 buf := make([]byte, 1<<20)
697 for {
698 <-sigs
699- runtime.Stack(buf, true)
700- log.Printf("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end\n", buf)
701+ sz := runtime.Stack(buf, true)
702+ log.Printf("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end", buf[:sz])
703 }
704 }()
705 }

Subscribers

People subscribed via source and target branches