Merge lp:~mvo/snappy/snappy-snapfs-install-via-unpack into lp:~snappy-dev/snappy/snappy-moved-to-github

Proposed by Michael Vogt
Status: Merged
Approved by: John Lenton
Approved revision: 751
Merged at revision: 753
Proposed branch: lp:~mvo/snappy/snappy-snapfs-install-via-unpack
Merge into: lp:~snappy-dev/snappy/snappy-moved-to-github
Prerequisite: lp:~mvo/snappy/snappy-snapfs-tests
Diff against target: 288 lines (+191/-10)
6 files modified
pkg/clickdeb/deb.go (+5/-0)
pkg/snapfs/pkg.go (+26/-0)
snappy/common_test.go (+4/-1)
snappy/pkgformat.go (+64/-0)
snappy/snapp.go (+8/-9)
snappy/snapp_snapfs_test.go (+84/-0)
To merge this branch: bzr merge lp:~mvo/snappy/snappy-snapfs-install-via-unpack
Reviewer Review Type Date Requested Status
John Lenton (community) Approve
Review via email: mp+273810@code.launchpad.net

Commit message

Add install support (via unpack) to new style snaps

Description of the change

This branch adds support for install of new style snaps via unpack.

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

lgtm, beyond conflicts and nits below

750. By Michael Vogt

merged lp:snappy and resolved conflicts

751. By Michael Vogt

address execllent review comments

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

Thanks, your review is invaluable!

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

I addressed the comments.

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'pkg/clickdeb/deb.go'
2--- pkg/clickdeb/deb.go 2015-09-16 11:02:59 +0000
3+++ pkg/clickdeb/deb.go 2015-10-08 17:42:26 +0000
4@@ -155,6 +155,11 @@
5 return d.file.Close()
6 }
7
8+// Verify checks that the clickdeb is signed
9+func (d *ClickDeb) Verify(allowUnauthenticated bool) error {
10+ return Verify(d.Name(), allowUnauthenticated)
11+}
12+
13 // ControlMember returns the content of the given control member file
14 // (e.g. the content of the "manifest" file in the control.tar.gz ar member)
15 func (d *ClickDeb) ControlMember(controlMember string) (content []byte, err error) {
16
17=== modified file 'pkg/snapfs/pkg.go'
18--- pkg/snapfs/pkg.go 2015-10-08 07:44:05 +0000
19+++ pkg/snapfs/pkg.go 2015-10-08 17:42:26 +0000
20@@ -45,6 +45,32 @@
21 return &Snap{path: path}
22 }
23
24+// Close is not doing anything for snapfs - COMPAT
25+func (s *Snap) Close() error {
26+ return nil
27+}
28+
29+// ControlMember extracts from meta/ - COMPAT
30+func (s *Snap) ControlMember(controlMember string) ([]byte, error) {
31+ return s.ReadFile(filepath.Join("DEBIAN", controlMember))
32+}
33+
34+// MetaMember extracts from meta/ - COMPAT
35+func (s *Snap) MetaMember(metaMember string) ([]byte, error) {
36+ return s.ReadFile(filepath.Join("meta", metaMember))
37+}
38+
39+// ExtractHashes does notthing for snapfs snaps - COMAPT
40+func (s *Snap) ExtractHashes(dir string) error {
41+ return nil
42+}
43+
44+// UnpackWithDropPrivs unpacks the meta and puts stuff in place - COMAPT
45+func (s *Snap) UnpackWithDropPrivs(instDir, rootdir string) error {
46+ // FIXME: actually drop privs
47+ return s.Unpack("*", instDir)
48+}
49+
50 // UnpackMeta unpacks just the meta/* directory of the given snap
51 func (s *Snap) UnpackMeta(dst string) error {
52 if err := s.Unpack("meta/*", dst); err != nil {
53
54=== modified file 'snappy/common_test.go'
55--- snappy/common_test.go 2015-10-08 06:25:35 +0000
56+++ snappy/common_test.go 2015-10-08 17:42:26 +0000
57@@ -39,6 +39,9 @@
58 helloAppComposedName = "hello-app.testspacethename"
59 )
60
61+// here to make it easy to switch in tests to "BuildSnapfsSnap"
62+var snapBuilderFunc = BuildLegacySnap
63+
64 // makeInstalledMockSnap creates a installed mock snap without any
65 // content other than the meta data
66 func makeInstalledMockSnap(tempdir, packageYamlContent string) (yamlFile string, err error) {
67@@ -142,7 +145,7 @@
68 // build it
69 err := helpers.ChDir(tmpdir, func() error {
70 var err error
71- snapFile, err = BuildLegacySnap(tmpdir, "")
72+ snapFile, err = snapBuilderFunc(tmpdir, "")
73 c.Assert(err, IsNil)
74 return err
75 })
76
77=== added file 'snappy/pkgformat.go'
78--- snappy/pkgformat.go 1970-01-01 00:00:00 +0000
79+++ snappy/pkgformat.go 2015-10-08 17:42:26 +0000
80@@ -0,0 +1,64 @@
81+// -*- Mode: Go; indent-tabs-mode: t -*-
82+
83+/*
84+ * Copyright (C) 2014-2015 Canonical Ltd
85+ *
86+ * This program is free software: you can redistribute it and/or modify
87+ * it under the terms of the GNU General Public License version 3 as
88+ * published by the Free Software Foundation.
89+ *
90+ * This program is distributed in the hope that it will be useful,
91+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
92+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
93+ * GNU General Public License for more details.
94+ *
95+ * You should have received a copy of the GNU General Public License
96+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
97+ *
98+ */
99+
100+package snappy
101+
102+import (
103+ "bytes"
104+ "fmt"
105+ "os"
106+ "strings"
107+
108+ "launchpad.net/snappy/pkg/clickdeb"
109+ "launchpad.net/snappy/pkg/snapfs"
110+)
111+
112+// PackageFile is the interface to interact with the low-level snap files
113+type PackageFile interface {
114+ Verify(allowUnauthenticated bool) error
115+ Close() error
116+ UnpackWithDropPrivs(targetDir, rootDir string) error
117+ ControlMember(name string) ([]byte, error)
118+ MetaMember(name string) ([]byte, error)
119+ ExtractHashes(targetDir string) error
120+}
121+
122+// OpenPackageFile opens a given snap file with the right backend
123+func OpenPackageFile(path string) (PackageFile, error) {
124+ f, err := os.Open(path)
125+ if err != nil {
126+ return nil, err
127+ }
128+ defer f.Close()
129+
130+ // look, libmagic!
131+ header := make([]byte, 20)
132+ if _, err := f.Read(header); err != nil {
133+ return nil, err
134+ }
135+ // note that we only support little endian squashfs for now
136+ if bytes.HasPrefix(header, []byte{'h', 's', 'q', 's'}) {
137+ return snapfs.New(path), nil
138+ }
139+ if strings.HasPrefix(string(header), "!<arch>\ndebian") {
140+ return clickdeb.Open(path)
141+ }
142+
143+ return nil, fmt.Errorf("unknown header %v", header)
144+}
145
146=== modified file 'snappy/snapp.go'
147--- snappy/snapp.go 2015-10-08 12:20:09 +0000
148+++ snappy/snapp.go 2015-10-08 17:42:26 +0000
149@@ -43,7 +43,6 @@
150 "launchpad.net/snappy/logger"
151 "launchpad.net/snappy/oauth"
152 "launchpad.net/snappy/pkg"
153- "launchpad.net/snappy/pkg/clickdeb"
154 "launchpad.net/snappy/pkg/remote"
155 "launchpad.net/snappy/policy"
156 "launchpad.net/snappy/progress"
157@@ -182,7 +181,7 @@
158 isActive bool
159 isInstalled bool
160 description string
161- deb *clickdeb.ClickDeb
162+ deb PackageFile
163 basedir string
164 }
165
166@@ -433,7 +432,7 @@
167 // package, as deduced from the license agreement (which might involve asking
168 // the user), or an error that explains the reason why installation should not
169 // proceed.
170-func (m *packageYaml) checkLicenseAgreement(ag agreer, d *clickdeb.ClickDeb, currentActiveDir string) error {
171+func (m *packageYaml) checkLicenseAgreement(ag agreer, d PackageFile, currentActiveDir string) error {
172 if !m.ExplicitLicenseAgreement {
173 return nil
174 }
175@@ -541,18 +540,18 @@
176 }
177
178 // NewSnapPartFromSnapFile loads a snap from the given (clickdeb) snap file.
179-// Caller should call Close on the clickdeb.
180+// Caller should call Close on the pkg.
181 // TODO: expose that Close.
182 func NewSnapPartFromSnapFile(snapFile string, origin string, unauthOk bool) (*SnapPart, error) {
183- if err := clickdeb.Verify(snapFile, unauthOk); err != nil {
184- return nil, err
185- }
186-
187- d, err := clickdeb.Open(snapFile)
188+ d, err := OpenPackageFile(snapFile)
189 if err != nil {
190 return nil, err
191 }
192
193+ if err := d.Verify(unauthOk); err != nil {
194+ return nil, err
195+ }
196+
197 yamlData, err := d.MetaMember("package.yaml")
198 if err != nil {
199 return nil, err
200
201=== added file 'snappy/snapp_snapfs_test.go'
202--- snappy/snapp_snapfs_test.go 1970-01-01 00:00:00 +0000
203+++ snappy/snapp_snapfs_test.go 2015-10-08 17:42:26 +0000
204@@ -0,0 +1,84 @@
205+// -*- Mode: Go; indent-tabs-mode: t -*-
206+
207+/*
208+ * Copyright (C) 2014-2015 Canonical Ltd
209+ *
210+ * This program is free software: you can redistribute it and/or modify
211+ * it under the terms of the GNU General Public License version 3 as
212+ * published by the Free Software Foundation.
213+ *
214+ * This program is distributed in the hope that it will be useful,
215+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
216+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
217+ * GNU General Public License for more details.
218+ *
219+ * You should have received a copy of the GNU General Public License
220+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
221+ *
222+ */
223+
224+package snappy
225+
226+import (
227+ "path/filepath"
228+
229+ "launchpad.net/snappy/dirs"
230+ "launchpad.net/snappy/helpers"
231+ "launchpad.net/snappy/pkg/snapfs"
232+
233+ . "gopkg.in/check.v1"
234+)
235+
236+type SnapfsTestSuite struct {
237+}
238+
239+func (s *SnapfsTestSuite) SetUpTest(c *C) {
240+ // mocks
241+ aaClickHookCmd = "/bin/true"
242+ dirs.SetRootDir(c.MkDir())
243+
244+ // ensure we use the right builder func (snapfs)
245+ snapBuilderFunc = BuildSnapfsSnap
246+}
247+
248+func (s *SnapfsTestSuite) TearDownTest(c *C) {
249+ snapBuilderFunc = BuildLegacySnap
250+}
251+
252+var _ = Suite(&SnapfsTestSuite{})
253+
254+const packageHello = `name: hello-app
255+version: 1.10
256+vendor: Somebody
257+icon: meta/hello.svg
258+`
259+
260+func (s *SnapfsTestSuite) TestMakeSnapMakesSnapfs(c *C) {
261+ snapPkg := makeTestSnapPackage(c, packageHello)
262+ part, err := NewSnapPartFromSnapFile(snapPkg, "origin", true)
263+ c.Assert(err, IsNil)
264+
265+ // ensure the right backend got picked up
266+ c.Assert(part.deb, FitsTypeOf, &snapfs.Snap{})
267+}
268+
269+func (s *SnapfsTestSuite) TestInstallViaSnapfsWorks(c *C) {
270+ snapPkg := makeTestSnapPackage(c, packageHello)
271+ part, err := NewSnapPartFromSnapFile(snapPkg, "origin", true)
272+ c.Assert(err, IsNil)
273+
274+ _, err = part.Install(&MockProgressMeter{}, 0)
275+ c.Assert(err, IsNil)
276+
277+ // after install its just on disk for now, note that this will
278+ // change once the mounting gets added
279+ base := filepath.Join(dirs.SnapAppsDir, "hello-app.origin", "1.10")
280+ for _, needle := range []string{
281+ "bin/foo",
282+ "meta/package.yaml",
283+ ".click/info/hello-app.origin.manifest",
284+ } {
285+ println(needle)
286+ c.Assert(helpers.FileExists(filepath.Join(base, needle)), Equals, true)
287+ }
288+}

Subscribers

People subscribed via source and target branches