Merge lp:~pedronis/ubuntu-push/vivid-fixes into lp:ubuntu-push/vivid-overlay

Proposed by Samuele Pedroni
Status: Merged
Approved by: Samuele Pedroni
Approved revision: 149
Merged at revision: 148
Proposed branch: lp:~pedronis/ubuntu-push/vivid-fixes
Merge into: lp:ubuntu-push/vivid-overlay
Diff against target: 736 lines (+260/-139)
10 files modified
client/service/postal.go (+0/-2)
launch_helper/kindpool_test.go (+3/-3)
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/vivid-fixes
Reviewer Review Type Date Requested Status
John Lenton (community) Approve
Review via email: mp+268066@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
* go's compatibility promise fails us again; fixes for 1.4

Description of the change

bring in recent fixes to vivid overlay, mainly addressing lp:1451510

To post a comment you must log in.
Revision history for this message
John Lenton (chipaca) :
review: Approve
lp:~pedronis/ubuntu-push/vivid-fixes updated
149. By Samuele Pedroni

revert rules changes

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

Subscribers

People subscribed via source and target branches