Merge lp:~sergiusens/snappy/lockDownRemove into lp:~snappy-dev/snappy/snappy-moved-to-github

Proposed by Sergio Schvezov
Status: Merged
Approved by: John Lenton
Approved revision: no longer in the source branch.
Merged at revision: 398
Proposed branch: lp:~sergiusens/snappy/lockDownRemove
Merge into: lp:~snappy-dev/snappy/snappy-moved-to-github
Diff against target: 496 lines (+298/-123)
4 files modified
snappy/oem.go (+197/-0)
snappy/oem_test.go (+59/-0)
snappy/snapp.go (+9/-121)
snappy/snapp_test.go (+33/-2)
To merge this branch: bzr merge lp:~sergiusens/snappy/lockDownRemove
Reviewer Review Type Date Requested Status
John Lenton (community) Approve
Review via email: mp+256849@code.launchpad.net

Commit message

Moving oem related tasks to an oem.go unit and adding support for Uninstall prevention of builtins.

Description of the change

This will need a remerge of mvo's changes, but wanted to get the general idea.

To post a comment you must log in.
Revision history for this message
John Lenton (chipaca) :
review: Approve
Revision history for this message
Snappy Tarmac (snappydevtarmac) wrote :
Download full text (6.2 KiB)

The attempt to merge lp:~sergiusens/snappy/lockDownRemove into lp:snappy failed. Below is the output from the failed tests.

Checking formatting
Installing godeps
Install golint
Obtaining dependencies
update code.google.com/p/go.crypto failed; trying to fetch newer version
update github.com/blakesmith/ar failed; trying to fetch newer version
code.google.com/p/go.crypto now at 69e2a90ed92d03812364aeb947b7068dc42e561e
update github.com/cheggaaa/pb failed; trying to fetch newer version
github.com/blakesmith/ar now at c9a977dd0cc1392b023382c7bfa5a22af8d3b730
update github.com/jessevdk/go-flags failed; trying to fetch newer version
github.com/cheggaaa/pb now at e8c7cc515bfde3e267957a3b110080ceed51354e
update github.com/juju/loggo failed; trying to fetch newer version
github.com/jessevdk/go-flags now at 15347ef417a300349807983f15af9e65cd2e1b3a
update github.com/mvo5/goconfigparser failed; trying to fetch newer version
github.com/juju/loggo now at 4c7cbce140ca070eeb59a28f4bf9507e511711f9
update gopkg.in/yaml.v2 failed; trying to fetch newer version
github.com/mvo5/goconfigparser now at 26426272dda20cc76aa1fa44286dc743d2972fe8
update launchpad.net/gocheck failed; trying to fetch newer version
gopkg.in/yaml.v2 now at 49c95bdc21843256fb6c4e0d370a05f24a0bf213
launchpad.net/gocheck now at <email address hidden>
Building
Running tests from /tmp/tmp.lNdVwxZXOl/src/launchpad.net/snappy
=== RUN Test
OK: 8 passed
--- PASS: Test (0.21 seconds)
PASS
coverage: 80.0% of statements
ok launchpad.net/snappy/clickdeb 0.212s coverage: 80.0% of statements
=== RUN Test
OK: 6 passed
--- PASS: Test (0.01 seconds)
PASS
coverage: 13.0% of statements
ok launchpad.net/snappy/cmd/snappy 0.017s coverage: 13.0% of statements
=== RUN Test
OK: 24 passed
--- PASS: Test (0.04 seconds)
PASS
coverage: 100.0% of statements
ok launchpad.net/snappy/coreconfig 0.044s coverage: 100.0% of statements
=== RUN Test
OK: 30 passed
--- PASS: Test (1.44 seconds)
PASS
coverage: 82.4% of statements
ok launchpad.net/snappy/helpers 1.442s coverage: 82.4% of statements
=== RUN Test
OK: 7 passed
--- PASS: Test (0.03 seconds)
PASS
coverage: 92.5% of statements
ok launchpad.net/snappy/logger 0.035s coverage: 92.5% of statements
=== RUN Test
OK: 36 passed
--- PASS: Test (0.10 seconds)
PASS
coverage: 81.7% of statements
ok launchpad.net/snappy/partition 0.105s coverage: 81.7% of statements
=== RUN Test
OK: 12 passed
--- PASS: Test (0.07 seconds)
PASS
coverage: 87.8% of statements
ok launchpad.net/snappy/policy 0.077s coverage: 87.8% of statements
=== RUN Test
OK: 3 passed
--- PASS: Test (0.00 seconds)
PASS
coverage: 84.8% of statements
ok launchpad.net/snappy/priv 0.004s coverage: 84.8% of statements
=== RUN Test
OK: 3 passed
--- PASS: Test (0.01 seconds)
PASS
coverage: 45.2% of statements
ok launchpad.net/snappy/progress 0.011s coverage: 45.2% of statements
=== RUN Test
OK: 6 passed
--- PASS: Test (0.00 seconds)
PASS
coverage: 100.0% of statements
ok launchpad.net/snappy/release 0.006s coverage: 100.0% of statements
=== RUN Test
2015-04-20 23:41:47 ERROR snappy logger.go:199 hello-app.potato failed to install: a package by that name is already installed
201...

Read more...

Revision history for this message
John Lenton (chipaca) :
review: Approve
lp:~sergiusens/snappy/lockDownRemove updated
398. By Sergio Schvezov

Moving oem related tasks to an oem.go unit and adding support for Uninstall prevention of builtins. by sergiusens approved by chipaca

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'snappy/oem.go'
2--- snappy/oem.go 1970-01-01 00:00:00 +0000
3+++ snappy/oem.go 2015-04-20 23:57:04 +0000
4@@ -0,0 +1,197 @@
5+/*
6+ * Copyright (C) 2014-2015 Canonical Ltd
7+ *
8+ * This program is free software: you can redistribute it and/or modify
9+ * it under the terms of the GNU General Public License version 3 as
10+ * published by the Free Software Foundation.
11+ *
12+ * This program is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ * GNU General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU General Public License
18+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19+ *
20+ */
21+
22+// TODO this should be it's own package, but depends on splitting out
23+// package.yaml's
24+
25+package snappy
26+
27+import (
28+ "errors"
29+ "fmt"
30+ "io/ioutil"
31+ "os"
32+ "os/exec"
33+ "path/filepath"
34+ "strings"
35+)
36+
37+// OEM represents the structure inside the package.yaml for the oem component
38+// of an oem package type.
39+type OEM struct {
40+ Store Store `yaml:"store,omitempty"`
41+ Hardware struct {
42+ Assign []HardwareAssign `yaml:"assign,omitempty"`
43+ } `yaml:"hardware,omitempty"`
44+ Software Software `yaml:"software,omitempty"`
45+}
46+
47+// Store holds information relevant to the store provided by an OEM snap
48+type Store struct {
49+ ID string `yaml:"id,omitempty"`
50+}
51+
52+// Software describes the installed software provided by an OEM snap
53+type Software struct {
54+ BuiltIn []string `yaml:"built-in,omitempty"`
55+}
56+
57+// HardwareAssign describes the hardware a app can use
58+type HardwareAssign struct {
59+ PartID string `yaml:"part-id,omitempty"`
60+ Rules []struct {
61+ Kernel string `yaml:"kernel,omitempty"`
62+ Subsystem string `yaml:"subsystem,omitempty"`
63+ WithSubsystems string `yaml:"with-subsystems,omitempty"`
64+ WithDriver string `yaml:"with-driver,omitempty"`
65+ WithAttrs []string `yaml:"with-attrs,omitempty"`
66+ WithProps []string `yaml:"with-props,omitempty"`
67+ } `yaml:"rules,omitempty"`
68+}
69+
70+func (hw *HardwareAssign) generateUdevRuleContent() (string, error) {
71+ s := ""
72+ for _, r := range hw.Rules {
73+ if r.Kernel != "" {
74+ s += fmt.Sprintf(`KERNEL=="%v", `, r.Kernel)
75+ }
76+ if r.Subsystem != "" {
77+ s += fmt.Sprintf(`SUBSYSTEM=="%v", `, r.Subsystem)
78+ }
79+ if r.WithSubsystems != "" {
80+ s += fmt.Sprintf(`SUBSYSTEMS=="%v", `, r.WithSubsystems)
81+ }
82+ if r.WithDriver != "" {
83+ s += fmt.Sprintf(`DRIVER=="%v", `, r.WithDriver)
84+ }
85+ for _, a := range r.WithAttrs {
86+ l := strings.Split(a, "=")
87+ s += fmt.Sprintf(`ATTRS{%v}=="%v", `, l[0], l[1])
88+ }
89+ for _, a := range r.WithProps {
90+ l := strings.SplitN(a, "=", 2)
91+ s += fmt.Sprintf(`ENV{%v}=="%v", `, l[0], l[1])
92+ }
93+ s += fmt.Sprintf(`TAG:="snappy-assign", ENV{SNAPPY_APP}:="%s"`, hw.PartID)
94+ s += "\n\n"
95+ }
96+
97+ return s, nil
98+}
99+
100+// getOem is a convenience function to not go into the details for the business
101+// logic for an oem package in every other function
102+var getOem = getOemImpl
103+
104+var getOemImpl = func() (*packageYaml, error) {
105+ oems, _ := ActiveSnapsByType(SnapTypeOem)
106+ if len(oems) == 1 {
107+ return oems[0].(*SnapPart).m, nil
108+ }
109+
110+ return nil, errors.New("no oem snap")
111+}
112+
113+// StoreID returns the store id setup by the oem package or an empty string
114+func StoreID() string {
115+ oem, err := getOem()
116+ if err != nil {
117+ return ""
118+ }
119+
120+ return oem.OEM.Store.ID
121+}
122+
123+// IsBuiltInSoftware returns true if the package is part of the built-in software
124+// defined by the oem.
125+func IsBuiltInSoftware(name string) bool {
126+ oem, err := getOem()
127+ if err != nil {
128+ return false
129+ }
130+
131+ for _, builtin := range oem.OEM.Software.BuiltIn {
132+ if builtin == name {
133+ return true
134+ }
135+ }
136+
137+ return false
138+}
139+
140+func cleanupOemHardwareUdevRules(m *packageYaml) error {
141+ oldFiles, err := filepath.Glob(filepath.Join(snapUdevRulesDir, fmt.Sprintf("80-snappy_%s_*.rules", m.Name)))
142+ if err != nil {
143+ return err
144+ }
145+
146+ for _, f := range oldFiles {
147+ os.Remove(f)
148+ }
149+
150+ return nil
151+}
152+
153+func writeOemHardwareUdevRules(m *packageYaml) error {
154+ // cleanup
155+ if err := cleanupOemHardwareUdevRules(m); err != nil {
156+ return err
157+ }
158+ // write new files
159+ for _, h := range m.OEM.Hardware.Assign {
160+ rulesContent, err := h.generateUdevRuleContent()
161+ if err != nil {
162+ return err
163+ }
164+ outfile := filepath.Join(snapUdevRulesDir, fmt.Sprintf("80-snappy_%s_%s.rules", m.Name, h.PartID))
165+ if err := ioutil.WriteFile(outfile, []byte(rulesContent), 0644); err != nil {
166+ return err
167+ }
168+ }
169+
170+ return nil
171+}
172+
173+// var to make testing easier
174+var runUdevAdm = runUdevAdmImpl
175+
176+func runUdevAdmImpl(args ...string) error {
177+ cmd := exec.Command(args[0], args[1:]...)
178+ cmd.Stdout = os.Stdout
179+ cmd.Stderr = os.Stderr
180+ return cmd.Run()
181+}
182+
183+func activateOemHardwareUdevRules(m *packageYaml) error {
184+ if err := runUdevAdm("udevadm", "control", "--reload-rules"); err != nil {
185+ return err
186+ }
187+
188+ return runUdevAdm("udevadm", "trigger")
189+}
190+
191+func installOemHardwareUdevRules(m *packageYaml) error {
192+ if err := writeOemHardwareUdevRules(m); err != nil {
193+ return err
194+ }
195+
196+ if err := activateOemHardwareUdevRules(m); err != nil {
197+ return err
198+ }
199+
200+ return nil
201+}
202
203=== added file 'snappy/oem_test.go'
204--- snappy/oem_test.go 1970-01-01 00:00:00 +0000
205+++ snappy/oem_test.go 2015-04-20 23:57:04 +0000
206@@ -0,0 +1,59 @@
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+// TODO this should be it's own package, but depends on splitting out
225+// package.yaml's
226+
227+package snappy
228+
229+import (
230+ . "launchpad.net/gocheck"
231+)
232+
233+type OemSuite struct {
234+}
235+
236+var _ = Suite(&OemSuite{})
237+
238+var (
239+ getOemOrig = getOem
240+)
241+
242+func (s *OemSuite) SetUpTest(c *C) {
243+ getOem = func() (*packageYaml, error) {
244+ return &packageYaml{
245+ OEM: OEM{
246+ Software: Software{[]string{"makeuppackage", "anotherpackage"}},
247+ Store: Store{"ninjablocks"},
248+ },
249+ }, nil
250+ }
251+}
252+
253+func (s *OemSuite) TearDownTest(c *C) {
254+ getOem = getOemImpl
255+}
256+
257+func (s *OemSuite) TestIsBuildIn(c *C) {
258+ c.Check(IsBuiltInSoftware("notapackage"), Equals, false)
259+ c.Check(IsBuiltInSoftware("makeuppackage"), Equals, true)
260+ c.Check(IsBuiltInSoftware("anotherpackage"), Equals, true)
261+}
262+
263+func (s *OemSuite) TestStoreID(c *C) {
264+ c.Assert(StoreID(), Equals, "ninjablocks")
265+}
266
267=== modified file 'snappy/snapp.go'
268--- snappy/snapp.go 2015-04-20 16:51:29 +0000
269+++ snappy/snapp.go 2015-04-20 23:57:04 +0000
270@@ -173,6 +173,8 @@
271
272 var commasplitter = regexp.MustCompile(`\s*,\s*`).Split
273
274+// TODO split into payloads per package type composing the common
275+// elements for all snaps.
276 type packageYaml struct {
277 Name string
278 Version string
279@@ -192,14 +194,7 @@
280 Binaries []Binary `yaml:"binaries,omitempty"`
281
282 // oem snap only
283- OEM struct {
284- Store struct {
285- ID string `yaml:"id,omitempty"`
286- } `yaml:"store,omitempty"`
287- Hardware struct {
288- Assign []HardwareAssign `yaml:"assign,omitempty"`
289- } `yaml:"hardware,omitempty"`
290- } `yaml:"oem,omitempty"`
291+ OEM OEM `yaml:"oem,omitempty"`
292 Config SystemConfig `yaml:"config,omitempty"`
293
294 // this is a bit ugly, but right now integration is a one:one
295@@ -210,19 +205,6 @@
296 LicenseVersion string `yaml:"license-version,omitempty"`
297 }
298
299-// HardwareAssign describes the hardware a app can use
300-type HardwareAssign struct {
301- PartID string `yaml:"part-id,omitempty"`
302- Rules []struct {
303- Kernel string `yaml:"kernel,omitempty"`
304- Subsystem string `yaml:"subsystem,omitempty"`
305- WithSubsystems string `yaml:"with-subsystems,omitempty"`
306- WithDriver string `yaml:"with-driver,omitempty"`
307- WithAttrs []string `yaml:"with-attrs,omitempty"`
308- WithProps []string `yaml:"with-props,omitempty"`
309- } `yaml:"rules,omitempty"`
310-}
311-
312 type remoteSnap struct {
313 Alias string `json:"alias,omitempty"`
314 AnonDownloadURL string `json:"anon_download_url,omitempty"`
315@@ -248,99 +230,6 @@
316 } `json:"_embedded"`
317 }
318
319-func cleanupOemHardwareUdevRules(m *packageYaml) error {
320- oldFiles, err := filepath.Glob(filepath.Join(snapUdevRulesDir, fmt.Sprintf("80-snappy_%s_*.rules", m.Name)))
321- if err != nil {
322- return err
323- }
324-
325- for _, f := range oldFiles {
326- os.Remove(f)
327- }
328-
329- return nil
330-}
331-
332-func writeOemHardwareUdevRules(m *packageYaml) error {
333- // cleanup
334- if err := cleanupOemHardwareUdevRules(m); err != nil {
335- return err
336- }
337- // write new files
338- for _, h := range m.OEM.Hardware.Assign {
339- rulesContent, err := h.generateUdevRuleContent()
340- if err != nil {
341- return err
342- }
343- outfile := filepath.Join(snapUdevRulesDir, fmt.Sprintf("80-snappy_%s_%s.rules", m.Name, h.PartID))
344- if err := ioutil.WriteFile(outfile, []byte(rulesContent), 0644); err != nil {
345- return err
346- }
347- }
348-
349- return nil
350-}
351-
352-// var to make testing easier
353-var runUdevAdm = runUdevAdmImpl
354-
355-func runUdevAdmImpl(args ...string) error {
356- cmd := exec.Command(args[0], args[1:]...)
357- cmd.Stdout = os.Stdout
358- cmd.Stderr = os.Stderr
359- return cmd.Run()
360-}
361-
362-func activateOemHardwareUdevRules(m *packageYaml) error {
363- if err := runUdevAdm("udevadm", "control", "--reload-rules"); err != nil {
364- return err
365- }
366-
367- return runUdevAdm("udevadm", "trigger")
368-}
369-
370-func installOemHardwareUdevRules(m *packageYaml) error {
371- if err := writeOemHardwareUdevRules(m); err != nil {
372- return err
373- }
374-
375- if err := activateOemHardwareUdevRules(m); err != nil {
376- return err
377- }
378-
379- return nil
380-}
381-
382-func (hw *HardwareAssign) generateUdevRuleContent() (string, error) {
383- s := ""
384- for _, r := range hw.Rules {
385- if r.Kernel != "" {
386- s += fmt.Sprintf(`KERNEL=="%v", `, r.Kernel)
387- }
388- if r.Subsystem != "" {
389- s += fmt.Sprintf(`SUBSYSTEM=="%v", `, r.Subsystem)
390- }
391- if r.WithSubsystems != "" {
392- s += fmt.Sprintf(`SUBSYSTEMS=="%v", `, r.WithSubsystems)
393- }
394- if r.WithDriver != "" {
395- s += fmt.Sprintf(`DRIVER=="%v", `, r.WithDriver)
396- }
397- for _, a := range r.WithAttrs {
398- l := strings.Split(a, "=")
399- s += fmt.Sprintf(`ATTRS{%v}=="%v", `, l[0], l[1])
400- }
401- for _, a := range r.WithProps {
402- l := strings.SplitN(a, "=", 2)
403- s += fmt.Sprintf(`ENV{%v}=="%v", `, l[0], l[1])
404- }
405- s += fmt.Sprintf(`TAG:="snappy-assign", ENV{SNAPPY_APP}:="%s"`, hw.PartID)
406- s += "\n\n"
407- }
408-
409- return s, nil
410-}
411-
412 func parsePackageYamlFile(yamlPath string) (*packageYaml, error) {
413
414 yamlData, err := ioutil.ReadFile(yamlPath)
415@@ -689,6 +578,10 @@
416 return ErrPackageNotRemovable
417 }
418
419+ if IsBuiltInSoftware(s.Name()) && s.IsActive() {
420+ return ErrPackageNotRemovable
421+ }
422+
423 deps, err := s.DependentNames()
424 if err != nil {
425 return err
426@@ -1206,13 +1099,8 @@
427 req.Header.Set("X-Ubuntu-Architecture", string(Architecture()))
428 req.Header.Set("X-Ubuntu-Release", release.String())
429
430- // check if the oem part sets a custom store-id
431- oems, _ := ActiveSnapsByType(SnapTypeOem)
432- if len(oems) == 1 {
433- storeID := oems[0].(*SnapPart).m.OEM.Store.ID
434- if storeID != "" {
435- req.Header.Set("X-Ubuntu-Store", storeID)
436- }
437+ if storeID := StoreID(); storeID != "" {
438+ req.Header.Set("X-Ubuntu-Store", storeID)
439 }
440
441 // sso
442
443=== modified file 'snappy/snapp_test.go'
444--- snappy/snapp_test.go 2015-04-20 18:40:29 +0000
445+++ snappy/snapp_test.go 2015-04-20 23:57:04 +0000
446@@ -835,6 +835,37 @@
447 repo.Details("xkcd")
448 }
449
450+func (s *SnapTestSuite) TestUninstallBuiltIn(c *C) {
451+ // install custom oem snap with store-id
452+ oemYaml, err := makeInstalledMockSnap(s.tempdir, `name: oem-test
453+version: 1.0
454+vendor: mvo
455+oem:
456+ store:
457+ id: my-store
458+ software:
459+ built-in:
460+ - hello-app
461+type: oem
462+`)
463+ c.Assert(err, IsNil)
464+ makeSnapActive(oemYaml)
465+
466+ packageYaml, err := makeInstalledMockSnap(s.tempdir, "")
467+ c.Assert(err, IsNil)
468+ makeSnapActive(packageYaml)
469+
470+ p := &MockProgressMeter{}
471+
472+ snap := NewLocalSnapRepository(filepath.Join(s.tempdir, "apps"))
473+ c.Assert(snap, NotNil)
474+ installed, err := snap.Installed()
475+ c.Assert(err, IsNil)
476+ parts := FindSnapsByName("hello-app", installed)
477+ c.Assert(parts, HasLen, 1)
478+ c.Check(parts[0].Uninstall(p), Equals, ErrPackageNotRemovable)
479+}
480+
481 var securityBinaryPackageYaml = []byte(`name: test-snap
482 version: 1.2.8
483 vendor: Jamie Strandboge <jamie@canonical.com>
484@@ -1209,10 +1240,10 @@
485 - subsystem: tty
486 with-subsystems: usb-serial
487 with-driver: pl2303
488- with-attrs:
489+ with-attrs:
490 - idVendor=0xf00f00
491 - idProduct=0xb00
492- with-props:
493+ with-props:
494 - BAUD=9600
495 - META1=foo*
496 - META2=foo?

Subscribers

People subscribed via source and target branches