Merge lp:~chipaca/snappy/serve into lp:~snappy-dev/snappy/snappy-moved-to-github

Proposed by John Lenton
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
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.

To post a comment you must log in.
Revision history for this message
Leo Arias (elopio) wrote :

I think you need to update the dependencies.tsv.

Some tiny comments in the diff...

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

Fixed, thank you!

To test you can use systemd-activate(8) on a snappy system.

Revision history for this message
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.

review: Approve
Revision history for this message
John Lenton (chipaca) :
Revision history for this message
Michael Vogt (mvo) wrote :

Looks like we will have to backport "golang-gopkg-tomb.v2-dev" to vivid (only available in vivid right now). No problem though.

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.com/gorilla/mux"
- "github.com/stgraber/lxd-go-systemd/activation"
+ "github.com/coreos/go-systemd/activation"
  "gopkg.in/tomb.v2"

  "launchpad.net/snappy/logger"

=== 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-pb-dev,
                golang-uboot-go-dev,
                golang-yaml.v2-dev,
+ golang-mux-dev,
+ golang-gopkg-tomb.v2-dev,
+ golang-go-systemd-dev,
                python3,
                python3-markdown
 Standards-Version: 3.9.6

=== modified file 'debian/ubuntu-snappy-cli.install'
--- debian/ubuntu-snappy-cli.install 2015-07-29 18:50:28 +0000
+++ debian/ubuntu-snappy-cli.install 2015-09-09 12:14:34 +0000
@@ -1,4 +1,5 @@
 /usr/bin/snappy
+/usr/bin/snapd
 data/completion/snappy /usr/share/bash-completion/completions/
 # i18n stuff
 ../../share /usr

"""

Note that I switched from lxd-go-sytemd/activation to the upstream one. this should be ok because we have golang-go-systemd-dev v2 in the archive which should work with go1.3 (unless I miss something).

Revision history for this message
Michael Vogt (mvo) wrote :

Feel free to top-approve once the above diff (or something similar) lands and its bzr-buildpackage able.

Revision history for this message
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.com/gorilla/mux failed; trying to fetch newer version
update github.com/gosexy/gettext failed; trying to fetch newer version
github.com/gorilla/mux now at ee1815431e497d3850809578c93ab6705f1a19f7
update github.com/mvo5/goconfigparser failed; trying to fetch newer version
github.com/gosexy/gettext now at 98b7b91596d20b96909e6b60d57411547dd9959c
update gopkg.in/tomb.v2 failed; trying to fetch newer version
github.com/mvo5/goconfigparser now at 26426272dda20cc76aa1fa44286dc743d2972fe8
update github.com/blakesmith/ar failed; trying to fetch newer version
gopkg.in/tomb.v2 now at 14b3d72120e8d10ea6e6b7f87f7175734b1faab8
update github.com/cheggaaa/pb failed; trying to fetch newer version
github.com/blakesmith/ar now at c9a977dd0cc1392b023382c7bfa5a22af8d3b730
update github.com/gorilla/context failed; trying to fetch newer version
github.com/cheggaaa/pb now at e8c7cc515bfde3e267957a3b110080ceed51354e
update github.com/jessevdk/go-flags failed; trying to fetch newer version
github.com/gorilla/context now at 1c83b3eabd45b6d76072b66b746c20815fb2872d
update github.com/mvo5/uboot-go failed; trying to fetch newer version
github.com/jessevdk/go-flags now at 1acbbaff2f347c412a0c7884873bd72cc9c1f5b4
update github.com/stgraber/lxd-go-systemd failed; trying to fetch newer version
github.com/mvo5/uboot-go now at 361f6ebcbb54f389d15dc9faefa000e996ba3e37
update golang.org/x/crypto failed; trying to fetch newer version
github.com/stgraber/lxd-go-systemd now at a3dcd1d0480ee0ae9ec354f1632202bfba715e03
update gopkg.in/check.v1 failed; trying to fetch newer version
golang.org/x/crypto now at 60052bd85f2d91293457e8811b0cf26b773de469
update gopkg.in/yaml.v2 failed; trying to fetch newer version
gopkg.in/check.v1 now at 64131543e7896d5bcc6bd5a76287eb75ea96c673
gopkg.in/yaml.v2 now at 49c95bdc21843256fb6c4e0d370a05f24a0bf213
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/src/launchpad.net/snappy
cp -a . $GOPATH/src/launchpad.net/snappy/
cd $GOPATH/src/launchpad.net/snappy

./run-checks

if which goctest >/dev/null; then
    goctest="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.net/godeps
export PATH=$PATH:$GOPATH/bin

echo Install golint
go get github.com/golang/lint/golint
export PATH=$PATH:$GOPATH/bin

echo Obtaining dependencies
godeps -u dependencies.tsv

echo Building
go build -v launchpad.net/snappy/...
daemon/daemon.go:27:2: cannot find package "github.com/coreos/go-systemd/activation" in any of:
 /usr/lib/go/src/pkg/github.com/coreos/go-systemd/activation (from $GOROOT)
 /tmp/tmp.DqGQs5Bgjf/src/github.com/coreos/go-systemd/activation (from $GOPATH)

Revision history for this message
Snappy Tarmac (snappydevtarmac) wrote :
Download full text (3.8 KiB)

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.com/blakesmith/ar failed; trying to fetch newer version
update github.com/cheggaaa/pb failed; trying to fetch newer version
github.com/blakesmith/ar now at c9a977dd0cc1392b023382c7bfa5a22af8d3b730
update github.com/coreos/go-systemd failed; trying to fetch newer version
github.com/cheggaaa/pb now at e8c7cc515bfde3e267957a3b110080ceed51354e
update github.com/gorilla/context failed; trying to fetch newer version
github.com/coreos/go-systemd now at 392c689e425689acb51976419a8d62878966511f
update github.com/jessevdk/go-flags failed; trying to fetch newer version
github.com/gorilla/context now at 1c83b3eabd45b6d76072b66b746c20815fb2872d
update github.com/mvo5/uboot-go failed; trying to fetch newer version
github.com/jessevdk/go-flags now at 1acbbaff2f347c412a0c7884873bd72cc9c1f5b4
update golang.org/x/crypto failed; trying to fetch newer version
github.com/mvo5/uboot-go now at 361f6ebcbb54f389d15dc9faefa000e996ba3e37
update gopkg.in/check.v1 failed; trying to fetch newer version
golang.org/x/crypto now at 60052bd85f2d91293457e8811b0cf26b773de469
update gopkg.in/yaml.v2 failed; trying to fetch newer version
gopkg.in/check.v1 now at 64131543e7896d5bcc6bd5a76287eb75ea96c673
update github.com/gorilla/mux failed; trying to fetch newer version
gopkg.in/yaml.v2 now at 49c95bdc21843256fb6c4e0d370a05f24a0bf213
update github.com/gosexy/gettext failed; trying to fetch newer version
github.com/gorilla/mux now at ee1815431e497d3850809578c93ab6705f1a19f7
update github.com/mvo5/goconfigparser failed; trying to fetch newer version
github.com/gosexy/gettext now at 98b7b91596d20b96909e6b60d57411547dd9959c
update gopkg.in/tomb.v2 failed; trying to fetch newer version
github.com/mvo5/goconfigparser now at 26426272dda20cc76aa1fa44286dc743d2972fe8
gopkg.in/tomb.v2 now at 14b3d72120e8d10ea6e6b7f87f7175734b1faab8
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/src/launchpad.net/snappy
cp -a . $GOPATH/src/launchpad.net/snappy/
cd $GOPATH/src/launchpad.net/snappy

./run-checks

if which goctest >/dev/null; then
    goctest="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.net/godeps
export PATH=$PATH:$GOPATH/bin

echo Install golint
go get github.com/golang/lint/golint
export PATH=$PATH:$GOPATH/bin

echo Obtaining dependencies
godeps -u dependencies.tsv

echo Building
go build -v launchpad.net/snappy/...
github.com/blakesmith/ar
launchpad.net/snappy/logger
launchpad.net/snappy/helpers
github.com/coreos/go-systemd/activation
# github.com/coreos/go-systemd/activation
../../github.com/coreos/go-systemd/activation/files.go:31: undefined: os.Unsetenv
../../github.com/coreos/go-systemd/activation/files.go:32: undefined...

Read more...

Revision history for this message
Leo Arias (elopio) wrote :

Any idea what's this about?
../../github.com/coreos/go-systemd/activation/files.go:31: undefined: os.Unsetenv
../../github.com/coreos/go-systemd/activation/files.go:32: undefined...

I get it in vivid, not in wily.

Revision history for this message
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.com/coreos/go-systemd/activation/files.go:31: undefined: os.Unsetenv
> ../../github.com/coreos/go-systemd/activation/files.go:32: undefined...
>
> I get it in vivid, not in wily.
> --
> https://code.launchpad.net/~chipaca/snappy/serve/+merge/270372
> You are the owner of lp:~chipaca/snappy/serve.

Revision history for this message
Leo Arias (elopio) wrote :

> yes, os.Unsetenv is not in go 1.3.

Should I upgrade tarmac to wily?

Revision history for this message
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://code.launchpad.net/~chipaca/snappy/serve/+merge/270372
> You are the owner of lp:~chipaca/snappy/serve.

Revision history for this message
Michael Vogt (mvo) wrote :

We have golang-go-systemd-dev v2 in the archive which will work fine with go1.3. So its only a problem in CI AFAICT. It seems like the easiest way to unblock this would be to update dependencies.tsv to point to the v2 commit ? Unfortuantely it seems like godeps files can not have comments so I can add a comment why this commit was chosen in the file itself.

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.com/blakesmith/ar git c9a977dd0cc1392b023382c7bfa5a22af8d3b7302013-02-19T04:59:55Z
 github.com/cheggaaa/pb git e8c7cc515bfde3e267957a3b110080ceed51354e 2014-12-02T07:01:21Z
-github.com/coreos/go-systemd git 392c689e425689acb51976419a8d62878966511f2015-09-08T19:15:25Z
+github.com/coreos/go-systemd git f743bc15d6bddd23662280b4ad20f7c874cdd5ad2015-09-08T19:15:25Z
 github.com/gorilla/context git 1c83b3eabd45b6d76072b66b746c20815fb2872d2015-08-20T05:12:45Z
 github.com/gorilla/mux git ee1815431e497d3850809578c93ab6705f1a19f7 2015-08-20T05:15:06Z
 github.com/gosexy/gettext git 98b7b91596d20b96909e6b60d57411547dd9959c2013-02-21T11:21:43Z
"""

Revision history for this message
Snappy Tarmac (snappydevtarmac) wrote :

Attempt to merge into lp:snappy failed due to conflicts:

text conflict in po/snappy.pot

Revision history for this message
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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

Subscribers

People subscribed via source and target branches