Merge lp:~mvo/snappy/snappy-verify into lp:~snappy-dev/snappy/snappy-moved-to-github

Proposed by Michael Vogt
Status: Work in progress
Proposed branch: lp:~mvo/snappy/snappy-verify
Merge into: lp:~snappy-dev/snappy/snappy-moved-to-github
Diff against target: 468 lines (+310/-45)
9 files modified
cmd/snappy/cmd_verify.go (+43/-0)
helpers/helpers.go (+4/-0)
snappy/build.go (+3/-37)
snappy/build_test.go (+1/-3)
snappy/hashes.go (+85/-0)
snappy/hashes_test.go (+65/-0)
snappy/snapp.go (+26/-5)
snappy/verify.go (+48/-0)
snappy/verify_test.go (+35/-0)
To merge this branch: bzr merge lp:~mvo/snappy/snappy-verify
Reviewer Review Type Date Requested Status
Leo Arias (community) Needs Fixing
Federico Gimenez (community) continuous-integration Needs Fixing
Snappy Tarmac continuous-integration Pending
Review via email: mp+261718@code.launchpad.net

Description of the change

Implement "snappy verify" that will ensure that all files are correct on
disk.

To post a comment you must log in.
Revision history for this message
John Lenton (chipaca) :
Revision history for this message
Leo Arias (elopio) :
lp:~mvo/snappy/snappy-verify updated
509. By Michael Vogt

merged lp:snappy

510. By Michael Vogt

snappy/parts.go: take the easy route and cast to SnapPart in VerifyInstalled

511. By Michael Vogt

snappy/snapp.go: remove RemoteSnapPart.Verify, SystemImagePart.Verify

512. By Michael Vogt

cmd/snappy/cmd_verify.go: improve help message (thanks Leo!)

513. By Michael Vogt

helpers/helpers.go: fix typo in comment (thanks Leo)

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

Thanks John and Leo for the review! I addressed the comments now. I will do a followup branch (or some) to address the interface problem, its too big but its hard to change unfortunately.

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

When I run snappy verify I get this:

Error: panic: interface conversion: snappy.Part is *snappy.SystemImagePart, not *snappy.SnapPart

goroutine 16 [running]:
runtime.panic(0x809060, 0xc2080c4900)
 /usr/lib/go/src/pkg/runtime/panic.c:279 +0xf5
launchpad.net/snappy/snappy.VerifyInstalled(0x7f164e41d8d0, 0xcd9c60, 0x0, 0x0)
 /home/elopio/workspace/canonical/snappy/experimental/build-area/ubuntu-snappy-1.2/obj-x86_64-linux-gnu/src/launchpad.net/snappy/snappy/verify.go:38 +0x249
main.(*cmdVerify).Execute(0xcd9c60, 0xc208000e80, 0x0, 0x1, 0x0, 0x0)
 /home/elopio/workspace/canonical/snappy/experimental/build-area/ubuntu-snappy-1.2/obj-x86_64-linux-gnu/src/launchpad.net/snappy/cmd/snappy/cmd_verify.go:42 +0x51
github.com/jessevdk/go-flags.(*Parser).ParseArgs(0xc20804edc0, 0xc20800e010, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0)
 /home/elopio/workspace/canonical/snappy/experimental/build-area/ubuntu-snappy-1.2/obj-x86_64-linux-gnu/src/github.com/jessevdk/go-flags/parser.go:241 +0x7cd
github.com/jessevdk/go-flags.(*Parser).Parse(0xc20804edc0, 0x0, 0x0, 0x0, 0x0, 0x0)
 /home/elopio/workspace/canonical/snappy/experimental/build-area/ubuntu-snappy-1.2/obj-x86_64-linux-gnu/src/github.com/jessevdk/go-flags/parser.go:126 +0xb3
main.main()
 /home/elopio/workspace/canonical/snappy/experimental/build-area/ubuntu-snappy-1.2/obj-x86_64-linux-gnu/src/launchpad.net/snappy/cmd/snappy/main.go:54 +0x32

goroutine 19 [finalizer wait]:
runtime.park(0x422370, 0xcd8f38, 0xcc50e9)
 /usr/lib/go/src/pkg/runtime/proc.c:1369 +0x89
runtime.parkunlock(0xcd8f38, 0xcc50e9)
 /usr/lib/go/src/pkg/runtime/proc.c:1385 +0x3b
runfinq()
 /usr/lib/go/src/pkg/runtime/mgc0.c:2644 +0xcf
runtime.goexit()
 /usr/lib/go/src/pkg/runtime/proc.c:1445

goroutine 20 [syscall]:
os/signal.loop()
 /usr/lib/go/src/pkg/os/signal/signal_unix.go:21 +0x1e
created by os/signal.init·1
 /usr/lib/go/src/pkg/os/signal/signal_unix.go:27 +0x32

goroutine 21 [chan receive]:
launchpad.net/snappy/partition.func·005()
 /home/elopio/workspace/canonical/snappy/experimental/build-area/ubuntu-snappy-1.2/obj-x86_64-linux-gnu/src/launchpad.net/snappy/partition/partition.go:270 +0x4e
created by launchpad.net/snappy/partition.setupSignalHandler
 /home/elopio/workspace/canonical/snappy/experimental/build-area/ubuntu-snappy-1.2/obj-x86_64-linux-gnu/src/launchpad.net/snappy/partition/partition.go:275 +0x174

goroutine 17 [syscall]:
runtime.goexit()
 /usr/lib/go/src/pkg/runtime/proc.c:1445

I don't fully understand the interface conversion error and I could be doing something wrong when setting this up, but in case of doubt, I'll leave a needs fixing.

review: Needs Fixing (exploratory tests)
Revision history for this message
Sergio Schvezov (sergiusens) wrote :

On Wed, Jun 24, 2015 at 11:54:14PM -0000, Leo Arias wrote:
> Review: Needs Fixing exploratory tests
>
> When I run snappy verify I get this:
>
> Error: panic: interface conversion: snappy.Part is *snappy.SystemImagePart, not *snappy.SnapPart

before converting you need to do something like:

if part, ok := s.(*snappy.SnapPart); ok {{
    // operate on part
}

>
> goroutine 16 [running]:
> runtime.panic(0x809060, 0xc2080c4900)
> /usr/lib/go/src/pkg/runtime/panic.c:279 +0xf5
> launchpad.net/snappy/snappy.VerifyInstalled(0x7f164e41d8d0, 0xcd9c60, 0x0, 0x0)
> /home/elopio/workspace/canonical/snappy/experimental/build-area/ubuntu-snappy-1.2/obj-x86_64-linux-gnu/src/launchpad.net/snappy/snappy/verify.go:38 +0x249
> main.(*cmdVerify).Execute(0xcd9c60, 0xc208000e80, 0x0, 0x1, 0x0, 0x0)
> /home/elopio/workspace/canonical/snappy/experimental/build-area/ubuntu-snappy-1.2/obj-x86_64-linux-gnu/src/launchpad.net/snappy/cmd/snappy/cmd_verify.go:42 +0x51
> github.com/jessevdk/go-flags.(*Parser).ParseArgs(0xc20804edc0, 0xc20800e010, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0)
> /home/elopio/workspace/canonical/snappy/experimental/build-area/ubuntu-snappy-1.2/obj-x86_64-linux-gnu/src/github.com/jessevdk/go-flags/parser.go:241 +0x7cd
> github.com/jessevdk/go-flags.(*Parser).Parse(0xc20804edc0, 0x0, 0x0, 0x0, 0x0, 0x0)
> /home/elopio/workspace/canonical/snappy/experimental/build-area/ubuntu-snappy-1.2/obj-x86_64-linux-gnu/src/github.com/jessevdk/go-flags/parser.go:126 +0xb3
> main.main()
> /home/elopio/workspace/canonical/snappy/experimental/build-area/ubuntu-snappy-1.2/obj-x86_64-linux-gnu/src/launchpad.net/snappy/cmd/snappy/main.go:54 +0x32
>
> goroutine 19 [finalizer wait]:
> runtime.park(0x422370, 0xcd8f38, 0xcc50e9)
> /usr/lib/go/src/pkg/runtime/proc.c:1369 +0x89
> runtime.parkunlock(0xcd8f38, 0xcc50e9)
> /usr/lib/go/src/pkg/runtime/proc.c:1385 +0x3b
> runfinq()
> /usr/lib/go/src/pkg/runtime/mgc0.c:2644 +0xcf
> runtime.goexit()
> /usr/lib/go/src/pkg/runtime/proc.c:1445
>
> goroutine 20 [syscall]:
> os/signal.loop()
> /usr/lib/go/src/pkg/os/signal/signal_unix.go:21 +0x1e
> created by os/signal.init·1
> /usr/lib/go/src/pkg/os/signal/signal_unix.go:27 +0x32
>
> goroutine 21 [chan receive]:
> launchpad.net/snappy/partition.func·005()
> /home/elopio/workspace/canonical/snappy/experimental/build-area/ubuntu-snappy-1.2/obj-x86_64-linux-gnu/src/launchpad.net/snappy/partition/partition.go:270 +0x4e
> created by launchpad.net/snappy/partition.setupSignalHandler
> /home/elopio/workspace/canonical/snappy/experimental/build-area/ubuntu-snappy-1.2/obj-x86_64-linux-gnu/src/launchpad.net/snappy/partition/partition.go:275 +0x174
>
> goroutine 17 [syscall]:
> runtime.goexit()
> /usr/lib/go/src/pkg/runtime/proc.c:1445
>
> I don't fully understand the interface conversion error and I could be doing something wrong when setting this up, but in case of doubt, I'll leave a needs fixing.
> --
> https://code.launchpad.net/~mvo/snappy/snappy-verify/+merge/261718
> Your team Snappy Developers is subscribed to branch lp:snappy.

lp:~mvo/snappy/snappy-verify updated
514. By Michael Vogt

fix crash when trying to verify a SystemImageSnap

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

Thanks Leo and Sergio! Sorry for this issue, I fixed it now and added a proper test.

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

I was trying to add a test for the command, and it fails with:
Error: verify for hello-world failed: file mode mismatch for bin: 020000000775 != 020000000755

The MP with the test is here: https://code.launchpad.net/~elopio/snappy/test-verify/+merge/263318

review: Needs Fixing
Revision history for this message
Federico Gimenez (fgimenez) wrote :

FAILED: Continuous integration, rev:514
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~mvo/snappy/snappy-verify/+merge/261718/+edit-commit-message

http://10.55.60.183:8080/job/snappy-rolling-ci/27/
Executed test runs:

Click here to trigger a rebuild:
http://10.55.60.183:8080/job/snappy-rolling-ci/27/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Leo Arias (elopio) wrote :

this has a conflict with trunk.

review: Needs Fixing

Unmerged revisions

514. By Michael Vogt

fix crash when trying to verify a SystemImageSnap

513. By Michael Vogt

helpers/helpers.go: fix typo in comment (thanks Leo)

512. By Michael Vogt

cmd/snappy/cmd_verify.go: improve help message (thanks Leo!)

511. By Michael Vogt

snappy/snapp.go: remove RemoteSnapPart.Verify, SystemImagePart.Verify

510. By Michael Vogt

snappy/parts.go: take the easy route and cast to SnapPart in VerifyInstalled

509. By Michael Vogt

merged lp:snappy

508. By Michael Vogt

improve verify output

507. By Michael Vogt

ensure unpack is faithful to the permissiosn in the tar

506. By Michael Vogt

improve error message

505. By Michael Vogt

implement snappy verify

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'cmd/snappy/cmd_verify.go'
2--- cmd/snappy/cmd_verify.go 1970-01-01 00:00:00 +0000
3+++ cmd/snappy/cmd_verify.go 2015-06-25 08:56:02 +0000
4@@ -0,0 +1,43 @@
5+// -*- Mode: Go; indent-tabs-mode: t -*-
6+
7+/*
8+ * Copyright (C) 2014-2015 Canonical Ltd
9+ *
10+ * This program is free software: you can redistribute it and/or modify
11+ * it under the terms of the GNU General Public License version 3 as
12+ * published by the Free Software Foundation.
13+ *
14+ * This program is distributed in the hope that it will be useful,
15+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+ * GNU General Public License for more details.
18+ *
19+ * You should have received a copy of the GNU General Public License
20+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
21+ *
22+ */
23+
24+package main
25+
26+import (
27+ "launchpad.net/snappy/logger"
28+ "launchpad.net/snappy/progress"
29+ "launchpad.net/snappy/snappy"
30+)
31+
32+type cmdVerify struct {
33+}
34+
35+func init() {
36+ _, err := parser.AddCommand("verify",
37+ "Verify the integrity of all installed snap packages",
38+ "Verify the integrity of all installed snap packages by comparing the permissions, sizes and file hashes of each file",
39+ &cmdVerify{})
40+ if err != nil {
41+ logger.Panicf("Unable to verify: %v", err)
42+ }
43+}
44+
45+func (x *cmdVerify) Execute(args []string) (err error) {
46+ return snappy.VerifyInstalled(progress.MakeProgressBar())
47+}
48
49=== modified file 'helpers/helpers.go'
50--- helpers/helpers.go 2015-06-09 19:11:54 +0000
51+++ helpers/helpers.go 2015-06-25 08:56:02 +0000
52@@ -115,6 +115,10 @@
53
54 // UnpackTar unpacks the given tar file into the target directory
55 func UnpackTar(r io.Reader, targetDir string, fn UnpackTarTransformFunc) error {
56+ // ensure we extract with the original permissions
57+ oldUmask := syscall.Umask(0)
58+ defer syscall.Umask(oldUmask)
59+
60 return TarIterate(r, func(tr *tar.Reader, hdr *tar.Header) (err error) {
61 // run tar transform func
62 name := hdr.Name
63
64=== modified file 'snappy/build.go'
65--- snappy/build.go 2015-06-11 19:30:45 +0000
66+++ snappy/build.go 2015-06-25 08:56:02 +0000
67@@ -186,42 +186,6 @@
68 return strings.Fields(string(output))[0], nil
69 }
70
71-func hashForFile(buildDir, path string, info os.FileInfo) (h *fileHash, err error) {
72- sha512sum := ""
73- // pointer so that omitempty works (we don't want size for
74- // directories or symlinks)
75- var size *int64
76- if info.Mode().IsRegular() {
77- sha512sum, err = helpers.Sha512sum(path)
78- if err != nil {
79- return nil, err
80- }
81- fsize := info.Size()
82- size = &fsize
83- }
84-
85- // major/minor handling
86- device := ""
87- major, minor, err := helpers.MajorMinor(info)
88- if err == nil {
89- device = fmt.Sprintf("%v,%v", major, minor)
90- }
91-
92- if buildDir != "" {
93- path = path[len(buildDir)+1:]
94- }
95-
96- return &fileHash{
97- Name: path,
98- Size: size,
99- Sha512: sha512sum,
100- Device: device,
101- // FIXME: not portable, this output is different on
102- // windows, macos
103- Mode: newYamlFileMode(info.Mode()),
104- }, nil
105-}
106-
107 func writeHashes(buildDir, dataTar string) error {
108
109 debianDir := filepath.Join(buildDir, "DEBIAN")
110@@ -244,10 +208,12 @@
111 return nil
112 }
113
114- hash, err := hashForFile(buildDir, path, info)
115+ hash, err := hashForFile(path)
116 if err != nil {
117 return err
118 }
119+ // adjust the name by removing the builddir
120+ hash.Name = hash.Name[len(buildDir)+1:]
121 hashes.Files = append(hashes.Files, hash)
122
123 return nil
124
125=== modified file 'snappy/build_test.go'
126--- snappy/build_test.go 2015-06-08 16:26:25 +0000
127+++ snappy/build_test.go 2015-06-25 08:56:02 +0000
128@@ -432,9 +432,7 @@
129 c.Skip("no /dev/kmsg")
130 }
131
132- stat, err := os.Stat("/dev/kmsg")
133- c.Assert(err, IsNil)
134- h, err := hashForFile("", "/dev/kmsg", stat)
135+ h, err := hashForFile("/dev/kmsg")
136 c.Assert(err, IsNil)
137 c.Assert(h.Name, Equals, "/dev/kmsg")
138 c.Assert(h.Device, Equals, "1,11")
139
140=== modified file 'snappy/hashes.go'
141--- snappy/hashes.go 2015-05-15 13:33:27 +0000
142+++ snappy/hashes.go 2015-06-25 08:56:02 +0000
143@@ -22,6 +22,8 @@
144 import (
145 "fmt"
146 "os"
147+
148+ "launchpad.net/snappy/helpers"
149 )
150
151 type yamlFileMode struct {
152@@ -111,6 +113,40 @@
153 XAttr map[string]string `yaml:"xattr,omitempty"`
154 }
155
156+func (fh *fileHash) Verify() error {
157+ fh2, err := hashForFile(fh.Name)
158+ if err != nil {
159+ return err
160+ }
161+
162+ // check permissions
163+ if fh2.Mode.mode != fh.Mode.mode {
164+ return fmt.Errorf("file mode mismatch for %v: 0%o != 0%o", fh.Name, fh.Mode.mode, fh2.Mode.mode)
165+ }
166+
167+ // check size (only files have them)
168+ if (fh2.Size == nil && fh.Size != nil) || (fh2.Size != nil && fh.Size == nil) {
169+ return fmt.Errorf("size data mismatch for %v", fh.Name)
170+ }
171+ if fh2.Size != nil && fh.Size != nil {
172+ if *fh2.Size != *fh.Size {
173+ return fmt.Errorf("size mismatch for %v: %v != %v", fh.Name, *fh.Size, *fh2.Size)
174+ }
175+ }
176+
177+ // check hash
178+ if fh2.Sha512 != fh.Sha512 {
179+ return fmt.Errorf("hash mismatch for %v: %v != %v", fh.Name, fh.Sha512, fh2.Sha512)
180+ }
181+
182+ // check device
183+ if fh2.Device != fh.Device {
184+ return fmt.Errorf("device info mismatch for %v: %v != %v", fh.Name, fh.Device, fh2.Device)
185+ }
186+
187+ return nil
188+}
189+
190 // the meta/hashes file
191 type hashesYaml struct {
192 // the archive hash
193@@ -119,3 +155,52 @@
194 // the hashes for the files in the archive
195 Files []*fileHash
196 }
197+
198+func (h *hashesYaml) Verify() error {
199+ for _, fh := range h.Files {
200+ if err := fh.Verify(); err != nil {
201+ return err
202+ }
203+ }
204+
205+ return nil
206+}
207+
208+// get the path for the given file
209+func hashForFile(path string) (h *fileHash, err error) {
210+ sha512sum := ""
211+
212+ info, err := os.Lstat(path)
213+ if err != nil {
214+ return nil, err
215+ }
216+
217+ // pointer so that omitempty works (we don't want size for
218+ // directories or symlinks)
219+ var size *int64
220+ if info.Mode().IsRegular() {
221+ sha512sum, err = helpers.Sha512sum(path)
222+ if err != nil {
223+ return nil, err
224+ }
225+ fsize := info.Size()
226+ size = &fsize
227+ }
228+
229+ // major/minor handling
230+ device := ""
231+ major, minor, err := helpers.MajorMinor(info)
232+ if err == nil {
233+ device = fmt.Sprintf("%v,%v", major, minor)
234+ }
235+
236+ return &fileHash{
237+ Name: path,
238+ Size: size,
239+ Sha512: sha512sum,
240+ Device: device,
241+ // FIXME: not portable, this output is different on
242+ // windows, macos
243+ Mode: newYamlFileMode(info.Mode()),
244+ }, nil
245+}
246
247=== modified file 'snappy/hashes_test.go'
248--- snappy/hashes_test.go 2015-06-02 20:46:07 +0000
249+++ snappy/hashes_test.go 2015-06-25 08:56:02 +0000
250@@ -152,3 +152,68 @@
251 mode: frw-r--r--
252 `)
253 }
254+
255+func makeTestFileWithHash(c *C) (*fileHash, string) {
256+ p := filepath.Join(c.MkDir(), "foo")
257+ err := ioutil.WriteFile(p, []byte("bar\n"), 0644)
258+ c.Assert(err, IsNil)
259+ st, err := os.Stat(p)
260+ c.Assert(err, IsNil)
261+
262+ size := int64(4)
263+ mode := newYamlFileMode(st.Mode())
264+ fh := fileHash{
265+ Name: p,
266+ Size: &size,
267+ Sha512: "cc06808cbbee0510331aa97974132e8dc296aeb795be229d064bae784b0a87a5cf4281d82e8c99271b75db2148f08a026c1a60ed9cabdb8cac6d24242dac4063",
268+ Mode: mode,
269+ }
270+ return &fh, p
271+}
272+
273+func (s *SnapTestSuite) TestFileHashSimple(c *C) {
274+ fh, _ := makeTestFileWithHash(c)
275+ err := fh.Verify()
276+ c.Assert(err, IsNil)
277+}
278+
279+func (s *SnapTestSuite) TestFileHashWrongSize(c *C) {
280+ fh, _ := makeTestFileWithHash(c)
281+
282+ fakeSize := int64(1)
283+ fh.Size = &fakeSize
284+
285+ err := fh.Verify()
286+ c.Assert(err, ErrorMatches, "size mismatch for .*/foo: 1 != 4")
287+}
288+
289+func (s *SnapTestSuite) TestFileHashWrongMode(c *C) {
290+ fh, _ := makeTestFileWithHash(c)
291+ fh.Mode.mode = 0444
292+
293+ err := fh.Verify()
294+ c.Assert(err, ErrorMatches, "file mode mismatch for .*/foo: 0444 != 0644")
295+}
296+
297+func (s *SnapTestSuite) TestFileHashWrongHash(c *C) {
298+ fh, _ := makeTestFileWithHash(c)
299+ fh.Sha512 = "xx"
300+
301+ err := fh.Verify()
302+ c.Assert(err, ErrorMatches, "hash mismatch for .*/foo: xx != cc06808cbbee0510331aa97974132e8dc296aeb795be229d064bae784b0a87a5cf4281d82e8c99271b75db2148f08a026c1a60ed9cabdb8cac6d24242dac4063")
303+}
304+
305+func (s *SnapTestSuite) TestFileHashForDir(c *C) {
306+ name := c.MkDir()
307+ st, err := os.Stat(name)
308+ c.Assert(err, IsNil)
309+
310+ mode := newYamlFileMode(st.Mode())
311+ fh := fileHash{
312+ Name: name,
313+ Mode: mode,
314+ }
315+
316+ err = fh.Verify()
317+ c.Assert(err, IsNil)
318+}
319
320=== modified file 'snappy/snapp.go'
321--- snappy/snapp.go 2015-06-12 03:55:01 +0000
322+++ snappy/snapp.go 2015-06-25 08:56:02 +0000
323@@ -608,9 +608,18 @@
324 part.description = description
325 }
326
327- // read hash, its ok if its not there, some older versions of
328- // snappy did not write this file
329- hashesData, err := ioutil.ReadFile(filepath.Join(part.basedir, "meta", "hashes.yaml"))
330+ // read hash
331+ h, err := part.hashesData()
332+ if err != nil {
333+ return nil, err
334+ }
335+ part.hash = h.ArchiveSha512
336+
337+ return part, nil
338+}
339+
340+func (s *SnapPart) hashesData() (*hashesYaml, error) {
341+ hashesData, err := ioutil.ReadFile(filepath.Join(s.basedir, "meta", "hashes.yaml"))
342 if err != nil {
343 return nil, err
344 }
345@@ -620,9 +629,8 @@
346 if err != nil {
347 return nil, &ErrInvalidYaml{file: "hashes.yaml", err: err, yaml: hashesData}
348 }
349- part.hash = h.ArchiveSha512
350
351- return part, nil
352+ return &h, nil
353 }
354
355 // Type returns the type of the SnapPart (app, oem, ...)
356@@ -1083,6 +1091,19 @@
357 return s.m.Frameworks, nil
358 }
359
360+// Verify checks the integrity
361+func (s *SnapPart) Verify(pb progress.Meter) error {
362+ hashesData, err := s.hashesData()
363+ if err != nil {
364+ return err
365+ }
366+
367+ helpers.ChDir(s.basedir, func() {
368+ err = hashesData.Verify()
369+ })
370+ return err
371+}
372+
373 // DependentNames returns a list of the names of apps installed that
374 // depend on this one
375 //
376
377=== added file 'snappy/verify.go'
378--- snappy/verify.go 1970-01-01 00:00:00 +0000
379+++ snappy/verify.go 2015-06-25 08:56:02 +0000
380@@ -0,0 +1,48 @@
381+// -*- Mode: Go; indent-tabs-mode: t -*-
382+
383+/*
384+ * Copyright (C) 2014-2015 Canonical Ltd
385+ *
386+ * This program is free software: you can redistribute it and/or modify
387+ * it under the terms of the GNU General Public License version 3 as
388+ * published by the Free Software Foundation.
389+ *
390+ * This program is distributed in the hope that it will be useful,
391+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
392+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
393+ * GNU General Public License for more details.
394+ *
395+ * You should have received a copy of the GNU General Public License
396+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
397+ *
398+ */
399+
400+package snappy
401+
402+import (
403+ "fmt"
404+
405+ "launchpad.net/snappy/progress"
406+)
407+
408+// VerifyInstalled verifies all installed snaps
409+func VerifyInstalled(pb progress.Meter) error {
410+ m := NewMetaLocalRepository()
411+ installed, err := m.Installed()
412+ if err != nil {
413+ return err
414+ }
415+
416+ for _, part := range installed {
417+ if _, ok := part.(*SnapPart); !ok {
418+ continue
419+ }
420+ pb.Notify(fmt.Sprintf("Verifying %s", part.Name()))
421+ if err := part.(*SnapPart).Verify(pb); err != nil {
422+ return fmt.Errorf("verify for %v failed: %v", part.Name(), err)
423+ }
424+ }
425+ pb.Notify(fmt.Sprintf("Verified %d successfully", len(installed)))
426+
427+ return nil
428+}
429
430=== added file 'snappy/verify_test.go'
431--- snappy/verify_test.go 1970-01-01 00:00:00 +0000
432+++ snappy/verify_test.go 2015-06-25 08:56:02 +0000
433@@ -0,0 +1,35 @@
434+// -*- Mode: Go; indent-tabs-mode: t -*-
435+
436+/*
437+ * Copyright (C) 2014-2015 Canonical Ltd
438+ *
439+ * This program is free software: you can redistribute it and/or modify
440+ * it under the terms of the GNU General Public License version 3 as
441+ * published by the Free Software Foundation.
442+ *
443+ * This program is distributed in the hope that it will be useful,
444+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
445+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
446+ * GNU General Public License for more details.
447+ *
448+ * You should have received a copy of the GNU General Public License
449+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
450+ *
451+ */
452+
453+package snappy
454+
455+import (
456+ "path/filepath"
457+
458+ . "gopkg.in/check.v1"
459+)
460+
461+func (s *SnapTestSuite) TestSnapVerifyWorksWithSystemImage(c *C) {
462+ systemImageRoot = c.MkDir()
463+
464+ makeFakeSystemImageChannelConfig(c, filepath.Join(systemImageRoot, systemImageChannelConfig), "1")
465+
466+ err := VerifyInstalled(&MockProgressMeter{})
467+ c.Assert(err, IsNil)
468+}

Subscribers

People subscribed via source and target branches