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
=== added file 'snappy/oem.go'
--- snappy/oem.go 1970-01-01 00:00:00 +0000
+++ snappy/oem.go 2015-04-20 23:57:04 +0000
@@ -0,0 +1,197 @@
1/*
2 * Copyright (C) 2014-2015 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18// TODO this should be it's own package, but depends on splitting out
19// package.yaml's
20
21package snappy
22
23import (
24 "errors"
25 "fmt"
26 "io/ioutil"
27 "os"
28 "os/exec"
29 "path/filepath"
30 "strings"
31)
32
33// OEM represents the structure inside the package.yaml for the oem component
34// of an oem package type.
35type OEM struct {
36 Store Store `yaml:"store,omitempty"`
37 Hardware struct {
38 Assign []HardwareAssign `yaml:"assign,omitempty"`
39 } `yaml:"hardware,omitempty"`
40 Software Software `yaml:"software,omitempty"`
41}
42
43// Store holds information relevant to the store provided by an OEM snap
44type Store struct {
45 ID string `yaml:"id,omitempty"`
46}
47
48// Software describes the installed software provided by an OEM snap
49type Software struct {
50 BuiltIn []string `yaml:"built-in,omitempty"`
51}
52
53// HardwareAssign describes the hardware a app can use
54type HardwareAssign struct {
55 PartID string `yaml:"part-id,omitempty"`
56 Rules []struct {
57 Kernel string `yaml:"kernel,omitempty"`
58 Subsystem string `yaml:"subsystem,omitempty"`
59 WithSubsystems string `yaml:"with-subsystems,omitempty"`
60 WithDriver string `yaml:"with-driver,omitempty"`
61 WithAttrs []string `yaml:"with-attrs,omitempty"`
62 WithProps []string `yaml:"with-props,omitempty"`
63 } `yaml:"rules,omitempty"`
64}
65
66func (hw *HardwareAssign) generateUdevRuleContent() (string, error) {
67 s := ""
68 for _, r := range hw.Rules {
69 if r.Kernel != "" {
70 s += fmt.Sprintf(`KERNEL=="%v", `, r.Kernel)
71 }
72 if r.Subsystem != "" {
73 s += fmt.Sprintf(`SUBSYSTEM=="%v", `, r.Subsystem)
74 }
75 if r.WithSubsystems != "" {
76 s += fmt.Sprintf(`SUBSYSTEMS=="%v", `, r.WithSubsystems)
77 }
78 if r.WithDriver != "" {
79 s += fmt.Sprintf(`DRIVER=="%v", `, r.WithDriver)
80 }
81 for _, a := range r.WithAttrs {
82 l := strings.Split(a, "=")
83 s += fmt.Sprintf(`ATTRS{%v}=="%v", `, l[0], l[1])
84 }
85 for _, a := range r.WithProps {
86 l := strings.SplitN(a, "=", 2)
87 s += fmt.Sprintf(`ENV{%v}=="%v", `, l[0], l[1])
88 }
89 s += fmt.Sprintf(`TAG:="snappy-assign", ENV{SNAPPY_APP}:="%s"`, hw.PartID)
90 s += "\n\n"
91 }
92
93 return s, nil
94}
95
96// getOem is a convenience function to not go into the details for the business
97// logic for an oem package in every other function
98var getOem = getOemImpl
99
100var getOemImpl = func() (*packageYaml, error) {
101 oems, _ := ActiveSnapsByType(SnapTypeOem)
102 if len(oems) == 1 {
103 return oems[0].(*SnapPart).m, nil
104 }
105
106 return nil, errors.New("no oem snap")
107}
108
109// StoreID returns the store id setup by the oem package or an empty string
110func StoreID() string {
111 oem, err := getOem()
112 if err != nil {
113 return ""
114 }
115
116 return oem.OEM.Store.ID
117}
118
119// IsBuiltInSoftware returns true if the package is part of the built-in software
120// defined by the oem.
121func IsBuiltInSoftware(name string) bool {
122 oem, err := getOem()
123 if err != nil {
124 return false
125 }
126
127 for _, builtin := range oem.OEM.Software.BuiltIn {
128 if builtin == name {
129 return true
130 }
131 }
132
133 return false
134}
135
136func cleanupOemHardwareUdevRules(m *packageYaml) error {
137 oldFiles, err := filepath.Glob(filepath.Join(snapUdevRulesDir, fmt.Sprintf("80-snappy_%s_*.rules", m.Name)))
138 if err != nil {
139 return err
140 }
141
142 for _, f := range oldFiles {
143 os.Remove(f)
144 }
145
146 return nil
147}
148
149func writeOemHardwareUdevRules(m *packageYaml) error {
150 // cleanup
151 if err := cleanupOemHardwareUdevRules(m); err != nil {
152 return err
153 }
154 // write new files
155 for _, h := range m.OEM.Hardware.Assign {
156 rulesContent, err := h.generateUdevRuleContent()
157 if err != nil {
158 return err
159 }
160 outfile := filepath.Join(snapUdevRulesDir, fmt.Sprintf("80-snappy_%s_%s.rules", m.Name, h.PartID))
161 if err := ioutil.WriteFile(outfile, []byte(rulesContent), 0644); err != nil {
162 return err
163 }
164 }
165
166 return nil
167}
168
169// var to make testing easier
170var runUdevAdm = runUdevAdmImpl
171
172func runUdevAdmImpl(args ...string) error {
173 cmd := exec.Command(args[0], args[1:]...)
174 cmd.Stdout = os.Stdout
175 cmd.Stderr = os.Stderr
176 return cmd.Run()
177}
178
179func activateOemHardwareUdevRules(m *packageYaml) error {
180 if err := runUdevAdm("udevadm", "control", "--reload-rules"); err != nil {
181 return err
182 }
183
184 return runUdevAdm("udevadm", "trigger")
185}
186
187func installOemHardwareUdevRules(m *packageYaml) error {
188 if err := writeOemHardwareUdevRules(m); err != nil {
189 return err
190 }
191
192 if err := activateOemHardwareUdevRules(m); err != nil {
193 return err
194 }
195
196 return nil
197}
0198
=== added file 'snappy/oem_test.go'
--- snappy/oem_test.go 1970-01-01 00:00:00 +0000
+++ snappy/oem_test.go 2015-04-20 23:57:04 +0000
@@ -0,0 +1,59 @@
1/*
2 * Copyright (C) 2014-2015 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18// TODO this should be it's own package, but depends on splitting out
19// package.yaml's
20
21package snappy
22
23import (
24 . "launchpad.net/gocheck"
25)
26
27type OemSuite struct {
28}
29
30var _ = Suite(&OemSuite{})
31
32var (
33 getOemOrig = getOem
34)
35
36func (s *OemSuite) SetUpTest(c *C) {
37 getOem = func() (*packageYaml, error) {
38 return &packageYaml{
39 OEM: OEM{
40 Software: Software{[]string{"makeuppackage", "anotherpackage"}},
41 Store: Store{"ninjablocks"},
42 },
43 }, nil
44 }
45}
46
47func (s *OemSuite) TearDownTest(c *C) {
48 getOem = getOemImpl
49}
50
51func (s *OemSuite) TestIsBuildIn(c *C) {
52 c.Check(IsBuiltInSoftware("notapackage"), Equals, false)
53 c.Check(IsBuiltInSoftware("makeuppackage"), Equals, true)
54 c.Check(IsBuiltInSoftware("anotherpackage"), Equals, true)
55}
56
57func (s *OemSuite) TestStoreID(c *C) {
58 c.Assert(StoreID(), Equals, "ninjablocks")
59}
060
=== modified file 'snappy/snapp.go'
--- snappy/snapp.go 2015-04-20 16:51:29 +0000
+++ snappy/snapp.go 2015-04-20 23:57:04 +0000
@@ -173,6 +173,8 @@
173173
174var commasplitter = regexp.MustCompile(`\s*,\s*`).Split174var commasplitter = regexp.MustCompile(`\s*,\s*`).Split
175175
176// TODO split into payloads per package type composing the common
177// elements for all snaps.
176type packageYaml struct {178type packageYaml struct {
177 Name string179 Name string
178 Version string180 Version string
@@ -192,14 +194,7 @@
192 Binaries []Binary `yaml:"binaries,omitempty"`194 Binaries []Binary `yaml:"binaries,omitempty"`
193195
194 // oem snap only196 // oem snap only
195 OEM struct {197 OEM OEM `yaml:"oem,omitempty"`
196 Store struct {
197 ID string `yaml:"id,omitempty"`
198 } `yaml:"store,omitempty"`
199 Hardware struct {
200 Assign []HardwareAssign `yaml:"assign,omitempty"`
201 } `yaml:"hardware,omitempty"`
202 } `yaml:"oem,omitempty"`
203 Config SystemConfig `yaml:"config,omitempty"`198 Config SystemConfig `yaml:"config,omitempty"`
204199
205 // this is a bit ugly, but right now integration is a one:one200 // this is a bit ugly, but right now integration is a one:one
@@ -210,19 +205,6 @@
210 LicenseVersion string `yaml:"license-version,omitempty"`205 LicenseVersion string `yaml:"license-version,omitempty"`
211}206}
212207
213// HardwareAssign describes the hardware a app can use
214type HardwareAssign struct {
215 PartID string `yaml:"part-id,omitempty"`
216 Rules []struct {
217 Kernel string `yaml:"kernel,omitempty"`
218 Subsystem string `yaml:"subsystem,omitempty"`
219 WithSubsystems string `yaml:"with-subsystems,omitempty"`
220 WithDriver string `yaml:"with-driver,omitempty"`
221 WithAttrs []string `yaml:"with-attrs,omitempty"`
222 WithProps []string `yaml:"with-props,omitempty"`
223 } `yaml:"rules,omitempty"`
224}
225
226type remoteSnap struct {208type remoteSnap struct {
227 Alias string `json:"alias,omitempty"`209 Alias string `json:"alias,omitempty"`
228 AnonDownloadURL string `json:"anon_download_url,omitempty"`210 AnonDownloadURL string `json:"anon_download_url,omitempty"`
@@ -248,99 +230,6 @@
248 } `json:"_embedded"`230 } `json:"_embedded"`
249}231}
250232
251func cleanupOemHardwareUdevRules(m *packageYaml) error {
252 oldFiles, err := filepath.Glob(filepath.Join(snapUdevRulesDir, fmt.Sprintf("80-snappy_%s_*.rules", m.Name)))
253 if err != nil {
254 return err
255 }
256
257 for _, f := range oldFiles {
258 os.Remove(f)
259 }
260
261 return nil
262}
263
264func writeOemHardwareUdevRules(m *packageYaml) error {
265 // cleanup
266 if err := cleanupOemHardwareUdevRules(m); err != nil {
267 return err
268 }
269 // write new files
270 for _, h := range m.OEM.Hardware.Assign {
271 rulesContent, err := h.generateUdevRuleContent()
272 if err != nil {
273 return err
274 }
275 outfile := filepath.Join(snapUdevRulesDir, fmt.Sprintf("80-snappy_%s_%s.rules", m.Name, h.PartID))
276 if err := ioutil.WriteFile(outfile, []byte(rulesContent), 0644); err != nil {
277 return err
278 }
279 }
280
281 return nil
282}
283
284// var to make testing easier
285var runUdevAdm = runUdevAdmImpl
286
287func runUdevAdmImpl(args ...string) error {
288 cmd := exec.Command(args[0], args[1:]...)
289 cmd.Stdout = os.Stdout
290 cmd.Stderr = os.Stderr
291 return cmd.Run()
292}
293
294func activateOemHardwareUdevRules(m *packageYaml) error {
295 if err := runUdevAdm("udevadm", "control", "--reload-rules"); err != nil {
296 return err
297 }
298
299 return runUdevAdm("udevadm", "trigger")
300}
301
302func installOemHardwareUdevRules(m *packageYaml) error {
303 if err := writeOemHardwareUdevRules(m); err != nil {
304 return err
305 }
306
307 if err := activateOemHardwareUdevRules(m); err != nil {
308 return err
309 }
310
311 return nil
312}
313
314func (hw *HardwareAssign) generateUdevRuleContent() (string, error) {
315 s := ""
316 for _, r := range hw.Rules {
317 if r.Kernel != "" {
318 s += fmt.Sprintf(`KERNEL=="%v", `, r.Kernel)
319 }
320 if r.Subsystem != "" {
321 s += fmt.Sprintf(`SUBSYSTEM=="%v", `, r.Subsystem)
322 }
323 if r.WithSubsystems != "" {
324 s += fmt.Sprintf(`SUBSYSTEMS=="%v", `, r.WithSubsystems)
325 }
326 if r.WithDriver != "" {
327 s += fmt.Sprintf(`DRIVER=="%v", `, r.WithDriver)
328 }
329 for _, a := range r.WithAttrs {
330 l := strings.Split(a, "=")
331 s += fmt.Sprintf(`ATTRS{%v}=="%v", `, l[0], l[1])
332 }
333 for _, a := range r.WithProps {
334 l := strings.SplitN(a, "=", 2)
335 s += fmt.Sprintf(`ENV{%v}=="%v", `, l[0], l[1])
336 }
337 s += fmt.Sprintf(`TAG:="snappy-assign", ENV{SNAPPY_APP}:="%s"`, hw.PartID)
338 s += "\n\n"
339 }
340
341 return s, nil
342}
343
344func parsePackageYamlFile(yamlPath string) (*packageYaml, error) {233func parsePackageYamlFile(yamlPath string) (*packageYaml, error) {
345234
346 yamlData, err := ioutil.ReadFile(yamlPath)235 yamlData, err := ioutil.ReadFile(yamlPath)
@@ -689,6 +578,10 @@
689 return ErrPackageNotRemovable578 return ErrPackageNotRemovable
690 }579 }
691580
581 if IsBuiltInSoftware(s.Name()) && s.IsActive() {
582 return ErrPackageNotRemovable
583 }
584
692 deps, err := s.DependentNames()585 deps, err := s.DependentNames()
693 if err != nil {586 if err != nil {
694 return err587 return err
@@ -1206,13 +1099,8 @@
1206 req.Header.Set("X-Ubuntu-Architecture", string(Architecture()))1099 req.Header.Set("X-Ubuntu-Architecture", string(Architecture()))
1207 req.Header.Set("X-Ubuntu-Release", release.String())1100 req.Header.Set("X-Ubuntu-Release", release.String())
12081101
1209 // check if the oem part sets a custom store-id1102 if storeID := StoreID(); storeID != "" {
1210 oems, _ := ActiveSnapsByType(SnapTypeOem)1103 req.Header.Set("X-Ubuntu-Store", storeID)
1211 if len(oems) == 1 {
1212 storeID := oems[0].(*SnapPart).m.OEM.Store.ID
1213 if storeID != "" {
1214 req.Header.Set("X-Ubuntu-Store", storeID)
1215 }
1216 }1104 }
12171105
1218 // sso1106 // sso
12191107
=== modified file 'snappy/snapp_test.go'
--- snappy/snapp_test.go 2015-04-20 18:40:29 +0000
+++ snappy/snapp_test.go 2015-04-20 23:57:04 +0000
@@ -835,6 +835,37 @@
835 repo.Details("xkcd")835 repo.Details("xkcd")
836}836}
837837
838func (s *SnapTestSuite) TestUninstallBuiltIn(c *C) {
839 // install custom oem snap with store-id
840 oemYaml, err := makeInstalledMockSnap(s.tempdir, `name: oem-test
841version: 1.0
842vendor: mvo
843oem:
844 store:
845 id: my-store
846 software:
847 built-in:
848 - hello-app
849type: oem
850`)
851 c.Assert(err, IsNil)
852 makeSnapActive(oemYaml)
853
854 packageYaml, err := makeInstalledMockSnap(s.tempdir, "")
855 c.Assert(err, IsNil)
856 makeSnapActive(packageYaml)
857
858 p := &MockProgressMeter{}
859
860 snap := NewLocalSnapRepository(filepath.Join(s.tempdir, "apps"))
861 c.Assert(snap, NotNil)
862 installed, err := snap.Installed()
863 c.Assert(err, IsNil)
864 parts := FindSnapsByName("hello-app", installed)
865 c.Assert(parts, HasLen, 1)
866 c.Check(parts[0].Uninstall(p), Equals, ErrPackageNotRemovable)
867}
868
838var securityBinaryPackageYaml = []byte(`name: test-snap869var securityBinaryPackageYaml = []byte(`name: test-snap
839version: 1.2.8870version: 1.2.8
840vendor: Jamie Strandboge <jamie@canonical.com>871vendor: Jamie Strandboge <jamie@canonical.com>
@@ -1209,10 +1240,10 @@
1209 - subsystem: tty1240 - subsystem: tty
1210 with-subsystems: usb-serial1241 with-subsystems: usb-serial
1211 with-driver: pl23031242 with-driver: pl2303
1212 with-attrs: 1243 with-attrs:
1213 - idVendor=0xf00f001244 - idVendor=0xf00f00
1214 - idProduct=0xb001245 - idProduct=0xb00
1215 with-props: 1246 with-props:
1216 - BAUD=96001247 - BAUD=9600
1217 - META1=foo*1248 - META1=foo*
1218 - META2=foo?1249 - META2=foo?

Subscribers

People subscribed via source and target branches