Merge lp:~pedronis/ubuntu-push/server-lego into lp:ubuntu-push

Proposed by Samuele Pedroni
Status: Merged
Approved by: Samuele Pedroni
Approved revision: 18
Merged at revision: 17
Proposed branch: lp:~pedronis/ubuntu-push/server-lego
Merge into: lp:ubuntu-push
Prerequisite: lp:~pedronis/ubuntu-push/server-lego-preps
Diff against target: 654 lines (+290/-212)
7 files modified
server/dev/bootlog.go (+35/-0)
server/dev/bootlog_test.go (+45/-0)
server/dev/config_test.go (+27/-61)
server/dev/runner_devices.go (+67/-69)
server/dev/runner_http.go (+22/-12)
server/dev/runner_test.go (+73/-27)
server/dev/server.go (+21/-43)
To merge this branch: bzr merge lp:~pedronis/ubuntu-push/server-lego
Reviewer Review Type Date Requested Status
John Lenton (community) Approve
Review via email: mp+202628@code.launchpad.net

Commit message

make server/dev into composable pieces, somewhat big mostly because of lots of shuffling around

Description of the change

make server/dev into composable pieces, somewhat big mostly because of lots of shuffling around

probably still needs some moving around in a subsequent branch

To post a comment you must log in.
Revision history for this message
John Lenton (chipaca) wrote :

Lovely! :-)

Revision history for this message
John Lenton (chipaca) :
review: Disapprove
Revision history for this message
John Lenton (chipaca) wrote :

j/k :-)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'server/dev/bootlog.go'
2--- server/dev/bootlog.go 1970-01-01 00:00:00 +0000
3+++ server/dev/bootlog.go 2014-01-22 09:51:22 +0000
4@@ -0,0 +1,35 @@
5+/*
6+ Copyright 2013-2014 Canonical Ltd.
7+
8+ This program is free software: you can redistribute it and/or modify it
9+ under the terms of the GNU General Public License version 3, as published
10+ by the Free Software Foundation.
11+
12+ This program is distributed in the hope that it will be useful, but
13+ WITHOUT ANY WARRANTY; without even the implied warranties of
14+ MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15+ PURPOSE. See the GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License along
18+ with this program. If not, see <http://www.gnu.org/licenses/>.
19+*/
20+
21+package main
22+
23+import (
24+ "launchpad.net/ubuntu-push/logger"
25+ "net"
26+ "os"
27+)
28+
29+// boot logging and hooks
30+
31+func bootLogListener(kind string, lst net.Listener) {
32+ BootLogger.Infof("listening for %s on %v", kind, lst.Addr())
33+}
34+
35+var (
36+ BootLogger = logger.NewSimpleLogger(os.Stderr, "debug")
37+ BootLogListener = bootLogListener
38+ BootLogFatalf = BootLogger.Fatalf
39+)
40
41=== added file 'server/dev/bootlog_test.go'
42--- server/dev/bootlog_test.go 1970-01-01 00:00:00 +0000
43+++ server/dev/bootlog_test.go 2014-01-22 09:51:22 +0000
44@@ -0,0 +1,45 @@
45+/*
46+ Copyright 2013-2014 Canonical Ltd.
47+
48+ This program is free software: you can redistribute it and/or modify it
49+ under the terms of the GNU General Public License version 3, as published
50+ by the Free Software Foundation.
51+
52+ This program is distributed in the hope that it will be useful, but
53+ WITHOUT ANY WARRANTY; without even the implied warranties of
54+ MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
55+ PURPOSE. See the GNU General Public License for more details.
56+
57+ You should have received a copy of the GNU General Public License along
58+ with this program. If not, see <http://www.gnu.org/licenses/>.
59+*/
60+
61+package main
62+
63+import (
64+ "bytes"
65+ . "launchpad.net/gocheck"
66+ "launchpad.net/ubuntu-push/logger"
67+ "net"
68+ "testing"
69+)
70+
71+func TestRunners(t *testing.T) { TestingT(t) }
72+
73+type bootlogSuite struct{}
74+
75+var _ = Suite(&bootlogSuite{})
76+
77+func (s *bootlogSuite) TestBootLogListener(c *C) {
78+ buf := &bytes.Buffer{}
79+ prevBootLogger := BootLogger
80+ BootLogger = logger.NewSimpleLogger(buf, "info")
81+ defer func() {
82+ BootLogger = prevBootLogger
83+ }()
84+ lst, err := net.Listen("tcp", "127.0.0.1:0")
85+ c.Assert(err, IsNil)
86+ defer lst.Close()
87+ BootLogListener("client", lst)
88+ c.Check(buf.String(), Matches, ".* INFO listening for client on "+lst.Addr().String()+"\n")
89+}
90
91=== renamed file 'server/dev/server_test.go' => 'server/dev/config_test.go'
92--- server/dev/server_test.go 2014-01-14 15:35:20 +0000
93+++ server/dev/config_test.go 2014-01-22 09:51:22 +0000
94@@ -17,28 +17,20 @@
95 package main
96
97 import (
98- // "fmt"
99 "bytes"
100 "io/ioutil"
101 . "launchpad.net/gocheck"
102+ "launchpad.net/ubuntu-push/config"
103 "os"
104 "path/filepath"
105- "testing"
106 "time"
107 )
108
109-func TestDevserver(t *testing.T) { TestingT(t) }
110-
111-type devserverSuite struct{}
112-
113-var _ = Suite(&devserverSuite{})
114-
115-func (s *devserverSuite) TestConfigRead(c *C) {
116- tmpDir := c.MkDir()
117- err := ioutil.WriteFile(filepath.Join(tmpDir, "key.key"), []byte("KeY"), os.ModePerm)
118- c.Assert(err, IsNil)
119- err = ioutil.WriteFile(filepath.Join(tmpDir, "cert.cert"), []byte("CeRt"), os.ModePerm)
120- c.Assert(err, IsNil)
121+type configSuite struct{}
122+
123+var _ = Suite(&configSuite{})
124+
125+func (s *configSuite) TestDevicesParsedConfig(c *C) {
126 buf := bytes.NewBufferString(`{
127 "ping_interval": "5m",
128 "exchange_timeout": "10s",
129@@ -46,60 +38,34 @@
130 "broker_queue_size": 100,
131 "addr": "127.0.0.1:9999",
132 "key_pem_file": "key.key",
133-"cert_pem_file": "cert.cert",
134-"http_addr": "127.0.0.1:8080",
135-"http_read_timeout": "5s",
136-"http_write_timeout": "10s"
137+"cert_pem_file": "cert.cert"
138 }`)
139- cfg := &configuration{}
140- err = cfg.read(buf, tmpDir)
141+ cfg := &DevicesParsedConfig{}
142+ err := config.ReadConfig(buf, cfg)
143 c.Assert(err, IsNil)
144 c.Check(cfg.PingInterval(), Equals, 5*time.Minute)
145 c.Check(cfg.ExchangeTimeout(), Equals, 10*time.Second)
146 c.Check(cfg.BrokerQueueSize(), Equals, uint(100))
147 c.Check(cfg.SessionQueueSize(), Equals, uint(10))
148 c.Check(cfg.Addr(), Equals, "127.0.0.1:9999")
149+}
150+
151+func (s *configSuite) TestDevicesParsedConfigLoadFinish(c *C) {
152+ tmpDir := c.MkDir()
153+ cfg := &DevicesParsedConfig{
154+ ParsedKeyPEMFile: "key.key",
155+ ParsedCertPEMFile: "cert.cert",
156+ }
157+ err := cfg.FinishLoad(tmpDir)
158+ c.Check(err, ErrorMatches, "reading key_pem_file:.*no such file.*")
159+ err = ioutil.WriteFile(filepath.Join(tmpDir, "key.key"), []byte("KeY"), os.ModePerm)
160+ c.Assert(err, IsNil)
161+ err = cfg.FinishLoad(tmpDir)
162+ c.Check(err, ErrorMatches, "reading cert_pem_file:.*no such file.*")
163+ err = ioutil.WriteFile(filepath.Join(tmpDir, "cert.cert"), []byte("CeRt"), os.ModePerm)
164+ c.Assert(err, IsNil)
165+ err = cfg.FinishLoad(tmpDir)
166+ c.Assert(err, IsNil)
167 c.Check(string(cfg.KeyPEMBlock()), Equals, "KeY")
168 c.Check(string(cfg.CertPEMBlock()), Equals, "CeRt")
169- c.Check(cfg.HTTPAddr(), Equals, "127.0.0.1:8080")
170- c.Check(cfg.HTTPReadTimeout(), Equals, 5*time.Second)
171- c.Check(cfg.HTTPWriteTimeout(), Equals, 10*time.Second)
172-}
173-
174-func (s *devserverSuite) TestConfigReadErrors(c *C) {
175- tmpDir := c.MkDir()
176- checkError := func(config, expectedErr string) {
177- cfg := &configuration{}
178- err := cfg.read(bytes.NewBufferString(config), tmpDir)
179- c.Check(err, ErrorMatches, expectedErr)
180- }
181- checkError("", "EOF")
182- checkError(`{"ping_interval": "1m"}`, "missing exchange_timeout")
183- checkError(`{"ping_interval": "1m", "exchange_timeout": "5s", "session_queue_size": "foo"}`, "session_queue_size:.*type uint")
184- checkError(`{
185-"exchange_timeout": "10s",
186-"ping_interval": "5m",
187-"broker_queue_size": 100,
188-"session_queue_size": 10,
189-"addr": ":9000",
190-"key_pem_file": "doesntexist",
191-"cert_pem_file": "doesntexist",
192-"http_addr": ":8080",
193-"http_read_timeout": "5s",
194-"http_write_timeout": "10s"
195-}`, "reading key_pem_file:.*no such file.*")
196- err := ioutil.WriteFile(filepath.Join(tmpDir, "key.key"), []byte("KeY"), os.ModePerm)
197- c.Assert(err, IsNil)
198- checkError(`{
199-"exchange_timeout": "10s",
200-"ping_interval": "5m",
201-"broker_queue_size": 100,
202-"session_queue_size": 10,
203-"addr": ":9000",
204-"key_pem_file": "key.key",
205-"cert_pem_file": "doesntexist",
206-"http_addr": ":8080",
207-"http_read_timeout": "5s",
208-"http_write_timeout": "10s"
209-}`, "reading cert_pem_file:.*no such file.*")
210 }
211
212=== renamed file 'server/dev/config.go' => 'server/dev/runner_devices.go'
213--- server/dev/config.go 2014-01-14 15:35:20 +0000
214+++ server/dev/runner_devices.go 2014-01-22 09:51:22 +0000
215@@ -18,89 +18,37 @@
216
217 import (
218 "fmt"
219- "io"
220 "launchpad.net/ubuntu-push/config"
221+ "launchpad.net/ubuntu-push/logger"
222+ "launchpad.net/ubuntu-push/server/listener"
223+ "net"
224+ "syscall"
225 "time"
226 )
227
228-// expectedConfiguration is used as target for JSON parsing the configuration.
229-type expectedConfiguration struct {
230+// A DevicesParsedConfig holds and can be used to parse the device server config.
231+type DevicesParsedConfig struct {
232 // session configuration
233- PingInterval config.ConfigTimeDuration `json:"ping_interval"`
234- ExchangeTimeout config.ConfigTimeDuration `json:"exchange_timeout"`
235+ ParsedPingInterval config.ConfigTimeDuration `json:"ping_interval"`
236+ ParsedExchangeTimeout config.ConfigTimeDuration `json:"exchange_timeout"`
237 // broker configuration
238- SessionQueueSize config.ConfigQueueSize `json:"session_queue_size"`
239- BrokerQueueSize config.ConfigQueueSize `json:"broker_queue_size"`
240+ ParsedSessionQueueSize config.ConfigQueueSize `json:"session_queue_size"`
241+ ParsedBrokerQueueSize config.ConfigQueueSize `json:"broker_queue_size"`
242 // device listener configuration
243- Addr config.ConfigHostPort `json:"addr"`
244- KeyPEMFile string `json:"key_pem_file"`
245- CertPEMFile string `json:"cert_pem_file"`
246- // api http server configuration
247- HTTPAddr config.ConfigHostPort `json:"http_addr"`
248- HTTPReadTimeout config.ConfigTimeDuration `json:"http_read_timeout"`
249- HTTPWriteTimeout config.ConfigTimeDuration `json:"http_write_timeout"`
250-}
251-
252-// configuration holds the server configuration and gives it access
253-// through the various component config interfaces.
254-type configuration struct {
255- parsed expectedConfiguration
256+ ParsedAddr config.ConfigHostPort `json:"addr"`
257+ ParsedKeyPEMFile string `json:"key_pem_file"`
258+ ParsedCertPEMFile string `json:"cert_pem_file"`
259+ // private post-processed config
260 certPEMBlock []byte
261 keyPEMBlock []byte
262 }
263
264-func (cfg *configuration) PingInterval() time.Duration {
265- return cfg.parsed.PingInterval.TimeDuration()
266-}
267-
268-func (cfg *configuration) ExchangeTimeout() time.Duration {
269- return cfg.parsed.ExchangeTimeout.TimeDuration()
270-}
271-
272-func (cfg *configuration) SessionQueueSize() uint {
273- return cfg.parsed.SessionQueueSize.QueueSize()
274-}
275-
276-func (cfg *configuration) BrokerQueueSize() uint {
277- return cfg.parsed.BrokerQueueSize.QueueSize()
278-}
279-
280-func (cfg *configuration) Addr() string {
281- return cfg.parsed.Addr.HostPort()
282-}
283-
284-func (cfg *configuration) KeyPEMBlock() []byte {
285- return cfg.keyPEMBlock
286-}
287-
288-func (cfg *configuration) CertPEMBlock() []byte {
289- return cfg.certPEMBlock
290-}
291-
292-func (cfg *configuration) HTTPAddr() string {
293- return cfg.parsed.HTTPAddr.HostPort()
294-}
295-
296-func (cfg *configuration) HTTPReadTimeout() time.Duration {
297- return cfg.parsed.HTTPReadTimeout.TimeDuration()
298-}
299-
300-func (cfg *configuration) HTTPWriteTimeout() time.Duration {
301- return cfg.parsed.HTTPWriteTimeout.TimeDuration()
302-}
303-
304-// read reads & parses configuration from the reader. it uses baseDir
305-// to load mentioned files in the configuration.
306-func (cfg *configuration) read(r io.Reader, baseDir string) error {
307- err := config.ReadConfig(r, &cfg.parsed)
308- if err != nil {
309- return err
310- }
311- keyPEMBlock, err := config.LoadFile(cfg.parsed.KeyPEMFile, baseDir)
312+func (cfg *DevicesParsedConfig) FinishLoad(baseDir string) error {
313+ keyPEMBlock, err := config.LoadFile(cfg.ParsedKeyPEMFile, baseDir)
314 if err != nil {
315 return fmt.Errorf("reading key_pem_file: %v", err)
316 }
317- certPEMBlock, err := config.LoadFile(cfg.parsed.CertPEMFile, baseDir)
318+ certPEMBlock, err := config.LoadFile(cfg.ParsedCertPEMFile, baseDir)
319 if err != nil {
320 return fmt.Errorf("reading cert_pem_file: %v", err)
321 }
322@@ -108,3 +56,53 @@
323 cfg.certPEMBlock = certPEMBlock
324 return nil
325 }
326+
327+func (cfg *DevicesParsedConfig) PingInterval() time.Duration {
328+ return cfg.ParsedPingInterval.TimeDuration()
329+}
330+
331+func (cfg *DevicesParsedConfig) ExchangeTimeout() time.Duration {
332+ return cfg.ParsedExchangeTimeout.TimeDuration()
333+}
334+
335+func (cfg *DevicesParsedConfig) SessionQueueSize() uint {
336+ return cfg.ParsedSessionQueueSize.QueueSize()
337+}
338+
339+func (cfg *DevicesParsedConfig) BrokerQueueSize() uint {
340+ return cfg.ParsedBrokerQueueSize.QueueSize()
341+}
342+
343+func (cfg *DevicesParsedConfig) Addr() string {
344+ return cfg.ParsedAddr.HostPort()
345+}
346+
347+func (cfg *DevicesParsedConfig) KeyPEMBlock() []byte {
348+ return cfg.keyPEMBlock
349+}
350+
351+func (cfg *DevicesParsedConfig) CertPEMBlock() []byte {
352+ return cfg.certPEMBlock
353+}
354+
355+// RunDevices listens for device connections.
356+func DevicesRunner(session func(net.Conn) error, logger logger.Logger, parsedCfg *DevicesParsedConfig) func() {
357+ BootLogger.Debugf("PingInterval: %s, ExchangeTimeout %s", parsedCfg.PingInterval(), parsedCfg.ExchangeTimeout())
358+ var rlim syscall.Rlimit
359+ err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim)
360+ if err != nil {
361+ BootLogFatalf("getrlimit failed: %v", err)
362+ }
363+ BootLogger.Debugf("nofile soft: %d hard: %d", rlim.Cur, rlim.Max)
364+ lst, err := listener.DeviceListen(parsedCfg)
365+ if err != nil {
366+ BootLogFatalf("start device listening: %v", err)
367+ }
368+ BootLogListener("devices", lst)
369+ return func() {
370+ err = lst.AcceptLoop(session, logger)
371+ if err != nil {
372+ BootLogFatalf("accepting device connections: %v", err)
373+ }
374+ }
375+}
376
377=== renamed file 'server/dev/http.go' => 'server/dev/runner_http.go'
378--- server/dev/http.go 2014-01-14 15:35:20 +0000
379+++ server/dev/runner_http.go 2014-01-22 09:51:22 +0000
380@@ -17,24 +17,34 @@
381 package main
382
383 import (
384+ "launchpad.net/ubuntu-push/config"
385 "net"
386 "net/http"
387- "time"
388 )
389
390-// A HTTPServeConfig holds the HTTP server config.
391-type HTTPServeConfig interface {
392- HTTPAddr() string
393- HTTPReadTimeout() time.Duration
394- HTTPWriteTimeout() time.Duration
395+// A HTTPServeParsedConfig holds and can be used to parse the HTTP server config.
396+type HTTPServeParsedConfig struct {
397+ ParsedHTTPAddr config.ConfigHostPort `json:"http_addr"`
398+ ParsedHTTPReadTimeout config.ConfigTimeDuration `json:"http_read_timeout"`
399+ ParsedHTTPWriteTimeout config.ConfigTimeDuration `json:"http_write_timeout"`
400 }
401
402-// RunHTTPServe serves HTTP requests.
403-func RunHTTPServe(lst net.Listener, h http.Handler, cfg HTTPServeConfig) error {
404+// HTTPServeRunner returns a function to serve HTTP requests.
405+func HTTPServeRunner(h http.Handler, parsedCfg *HTTPServeParsedConfig) func() {
406+ httpLst, err := net.Listen("tcp", parsedCfg.ParsedHTTPAddr.HostPort())
407+ if err != nil {
408+ BootLogFatalf("start http listening: %v", err)
409+ }
410+ BootLogListener("http", httpLst)
411 srv := &http.Server{
412 Handler: h,
413- ReadTimeout: cfg.HTTPReadTimeout(),
414- WriteTimeout: cfg.HTTPReadTimeout(),
415- }
416- return srv.Serve(lst)
417+ ReadTimeout: parsedCfg.ParsedHTTPReadTimeout.TimeDuration(),
418+ WriteTimeout: parsedCfg.ParsedHTTPWriteTimeout.TimeDuration(),
419+ }
420+ return func() {
421+ err := srv.Serve(httpLst)
422+ if err != nil {
423+ BootLogFatalf("accepting http connections: %v", err)
424+ }
425+ }
426 }
427
428=== renamed file 'server/dev/http_test.go' => 'server/dev/runner_test.go'
429--- server/dev/http_test.go 2014-01-14 15:35:20 +0000
430+++ server/dev/runner_test.go 2014-01-22 09:51:22 +0000
431@@ -17,54 +17,100 @@
432 package main
433
434 import (
435+ "bytes"
436 "fmt"
437 "io/ioutil"
438 . "launchpad.net/gocheck"
439- // "log"
440+ "launchpad.net/ubuntu-push/config"
441+ "launchpad.net/ubuntu-push/logger"
442+ helpers "launchpad.net/ubuntu-push/testing"
443 "net"
444 "net/http"
445 "time"
446 )
447
448-type httpSuite struct{}
449-
450-var _ = Suite(&httpSuite{})
451-
452-type testHTTPServeConfig struct{}
453-
454-func (cfg testHTTPServeConfig) HTTPAddr() string {
455- return "127.0.0.1:0"
456-}
457-
458-func (cfg testHTTPServeConfig) HTTPReadTimeout() time.Duration {
459- return 5 * time.Second
460-}
461-
462-func (cfg testHTTPServeConfig) HTTPWriteTimeout() time.Duration {
463- return 5 * time.Second
464+type runnerSuite struct {
465+ prevBootLogListener func(string, net.Listener)
466+ prevBootLogFatalf func(string, ...interface{})
467+ lst net.Listener
468+ kind string
469+}
470+
471+var _ = Suite(&runnerSuite{})
472+
473+func (s *runnerSuite) SetUpSuite(c *C) {
474+ s.prevBootLogFatalf = BootLogFatalf
475+ s.prevBootLogListener = BootLogListener
476+ BootLogFatalf = func(format string, v ...interface{}) {
477+ panic(fmt.Sprintf(format, v...))
478+ }
479+ BootLogListener = func(kind string, lst net.Listener) {
480+ s.kind = kind
481+ s.lst = lst
482+ }
483+}
484+
485+func (s *runnerSuite) TearDownSuite(c *C) {
486+ BootLogListener = s.prevBootLogListener
487+ BootLogFatalf = s.prevBootLogFatalf
488+}
489+
490+var testHTTPServeParsedConfig = HTTPServeParsedConfig{
491+ "127.0.0.1:0",
492+ config.ConfigTimeDuration{5 * time.Second},
493+ config.ConfigTimeDuration{5 * time.Second},
494 }
495
496 func testHandle(w http.ResponseWriter, r *http.Request) {
497 fmt.Fprintf(w, "yay!\n")
498 }
499
500-func (s *httpSuite) TestRunHTTPServe(c *C) {
501- cfg := testHTTPServeConfig{}
502- lst, err := net.Listen("tcp", cfg.HTTPAddr())
503- c.Assert(err, IsNil)
504- defer lst.Close()
505- errCh := make(chan error, 1)
506+func (s *runnerSuite) TestHTTPServeRunner(c *C) {
507+ errCh := make(chan interface{}, 1)
508 h := http.HandlerFunc(testHandle)
509+ runner := HTTPServeRunner(h, &testHTTPServeParsedConfig)
510+ c.Assert(s.lst, Not(IsNil))
511+ defer s.lst.Close()
512+ c.Check(s.kind, Equals, "http")
513 go func() {
514- errCh <- RunHTTPServe(lst, h, cfg)
515+ defer func() {
516+ errCh <- recover()
517+ }()
518+ runner()
519 }()
520- resp, err := http.Get(fmt.Sprintf("http://%s/", lst.Addr()))
521+ resp, err := http.Get(fmt.Sprintf("http://%s/", s.lst.Addr()))
522 c.Assert(err, IsNil)
523 defer resp.Body.Close()
524 c.Assert(resp.StatusCode, Equals, 200)
525 body, err := ioutil.ReadAll(resp.Body)
526 c.Assert(err, IsNil)
527 c.Check(string(body), Equals, "yay!\n")
528- lst.Close()
529- c.Check(<-errCh, ErrorMatches, ".*closed.*")
530+ s.lst.Close()
531+ c.Check(<-errCh, Matches, "accepting http connections:.*closed.*")
532+}
533+
534+var testDevicesParsedConfig = DevicesParsedConfig{
535+ ParsedPingInterval: config.ConfigTimeDuration{60 * time.Second},
536+ ParsedExchangeTimeout: config.ConfigTimeDuration{10 * time.Second},
537+ ParsedBrokerQueueSize: config.ConfigQueueSize(1000),
538+ ParsedSessionQueueSize: config.ConfigQueueSize(10),
539+ ParsedAddr: "127.0.0.1:0",
540+ ParsedKeyPEMFile: "",
541+ ParsedCertPEMFile: "",
542+ keyPEMBlock: helpers.TestKeyPEMBlock,
543+ certPEMBlock: helpers.TestCertPEMBlock,
544+}
545+
546+func (s *runnerSuite) TestDevicesRunner(c *C) {
547+ buf := &bytes.Buffer{}
548+ prevBootLogger := BootLogger
549+ BootLogger = logger.NewSimpleLogger(buf, "debug")
550+ defer func() {
551+ BootLogger = prevBootLogger
552+ }()
553+ runner := DevicesRunner(func(conn net.Conn) error { return nil }, BootLogger, &testDevicesParsedConfig)
554+ c.Assert(s.lst, Not(IsNil))
555+ s.lst.Close()
556+ c.Check(s.kind, Equals, "devices")
557+ c.Check(runner, PanicMatches, "accepting device connections:.*closed.*")
558 }
559
560=== modified file 'server/dev/server.go'
561--- server/dev/server.go 2014-01-17 17:21:35 +0000
562+++ server/dev/server.go 2014-01-22 09:51:22 +0000
563@@ -18,70 +18,48 @@
564 package main
565
566 import (
567+ "launchpad.net/ubuntu-push/config"
568 "launchpad.net/ubuntu-push/logger"
569 "launchpad.net/ubuntu-push/server/api"
570 "launchpad.net/ubuntu-push/server/broker"
571- "launchpad.net/ubuntu-push/server/listener"
572 "launchpad.net/ubuntu-push/server/session"
573 "launchpad.net/ubuntu-push/server/store"
574 "net"
575 "os"
576 "path/filepath"
577- "syscall"
578 )
579
580+type configuration struct {
581+ // device server configuration
582+ DevicesParsedConfig
583+ // api http server configuration
584+ HTTPServeParsedConfig
585+}
586+
587 func main() {
588+ cfgFpaths := os.Args[1:]
589+ cfg := &configuration{}
590+ err := config.ReadFiles(cfg, cfgFpaths...)
591+ if err != nil {
592+ BootLogFatalf("reading config: %v", err)
593+ }
594+ err = cfg.DevicesParsedConfig.FinishLoad(filepath.Dir(cfgFpaths[len(cfgFpaths)-1]))
595+ if err != nil {
596+ BootLogFatalf("reading config: %v", err)
597+ }
598 logger := logger.NewSimpleLogger(os.Stderr, "debug")
599- if len(os.Args) < 2 { // xxx use flag
600- logger.Fatalf("missing config file")
601- }
602- configFName := os.Args[1]
603- f, err := os.Open(configFName)
604- if err != nil {
605- logger.Fatalf("reading config: %v", err)
606- }
607- cfg := &configuration{}
608- err = cfg.read(f, filepath.Dir(configFName))
609- if err != nil {
610- logger.Fatalf("reading config: %v", err)
611- }
612 // setup a pending store and start the broker
613 sto := store.NewInMemoryPendingStore()
614 broker := broker.NewSimpleBroker(sto, cfg, logger)
615 broker.Start()
616 defer broker.Stop()
617 // serve the http api
618- httpLst, err := net.Listen("tcp", cfg.HTTPAddr())
619- if err != nil {
620- logger.Fatalf("start http listening: %v", err)
621- }
622 handler := api.MakeHandlersMux(sto, broker, logger)
623 handler = api.PanicTo500Handler(handler, logger)
624- logger.Infof("listening for http on %v", httpLst.Addr())
625- go func() {
626- err := RunHTTPServe(httpLst, handler, cfg)
627- if err != nil {
628- logger.Fatalf("accepting http connections: %v", err)
629- }
630- }()
631+ go HTTPServeRunner(handler, &cfg.HTTPServeParsedConfig)()
632 // listen for device connections
633- logger.Debugf("PingInterval: %s, ExchangeTimeout %s", cfg.PingInterval(), cfg.ExchangeTimeout())
634- var rlim syscall.Rlimit
635- err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim)
636- if err != nil {
637- logger.Fatalf("getrlimit failed: %v", err)
638- }
639- logger.Debugf("nofile soft: %d hard: %d", rlim.Cur, rlim.Max)
640- lst, err := listener.DeviceListen(cfg)
641- if err != nil {
642- logger.Fatalf("start device listening: %v", err)
643- }
644- logger.Infof("listening for devices on %v", lst.Addr())
645- err = lst.AcceptLoop(func(conn net.Conn) error {
646+ DevicesRunner(func(conn net.Conn) error {
647 track := session.NewTracker(logger)
648 return session.Session(conn, broker, cfg, track)
649- }, logger)
650- if err != nil {
651- logger.Fatalf("accepting device connections: %v", err)
652- }
653+ }, logger, &cfg.DevicesParsedConfig)()
654 }

Subscribers

People subscribed via source and target branches