Merge lp:~chipaca/snappy/serve into lp:~snappy-dev/snappy/snappy-moved-to-github
- serve
- Merge into snappy-moved-to-github
Status: | Merged |
---|---|
Approved by: | John Lenton |
Approved revision: | 658 |
Merged at revision: | 674 |
Proposed branch: | lp:~chipaca/snappy/serve |
Merge into: | lp:~snappy-dev/snappy/snappy-moved-to-github |
Diff against target: |
580 lines (+497/-1) 10 files modified
cmd/snapd/main.go (+65/-0) daemon/api.go (+54/-0) daemon/api_test.go (+132/-0) daemon/daemon.go (+125/-0) daemon/response.go (+107/-0) debian/control (+3/-0) debian/ubuntu-snappy-cli.install (+1/-0) dependencies.tsv (+4/-0) po/snappy.pot (+1/-1) release/release.go (+5/-0) |
To merge this branch: | bzr merge lp:~chipaca/snappy/serve |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Vogt (community) | Approve | ||
Review via email: mp+270372@code.launchpad.net |
Commit message
Introducing snapd.
Description of the change
Initial daemon branch.
Leo Arias (elopio) wrote : | # |
John Lenton (chipaca) wrote : | # |
Fixed, thank you!
To test you can use systemd-activate(8) on a snappy system.
Michael Vogt (mvo) wrote : | # |
Hey, thanks a bunch! This looks very good, I have lots of silly questions in the comments but given our tight deadline feel free to ignore, nothing that needs fixing.
John Lenton (chipaca) : | # |
Michael Vogt (mvo) wrote : | # |
Looks like we will have to backport "golang-
With the following diff I can build the package:
"""
=== modified file 'daemon/daemon.go'
--- daemon/daemon.go 2015-09-09 09:22:36 +0000
+++ daemon/daemon.go 2015-09-09 12:07:32 +0000
@@ -25,7 +25,7 @@
"net/http"
"github.
- "github.
+ "github.
"gopkg.
"launchpad.
=== modified file 'debian/control'
--- debian/control 2015-07-21 19:07:56 +0000
+++ debian/control 2015-09-09 12:05:57 +0000
@@ -18,6 +18,9 @@
+ golang-mux-dev,
+ golang-
+ golang-
Standards-Version: 3.9.6
=== modified file 'debian/
--- debian/
+++ debian/
@@ -1,4 +1,5 @@
/usr/bin/snappy
+/usr/bin/snapd
data/completio
# i18n stuff
../../share /usr
"""
Note that I switched from lxd-go-
Michael Vogt (mvo) wrote : | # |
Feel free to top-approve once the above diff (or something similar) lands and its bzr-buildpackage able.
Snappy Tarmac (snappydevtarmac) wrote : | # |
The attempt to merge lp:~chipaca/snappy/serve into lp:snappy failed. Below is the output from the failed tests.
Checking docs
Checking formatting
Installing godeps
Install golint
Obtaining dependencies
update github.
update github.
github.
update github.
github.
update gopkg.in/tomb.v2 failed; trying to fetch newer version
github.
update github.
gopkg.in/tomb.v2 now at 14b3d72120e8d10
update github.
github.
update github.
github.
update github.
github.
update github.
github.
update github.
github.
update golang.org/x/crypto failed; trying to fetch newer version
github.
update gopkg.in/check.v1 failed; trying to fetch newer version
golang.org/x/crypto now at 60052bd85f2d912
update gopkg.in/yaml.v2 failed; trying to fetch newer version
gopkg.in/check.v1 now at 64131543e7896d5
gopkg.in/yaml.v2 now at 49c95bdc2184325
Building
# we always run in a fresh dir in tarmac
export GOPATH=$(mktemp -d)
trap 'rm -rf "$GOPATH"' EXIT
# this is a hack, but not sure tarmac is golang friendly
mkdir -p $GOPATH/
cp -a . $GOPATH/
cd $GOPATH/
./run-checks
if which goctest >/dev/null; then
goctest=
else
goctest="go test"
fi
echo Checking docs
./mdlint.py docs/*.md
echo Checking formatting
fmt=$(gofmt -l .)
if [ -n "$fmt" ]; then
echo "Formatting wrong in following files"
echo "$fmt"
exit 1
fi
echo Installing godeps
go get launchpad.
export PATH=$PATH:
echo Install golint
go get github.
export PATH=$PATH:
echo Obtaining dependencies
godeps -u dependencies.tsv
echo Building
go build -v launchpad.
daemon/
/usr/lib/
/tmp/tmp.
Snappy Tarmac (snappydevtarmac) wrote : | # |
The attempt to merge lp:~chipaca/snappy/serve into lp:snappy failed. Below is the output from the failed tests.
Checking docs
Checking formatting
Installing godeps
Install golint
Obtaining dependencies
update github.
update github.
github.
update github.
github.
update github.
github.
update github.
github.
update github.
github.
update golang.org/x/crypto failed; trying to fetch newer version
github.
update gopkg.in/check.v1 failed; trying to fetch newer version
golang.org/x/crypto now at 60052bd85f2d912
update gopkg.in/yaml.v2 failed; trying to fetch newer version
gopkg.in/check.v1 now at 64131543e7896d5
update github.
gopkg.in/yaml.v2 now at 49c95bdc2184325
update github.
github.
update github.
github.
update gopkg.in/tomb.v2 failed; trying to fetch newer version
github.
gopkg.in/tomb.v2 now at 14b3d72120e8d10
Building
# we always run in a fresh dir in tarmac
export GOPATH=$(mktemp -d)
trap 'rm -rf "$GOPATH"' EXIT
# this is a hack, but not sure tarmac is golang friendly
mkdir -p $GOPATH/
cp -a . $GOPATH/
cd $GOPATH/
./run-checks
if which goctest >/dev/null; then
goctest=
else
goctest="go test"
fi
echo Checking docs
./mdlint.py docs/*.md
echo Checking formatting
fmt=$(gofmt -l .)
if [ -n "$fmt" ]; then
echo "Formatting wrong in following files"
echo "$fmt"
exit 1
fi
echo Installing godeps
go get launchpad.
export PATH=$PATH:
echo Install golint
go get github.
export PATH=$PATH:
echo Obtaining dependencies
godeps -u dependencies.tsv
echo Building
go build -v launchpad.
github.
launchpad.
launchpad.
github.
# github.
../../github.
../../github.
Leo Arias (elopio) wrote : | # |
Any idea what's this about?
../../github.
../../github.
I get it in vivid, not in wily.
John Lenton (chipaca) wrote : | # |
yes, os.Unsetenv is not in go 1.3.
On 13 September 2015 at 01:39, Leo Arias <email address hidden> wrote:
> Any idea what's this about?
> ../../github.
> ../../github.
>
> I get it in vivid, not in wily.
> --
> https:/
> You are the owner of lp:~chipaca/snappy/serve.
Leo Arias (elopio) wrote : | # |
> yes, os.Unsetenv is not in go 1.3.
Should I upgrade tarmac to wily?
John Lenton (chipaca) wrote : | # |
no, because 15.04 is what we target stable at. The fix here is to
either package stgraber's version (which i was using originally), or
patch the coreos one with stgraber's patch.
On 13 September 2015 at 02:14, Leo Arias <email address hidden> wrote:
>> yes, os.Unsetenv is not in go 1.3.
>
> Should I upgrade tarmac to wily?
> --
> https:/
> You are the owner of lp:~chipaca/snappy/serve.
Michael Vogt (mvo) wrote : | # |
We have golang-
Would this help?
"""
=== modified file 'dependencies.tsv'
--- dependencies.tsv 2015-09-09 13:46:17 +0000
+++ dependencies.tsv 2015-09-14 09:04:21 +0000
@@ -1,6 +1,6 @@
github.
github.
-github.
+github.
github.
github.
github.
"""
Snappy Tarmac (snappydevtarmac) wrote : | # |
Attempt to merge into lp:snappy failed due to conflicts:
text conflict in po/snappy.pot
Snappy Tarmac (snappydevtarmac) wrote : | # |
There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.
Preview Diff
1 | === added directory 'cmd/snapd' |
2 | === added file 'cmd/snapd/main.go' |
3 | --- cmd/snapd/main.go 1970-01-01 00:00:00 +0000 |
4 | +++ cmd/snapd/main.go 2015-09-14 09:25:29 +0000 |
5 | @@ -0,0 +1,65 @@ |
6 | +// -*- Mode: Go; indent-tabs-mode: t -*- |
7 | + |
8 | +/* |
9 | + * Copyright (C) 2015 Canonical Ltd |
10 | + * |
11 | + * This program is free software: you can redistribute it and/or modify |
12 | + * it under the terms of the GNU General Public License version 3 as |
13 | + * published by the Free Software Foundation. |
14 | + * |
15 | + * This program is distributed in the hope that it will be useful, |
16 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | + * GNU General Public License for more details. |
19 | + * |
20 | + * You should have received a copy of the GNU General Public License |
21 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 | + * |
23 | + */ |
24 | + |
25 | +package main |
26 | + |
27 | +import ( |
28 | + "fmt" |
29 | + "os" |
30 | + "os/signal" |
31 | + "syscall" |
32 | + |
33 | + "launchpad.net/snappy/daemon" |
34 | + "launchpad.net/snappy/logger" |
35 | +) |
36 | + |
37 | +func init() { |
38 | + err := logger.SimpleSetup() |
39 | + if err != nil { |
40 | + fmt.Fprintf(os.Stderr, "WARNING: failed to activate logging: %s\n", err) |
41 | + } |
42 | +} |
43 | + |
44 | +func main() { |
45 | + if err := run(); err != nil { |
46 | + fmt.Fprintf(os.Stderr, "error: %v\n", err) |
47 | + os.Exit(1) |
48 | + } |
49 | +} |
50 | + |
51 | +func run() error { |
52 | + d := daemon.New() |
53 | + |
54 | + if err := d.Init(); err != nil { |
55 | + return err |
56 | + } |
57 | + |
58 | + d.Start() |
59 | + |
60 | + ch := make(chan os.Signal) |
61 | + signal.Notify(ch, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM) |
62 | + select { |
63 | + case sig := <-ch: |
64 | + logger.Noticef("Exiting on %s signal.\n", sig) |
65 | + case <-d.Dying(): |
66 | + // something called Stop() |
67 | + } |
68 | + |
69 | + return d.Stop() |
70 | +} |
71 | |
72 | === added directory 'daemon' |
73 | === added file 'daemon/api.go' |
74 | --- daemon/api.go 1970-01-01 00:00:00 +0000 |
75 | +++ daemon/api.go 2015-09-14 09:25:29 +0000 |
76 | @@ -0,0 +1,54 @@ |
77 | +// -*- Mode: Go; indent-tabs-mode: t -*- |
78 | + |
79 | +/* |
80 | + * Copyright (C) 2015 Canonical Ltd |
81 | + * |
82 | + * This program is free software: you can redistribute it and/or modify |
83 | + * it under the terms of the GNU General Public License version 3 as |
84 | + * published by the Free Software Foundation. |
85 | + * |
86 | + * This program is distributed in the hope that it will be useful, |
87 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
88 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
89 | + * GNU General Public License for more details. |
90 | + * |
91 | + * You should have received a copy of the GNU General Public License |
92 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
93 | + * |
94 | + */ |
95 | + |
96 | +package daemon |
97 | + |
98 | +import ( |
99 | + "net/http" |
100 | + |
101 | + "launchpad.net/snappy/release" |
102 | + _ "launchpad.net/snappy/snappy" // FIXME: remove this import when it's imported elsewhere (we need the setroot for release) |
103 | +) |
104 | + |
105 | +var api = []*Command{ |
106 | + rootCmd, |
107 | + v1Cmd, |
108 | +} |
109 | + |
110 | +var ( |
111 | + rootCmd = &Command{ |
112 | + Path: "/", |
113 | + GET: SyncResponse([]string{"/1.0"}).Self, |
114 | + } |
115 | + |
116 | + v1Cmd = &Command{ |
117 | + Path: "/1.0", |
118 | + GET: v1Get, |
119 | + } |
120 | +) |
121 | + |
122 | +func v1Get(c *Command, r *http.Request) Response { |
123 | + rel := release.Get() |
124 | + return SyncResponse(map[string]string{ |
125 | + "flavor": rel.Flavor, |
126 | + "release": rel.Series, |
127 | + "default_channel": rel.Channel, |
128 | + "api_compat": "0", |
129 | + }).Self(c, r) |
130 | +} |
131 | |
132 | === added file 'daemon/api_test.go' |
133 | --- daemon/api_test.go 1970-01-01 00:00:00 +0000 |
134 | +++ daemon/api_test.go 2015-09-14 09:25:29 +0000 |
135 | @@ -0,0 +1,132 @@ |
136 | +// -*- Mode: Go; indent-tabs-mode: t -*- |
137 | + |
138 | +/* |
139 | + * Copyright (C) 2014-2015 Canonical Ltd |
140 | + * |
141 | + * This program is free software: you can redistribute it and/or modify |
142 | + * it under the terms of the GNU General Public License version 3 as |
143 | + * published by the Free Software Foundation. |
144 | + * |
145 | + * This program is distributed in the hope that it will be useful, |
146 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
147 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
148 | + * GNU General Public License for more details. |
149 | + * |
150 | + * You should have received a copy of the GNU General Public License |
151 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
152 | + * |
153 | + */ |
154 | + |
155 | +package daemon |
156 | + |
157 | +import ( |
158 | + "encoding/json" |
159 | + "go/ast" |
160 | + "go/parser" |
161 | + "go/token" |
162 | + "io/ioutil" |
163 | + "net/http/httptest" |
164 | + "os" |
165 | + "path/filepath" |
166 | + "testing" |
167 | + |
168 | + "gopkg.in/check.v1" |
169 | + |
170 | + "launchpad.net/snappy/release" |
171 | +) |
172 | + |
173 | +// Hook up check.v1 into the "go test" runner |
174 | +func Test(t *testing.T) { check.TestingT(t) } |
175 | + |
176 | +type apiSuite struct{} |
177 | + |
178 | +var _ = check.Suite(&apiSuite{}) |
179 | + |
180 | +func (s *apiSuite) TestListIncludesAll(c *check.C) { |
181 | + // Very basic check to help stop us from not adding all the |
182 | + // commands to the command list. |
183 | + // |
184 | + // It could get fancier, looking deeper into the AST to see |
185 | + // exactly what's being defined, but it's probably not worth |
186 | + // it; this gives us most of the benefits of that, with a |
187 | + // fraction of the work. |
188 | + // |
189 | + // NOTE: there's probably a |
190 | + // better/easier way of doing this (patches welcome) |
191 | + |
192 | + fset := token.NewFileSet() |
193 | + f, err := parser.ParseFile(fset, "api.go", nil, 0) |
194 | + if err != nil { |
195 | + panic(err) |
196 | + } |
197 | + |
198 | + found := 0 |
199 | + |
200 | + ast.Inspect(f, func(n ast.Node) bool { |
201 | + switch v := n.(type) { |
202 | + case *ast.ValueSpec: |
203 | + found += len(v.Values) |
204 | + return false |
205 | + } |
206 | + return true |
207 | + }) |
208 | + |
209 | + exceptions := []string{"api"} |
210 | + c.Check(found, check.Equals, len(api)+len(exceptions), |
211 | + check.Commentf(`At a glance it looks like you've not added all the Commands defined in api to the api list. If that is not the case, please add the exception to the "exceptions" list in this test.`)) |
212 | +} |
213 | + |
214 | +func (s *apiSuite) TestRootCmd(c *check.C) { |
215 | + // check it only does GET |
216 | + c.Check(rootCmd.PUT, check.IsNil) |
217 | + c.Check(rootCmd.POST, check.IsNil) |
218 | + c.Check(rootCmd.DELETE, check.IsNil) |
219 | + c.Assert(rootCmd.GET, check.NotNil) |
220 | + |
221 | + rec := httptest.NewRecorder() |
222 | + c.Check(rootCmd.Path, check.Equals, "/") |
223 | + |
224 | + rootCmd.GET(rootCmd, nil).Handler(rec, nil) |
225 | + c.Check(rec.Code, check.Equals, 200) |
226 | + c.Check(rec.HeaderMap.Get("Content-Type"), check.Equals, "application/json") |
227 | + |
228 | + expected := []interface{}{"/1.0"} |
229 | + var rsp resp |
230 | + c.Assert(json.Unmarshal(rec.Body.Bytes(), &rsp), check.IsNil) |
231 | + c.Check(rsp.Status, check.Equals, 200) |
232 | + c.Check(rsp.Metadata, check.DeepEquals, expected) |
233 | +} |
234 | + |
235 | +func (s *apiSuite) TestV1(c *check.C) { |
236 | + // check it only does GET |
237 | + c.Check(v1Cmd.PUT, check.IsNil) |
238 | + c.Check(v1Cmd.POST, check.IsNil) |
239 | + c.Check(v1Cmd.DELETE, check.IsNil) |
240 | + c.Assert(v1Cmd.GET, check.NotNil) |
241 | + |
242 | + rec := httptest.NewRecorder() |
243 | + c.Check(v1Cmd.Path, check.Equals, "/1.0") |
244 | + |
245 | + // set up release |
246 | + root := c.MkDir() |
247 | + d := filepath.Join(root, "etc", "system-image") |
248 | + c.Assert(os.MkdirAll(d, 0755), check.IsNil) |
249 | + c.Assert(ioutil.WriteFile(filepath.Join(d, "channel.ini"), []byte("[service]\nchannel: ubuntu-flavor/release/channel"), 0644), check.IsNil) |
250 | + c.Assert(release.Setup(root), check.IsNil) |
251 | + |
252 | + v1Cmd.GET(v1Cmd, nil).Handler(rec, nil) |
253 | + c.Check(rec.Code, check.Equals, 200) |
254 | + c.Check(rec.HeaderMap.Get("Content-Type"), check.Equals, "application/json") |
255 | + |
256 | + expected := map[string]interface{}{ |
257 | + "flavor": "flavor", |
258 | + "release": "release", |
259 | + "default_channel": "channel", |
260 | + "api_compat": "0", |
261 | + } |
262 | + var rsp resp |
263 | + c.Assert(json.Unmarshal(rec.Body.Bytes(), &rsp), check.IsNil) |
264 | + c.Check(rsp.Status, check.Equals, 200) |
265 | + c.Check(rsp.Type, check.Equals, ResponseTypeSync) |
266 | + c.Check(rsp.Metadata, check.DeepEquals, expected) |
267 | +} |
268 | |
269 | === added file 'daemon/daemon.go' |
270 | --- daemon/daemon.go 1970-01-01 00:00:00 +0000 |
271 | +++ daemon/daemon.go 2015-09-14 09:25:29 +0000 |
272 | @@ -0,0 +1,125 @@ |
273 | +// -*- Mode: Go; indent-tabs-mode: t -*- |
274 | + |
275 | +/* |
276 | + * Copyright (C) 2015 Canonical Ltd |
277 | + * |
278 | + * This program is free software: you can redistribute it and/or modify |
279 | + * it under the terms of the GNU General Public License version 3 as |
280 | + * published by the Free Software Foundation. |
281 | + * |
282 | + * This program is distributed in the hope that it will be useful, |
283 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
284 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
285 | + * GNU General Public License for more details. |
286 | + * |
287 | + * You should have received a copy of the GNU General Public License |
288 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
289 | + * |
290 | + */ |
291 | + |
292 | +package daemon |
293 | + |
294 | +import ( |
295 | + "fmt" |
296 | + "net" |
297 | + "net/http" |
298 | + |
299 | + "github.com/coreos/go-systemd/activation" |
300 | + "github.com/gorilla/mux" |
301 | + "gopkg.in/tomb.v2" |
302 | + |
303 | + "launchpad.net/snappy/logger" |
304 | +) |
305 | + |
306 | +// A Daemon listens for requests and routes them to the right command |
307 | +type Daemon struct { |
308 | + listener net.Listener |
309 | + tomb tomb.Tomb |
310 | + router *mux.Router |
311 | +} |
312 | + |
313 | +// A ResponseFunc handles one of the individual verbs for a method |
314 | +type ResponseFunc func(*Command, *http.Request) Response |
315 | + |
316 | +// A Command routes a request to an individual per-verb ResponseFUnc |
317 | +type Command struct { |
318 | + Path string |
319 | + // |
320 | + GET ResponseFunc |
321 | + PUT ResponseFunc |
322 | + POST ResponseFunc |
323 | + DELETE ResponseFunc |
324 | + // |
325 | + d *Daemon |
326 | +} |
327 | + |
328 | +func (c *Command) handler(w http.ResponseWriter, r *http.Request) { |
329 | + var rspf ResponseFunc |
330 | + rsp := BadMethod |
331 | + |
332 | + switch r.Method { |
333 | + case "GET": |
334 | + rspf = c.GET |
335 | + case "PUT": |
336 | + rspf = c.PUT |
337 | + case "POST": |
338 | + rspf = c.POST |
339 | + case "DELETE": |
340 | + rspf = c.DELETE |
341 | + } |
342 | + if rspf != nil { |
343 | + rsp = rspf(c, r) |
344 | + } |
345 | + |
346 | + rsp.Handler(w, r) |
347 | +} |
348 | + |
349 | +// Init sets up the Daemon's internal workings. |
350 | +// Don't call more than once. |
351 | +func (d *Daemon) Init() error { |
352 | + listeners, err := activation.Listeners(false) |
353 | + if err != nil { |
354 | + return err |
355 | + } |
356 | + |
357 | + if len(listeners) != 1 { |
358 | + return fmt.Errorf("daemon does not handle %d listeners right now, just one", len(listeners)) |
359 | + } |
360 | + |
361 | + d.listener = listeners[0] |
362 | + |
363 | + d.router = mux.NewRouter() |
364 | + |
365 | + for _, c := range api { |
366 | + c.d = d |
367 | + logger.Debugf("adding %s", c.Path) |
368 | + d.router.HandleFunc(c.Path, c.handler).Name(c.Path) |
369 | + } |
370 | + |
371 | + d.router.NotFoundHandler = http.HandlerFunc(NotFound.Handler) |
372 | + |
373 | + return nil |
374 | +} |
375 | + |
376 | +// Start the Daemon |
377 | +func (d *Daemon) Start() { |
378 | + d.tomb.Go(func() error { |
379 | + return http.Serve(d.listener, d.router) |
380 | + }) |
381 | +} |
382 | + |
383 | +// Stop shuts down the Daemon |
384 | +func (d *Daemon) Stop() error { |
385 | + d.tomb.Kill(nil) |
386 | + return d.tomb.Wait() |
387 | +} |
388 | + |
389 | +// Dying is a tomb-ish thing |
390 | +func (d *Daemon) Dying() <-chan struct{} { |
391 | + return d.tomb.Dying() |
392 | +} |
393 | + |
394 | +// New Daemon |
395 | +func New() *Daemon { |
396 | + return &Daemon{} |
397 | +} |
398 | |
399 | === added file 'daemon/response.go' |
400 | --- daemon/response.go 1970-01-01 00:00:00 +0000 |
401 | +++ daemon/response.go 2015-09-14 09:25:29 +0000 |
402 | @@ -0,0 +1,107 @@ |
403 | +// -*- Mode: Go; indent-tabs-mode: t -*- |
404 | + |
405 | +/* |
406 | + * Copyright (C) 2015 Canonical Ltd |
407 | + * |
408 | + * This program is free software: you can redistribute it and/or modify |
409 | + * it under the terms of the GNU General Public License version 3 as |
410 | + * published by the Free Software Foundation. |
411 | + * |
412 | + * This program is distributed in the hope that it will be useful, |
413 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
414 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
415 | + * GNU General Public License for more details. |
416 | + * |
417 | + * You should have received a copy of the GNU General Public License |
418 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
419 | + * |
420 | + */ |
421 | + |
422 | +package daemon |
423 | + |
424 | +import ( |
425 | + "encoding/json" |
426 | + "net/http" |
427 | + |
428 | + "launchpad.net/snappy/logger" |
429 | +) |
430 | + |
431 | +// ResponseType is the response type |
432 | +type ResponseType string |
433 | + |
434 | +// “there are three standard return types: Standard return value, |
435 | +// Background operation, Error”, each returning a JSON object with the |
436 | +// following “type” field: |
437 | +const ( |
438 | + ResponseTypeSync ResponseType = "sync" |
439 | + ResponseTypeAsync = "async" |
440 | + ResponseTypeError = "error" |
441 | +) |
442 | + |
443 | +// Response knows how to render itself, how to handle itself, and how to find itself |
444 | +type Response interface { |
445 | + Render(w http.ResponseWriter) ([]byte, int) |
446 | + Handler(w http.ResponseWriter, r *http.Request) |
447 | + Self(*Command, *http.Request) Response // has the same arity as ResponseFunc for convenience |
448 | +} |
449 | + |
450 | +type resp struct { |
451 | + Type ResponseType `json:"type"` |
452 | + Status int `json:"status_code"` |
453 | + Metadata interface{} `json:"metadata"` |
454 | +} |
455 | + |
456 | +func (r *resp) MarshalJSON() ([]byte, error) { |
457 | + return json.Marshal(map[string]interface{}{ |
458 | + "type": r.Type, |
459 | + "status": http.StatusText(r.Status), |
460 | + "status_code": r.Status, |
461 | + "metadata": &r.Metadata, |
462 | + }) |
463 | +} |
464 | + |
465 | +func (r *resp) Render(w http.ResponseWriter) (buf []byte, status int) { |
466 | + bs, err := r.MarshalJSON() |
467 | + if err != nil { |
468 | + logger.Noticef("unable to marshal %#v to JSON: %v", *r, err) |
469 | + return nil, http.StatusInternalServerError |
470 | + } |
471 | + |
472 | + return bs, r.Status |
473 | +} |
474 | + |
475 | +func (r *resp) Handler(w http.ResponseWriter, _ *http.Request) { |
476 | + bs, status := r.Render(w) |
477 | + |
478 | + w.Header().Set("Content-Type", "application/json") |
479 | + w.WriteHeader(status) |
480 | + w.Write(bs) |
481 | +} |
482 | + |
483 | +func (r *resp) Self(*Command, *http.Request) Response { |
484 | + return r |
485 | +} |
486 | + |
487 | +// SyncResponse builds a "sync" response from the given metadata. |
488 | +func SyncResponse(metadata interface{}) Response { |
489 | + return &resp{ |
490 | + Type: ResponseTypeSync, |
491 | + Status: http.StatusOK, |
492 | + Metadata: metadata, |
493 | + } |
494 | +} |
495 | + |
496 | +// ErrorResponse builds an "error" response from the given error status. |
497 | +func ErrorResponse(status int) Response { |
498 | + return &resp{ |
499 | + Type: ResponseTypeError, |
500 | + Status: status, |
501 | + } |
502 | +} |
503 | + |
504 | +// standard error responses |
505 | +var ( |
506 | + NotFound = ErrorResponse(http.StatusNotFound) |
507 | + BadMethod = ErrorResponse(http.StatusMethodNotAllowed) |
508 | + InternalError = ErrorResponse(http.StatusInternalServerError) |
509 | +) |
510 | |
511 | === modified file 'debian/control' |
512 | --- debian/control 2015-07-21 19:07:56 +0000 |
513 | +++ debian/control 2015-09-14 09:25:29 +0000 |
514 | @@ -18,6 +18,9 @@ |
515 | golang-pb-dev, |
516 | golang-uboot-go-dev, |
517 | golang-yaml.v2-dev, |
518 | + golang-mux-dev, |
519 | + golang-gopkg-tomb.v2-dev, |
520 | + golang-go-systemd-dev, |
521 | python3, |
522 | python3-markdown |
523 | Standards-Version: 3.9.6 |
524 | |
525 | === modified file 'debian/ubuntu-snappy-cli.install' |
526 | --- debian/ubuntu-snappy-cli.install 2015-07-29 18:50:28 +0000 |
527 | +++ debian/ubuntu-snappy-cli.install 2015-09-14 09:25:29 +0000 |
528 | @@ -1,4 +1,5 @@ |
529 | /usr/bin/snappy |
530 | +/usr/bin/snapd |
531 | data/completion/snappy /usr/share/bash-completion/completions/ |
532 | # i18n stuff |
533 | ../../share /usr |
534 | |
535 | === modified file 'dependencies.tsv' |
536 | --- dependencies.tsv 2015-08-18 13:34:46 +0000 |
537 | +++ dependencies.tsv 2015-09-14 09:25:29 +0000 |
538 | @@ -1,9 +1,13 @@ |
539 | github.com/blakesmith/ar git c9a977dd0cc1392b023382c7bfa5a22af8d3b730 2013-02-19T04:59:55Z |
540 | github.com/cheggaaa/pb git e8c7cc515bfde3e267957a3b110080ceed51354e 2014-12-02T07:01:21Z |
541 | +github.com/coreos/go-systemd git f743bc15d6bddd23662280b4ad20f7c874cdd5ad 2015-09-08T19:15:25Z |
542 | +github.com/gorilla/context git 1c83b3eabd45b6d76072b66b746c20815fb2872d 2015-08-20T05:12:45Z |
543 | +github.com/gorilla/mux git ee1815431e497d3850809578c93ab6705f1a19f7 2015-08-20T05:15:06Z |
544 | github.com/gosexy/gettext git 98b7b91596d20b96909e6b60d57411547dd9959c 2013-02-21T11:21:43Z |
545 | github.com/jessevdk/go-flags git 1acbbaff2f347c412a0c7884873bd72cc9c1f5b4 2015-08-16T10:05:21Z |
546 | github.com/mvo5/goconfigparser git 26426272dda20cc76aa1fa44286dc743d2972fe8 2015-02-12T09:37:50Z |
547 | github.com/mvo5/uboot-go git 361f6ebcbb54f389d15dc9faefa000e996ba3e37 2015-07-22T06:53:46Z |
548 | golang.org/x/crypto git 60052bd85f2d91293457e8811b0cf26b773de469 2015-06-22T23:34:07Z |
549 | gopkg.in/check.v1 git 64131543e7896d5bcc6bd5a76287eb75ea96c673 2014-10-24T13:38:53Z |
550 | +gopkg.in/tomb.v2 git 14b3d72120e8d10ea6e6b7f87f7175734b1faab8 2014-06-26T14:46:23Z |
551 | gopkg.in/yaml.v2 git 49c95bdc21843256fb6c4e0d370a05f24a0bf213 2015-02-24T22:57:58Z |
552 | |
553 | === modified file 'po/snappy.pot' |
554 | --- po/snappy.pot 2015-09-11 16:23:03 +0000 |
555 | +++ po/snappy.pot 2015-09-14 09:25:29 +0000 |
556 | @@ -7,7 +7,7 @@ |
557 | msgid "" |
558 | msgstr "Project-Id-Version: snappy\n" |
559 | "Report-Msgid-Bugs-To: snappy-devel@lists.ubuntu.com\n" |
560 | - "POT-Creation-Date: 2015-09-11 18:22+0200\n" |
561 | + "POT-Creation-Date: 2015-09-14 10:22+0100\n" |
562 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
563 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
564 | "Language-Team: LANGUAGE <LL@li.org>\n" |
565 | |
566 | === modified file 'release/release.go' |
567 | --- release/release.go 2015-05-15 13:33:27 +0000 |
568 | +++ release/release.go 2015-09-14 09:25:29 +0000 |
569 | @@ -51,6 +51,11 @@ |
570 | return rel.String() |
571 | } |
572 | |
573 | +// Get the release |
574 | +func Get() Release { |
575 | + return rel |
576 | +} |
577 | + |
578 | // Override sets up the release using a Release |
579 | func Override(r Release) { |
580 | rel = r |
I think you need to update the dependencies.tsv.
Some tiny comments in the diff...