Merge lp:~chipaca/snappy/no-sideload-overwrite into lp:~snappy-dev/snappy/snappy-moved-to-github

Proposed by John Lenton
Status: Merged
Approved by: Michael Vogt
Approved revision: 763
Merged at revision: 762
Proposed branch: lp:~chipaca/snappy/no-sideload-overwrite
Merge into: lp:~snappy-dev/snappy/snappy-moved-to-github
Prerequisite: lp:~chipaca/snappy/no-inactive-service-ops
Diff against target: 262 lines (+80/-28)
7 files modified
snappy/click_test.go (+18/-8)
snappy/common_test.go (+34/-3)
snappy/parts_test.go (+2/-2)
snappy/purge_test.go (+1/-0)
snappy/service_test.go (+1/-0)
snappy/snapp.go (+2/-4)
snappy/snapp_test.go (+22/-11)
To merge this branch: bzr merge lp:~chipaca/snappy/no-sideload-overwrite
Reviewer Review Type Date Requested Status
Michael Vogt (community) Approve
Review via email: mp+274046@code.launchpad.net

Commit message

Don't let people sideload over things that are installed; it breaks stuff.

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

This breaks sideloading an OEM snap. I'm not sure whether that is good or bad, please advise.

762. By John Lenton

fixes lp:1504754

763. By John Lenton

oops, leftover println

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

<sergiusens> Chipaca, sideloading of oem was contemplated by some as a development feature, from my PoV, with our current system it should not be allowed. Only during image creation
<ogra_> Chipaca, it is needed for porting ... but only works in --developer-mode
<ogra_> Chipaca, i agree with sergiusens, it shouldnt be allowed on a running system, but the CI people might disagree (i think they want to test oem snaps like this)
<sergiusens> ogra_, half of what the oem snap does is only done on first boot though
<ogra_> right

for CI sideloading the right approach is the staging store (or airgap, when/if that happens).

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

Thanks for this branch. I think the change is ok, it make the whole system more predictable.

However this also makes me wonder if we can go back to have the "origin" in the framework path again. I.e. instead of /apps/hello-dbus-fwk we would use /apps/hello-dbus-fwk.ubuntu to match what every other snap has. IIRC we did not do that initially because we wanted to ensure that apps have a stable path regardless of origin. However we also said at some point that frameworks can not be forked, so unless I miss something we could reconsider the path and simply some internal code. But obviously not in this branch :)

review: Approve
Revision history for this message
Sergio Schvezov (sergiusens) wrote :

On Mon, Oct 12, 2015 at 3:31 AM, Michael Vogt <email address hidden>
wrote:

> Review: Approve
>
> Thanks for this branch. I think the change is ok, it make the whole system
> more predictable.
>
> However this also makes me wonder if we can go back to have the "origin"
> in the framework path again. I.e. instead of /apps/hello-dbus-fwk we would
> use /apps/hello-dbus-fwk.ubuntu to match what every other snap has. IIRC we
> did not do that initially because we wanted to ensure that apps have a
> stable path regardless of origin. However we also said at some point that
> frameworks can not be forked, so unless I miss something we could
> reconsider the path and simply some internal code. But obviously not in
> this branch :)
>

Doing this would break docker, it has the same problems we saw when doing
that camera framework at the sprint, you need to specify the path to the
binary, as in /apps/docker/bin/docker and not /apps/bin/docker

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

On 13 October 2015 at 12:24, Sergio Schvezov
<email address hidden> wrote:
> Doing this would break docker, it has the same problems we saw when doing
> that camera framework at the sprint, you need to specify the path to the
> binary, as in /apps/docker/bin/docker and not /apps/bin/docker

but that could be /apps/docker.docker/current/bin/docker just fine, as
long as we tracked sideloaded things separately from the filesystem
path.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'snappy/click_test.go'
2--- snappy/click_test.go 2015-10-07 15:47:01 +0000
3+++ snappy/click_test.go 2015-10-10 13:38:04 +0000
4@@ -453,12 +453,15 @@
5 defer func() { policy.SecBase = secbase }()
6 policy.SecBase = c.MkDir()
7
8- snapName := s.buildFramework(c)
9+ s.buildFramework(c)
10+
11+ // ...?
12+
13 // rename the policy
14 //poldir := filepath.Join(tmpdir, "meta", "framework-policy", "apparmor", "policygroups")
15
16- _, err := installClick(snapName, 0, nil, testOrigin)
17- c.Assert(err, IsNil)
18+ // _, err := installClick(snapName, 0, nil, testOrigin)
19+ // c.Assert(err, IsNil)
20 // appdir := filepath.Join(s.tempdir, "apps", "hello.testspacethename", "1.0.1")
21 // c.Assert(removeClick(appdir, nil), IsNil)
22 }
23@@ -520,6 +523,7 @@
24 vendor: Foo Bar <foo@example.com>`)
25 _, err := installClick(snapFile, AllowOEM, nil, testOrigin)
26 c.Assert(err, IsNil)
27+ c.Assert(storeMinimalRemoteManifest("foo", "foo", testOrigin, "1.0", ""), IsNil)
28
29 contentFile := filepath.Join(s.tempdir, "oem", "foo", "1.0", "bin", "foo")
30 _, err = os.Stat(contentFile)
31@@ -527,7 +531,7 @@
32 _, err = os.Stat(filepath.Join(s.tempdir, "oem", "foo", "1.0", ".click", "info", "foo.manifest"))
33 c.Assert(err, IsNil)
34
35- // an package update
36+ // a package update
37 snapFile = makeTestSnapPackage(c, `name: foo
38 version: 2.0
39 type: oem
40@@ -535,11 +539,17 @@
41 vendor: Foo Bar <foo@example.com>`)
42 _, err = installClick(snapFile, 0, nil, testOrigin)
43 c.Check(err, IsNil)
44+ c.Assert(storeMinimalRemoteManifest("foo", "foo", testOrigin, "2.0", ""), IsNil)
45
46- // different origin, this shows we have no origin support at this
47- // level, but sideloading also works.
48- _, err = installClick(snapFile, 0, nil, SideloadedOrigin)
49- c.Check(err, IsNil)
50+ // XXX: I think this next test now tests something we actually don't
51+ // want. At least for fwks and apps, sideloading something installed
52+ // is a no-no. Are OEMs different in this regard?
53+ //
54+ // // different origin, this shows we have no origin support at this
55+ // // level, but sideloading also works.
56+ // _, err = installClick(snapFile, 0, nil, SideloadedOrigin)
57+ // c.Check(err, IsNil)
58+ // c.Assert(storeMinimalRemoteManifest("foo", "foo", SideloadedOrigin, "1.0", ""), IsNil)
59
60 // a package name fork, IOW, a different OEM package.
61 snapFile = makeTestSnapPackage(c, `name: foo-fork
62
63=== modified file 'snappy/common_test.go'
64--- snappy/common_test.go 2015-10-08 10:33:37 +0000
65+++ snappy/common_test.go 2015-10-10 13:38:04 +0000
66@@ -26,11 +26,13 @@
67 "path/filepath"
68 "strings"
69
70+ . "gopkg.in/check.v1"
71+ "gopkg.in/yaml.v2"
72+
73+ "launchpad.net/snappy/dirs"
74 "launchpad.net/snappy/helpers"
75 "launchpad.net/snappy/pkg"
76-
77- . "gopkg.in/check.v1"
78- "gopkg.in/yaml.v2"
79+ "launchpad.net/snappy/pkg/remote"
80 )
81
82 const (
83@@ -90,9 +92,34 @@
84 return "", err
85 }
86
87+ if err := storeMinimalRemoteManifest(dirName, m.Name, testOrigin, m.Version, "Hello"); err != nil {
88+ return "", err
89+ }
90+
91 return yamlFile, nil
92 }
93
94+func storeMinimalRemoteManifest(qn, name, origin, version, desc string) error {
95+ if origin == SideloadedOrigin {
96+ panic("store remote manifest for sideloaded package")
97+ }
98+ content, err := yaml.Marshal(remote.Snap{
99+ Name: name,
100+ Origin: origin,
101+ Version: version,
102+ Description: desc,
103+ })
104+ if err != nil {
105+ return err
106+ }
107+
108+ if err := ioutil.WriteFile(filepath.Join(dirs.SnapMetaDir, fmt.Sprintf("%s_%s.manifest", qn, version)), content, 0644); err != nil {
109+ return err
110+ }
111+
112+ return nil
113+}
114+
115 func addDefaultApparmorJSON(tempdir, apparmorJSONPath string) error {
116 appArmorDir := filepath.Join(tempdir, "var", "lib", "apparmor", "clicks")
117 if err := os.MkdirAll(appArmorDir, 0775); err != nil {
118@@ -167,19 +194,23 @@
119 packageYaml += strings.Join(extra, "\n") + "\n"
120 }
121
122+ qn := "foo." + testOrigin
123 if snapType != pkg.TypeApp {
124 packageYaml += fmt.Sprintf("type: %s\n", snapType)
125+ qn = "foo"
126 }
127
128 snapFile := makeTestSnapPackage(c, packageYaml+"version: 1.0")
129 n, err := installClick(snapFile, AllowUnauthenticated|AllowOEM, inter, testOrigin)
130 c.Assert(err, IsNil)
131 c.Assert(n, Equals, "foo")
132+ c.Assert(storeMinimalRemoteManifest(qn, "foo", testOrigin, "1.0", ""), IsNil)
133
134 snapFile = makeTestSnapPackage(c, packageYaml+"version: 2.0")
135 n, err = installClick(snapFile, AllowUnauthenticated|AllowOEM, inter, testOrigin)
136 c.Assert(err, IsNil)
137 c.Assert(n, Equals, "foo")
138+ c.Assert(storeMinimalRemoteManifest(qn, "foo", testOrigin, "2.0", ""), IsNil)
139
140 m := NewMetaRepository()
141 installed, err := m.Installed()
142
143=== modified file 'snappy/parts_test.go'
144--- snappy/parts_test.go 2015-10-01 19:28:27 +0000
145+++ snappy/parts_test.go 2015-10-10 13:38:04 +0000
146@@ -84,7 +84,7 @@
147 {QualifiedName, pkg.TypeApp, "app." + testOrigin},
148 {QualifiedName, pkg.TypeFramework, "fwk"},
149 {FullName, pkg.TypeApp, "app." + testOrigin},
150- {FullName, pkg.TypeFramework, "fwk.sideload"}, // .sideload here is an artifact of where we're storing the origin for frameworks :-/
151+ {FullName, pkg.TypeFramework, "fwk." + testOrigin},
152 } {
153 names, err := ActiveSnapIterByType(t.f, t.t)
154 c.Check(err, IsNil)
155@@ -212,7 +212,7 @@
156 c.Assert(err, IsNil)
157
158 parts := FindSnapsByNameAndVersion("fmk."+testOrigin, "1", installed)
159- c.Check(parts, HasLen, 0)
160+ c.Check(parts, HasLen, 1)
161 parts = FindSnapsByNameAndVersion("fmk.badOrigin", "1", installed)
162 c.Check(parts, HasLen, 0)
163
164
165=== modified file 'snappy/purge_test.go'
166--- snappy/purge_test.go 2015-09-29 07:07:13 +0000
167+++ snappy/purge_test.go 2015-10-10 13:38:04 +0000
168@@ -41,6 +41,7 @@
169 func (s *purgeSuite) SetUpTest(c *C) {
170 s.tempdir = c.MkDir()
171 dirs.SetRootDir(s.tempdir)
172+ os.MkdirAll(dirs.SnapMetaDir, 0755)
173 os.MkdirAll(filepath.Join(dirs.SnapServicesDir, "multi-user.target.wants"), 0755)
174 systemd.SystemctlCmd = func(cmd ...string) ([]byte, error) {
175 return []byte("ActiveState=inactive\n"), nil
176
177=== modified file 'snappy/service_test.go'
178--- snappy/service_test.go 2015-10-10 13:38:04 +0000
179+++ snappy/service_test.go 2015-10-10 13:38:04 +0000
180@@ -76,6 +76,7 @@
181 os.Setenv("TZ", "")
182
183 dirs.SetRootDir(c.MkDir())
184+ c.Assert(os.MkdirAll(dirs.SnapMetaDir, 0755), IsNil)
185 // TODO: this mkdir hack is so enable doesn't fail; remove when enable is the same as the rest
186 c.Assert(os.MkdirAll(filepath.Join(dirs.GlobalRootDir, "/etc/systemd/system/multi-user.target.wants"), 0755), IsNil)
187 systemd.SystemctlCmd = s.myRun
188
189=== modified file 'snappy/snapp.go'
190--- snappy/snapp.go 2015-10-08 17:42:22 +0000
191+++ snappy/snapp.go 2015-10-10 13:38:04 +0000
192@@ -374,10 +374,8 @@
193 return nil
194 }
195
196- if m.Type != pkg.TypeFramework && m.Type != pkg.TypeOem {
197- if part.Origin() != origin {
198- return ErrPackageNameAlreadyInstalled
199- }
200+ if part.Origin() != origin {
201+ return ErrPackageNameAlreadyInstalled
202 }
203
204 return nil
205
206=== modified file 'snappy/snapp_test.go'
207--- snappy/snapp_test.go 2015-10-07 15:47:01 +0000
208+++ snappy/snapp_test.go 2015-10-10 13:38:04 +0000
209@@ -63,6 +63,7 @@
210 policy.SecBase = filepath.Join(s.tempdir, "security")
211 os.MkdirAll(dirs.SnapServicesDir, 0755)
212 os.MkdirAll(dirs.SnapSeccompDir, 0755)
213+ os.MkdirAll(dirs.SnapMetaDir, 0755)
214
215 release.Override(release.Release{Flavor: "core", Series: "15.04"})
216
217@@ -1090,8 +1091,7 @@
218 }
219
220 func (s *SnapTestSuite) TestIgnoresAlreadyInstalledSameOrigin(c *C) {
221- // XXX: should this be allowed? right now it is (=> you can re-sideload the same version of your apps)
222- // (remote snaps are stopped before clickInstall gets to run)
223+ // NOTE remote snaps are stopped before clickInstall gets to run
224
225 data := "name: afoo\nversion: 1\nvendor: foo"
226 yamlPath, err := makeInstalledMockSnap(s.tempdir, data)
227@@ -1103,15 +1103,26 @@
228 c.Check(yaml.checkForPackageInstalled(testOrigin), IsNil)
229 }
230
231-func (s *SnapTestSuite) TestIgnoresAlreadyInstalledFrameworks(c *C) {
232- data := "name: afoo\nversion: 1\nvendor: foo\ntype: framework"
233- yamlPath, err := makeInstalledMockSnap(s.tempdir, data)
234- c.Assert(err, IsNil)
235- c.Assert(makeSnapActive(yamlPath), IsNil)
236-
237- yaml, err := parsePackageYamlData([]byte(data), false)
238- c.Assert(err, IsNil)
239- c.Check(yaml.checkForPackageInstalled("otherns"), IsNil)
240+func (s *SnapTestSuite) TestIgnoresAlreadyInstalledFrameworkSameOrigin(c *C) {
241+ data := "name: afoo\nversion: 1\nvendor: foo\ntype: framework"
242+ yamlPath, err := makeInstalledMockSnap(s.tempdir, data)
243+ c.Assert(err, IsNil)
244+ c.Assert(makeSnapActive(yamlPath), IsNil)
245+
246+ yaml, err := parsePackageYamlData([]byte(data), false)
247+ c.Assert(err, IsNil)
248+ c.Check(yaml.checkForPackageInstalled(testOrigin), IsNil)
249+}
250+
251+func (s *SnapTestSuite) TestDetectsAlreadyInstalledFramework(c *C) {
252+ data := "name: afoo\nversion: 1\nvendor: foo\ntype: framework"
253+ yamlPath, err := makeInstalledMockSnap(s.tempdir, data)
254+ c.Assert(err, IsNil)
255+ c.Assert(makeSnapActive(yamlPath), IsNil)
256+
257+ yaml, err := parsePackageYamlData([]byte(data), false)
258+ c.Assert(err, IsNil)
259+ c.Check(yaml.checkForPackageInstalled("otherns"), Equals, ErrPackageNameAlreadyInstalled)
260 }
261
262 func (s *SnapTestSuite) TestUsesStoreMetaData(c *C) {

Subscribers

People subscribed via source and target branches