summaryrefslogtreecommitdiff
diff options
authorPawel Stolowski <stolowski@gmail.com>2018-06-20 12:35:32 +0200
committerPawel Stolowski <stolowski@gmail.com>2018-06-20 12:35:32 +0200
commitf31897ab9500ad0aba03d51362019091fb1a2b84 (patch)
tree6b2d38d26ad3cc15f560093cfbced790967410f6
parent00ac0b391fbe9f0b3d8076a5e5811315ff6e9d2b (diff)
parent82479957466e54232b8eb162f42667154e582ddb (diff)
Merge branch 'master' into self-connect-fixself-connect-fix
-rw-r--r--asserts/device_asserts.go1
-rw-r--r--boot/kernel_os.go7
-rw-r--r--boot/kernel_os_test.go8
-rw-r--r--cmd/snap-update-ns/change.go22
-rw-r--r--cmd/snap/cmd_info.go2
-rw-r--r--cmd/snap/cmd_run.go22
-rw-r--r--cmd/snap/cmd_run_test.go47
-rw-r--r--daemon/api.go21
-rw-r--r--daemon/api_mock_test.go4
-rw-r--r--daemon/snap.go12
-rw-r--r--image/helpers.go4
-rw-r--r--image/image.go8
-rw-r--r--image/image_test.go8
-rw-r--r--interfaces/apparmor/backend.go60
-rw-r--r--interfaces/apparmor/backend_test.go59
-rw-r--r--interfaces/apparmor/export_test.go5
-rw-r--r--interfaces/apparmor/spec.go87
-rw-r--r--interfaces/apparmor/spec_test.go84
-rw-r--r--interfaces/apparmor/template_vars.go3
-rw-r--r--interfaces/builtin/content.go6
-rw-r--r--interfaces/builtin/content_test.go12
-rw-r--r--interfaces/builtin/desktop.go5
-rw-r--r--interfaces/builtin/export_test.go8
-rw-r--r--interfaces/builtin/gpio.go2
-rw-r--r--interfaces/builtin/spi.go2
-rw-r--r--interfaces/builtin/thumbnailer_service.go3
-rw-r--r--interfaces/builtin/ubuntu_download_manager.go3
-rw-r--r--interfaces/builtin/unity7.go3
-rw-r--r--interfaces/builtin/utils.go3
-rw-r--r--interfaces/builtin/utils_test.go4
-rw-r--r--interfaces/builtin/wayland.go3
-rw-r--r--interfaces/connection.go12
-rw-r--r--interfaces/core.go8
-rw-r--r--interfaces/dbus/backend.go2
-rw-r--r--interfaces/ifacetest/backendtest.go12
-rw-r--r--interfaces/json.go4
-rw-r--r--interfaces/kmod/backend.go4
-rw-r--r--interfaces/mount/backend.go4
-rw-r--r--interfaces/repo.go12
-rw-r--r--interfaces/repo_test.go92
-rw-r--r--interfaces/seccomp/backend.go2
-rw-r--r--interfaces/sorting.go16
-rw-r--r--interfaces/systemd/backend.go2
-rw-r--r--interfaces/udev/backend.go4
-rw-r--r--overlord/assertstate/assertstate.go8
-rw-r--r--overlord/devicestate/devicemgr.go2
-rw-r--r--overlord/devicestate/devicestate.go13
-rw-r--r--overlord/devicestate/devicestate_test.go6
-rw-r--r--overlord/devicestate/firstboot_test.go11
-rw-r--r--overlord/devicestate/handlers.go2
-rw-r--r--overlord/hookstate/ctlcmd/services_test.go8
-rw-r--r--overlord/ifacestate/handlers.go22
-rw-r--r--overlord/ifacestate/helpers.go16
-rw-r--r--overlord/ifacestate/ifacestate.go2
-rw-r--r--overlord/ifacestate/ifacestate_test.go96
-rw-r--r--overlord/managers_test.go6
-rw-r--r--overlord/servicestate/servicestate.go2
-rw-r--r--overlord/snapshotstate/backend/backend.go2
-rw-r--r--overlord/snapshotstate/backend/backend_test.go4
-rw-r--r--overlord/snapstate/aliasesv2.go5
-rw-r--r--overlord/snapstate/aliasesv2_test.go10
-rw-r--r--overlord/snapstate/backend/backend_test.go4
-rw-r--r--overlord/snapstate/backend/copydata.go8
-rw-r--r--overlord/snapstate/backend/link.go10
-rw-r--r--overlord/snapstate/backend/mountunit.go2
-rw-r--r--overlord/snapstate/backend_test.go2
-rw-r--r--overlord/snapstate/booted_test.go5
-rw-r--r--overlord/snapstate/check_snap.go19
-rw-r--r--overlord/snapstate/check_snap_test.go2
-rw-r--r--overlord/snapstate/export_test.go43
-rw-r--r--overlord/snapstate/handlers.go34
-rw-r--r--overlord/snapstate/handlers_aliasesv2_test.go28
-rw-r--r--overlord/snapstate/handlers_link_test.go114
-rw-r--r--overlord/snapstate/snapstate.go27
-rw-r--r--overlord/snapstate/snapstate_test.go26
-rw-r--r--overlord/snapstate/storehelpers.go10
-rw-r--r--snap/broken.go2
-rw-r--r--snap/container.go15
-rw-r--r--snap/info.go65
-rw-r--r--snap/info_snap_yaml_test.go70
-rw-r--r--snap/info_test.go22
-rw-r--r--snap/pack/pack.go2
-rw-r--r--snap/snapenv/snapenv.go6
-rw-r--r--snap/snaptest/snaptest_test.go8
-rw-r--r--snap/validate.go8
-rw-r--r--spread.yaml4
-rw-r--r--store/details.go18
-rw-r--r--store/store.go19
-rw-r--r--store/store_test.go279
-rw-r--r--tests/lib/fakestore/store/store.go4
-rwxr-xr-xtests/lib/prepare-restore.sh3
-rwxr-xr-xtests/lib/state.sh12
-rw-r--r--tests/main/econnreset/task.yaml22
-rw-r--r--tests/main/security-setuid-root/task.yaml4
-rw-r--r--tests/main/snap-confine-from-core/task.yaml8
-rw-r--r--wrappers/desktop.go9
-rw-r--r--wrappers/services.go8
97 files changed, 1183 insertions, 646 deletions
diff --git a/asserts/device_asserts.go b/asserts/device_asserts.go
index 4f2f7d7293..1feb83d69f 100644
--- a/asserts/device_asserts.go
+++ b/asserts/device_asserts.go
@@ -215,6 +215,7 @@ func assembleModel(assert assertionBase) (Assertion, error) {
return nil, err
}
+ // TODO parallel-install: verify if snap names are valid store names
reqSnaps, err := checkStringList(assert.headers, "required-snaps")
if err != nil {
return nil, err
diff --git a/boot/kernel_os.go b/boot/kernel_os.go
index 9bb2bb43f5..d63a670082 100644
--- a/boot/kernel_os.go
+++ b/boot/kernel_os.go
@@ -109,7 +109,7 @@ func SetNextBoot(s *snap.Info) error {
}
if s.Type != snap.TypeOS && s.Type != snap.TypeKernel && s.Type != snap.TypeBase {
- return fmt.Errorf("cannot set next boot to snap %q with type %q", s.Name(), s.Type)
+ return fmt.Errorf("cannot set next boot to snap %q with type %q", s.StoreName(), s.Type)
}
bootloader, err := partition.FindBootloader()
@@ -155,8 +155,9 @@ func SetNextBoot(s *snap.Info) error {
})
}
-// KernelOsBaseRebootRequired returns whether a reboot is required to swith to the given OS or kernel snap.
-func KernelOsBaseRebootRequired(s *snap.Info) bool {
+// ChangeRequiresReboot returns whether a reboot is required to switch
+// to the given OS, base or kernel snap.
+func ChangeRequiresReboot(s *snap.Info) bool {
if s.Type != snap.TypeKernel && s.Type != snap.TypeOS && s.Type != snap.TypeBase {
return false
}
diff --git a/boot/kernel_os_test.go b/boot/kernel_os_test.go
index a1bfac3593..a011ab9f0e 100644
--- a/boot/kernel_os_test.go
+++ b/boot/kernel_os_test.go
@@ -178,7 +178,7 @@ func (s *kernelOSSuite) TestSetNextBootForCore(c *C) {
"snap_mode": "try",
})
- c.Check(boot.KernelOsBaseRebootRequired(info), Equals, true)
+ c.Check(boot.ChangeRequiresReboot(info), Equals, true)
}
func (s *kernelOSSuite) TestSetNextBootWithBaseForCore(c *C) {
@@ -198,7 +198,7 @@ func (s *kernelOSSuite) TestSetNextBootWithBaseForCore(c *C) {
"snap_mode": "try",
})
- c.Check(boot.KernelOsBaseRebootRequired(info), Equals, true)
+ c.Check(boot.ChangeRequiresReboot(info), Equals, true)
}
func (s *kernelOSSuite) TestSetNextBootForKernel(c *C) {
@@ -220,11 +220,11 @@ func (s *kernelOSSuite) TestSetNextBootForKernel(c *C) {
s.bootloader.BootVars["snap_kernel"] = "krnl_40.snap"
s.bootloader.BootVars["snap_try_kernel"] = "krnl_42.snap"
- c.Check(boot.KernelOsBaseRebootRequired(info), Equals, true)
+ c.Check(boot.ChangeRequiresReboot(info), Equals, true)
// simulate good boot
s.bootloader.BootVars["snap_kernel"] = "krnl_42.snap"
- c.Check(boot.KernelOsBaseRebootRequired(info), Equals, false)
+ c.Check(boot.ChangeRequiresReboot(info), Equals, false)
}
func (s *kernelOSSuite) TestSetNextBootForKernelForTheSameKernel(c *C) {
diff --git a/cmd/snap-update-ns/change.go b/cmd/snap-update-ns/change.go
index 8587cdc27b..6e29137501 100644
--- a/cmd/snap-update-ns/change.go
+++ b/cmd/snap-update-ns/change.go
@@ -66,6 +66,18 @@ func (c Change) String() string {
// changePerform is Change.Perform that can be mocked for testing.
var changePerform func(*Change, *Secure) ([]*Change, error)
+// mimicRequired provides information if an error warrants a writable mimic.
+//
+// The returned path is the location where a mimic should be constructed.
+func mimicRequired(err error) (needsMimic bool, path string) {
+ switch err.(type) {
+ case *ReadOnlyFsError:
+ rofsErr := err.(*ReadOnlyFsError)
+ return true, rofsErr.Path
+ }
+ return false, ""
+}
+
func (c *Change) createPath(path string, pokeHoles bool, sec *Secure) ([]*Change, error) {
// If we've been asked to create a missing path, and the mount
// entry uses the ignore-missing option, return an error.
@@ -100,12 +112,12 @@ func (c *Change) createPath(path string, pokeHoles bool, sec *Secure) ([]*Change
case "symlink":
err = sec.MksymlinkAll(path, mode, uid, gid, c.Entry.XSnapdSymlink())
}
- if err2, ok := err.(*ReadOnlyFsError); ok && pokeHoles {
- // If the writing failed because the underlying file-system is read-only
- // we can construct a writable mimic to fix that.
- changes, err = createWritableMimic(err2.Path, path, sec)
+ if needsMimic, mimicPath := mimicRequired(err); needsMimic && pokeHoles {
+ // If the error can be recovered by using a writable mimic
+ // then construct one and try again.
+ changes, err = createWritableMimic(mimicPath, path, sec)
if err != nil {
- err = fmt.Errorf("cannot create writable mimic over %q: %s", err2.Path, err)
+ err = fmt.Errorf("cannot create writable mimic over %q: %s", mimicPath, err)
} else {
// Try once again. Note that we care *just* about the error. We have already
// performed the hole poking and thus additional changes must be nil.
diff --git a/cmd/snap/cmd_info.go b/cmd/snap/cmd_info.go
index 821379aee0..3356931abd 100644
--- a/cmd/snap/cmd_info.go
+++ b/cmd/snap/cmd_info.go
@@ -136,7 +136,7 @@ func tryDirect(w io.Writer, path string, verbose bool) bool {
return false
}
fmt.Fprintf(w, "path:\t%q\n", path)
- fmt.Fprintf(w, "name:\t%s\n", info.Name())
+ fmt.Fprintf(w, "name:\t%s\n", info.InstanceName())
fmt.Fprintf(w, "summary:\t%s\n", formatSummary(info.Summary()))
var notes *Notes
diff --git a/cmd/snap/cmd_run.go b/cmd/snap/cmd_run.go
index d28e18aa1a..0006fd4d0a 100644
--- a/cmd/snap/cmd_run.go
+++ b/cmd/snap/cmd_run.go
@@ -679,21 +679,29 @@ func (x *cmdRun) runCmdUnderStrace(origCmd, env []string) error {
func (x *cmdRun) runSnapConfine(info *snap.Info, securityTag, snapApp, hook string, args []string) error {
snapConfine := filepath.Join(dirs.DistroLibExecDir, "snap-confine")
- // if we re-exec, we must run the snap-confine from the core snap
+ // if we re-exec, we must run the snap-confine from the core/snapd snap
// as well, if they get out of sync, havoc will happen
if isReexeced() {
- // run snap-confine from the core snap. that will work because
- // snap-confine on the core snap is mostly statically linked
- // (except libudev and libc)
- snapConfine = filepath.Join(dirs.SnapMountDir, "core/current", dirs.CoreLibExecDir, "snap-confine")
+ // exe is something like /snap/{snapd,core}/123/usr/bin/snap
+ exe, err := osReadlink("/proc/self/exe")
+ if err != nil {
+ return err
+ }
+ // snapBase will be "/snap/{core,snapd}/$rev/" because
+ // the snap binary is always at $root/usr/bin/snap
+ snapBase := filepath.Clean(filepath.Join(filepath.Dir(exe), "..", ".."))
+ // Run snap-confine from the core/snapd snap. That
+ // will work because snap-confine on the core/snapd snap is
+ // mostly statically linked (except libudev and libc)
+ snapConfine = filepath.Join(snapBase, dirs.CoreLibExecDir, "snap-confine")
}
if !osutil.FileExists(snapConfine) {
if hook != "" {
- logger.Noticef("WARNING: skipping running hook %q of snap %q: missing snap-confine", hook, info.Name())
+ logger.Noticef("WARNING: skipping running hook %q of snap %q: missing snap-confine", hook, info.InstanceName())
return nil
}
- return fmt.Errorf(i18n.G("missing snap-confine: try updating your snapd package"))
+ return fmt.Errorf(i18n.G("missing snap-confine: try updating your core/snapd package"))
}
if err := createUserDataDirs(info); err != nil {
diff --git a/cmd/snap/cmd_run_test.go b/cmd/snap/cmd_run_test.go
index d6323fad86..234076045a 100644
--- a/cmd/snap/cmd_run_test.go
+++ b/cmd/snap/cmd_run_test.go
@@ -94,7 +94,7 @@ func (s *SnapSuite) TestSnapRunWhenMissingConfine(c *check.C) {
// and run it!
// a regular run will fail
_, err := snaprun.Parser().ParseArgs([]string{"run", "snapname.app", "--arg1", "arg2"})
- c.Assert(err, check.ErrorMatches, `.* your snapd package`)
+ c.Assert(err, check.ErrorMatches, `.* your core/snapd package`)
// a hook run will not fail
_, err = snaprun.Parser().ParseArgs([]string{"run", "--hook=configure", "snapname"})
c.Assert(err, check.IsNil)
@@ -465,7 +465,7 @@ func (s *SnapSuite) TestSnapRunIsReexeced(c *check.C) {
}
func (s *SnapSuite) TestSnapRunAppIntegrationFromCore(c *check.C) {
- defer mockSnapConfine(filepath.Join(dirs.SnapMountDir, "core", "current", dirs.CoreLibExecDir))()
+ defer mockSnapConfine(filepath.Join(dirs.SnapMountDir, "core", "111", dirs.CoreLibExecDir))()
// mock installed snap
snaptest.MockSnapCurrent(c, string(mockYaml), &snap.SideInfo{
@@ -494,9 +494,48 @@ func (s *SnapSuite) TestSnapRunAppIntegrationFromCore(c *check.C) {
rest, err := snaprun.Parser().ParseArgs([]string{"run", "snapname.app", "--arg1", "arg2"})
c.Assert(err, check.IsNil)
c.Assert(rest, check.DeepEquals, []string{"snapname.app", "--arg1", "arg2"})
- c.Check(execArg0, check.Equals, filepath.Join(dirs.SnapMountDir, "/core/current", dirs.CoreLibExecDir, "snap-confine"))
+ c.Check(execArg0, check.Equals, filepath.Join(dirs.SnapMountDir, "/core/111", dirs.CoreLibExecDir, "snap-confine"))
c.Check(execArgs, check.DeepEquals, []string{
- filepath.Join(dirs.SnapMountDir, "/core/current", dirs.CoreLibExecDir, "snap-confine"),
+ filepath.Join(dirs.SnapMountDir, "/core/111", dirs.CoreLibExecDir, "snap-confine"),
+ "snap.snapname.app",
+ filepath.Join(dirs.CoreLibExecDir, "snap-exec"),
+ "snapname.app", "--arg1", "arg2"})
+ c.Check(execEnv, testutil.Contains, "SNAP_REVISION=x2")
+}
+
+func (s *SnapSuite) TestSnapRunAppIntegrationFromSnapd(c *check.C) {
+ defer mockSnapConfine(filepath.Join(dirs.SnapMountDir, "snapd", "222", dirs.CoreLibExecDir))()
+
+ // mock installed snap
+ snaptest.MockSnapCurrent(c, string(mockYaml), &snap.SideInfo{
+ Revision: snap.R("x2"),
+ })
+
+ // pretend to be running from snapd
+ restorer := snaprun.MockOsReadlink(func(string) (string, error) {
+ return filepath.Join(dirs.SnapMountDir, "snapd/222/usr/bin/snap"), nil
+ })
+ defer restorer()
+
+ // redirect exec
+ execArg0 := ""
+ execArgs := []string{}
+ execEnv := []string{}
+ restorer = snaprun.MockSyscallExec(func(arg0 string, args []string, envv []string) error {
+ execArg0 = arg0
+ execArgs = args
+ execEnv = envv
+ return nil
+ })
+ defer restorer()
+
+ // and run it!
+ rest, err := snaprun.Parser().ParseArgs([]string{"run", "snapname.app", "--arg1", "arg2"})
+ c.Assert(err, check.IsNil)
+ c.Assert(rest, check.DeepEquals, []string{"snapname.app", "--arg1", "arg2"})
+ c.Check(execArg0, check.Equals, filepath.Join(dirs.SnapMountDir, "/snapd/222", dirs.CoreLibExecDir, "snap-confine"))
+ c.Check(execArgs, check.DeepEquals, []string{
+ filepath.Join(dirs.SnapMountDir, "/snapd/222", dirs.CoreLibExecDir, "snap-confine"),
"snap.snapname.app",
filepath.Join(dirs.CoreLibExecDir, "snap-exec"),
"snapname.app", "--arg1", "arg2"})
diff --git a/daemon/api.go b/daemon/api.go
index 60622f9e89..d72d235ba1 100644
--- a/daemon/api.go
+++ b/daemon/api.go
@@ -768,9 +768,9 @@ func storeUpdates(c *Command, r *http.Request, user *auth.UserState) Response {
func sendStorePackages(route *mux.Route, meta *Meta, found []*snap.Info) Response {
results := make([]*json.RawMessage, 0, len(found))
for _, x := range found {
- url, err := route.URL("name", x.Name())
+ url, err := route.URL("name", x.InstanceName())
if err != nil {
- logger.Noticef("Cannot build URL for snap %q revision %s: %v", x.Name(), x.Revision, err)
+ logger.Noticef("Cannot build URL for snap %q revision %s: %v", x.InstanceName(), x.Revision, err)
continue
}
@@ -826,7 +826,7 @@ func getSnapsInfo(c *Command, r *http.Request, user *auth.UserState) Response {
results := make([]*json.RawMessage, len(found))
for i, x := range found {
- name := x.info.Name()
+ name := x.info.InstanceName()
rev := x.info.Revision
url, err := route.URL("name", name)
@@ -1359,14 +1359,14 @@ func trySnap(c *Command, r *http.Request, user *auth.UserState, trydir string, f
return BadRequest("cannot read snap info for %s: %s", trydir, err)
}
- tset, err := snapstateTryPath(st, info.Name(), trydir, flags)
+ tset, err := snapstateTryPath(st, info.InstanceName(), trydir, flags)
if err != nil {
return BadRequest("cannot try %s: %s", trydir, err)
}
- msg := fmt.Sprintf(i18n.G("Try %q snap from %s"), info.Name(), trydir)
- chg := newChange(st, "try-snap", msg, []*state.TaskSet{tset}, []string{info.Name()})
- chg.Set("api-data", map[string]string{"snap-name": info.Name()})
+ msg := fmt.Sprintf(i18n.G("Try %q snap from %s"), info.InstanceName(), trydir)
+ chg := newChange(st, "try-snap", msg, []*state.TaskSet{tset}, []string{info.InstanceName()})
+ chg.Set("api-data", map[string]string{"snap-name": info.InstanceName()})
ensureStateSoon(st)
@@ -1567,7 +1567,7 @@ out:
if err != nil {
return BadRequest("cannot read snap file: %v", err)
}
- snapName = info.Name()
+ snapName = info.InstanceName()
sideInfo = &snap.SideInfo{RealName: snapName}
}
@@ -1576,6 +1576,7 @@ out:
msg = fmt.Sprintf(i18n.G("Install %q snap from file %q"), snapName, origPath)
}
+ // TODO parallel-install: pass instance key if needed
tset, err := snapstateInstallPath(st, sideInfo, tempPath, "", flags)
if err != nil {
return InternalError("cannot install snap file: %v", err)
@@ -1778,7 +1779,7 @@ func getLegacyConnections(c *Command, r *http.Request, user *auth.UserState) Res
apps = append(apps, app.Name)
}
pj := plugJSON{
- Snap: plug.Snap.Name(),
+ Snap: plug.Snap.InstanceName(),
Name: plug.Name,
Interface: plug.Interface,
Attrs: plug.Attrs,
@@ -1795,7 +1796,7 @@ func getLegacyConnections(c *Command, r *http.Request, user *auth.UserState) Res
}
sj := slotJSON{
- Snap: slot.Snap.Name(),
+ Snap: slot.Snap.InstanceName(),
Name: slot.Name,
Interface: slot.Interface,
Attrs: slot.Attrs,
diff --git a/daemon/api_mock_test.go b/daemon/api_mock_test.go
index 978518e492..b476b9deee 100644
--- a/daemon/api_mock_test.go
+++ b/daemon/api_mock_test.go
@@ -41,11 +41,11 @@ func (s *apiSuite) mockSnap(c *C, yamlText string) *snap.Info {
defer st.Unlock()
// Put a side info into the state
- snapstate.Set(st, snapInfo.Name(), &snapstate.SnapState{
+ snapstate.Set(st, snapInfo.InstanceName(), &snapstate.SnapState{
Active: true,
Sequence: []*snap.SideInfo{
{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
Revision: snapInfo.Revision,
SnapID: "ididid",
},
diff --git a/daemon/snap.go b/daemon/snap.go
index c49a2fca9d..368c848857 100644
--- a/daemon/snap.go
+++ b/daemon/snap.go
@@ -157,8 +157,8 @@ type bySnapApp []*snap.AppInfo
func (a bySnapApp) Len() int { return len(a) }
func (a bySnapApp) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a bySnapApp) Less(i, j int) bool {
- iName := a[i].Snap.Name()
- jName := a[j].Snap.Name()
+ iName := a[i].Snap.InstanceName()
+ jName := a[j].Snap.InstanceName()
if iName == jName {
return a[i].Name < a[j].Name
}
@@ -221,7 +221,7 @@ func appInfosFor(st *state.State, names []string, opts appInfoOptions) ([]*snap.
found := make(map[string]bool)
appInfos := make([]*snap.AppInfo, 0, len(requested))
for _, snp := range snaps {
- snapName := snp.info.Name()
+ snapName := snp.info.InstanceName()
apps := make([]*snap.AppInfo, 0, len(snp.info.Apps))
for _, app := range snp.info.Apps {
if !opts.service || app.IsService() {
@@ -272,7 +272,7 @@ func clientAppInfosFromSnapAppInfos(apps []*snap.AppInfo) []client.AppInfo {
out := make([]client.AppInfo, len(apps))
for i, app := range apps {
out[i] = client.AppInfo{
- Snap: app.Snap.Name(),
+ Snap: app.Snap.InstanceName(),
Name: app.Name,
CommonID: app.CommonID,
}
@@ -321,7 +321,7 @@ func mapLocal(about aboutSnap) *client.Snap {
ID: localSnap.SnapID,
InstallDate: localSnap.InstallDate(),
InstalledSize: localSnap.Size,
- Name: localSnap.Name(),
+ Name: localSnap.InstanceName(),
Revision: localSnap.Revision,
Status: status,
Summary: localSnap.Summary(),
@@ -382,7 +382,7 @@ func mapRemote(remoteSnap *snap.Info) *client.Snap {
DownloadSize: remoteSnap.Size,
Icon: snapIcon(remoteSnap),
ID: remoteSnap.SnapID,
- Name: remoteSnap.Name(),
+ Name: remoteSnap.InstanceName(),
Revision: remoteSnap.Revision,
Status: status,
Summary: remoteSnap.Summary(),
diff --git a/image/helpers.go b/image/helpers.go
index 6542ad1a43..7f4ff67467 100644
--- a/image/helpers.go
+++ b/image/helpers.go
@@ -306,7 +306,7 @@ func FetchAndCheckSnapAssertions(snapPath string, info *snap.Info, f asserts.Fet
}
// cross checks
- if err := snapasserts.CrossCheck(info.Name(), sha3_384, size, &info.SideInfo, db); err != nil {
+ if err := snapasserts.CrossCheck(info.InstanceName(), sha3_384, size, &info.SideInfo, db); err != nil {
return nil, err
}
@@ -315,7 +315,7 @@ func FetchAndCheckSnapAssertions(snapPath string, info *snap.Info, f asserts.Fet
"snap-id": info.SnapID,
})
if err != nil {
- return nil, fmt.Errorf("internal error: lost snap declaration for %q: %v", info.Name(), err)
+ return nil, fmt.Errorf("internal error: lost snap declaration for %q: %v", info.InstanceName(), err)
}
return a.(*asserts.SnapDeclaration), nil
}
diff --git a/image/image.go b/image/image.go
index 8e12fdfa14..9ba3182b4e 100644
--- a/image/image.go
+++ b/image/image.go
@@ -63,7 +63,7 @@ type localInfos struct {
func (li *localInfos) Name(pathOrName string) string {
if info := li.pathToInfo[pathOrName]; info != nil {
- return info.Name()
+ return info.InstanceName()
}
return pathOrName
}
@@ -101,7 +101,7 @@ func localSnaps(tsto *ToolingStore, opts *Options) (*localInfos, error) {
}
// local snap gets local revision
info.Revision = snap.R(-1)
- nameToPath[info.Name()] = snapName
+ nameToPath[info.InstanceName()] = snapName
local[snapName] = info
si, err := snapasserts.DeriveSideInfo(snapName, tsto)
@@ -137,6 +137,8 @@ func Prepare(opts *Options) error {
return err
}
+ // TODO parallel-install: parallel installs should be blocked for now
+
local, err := localSnaps(tsto, opts)
if err != nil {
return err
@@ -399,7 +401,7 @@ func bootstrapToRootDir(tsto *ToolingStore, model *asserts.Model, opts *Options,
// set seed.yaml
seedYaml.Snaps = append(seedYaml.Snaps, &snap.SeedSnap{
- Name: info.Name(),
+ Name: info.InstanceName(),
SnapID: info.SnapID, // cross-ref
Channel: info.Channel,
File: filepath.Base(fn),
diff --git a/image/image_test.go b/image/image_test.go
index e6f7942c61..80bbeeb572 100644
--- a/image/image_test.go
+++ b/image/image_test.go
@@ -338,7 +338,7 @@ func infoFromSnapYaml(c *C, snapYaml string, rev snap.Revision) *snap.Info {
c.Assert(err, IsNil)
if !rev.Unset() {
- info.SnapID = info.Name() + "-Id"
+ info.SnapID = info.InstanceName() + "-Id"
info.Revision = rev
}
return info
@@ -568,7 +568,7 @@ func (s *imageSuite) TestBootstrapToRootDirLocalCoreBrandKernel(c *C) {
c.Check(osutil.FileExists(p), Equals, true)
c.Check(seed.Snaps[i], DeepEquals, &snap.SeedSnap{
- Name: info.Name(),
+ Name: info.InstanceName(),
SnapID: info.SnapID,
File: fn,
Unasserted: unasserted,
@@ -761,7 +761,7 @@ func (s *imageSuite) TestBootstrapWithBase(c *C) {
c.Check(osutil.FileExists(p), Equals, true)
c.Check(seed.Snaps[i], DeepEquals, &snap.SeedSnap{
- Name: info.Name(),
+ Name: info.InstanceName(),
SnapID: info.SnapID,
File: fn,
Unasserted: unasserted,
@@ -949,7 +949,7 @@ func (s *imageSuite) TestBootstrapToRootDirLocalSnapsWithStoreAsserts(c *C) {
c.Check(osutil.FileExists(p), Equals, true, Commentf("cannot find %s", p))
c.Check(seed.Snaps[i], DeepEquals, &snap.SeedSnap{
- Name: info.Name(),
+ Name: info.InstanceName(),
SnapID: info.SnapID,
File: fn,
Unasserted: false,
diff --git a/interfaces/apparmor/backend.go b/interfaces/apparmor/backend.go
index 19fe157f88..4f20500b2e 100644
--- a/interfaces/apparmor/backend.go
+++ b/interfaces/apparmor/backend.go
@@ -176,16 +176,17 @@ func (b *Backend) Initialize() error {
return nil
}
-// snapConfineFromCoreProfile returns the apparmor profile for snap-confine in the given core snap.
-func snapConfineFromCoreProfile(coreInfo *snap.Info) (dir, glob string, content map[string]*osutil.FileState, err error) {
+// snapConfineFromSnapProfile returns the apparmor profile for
+// snap-confine in the given core/snapd snap.
+func snapConfineFromSnapProfile(info *snap.Info) (dir, glob string, content map[string]*osutil.FileState, err error) {
// Find the vanilla apparmor profile for snap-confine as present in the given core snap.
// We must test the ".real" suffix first, this is a workaround for
// https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=858004
- vanillaProfilePath := filepath.Join(coreInfo.MountDir(), "/etc/apparmor.d/usr.lib.snapd.snap-confine.real")
+ vanillaProfilePath := filepath.Join(info.MountDir(), "/etc/apparmor.d/usr.lib.snapd.snap-confine.real")
vanillaProfileText, err := ioutil.ReadFile(vanillaProfilePath)
if os.IsNotExist(err) {
- vanillaProfilePath = filepath.Join(coreInfo.MountDir(), "/etc/apparmor.d/usr.lib.snapd.snap-confine")
+ vanillaProfilePath = filepath.Join(info.MountDir(), "/etc/apparmor.d/usr.lib.snapd.snap-confine")
vanillaProfileText, err = ioutil.ReadFile(vanillaProfilePath)
}
if err != nil {
@@ -193,13 +194,20 @@ func snapConfineFromCoreProfile(coreInfo *snap.Info) (dir, glob string, content
}
// Replace the path to vanilla snap-confine with the path to the mounted snap-confine from core.
- snapConfineInCore := filepath.Join(coreInfo.MountDir(), "usr/lib/snapd/snap-confine")
+ snapConfineInCore := filepath.Join(info.MountDir(), "usr/lib/snapd/snap-confine")
patchedProfileText := bytes.Replace(
vanillaProfileText, []byte("/usr/lib/snapd/snap-confine"), []byte(snapConfineInCore), -1)
- // /snap/core/111/usr/lib/snapd/snap-confine -> snap.core.111.usr.lib.snapd.snap-confine
- patchedProfileName := strings.Replace(snapConfineInCore[1:], "/", ".", -1)
- // snap.core.111.usr.lib.snapd.snap-confine -> snap.core.*.usr.lib.snapd.snap-confine
- patchedProfileGlob := strings.Replace(patchedProfileName, "."+coreInfo.Revision.String()+".", ".*.", 1)
+
+ // We need to add a uniqe prefix that can never collide with a
+ // snap on the system. Using "snap-confine.*" is similar to
+ // "snap-update-ns.*" that is already used there
+ //
+ // So
+ // /snap/core/111/usr/lib/snapd/snap-confine
+ // becomes
+ // snap-confine.core.111
+ patchedProfileName := fmt.Sprintf("snap-confine.%s.%s", info.InstanceName(), info.Revision)
+ patchedProfileGlob := fmt.Sprintf("snap-confine.%s.*", info.InstanceName())
// Return information for EnsureDirState that describes the re-exec profile for snap-confine.
content = map[string]*osutil.FileState{
@@ -208,22 +216,23 @@ func snapConfineFromCoreProfile(coreInfo *snap.Info) (dir, glob string, content
Mode: 0644,
},
}
- return dirs.SystemApparmorDir, patchedProfileGlob, content, nil
+
+ return dirs.SnapAppArmorDir, patchedProfileGlob, content, nil
}
-// setupSnapConfineReexec will setup apparmor profiles on a classic
-// system on the hosts /etc/apparmor.d directory. This is needed for
-// running snap-confine from the core snap.
+// setupSnapConfineReexec will setup apparmor profiles inside the host's
+// /var/lib/snapd/apparmor/profiles directory. This is needed for
+// running snap-confine from the core or snapd snap.
//
// Additionally it will cleanup stale apparmor profiles it created.
-func setupSnapConfineReexec(coreInfo *snap.Info) error {
+func setupSnapConfineReexec(info *snap.Info) error {
err := os.MkdirAll(dirs.SnapConfineAppArmorDir, 0755)
if err != nil {
return fmt.Errorf("cannot create snap-confine policy directory: %s", err)
}
- dir, glob, content, err := snapConfineFromCoreProfile(coreInfo)
- cache := dirs.SystemApparmorCacheDir
+ dir, glob, content, err := snapConfineFromSnapProfile(info)
+ cache := dirs.AppArmorCacheDir
if err != nil {
return fmt.Errorf("cannot compute snap-confine profile: %s", err)
}
@@ -277,7 +286,7 @@ func profileGlobs(snapName string) []string {
// This method should be called after changing plug, slots, connections between
// them or application present in the snap.
func (b *Backend) Setup(snapInfo *snap.Info, opts interfaces.ConfinementOptions, repo *interfaces.Repository) error {
- snapName := snapInfo.Name()
+ snapName := snapInfo.InstanceName()
spec, err := repo.SnapSpecification(b.Name(), snapName)
if err != nil {
return fmt.Errorf("cannot obtain apparmor specification for snap %q: %s", snapName, err)
@@ -294,6 +303,16 @@ func (b *Backend) Setup(snapInfo *snap.Info, opts interfaces.ConfinementOptions,
logger.Noticef("cannot create host snap-confine apparmor configuration: %s", err)
}
}
+
+ // Deal with the "snapd" snap - we do the setup slightly differently
+ // here because this will run both on classic and on Ubuntu Core 18
+ // systems but /etc/apparmor.d is not writable on core18 systems
+ if snapName == "snapd" && release.AppArmorLevel() != release.NoAppArmor {
+ if err := setupSnapConfineReexec(snapInfo); err != nil {
+ logger.Noticef("cannot create host snap-confine apparmor configuration: %s", err)
+ }
+ }
+
// core on core devices is also special, the apparmor cache gets
// confused too easy, especially at rollbacks, so we delete the cache.
// See LP:#1460152 and
@@ -318,7 +337,7 @@ func (b *Backend) Setup(snapInfo *snap.Info, opts interfaces.ConfinementOptions,
return fmt.Errorf("cannot obtain expected security files for snap %q: %s", snapName, err)
}
dir := dirs.SnapAppArmorDir
- globs := profileGlobs(snapInfo.Name())
+ globs := profileGlobs(snapInfo.InstanceName())
cache := dirs.AppArmorCacheDir
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("cannot create directory for apparmor profiles %q: %s", dir, err)
@@ -397,7 +416,8 @@ func addUpdateNSProfile(snapInfo *snap.Info, opts interfaces.ConfinementOptions,
policy := templatePattern.ReplaceAllStringFunc(updateNSTemplate, func(placeholder string) string {
switch placeholder {
case "###SNAP_NAME###":
- return snapInfo.Name()
+ // TODO parallel-install: use of proper instance/store name
+ return snapInfo.InstanceName()
case "###SNIPPETS###":
return snippets
}
@@ -405,7 +425,7 @@ func addUpdateNSProfile(snapInfo *snap.Info, opts interfaces.ConfinementOptions,
})
// Ensure that the snap-update-ns profile is on disk.
- profileName := nsProfile(snapInfo.Name())
+ profileName := nsProfile(snapInfo.InstanceName())
content[profileName] = &osutil.FileState{
Content: []byte(policy),
Mode: 0644,
diff --git a/interfaces/apparmor/backend_test.go b/interfaces/apparmor/backend_test.go
index 3ef8db9fe0..0254d4e54c 100644
--- a/interfaces/apparmor/backend_test.go
+++ b/interfaces/apparmor/backend_test.go
@@ -25,7 +25,6 @@ import (
"os"
"os/user"
"path/filepath"
- "strings"
. "gopkg.in/check.v1"
@@ -604,6 +603,11 @@ func (s *backendSuite) TestCombineSnippetsOpenSUSETumbleweedOldKernel(c *C) {
const coreYaml = `name: core
version: 1
+type: os
+`
+
+const snapdYaml = `name: snapd
+version: 1
`
func (s *backendSuite) writeVanillaSnapConfineProfile(c *C, coreInfo *snap.Info) {
@@ -625,9 +629,9 @@ func (s *backendSuite) TestSnapConfineProfile(c *C) {
coreInfo := snaptest.MockInfo(c, coreYaml, &snap.SideInfo{Revision: snap.R(111)})
s.writeVanillaSnapConfineProfile(c, coreInfo)
// We expect to see the same profile, just anchored at a different directory.
- expectedProfileDir := filepath.Join(dirs.GlobalRootDir, "/etc/apparmor.d")
- expectedProfileName := strings.Replace(filepath.Join(coreInfo.MountDir(), "usr/lib/snapd/snap-confine")[1:], "/", ".", -1)
- expectedProfileGlob := strings.Replace(expectedProfileName, "."+coreInfo.Revision.String()+".", ".*.", -1)
+ expectedProfileDir := filepath.Join(dirs.GlobalRootDir, "/var/lib/snapd/apparmor/profiles")
+ expectedProfileName := "snap-confine.core.111"
+ expectedProfileGlob := "snap-confine.core.*"
expectedProfileText := fmt.Sprintf(`#include <tunables/global>
%s/usr/lib/snapd/snap-confine (attach_disconnected) {
# We run privileged, so be fanatical about what we include and don't use
@@ -639,7 +643,42 @@ func (s *backendSuite) TestSnapConfineProfile(c *C) {
c.Assert(expectedProfileName, testutil.Contains, coreInfo.Revision.String())
// Compute the profile and see if it matches.
- dir, glob, content, err := apparmor.SnapConfineFromCoreProfile(coreInfo)
+ dir, glob, content, err := apparmor.SnapConfineFromSnapProfile(coreInfo)
+ c.Assert(err, IsNil)
+ c.Assert(dir, Equals, expectedProfileDir)
+ c.Assert(glob, Equals, expectedProfileGlob)
+ c.Assert(content, DeepEquals, map[string]*osutil.FileState{
+ expectedProfileName: {
+ Content: []byte(expectedProfileText),
+ Mode: 0644,
+ },
+ })
+}
+
+func (s *backendSuite) TestSnapConfineProfileFromSnapdSnap(c *C) {
+ restore := release.MockOnClassic(false)
+ defer restore()
+ dirs.SetRootDir(s.RootDir)
+
+ snapdInfo := snaptest.MockInfo(c, snapdYaml, &snap.SideInfo{Revision: snap.R(222)})
+ s.writeVanillaSnapConfineProfile(c, snapdInfo)
+
+ // We expect to see the same profile, just anchored at a different directory.
+ expectedProfileDir := filepath.Join(dirs.GlobalRootDir, "/var/lib/snapd/apparmor/profiles")
+ expectedProfileName := "snap-confine.snapd.222"
+ expectedProfileGlob := "snap-confine.snapd.*"
+ expectedProfileText := fmt.Sprintf(`#include <tunables/global>
+%s/usr/lib/snapd/snap-confine (attach_disconnected) {
+ # We run privileged, so be fanatical about what we include and don't use
+ # any abstractions
+ /etc/ld.so.cache r,
+}
+`, snapdInfo.MountDir())
+
+ c.Assert(expectedProfileName, testutil.Contains, snapdInfo.Revision.String())
+
+ // Compute the profile and see if it matches.
+ dir, glob, content, err := apparmor.SnapConfineFromSnapProfile(snapdInfo)
c.Assert(err, IsNil)
c.Assert(dir, Equals, expectedProfileDir)
c.Assert(glob, Equals, expectedProfileGlob)
@@ -660,8 +699,8 @@ func (s *backendSuite) TestSetupHostSnapConfineApparmorForReexecCleans(c *C) {
coreInfo := snaptest.MockInfo(c, coreYaml, &snap.SideInfo{Revision: snap.R(111)})
s.writeVanillaSnapConfineProfile(c, coreInfo)
- canaryName := strings.Replace(filepath.Join(dirs.SnapMountDir, "/core/2718/usr/lib/snapd/snap-confine"), "/", ".", -1)[1:]
- canary := filepath.Join(dirs.SystemApparmorDir, canaryName)
+ canaryName := "snap-confine.core.2718"
+ canary := filepath.Join(dirs.SnapAppArmorDir, canaryName)
err := os.MkdirAll(filepath.Dir(canary), 0755)
c.Assert(err, IsNil)
err = ioutil.WriteFile(canary, nil, 0644)
@@ -689,10 +728,10 @@ func (s *backendSuite) TestSetupHostSnapConfineApparmorForReexecWritesNew(c *C)
// for this snap-confine on core
s.InstallSnap(c, interfaces.ConfinementOptions{}, coreYaml, 111)
- newAA, err := filepath.Glob(filepath.Join(dirs.SystemApparmorDir, "*"))
+ newAA, err := filepath.Glob(filepath.Join(dirs.SnapAppArmorDir, "*"))
c.Assert(err, IsNil)
c.Assert(newAA, HasLen, 1)
- c.Check(newAA[0], Matches, `.*/etc/apparmor.d/.*.snap.core.111.usr.lib.snapd.snap-confine`)
+ c.Check(newAA[0], Matches, `.*/var/lib/snapd/apparmor/profiles/snap-confine.core.111`)
// This is the key, rewriting "/usr/lib/snapd/snap-confine
c.Check(newAA[0], testutil.FileContains, "/snap/core/111/usr/lib/snapd/snap-confine (attach_disconnected) {")
@@ -706,7 +745,7 @@ func (s *backendSuite) TestSetupHostSnapConfineApparmorForReexecWritesNew(c *C)
`, dirs.SnapMountDir))
c.Check(s.parserCmd.Calls(), DeepEquals, [][]string{
- {"apparmor_parser", "--replace", "--write-cache", "-O", "no-expr-simplify", fmt.Sprintf("--cache-loc=%s", dirs.SystemApparmorCacheDir), "--quiet", newAA[0]},
+ {"apparmor_parser", "--replace", "--write-cache", "-O", "no-expr-simplify", fmt.Sprintf("--cache-loc=%s", dirs.AppArmorCacheDir), "--quiet", newAA[0]},
})
// snap-confine directory was created
diff --git a/interfaces/apparmor/export_test.go b/interfaces/apparmor/export_test.go
index 791f56b4ff..c7ec573e15 100644
--- a/interfaces/apparmor/export_test.go
+++ b/interfaces/apparmor/export_test.go
@@ -26,9 +26,10 @@ import (
)
var (
- SnapConfineFromCoreProfile = snapConfineFromCoreProfile
- ProfileGlobs = profileGlobs
+ ChopTree = chopTree
NsProfile = nsProfile
+ ProfileGlobs = profileGlobs
+ SnapConfineFromSnapProfile = snapConfineFromSnapProfile
)
// MockIsHomeUsingNFS mocks the real implementation of osutil.IsHomeUsingNFS
diff --git a/interfaces/apparmor/spec.go b/interfaces/apparmor/spec.go
index 0fde838356..b25ea81ad7 100644
--- a/interfaces/apparmor/spec.go
+++ b/interfaces/apparmor/spec.go
@@ -28,6 +28,7 @@ import (
"github.com/snapcore/snapd/interfaces"
"github.com/snapcore/snapd/snap"
+ "github.com/snapcore/snapd/strutil"
)
// Specification assists in collecting apparmor entries associated with an interface.
@@ -173,6 +174,92 @@ func isProbablyPresent(path string) bool {
return path == "/" || path == "/snap" || path == "/var" || path == "/var/snap" || path == "/tmp" || path == "/usr" || path == "/etc"
}
+// chopTree takes a path and depth and returns two lists of apparmor path expressions.
+//
+// The returned lists of expressions are referred to as left and right.
+//
+// The left list describes directories at depth up to and including
+// assumedPrefixDepth and can be used to grant read permission to them (by
+// appending the string "r, " to each element). This corresponds to an
+// assumption about those directories being present in the system and being
+// just traversed. Note that depth is defined as the number of directories
+// traversed, including the root directory.
+//
+// The right list describes the remaining directories and the leaf entry
+// (either file or directory) and is somewhat subtle. At each depth level the
+// expression describes all the files and directories at that level. Coupled
+// with the string "rw ," it can be used to create a rule that allows write
+// access to any file therein, but not deeper.
+//
+// For example, with path: "/foo/bar/froz/baz" and depth 3 the result is:
+// []string{"/", "/foo/", "/foo/bar/"} and []string{"/foo/bar/*",
+// "/foo/bar/*/", "/foo/bar/froz/*", "/foo/bar/froz/*/"}. Coupled with the
+// aforementioned constants this translates to the following apparmor rules:
+//
+// / r,
+// /foo/ r,
+// /foo/bar/ r,
+//
+// /foo/bar/* rw,
+// /foo/bar/*/ rw,
+// /foo/bar/froz/* rw,
+// /foo/bar/froz/*/ rw,
+//
+// Those rules are useful for constructing the apparmor profile for a writable
+// mimic that needs to be present in a specific directory (e.g. in
+// /foo/bar/froz/baz) assuming that part of that directory already exists (e.g.
+// /foo/bar/) but may need to be created earlier (e.g. in /foo/bar/froz).
+//
+// The mimic works by mounting a tmpfs over the mimicked directory and then
+// re-creating empty files and directories as mount points for the subsequent
+// bind-mount operations to latch onto. This is why the right list of
+// expressions use * and */, this allows the expressions to capture files and
+// directories at a specific path.
+func chopTree(path string, assumedPrefixDepth int) (left, right []string, err error) {
+ // NOTE: This implementation works around a bug in apparmor parser:
+ // https://bugs.launchpad.net/apparmor/+bug/1769971
+ //
+ // Due to the nature of apparmor path expressions we need to distinguish
+ // directories and files. The path expression denoting a directory must end
+ // with a trailing slash, that denoting a file must not.
+ //
+ // The iterator requires golang-clean paths which never have a trailing
+ // slash. We want to allow clean paths with an optional trailing slash.
+ isDir := strings.HasSuffix(path, "/")
+ cleanPath := filepath.Clean(path)
+ if (isDir && cleanPath+"/" != path) || (!isDir && cleanPath != path) {
+ return nil, nil, fmt.Errorf("cannot chop unclean path: %q", path)
+ }
+
+ // Iterate over the path and construct left and right.
+ iter, _ := strutil.NewPathIterator(cleanPath)
+ for iter.Next() {
+ if iter.Depth() <= assumedPrefixDepth {
+ // The left hand side is the part that is assumed to exist.
+ // We mostly enumerate those directories as-is except for the final
+ // entry that we re-create the trailing slash if the original path
+ // was a "directory" path.
+ if iter.CurrentPath() == iter.Path() && isDir {
+ left = append(left, iter.CurrentPath()+"/")
+ } else {
+ left = append(left, iter.CurrentPath())
+ }
+ } else {
+ // The right hand side rules should not allow creation of the root
+ // directory as that itself is meaningless.
+ if iter.Depth() > 1 {
+ // The right hand side replaces the final component with a "*"
+ // and "*/", meaning any file and any directory, respectively.
+ right = append(right, iter.CurrentBase()+"*")
+ right = append(right, iter.CurrentBase()+"*/")
+ }
+ }
+ }
+ // Note, for completeness we could append the full path but that is
+ // guaranteed to be captured by one of the two expressions above.
+ return left, right, nil
+}
+
// WritableFileProfile writes a profile for snap-update-ns for making given file writable.
func WritableFileProfile(buf *bytes.Buffer, path string) {
if path == "/" {
diff --git a/interfaces/apparmor/spec_test.go b/interfaces/apparmor/spec_test.go
index f4fa9af953..51ebe176d8 100644
--- a/interfaces/apparmor/spec_test.go
+++ b/interfaces/apparmor/spec_test.go
@@ -179,6 +179,7 @@ func (s *specSuite) TestApparmorSnippetsFromLayout(c *C) {
"# Layout path: /var/tmp\n/var/tmp{,/**} mrwklix,",
},
})
+ updateNS := s.spec.UpdateNS()
profile0 := ` # Layout /etc/foo.conf: bind-file $SNAP/foo.conf
mount options=(bind, rw) /snap/vanguard/42/foo.conf -> /etc/foo.conf,
@@ -210,6 +211,8 @@ func (s *specSuite) TestApparmorSnippetsFromLayout(c *C) {
/tmp/.snap/snap/ rw,
/tmp/.snap/ rw,
`
+ c.Assert(updateNS[0], Equals, profile0)
+
profile1 := ` # Layout /usr/foo: bind $SNAP/usr/foo
mount options=(rbind, rw) /snap/vanguard/42/usr/foo/ -> /usr/foo/,
umount /usr/foo/,
@@ -242,6 +245,8 @@ func (s *specSuite) TestApparmorSnippetsFromLayout(c *C) {
/tmp/.snap/snap/ rw,
/tmp/.snap/ rw,
`
+ c.Assert(updateNS[1], Equals, profile1)
+
profile2 := ` # Layout /var/cache/mylink: symlink $SNAP_DATA/link/target
/var/cache/mylink rw,
# Writable mimic /var/cache
@@ -258,6 +263,8 @@ func (s *specSuite) TestApparmorSnippetsFromLayout(c *C) {
/tmp/.snap/var/ rw,
/tmp/.snap/ rw,
`
+ c.Assert(updateNS[2], Equals, profile2)
+
profile3 := ` # Layout /var/tmp: type tmpfs, mode: 01777
mount fstype=tmpfs tmpfs -> /var/tmp/,
umount /var/tmp/,
@@ -273,10 +280,79 @@ func (s *specSuite) TestApparmorSnippetsFromLayout(c *C) {
/tmp/.snap/var/ rw,
/tmp/.snap/ rw,
`
- updateNS := s.spec.UpdateNS()
- c.Assert(updateNS[0], Equals, profile0)
- c.Assert(updateNS[1], Equals, profile1)
- c.Assert(updateNS[2], Equals, profile2)
c.Assert(updateNS[3], Equals, profile3)
c.Assert(updateNS, DeepEquals, []string{profile0, profile1, profile2, profile3})
}
+
+func (s *specSuite) TestChopTree(c *C) {
+ for _, tc := range []struct {
+ p string // path
+ d int // depth
+ l, r []string // left and right path expressions
+ e string // error pattern, if non-empty
+ }{
+ // Test case from the documentation of the function.
+ {p: "/foo/bar/froz/baz/", d: 3, // Assume first three directories exist
+ l: []string{"/", "/foo/", "/foo/bar/"},
+ // Assume that /foo/bar/froz and beyond may be missing
+ r: []string{"/foo/bar/*", "/foo/bar/*/", "/foo/bar/froz/*", "/foo/bar/froz/*/"}},
+
+ // Exhaustive test cases for directory paths.
+
+ {p: "/foo/bar/froz/", d: 0, // Assume that no directories exist (and '/' does not have 'w')
+ r: []string{"/*", "/*/", "/foo/*", "/foo/*/", "/foo/bar/*", "/foo/bar/*/"}},
+ {p: "/foo/bar/froz/", d: 1, // Assume that the root directory exists
+ l: []string{"/"},
+ r: []string{"/*", "/*/", "/foo/*", "/foo/*/", "/foo/bar/*", "/foo/bar/*/"}},
+ {p: "/foo/bar/froz/", d: 2, // Assume that /foo/ exists.
+ l: []string{"/", "/foo/"},
+ r: []string{"/foo/*", "/foo/*/", "/foo/bar/*", "/foo/bar/*/"}},
+ {p: "/foo/bar/froz/", d: 3, // Assume that /foo/bar/ exists.
+ l: []string{"/", "/foo/", "/foo/bar/"},
+ r: []string{"/foo/bar/*", "/foo/bar/*/"}},
+ {p: "/foo/bar/froz/", d: 4, // Assume that /foo/bar/froz/ exists.
+ l: []string{"/", "/foo/", "/foo/bar/", "/foo/bar/froz/"}},
+
+ // Exhaustive test cases for file paths.
+
+ {p: "/foo/bar/froz", d: 0, // Assume that no directories exist (and '/' does not have 'w')
+ r: []string{"/*", "/*/", "/foo/*", "/foo/*/", "/foo/bar/*", "/foo/bar/*/"}},
+ {p: "/foo/bar/froz", d: 1, // Assume that the root directory exists
+ l: []string{"/"},
+ r: []string{"/*", "/*/", "/foo/*", "/foo/*/", "/foo/bar/*", "/foo/bar/*/"}},
+ {p: "/foo/bar/froz", d: 2, // Assume that /foo/ exists.
+ l: []string{"/", "/foo/"},
+ r: []string{"/foo/*", "/foo/*/", "/foo/bar/*", "/foo/bar/*/"}},
+ {p: "/foo/bar/froz", d: 3, // Assume that /foo/bar/ exists.
+ l: []string{"/", "/foo/", "/foo/bar/"},
+ r: []string{"/foo/bar/*", "/foo/bar/*/"}},
+ {p: "/foo/bar/froz", d: 4, // Assume that /foo/bar/froz exists.
+ l: []string{"/", "/foo/", "/foo/bar/", "/foo/bar/froz"}},
+
+ // Assumed prefix depth larger than actual path depth is harmless.
+ {p: "/foo/bar/froz/", d: 5,
+ l: []string{"/", "/foo/", "/foo/bar/", "/foo/bar/froz/"}},
+ {p: "/foo/bar/froz", d: 5,
+ l: []string{"/", "/foo/", "/foo/bar/", "/foo/bar/froz"}},
+
+ // Unclean paths are not allowed.
+ {p: "/foo/../bar", d: 1, e: "cannot chop unclean path: .*"},
+ {p: "/foo//bar", d: 1, e: "cannot chop unclean path: .*"},
+ {p: "foo/../bar", d: 1, e: "cannot chop unclean path: .*"},
+ {p: "foo//bar", d: 1, e: "cannot chop unclean path: .*"},
+
+ // https://twitter.com/thebox193/status/654457902208557056
+ {p: "/foo/bar/froz/", d: -1,
+ r: []string{"/*", "/*/", "/foo/*", "/foo/*/", "/foo/bar/*", "/foo/bar/*/"}},
+ } {
+ l, r, err := apparmor.ChopTree(tc.p, tc.d)
+ comment := Commentf("test case: %#v", tc)
+ if tc.e == "" {
+ c.Assert(err, IsNil, comment)
+ c.Assert(l, DeepEquals, tc.l, comment)
+ c.Assert(r, DeepEquals, tc.r, comment)
+ } else {
+ c.Assert(err, ErrorMatches, tc.e, comment)
+ }
+ }
+}
diff --git a/interfaces/apparmor/template_vars.go b/interfaces/apparmor/template_vars.go
index 69cd064708..c27da2e891 100644
--- a/interfaces/apparmor/template_vars.go
+++ b/interfaces/apparmor/template_vars.go
@@ -31,7 +31,8 @@ import (
// apparmor template and by apparmor snippets.
func templateVariables(info *snap.Info, securityTag string) string {
var buf bytes.Buffer
- fmt.Fprintf(&buf, "@{SNAP_NAME}=\"%s\"\n", info.Name())
+ // TODO parallel-install: use of proper instance/store name
+ fmt.Fprintf(&buf, "@{SNAP_NAME}=\"%s\"\n", info.InstanceName())
fmt.Fprintf(&buf, "@{SNAP_REVISION}=\"%s\"\n", info.Revision)
fmt.Fprintf(&buf, "@{PROFILE_DBUS}=\"%s\"\n",
dbus.SafePath(securityTag))
diff --git a/interfaces/builtin/content.go b/interfaces/builtin/content.go
index 33f6f29e80..16815706a6 100644
--- a/interfaces/builtin/content.go
+++ b/interfaces/builtin/content.go
@@ -174,7 +174,8 @@ func resolveSpecialVariable(path string, snapInfo *snap.Info) string {
// inside the mount namespace snap-confine creates and there we will
// always have a /snap directory available regardless if the system
// we're running on supports this or not.
- return strings.Replace(path, "$SNAP", filepath.Join(dirs.CoreSnapMountDir, snapInfo.Name(), snapInfo.Revision.String()), 1)
+ // TODO parallel-install: use of proper instance/store name
+ return strings.Replace(path, "$SNAP", filepath.Join(dirs.CoreSnapMountDir, snapInfo.InstanceName(), snapInfo.Revision.String()), 1)
}
if strings.HasPrefix(path, "$SNAP_DATA/") || path == "$SNAP_DATA" {
return strings.Replace(path, "$SNAP_DATA", snapInfo.DataDir(), 1)
@@ -183,7 +184,8 @@ func resolveSpecialVariable(path string, snapInfo *snap.Info) string {
return strings.Replace(path, "$SNAP_COMMON", snapInfo.CommonDataDir(), 1)
}
// NOTE: assume $SNAP by default if nothing else is provided, for compatibility
- return filepath.Join(filepath.Join(dirs.CoreSnapMountDir, snapInfo.Name(), snapInfo.Revision.String()), path)
+ // TODO parallel-install: use of proper instance/store name
+ return filepath.Join(filepath.Join(dirs.CoreSnapMountDir, snapInfo.InstanceName(), snapInfo.Revision.String()), path)
}
func sourceTarget(plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot, relSrc string) (string, string) {
diff --git a/interfaces/builtin/content_test.go b/interfaces/builtin/content_test.go
index e78ecd3375..abb72da567 100644
--- a/interfaces/builtin/content_test.go
+++ b/interfaces/builtin/content_test.go
@@ -569,6 +569,8 @@ slots:
/var/snap/consumer/common/ rw,
/var/snap/consumer/ rw,
`
+ c.Assert(updateNS[0], Equals, profile0)
+
profile1 := ` # Read-write content sharing consumer:content -> producer:content (w#1)
mount options=(bind, rw) /var/snap/producer/2/write-data/ -> /var/snap/consumer/common/import/write-data/,
umount /var/snap/consumer/common/import/write-data/,
@@ -582,6 +584,8 @@ slots:
/var/snap/consumer/common/ rw,
/var/snap/consumer/ rw,
`
+ c.Assert(updateNS[1], Equals, profile1)
+
profile2 := ` # Read-only content sharing consumer:content -> producer:content (r#0)
mount options=(bind) /var/snap/producer/common/read-common/ -> /var/snap/consumer/common/import/read-common/,
remount options=(bind, ro) /var/snap/consumer/common/import/read-common/,
@@ -596,6 +600,8 @@ slots:
/var/snap/consumer/common/ rw,
/var/snap/consumer/ rw,
`
+ c.Assert(updateNS[2], Equals, profile2)
+
profile3 := ` # Read-only content sharing consumer:content -> producer:content (r#1)
mount options=(bind) /var/snap/producer/2/read-data/ -> /var/snap/consumer/common/import/read-data/,
remount options=(bind, ro) /var/snap/consumer/common/import/read-data/,
@@ -610,6 +616,8 @@ slots:
/var/snap/consumer/common/ rw,
/var/snap/consumer/ rw,
`
+ c.Assert(updateNS[3], Equals, profile3)
+
profile4 := ` # Read-only content sharing consumer:content -> producer:content (r#2)
mount options=(bind) /snap/producer/2/read-snap/ -> /var/snap/consumer/common/import/read-snap/,
remount options=(bind, ro) /var/snap/consumer/common/import/read-snap/,
@@ -635,10 +643,6 @@ slots:
/var/snap/consumer/common/ rw,
/var/snap/consumer/ rw,
`
- c.Assert(updateNS[0], Equals, profile0)
- c.Assert(updateNS[1], Equals, profile1)
- c.Assert(updateNS[2], Equals, profile2)
- c.Assert(updateNS[3], Equals, profile3)
c.Assert(updateNS[4], Equals, profile4)
c.Assert(updateNS, DeepEquals, []string{profile0, profile1, profile2, profile3, profile4})
}
diff --git a/interfaces/builtin/desktop.go b/interfaces/builtin/desktop.go
index 09c7e75646..9e266a81b8 100644
--- a/interfaces/builtin/desktop.go
+++ b/interfaces/builtin/desktop.go
@@ -240,7 +240,8 @@ func (iface *desktopInterface) AppArmorConnectedPlug(spec *apparmor.Specificatio
// Allow mounting document portal
var buf bytes.Buffer
fmt.Fprintf(&buf, " # Mount the document portal\n")
- fmt.Fprintf(&buf, " mount options=(bind) /run/user/[0-9]*/doc/by-app/snap.%s/ -> /run/user/[0-9]*/doc/,\n", plug.Snap().Name())
+ // TODO parallel-install: use of proper instance/store name
+ fmt.Fprintf(&buf, " mount options=(bind) /run/user/[0-9]*/doc/by-app/snap.%s/ -> /run/user/[0-9]*/doc/,\n", plug.Snap().InstanceName())
fmt.Fprintf(&buf, " umount /run/user/[0-9]*/doc/,\n\n")
spec.AddUpdateNS(buf.String())
@@ -265,7 +266,7 @@ func (iface *desktopInterface) AppArmorConnectedPlug(spec *apparmor.Specificatio
}
func (iface *desktopInterface) MountConnectedPlug(spec *mount.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
- appId := "snap." + plug.Snap().Name()
+ appId := "snap." + plug.Snap().InstanceName()
spec.AddUserMountEntry(osutil.MountEntry{
Name: "$XDG_RUNTIME_DIR/doc/by-app/" + appId,
Dir: "$XDG_RUNTIME_DIR/doc",
diff --git a/interfaces/builtin/export_test.go b/interfaces/builtin/export_test.go
index 0efc5ce9b7..1626bc848a 100644
--- a/interfaces/builtin/export_test.go
+++ b/interfaces/builtin/export_test.go
@@ -66,7 +66,7 @@ func MockPlug(c *C, yaml string, si *snap.SideInfo, plugName string) *snap.PlugI
if plugInfo, ok := info.Plugs[plugName]; ok {
return plugInfo
}
- panic(fmt.Sprintf("cannot find plug %q in snap %q", plugName, info.Name()))
+ panic(fmt.Sprintf("cannot find plug %q in snap %q", plugName, info.InstanceName()))
}
func MockSlot(c *C, yaml string, si *snap.SideInfo, slotName string) *snap.SlotInfo {
@@ -74,7 +74,7 @@ func MockSlot(c *C, yaml string, si *snap.SideInfo, slotName string) *snap.SlotI
if slotInfo, ok := info.Slots[slotName]; ok {
return slotInfo
}
- panic(fmt.Sprintf("cannot find slot %q in snap %q", slotName, info.Name()))
+ panic(fmt.Sprintf("cannot find slot %q in snap %q", slotName, info.InstanceName()))
}
func MockConnectedPlug(c *C, yaml string, si *snap.SideInfo, plugName string) (*interfaces.ConnectedPlug, *snap.PlugInfo) {
@@ -82,7 +82,7 @@ func MockConnectedPlug(c *C, yaml string, si *snap.SideInfo, plugName string) (*
if plugInfo, ok := info.Plugs[plugName]; ok {
return interfaces.NewConnectedPlug(plugInfo, nil), plugInfo
}
- panic(fmt.Sprintf("cannot find plug %q in snap %q", plugName, info.Name()))
+ panic(fmt.Sprintf("cannot find plug %q in snap %q", plugName, info.InstanceName()))
}
func MockConnectedSlot(c *C, yaml string, si *snap.SideInfo, slotName string) (*interfaces.ConnectedSlot, *snap.SlotInfo) {
@@ -90,7 +90,7 @@ func MockConnectedSlot(c *C, yaml string, si *snap.SideInfo, slotName string) (*
if slotInfo, ok := info.Slots[slotName]; ok {
return interfaces.NewConnectedSlot(slotInfo, nil), slotInfo
}
- panic(fmt.Sprintf("cannot find slot %q in snap %q", slotName, info.Name()))
+ panic(fmt.Sprintf("cannot find slot %q in snap %q", slotName, info.InstanceName()))
}
func MockOsGetenv(mock func(string) string) (restore func()) {
diff --git a/interfaces/builtin/gpio.go b/interfaces/builtin/gpio.go
index 9b9fdfc3d3..980a52aea7 100644
--- a/interfaces/builtin/gpio.go
+++ b/interfaces/builtin/gpio.go
@@ -108,7 +108,7 @@ func (iface *gpioInterface) SystemdConnectedSlot(spec *systemd.Specification, pl
return err
}
- serviceName := interfaces.InterfaceServiceName(slot.Snap().Name(), fmt.Sprintf("gpio-%d", gpioNum))
+ serviceName := interfaces.InterfaceServiceName(slot.Snap().InstanceName(), fmt.Sprintf("gpio-%d", gpioNum))
service := &systemd.Service{
Type: "oneshot",
RemainAfterExit: true,
diff --git a/interfaces/builtin/spi.go b/interfaces/builtin/spi.go
index c37b1f29a8..db238c5675 100644
--- a/interfaces/builtin/spi.go
+++ b/interfaces/builtin/spi.go
@@ -73,7 +73,7 @@ func (iface *spiInterface) BeforePrepareSlot(slot *snap.SlotInfo) error {
if err := sanitizeSlotReservedForOSOrGadget(iface, slot); err != nil {
return err
}
- _, err := iface.path(&interfaces.SlotRef{Snap: slot.Snap.Name(), Name: slot.Name}, slot)
+ _, err := iface.path(&interfaces.SlotRef{Snap: slot.Snap.InstanceName(), Name: slot.Name}, slot)
return err
}
diff --git a/interfaces/builtin/thumbnailer_service.go b/interfaces/builtin/thumbnailer_service.go
index a15622613b..53111fa9f6 100644
--- a/interfaces/builtin/thumbnailer_service.go
+++ b/interfaces/builtin/thumbnailer_service.go
@@ -127,7 +127,8 @@ func (iface *thumbnailerServiceInterface) AppArmorPermanentSlot(spec *apparmor.S
func (iface *thumbnailerServiceInterface) AppArmorConnectedSlot(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
snippet := thumbnailerServiceConnectedSlotAppArmor
old := "###PLUG_SNAP_NAME###"
- new := plug.Snap().Name()
+ // TODO parallel-install: use of proper instance/store name
+ new := plug.Snap().InstanceName()
snippet = strings.Replace(snippet, old, new, -1)
old = "###PLUG_SECURITY_TAGS###"
diff --git a/interfaces/builtin/ubuntu_download_manager.go b/interfaces/builtin/ubuntu_download_manager.go
index c184c0dd83..b44cd0c021 100644
--- a/interfaces/builtin/ubuntu_download_manager.go
+++ b/interfaces/builtin/ubuntu_download_manager.go
@@ -230,7 +230,8 @@ func (iface *ubuntuDownloadManagerInterface) AppArmorConnectedSlot(spec *apparmo
new := plugAppLabelExpr(plug)
snippet := strings.Replace(downloadConnectedSlotAppArmor, old, new, -1)
old = "###PLUG_NAME###"
- new = plug.Snap().Name()
+ // TODO parallel-install: use of proper instance/store name
+ new = plug.Snap().InstanceName()
snippet = strings.Replace(snippet, old, new, -1)
spec.AddSnippet(snippet)
return nil
diff --git a/interfaces/builtin/unity7.go b/interfaces/builtin/unity7.go
index 9e31dd9191..fd28fe9303 100644
--- a/interfaces/builtin/unity7.go
+++ b/interfaces/builtin/unity7.go
@@ -639,7 +639,8 @@ func (iface *unity7Interface) AppArmorConnectedPlug(spec *apparmor.Specification
// but we don't care about that here because the rule above already
// does that) to '_'. Since we know that the desktop filename starts
// with the snap name, perform this conversion on the snap name.
- new := strings.Replace(plug.Snap().Name(), "-", "_", -1)
+ // TODO parallel-install: use of proper instance/store name
+ new := strings.Replace(plug.Snap().InstanceName(), "-", "_", -1)
old := "###UNITY_SNAP_NAME###"
snippet := strings.Replace(unity7ConnectedPlugAppArmor, old, new, -1)
spec.AddSnippet(snippet)
diff --git a/interfaces/builtin/utils.go b/interfaces/builtin/utils.go
index 4b60cb3126..fd7a849af7 100644
--- a/interfaces/builtin/utils.go
+++ b/interfaces/builtin/utils.go
@@ -40,7 +40,8 @@ const UsbMaxInterfaces = 32
// - "snap.$snap.*" if all apps are bound to the slot
func appLabelExpr(apps map[string]*snap.AppInfo, snap *snap.Info) string {
var buf bytes.Buffer
- fmt.Fprintf(&buf, `"snap.%s.`, snap.Name())
+ // TODO parallel-install: use of proper instance/store name
+ fmt.Fprintf(&buf, `"snap.%s.`, snap.InstanceName())
if len(apps) == 1 {
for appName := range apps {
buf.WriteString(appName)
diff --git a/interfaces/builtin/utils_test.go b/interfaces/builtin/utils_test.go
index 0a032c0e75..aceaaa0dd8 100644
--- a/interfaces/builtin/utils_test.go
+++ b/interfaces/builtin/utils_test.go
@@ -79,7 +79,7 @@ func MockConnectedPlug(c *C, yaml string, si *snap.SideInfo, plugName string) (*
if plugInfo, ok := info.Plugs[plugName]; ok {
return interfaces.NewConnectedPlug(plugInfo, nil), plugInfo
}
- panic(fmt.Sprintf("cannot find plug %q in snap %q", plugName, info.Name()))
+ panic(fmt.Sprintf("cannot find plug %q in snap %q", plugName, info.InstanceName()))
}
func MockConnectedSlot(c *C, yaml string, si *snap.SideInfo, slotName string) (*interfaces.ConnectedSlot, *snap.SlotInfo) {
@@ -87,5 +87,5 @@ func MockConnectedSlot(c *C, yaml string, si *snap.SideInfo, slotName string) (*
if slotInfo, ok := info.Slots[slotName]; ok {
return interfaces.NewConnectedSlot(slotInfo, nil), slotInfo
}
- panic(fmt.Sprintf("cannot find slot %q in snap %q", slotName, info.Name()))
+ panic(fmt.Sprintf("cannot find slot %q in snap %q", slotName, info.InstanceName()))
}
diff --git a/interfaces/builtin/wayland.go b/interfaces/builtin/wayland.go
index dff8886388..6b2711eeba 100644
--- a/interfaces/builtin/wayland.go
+++ b/interfaces/builtin/wayland.go
@@ -128,7 +128,8 @@ func (iface *waylandInterface) AppArmorConnectedPlug(spec *apparmor.Specificatio
func (iface *waylandInterface) AppArmorConnectedSlot(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
if !release.OnClassic {
old := "###PLUG_SECURITY_TAGS###"
- new := "snap." + plug.Snap().Name() // forms the snap-specific subdirectory name of /run/user/*/ used for XDG_RUNTIME_DIR
+ // TODO parallel-install: use of proper instance/store name
+ new := "snap." + plug.Snap().InstanceName() // forms the snap-specific subdirectory name of /run/user/*/ used for XDG_RUNTIME_DIR
snippet := strings.Replace(waylandConnectedSlotAppArmor, old, new, -1)
spec.AddSnippet(snippet)
}
diff --git a/interfaces/connection.go b/interfaces/connection.go
index 362cc7a389..9990672b00 100644
--- a/interfaces/connection.go
+++ b/interfaces/connection.go
@@ -151,7 +151,7 @@ func (plug *ConnectedPlug) SecurityTags() []string {
// StaticAttr returns a static attribute with the given key, or error if attribute doesn't exist.
func (plug *ConnectedPlug) StaticAttr(key string, val interface{}) error {
- return getAttribute(plug.Snap().Name(), plug.Interface(), plug.staticAttrs, nil, key, val)
+ return getAttribute(plug.Snap().InstanceName(), plug.Interface(), plug.staticAttrs, nil, key, val)
}
// StaticAttrs returns all static attributes.
@@ -168,7 +168,7 @@ func (plug *ConnectedPlug) DynamicAttrs() map[string]interface{} {
// attribute if dynamic one doesn't exist. Error is returned if neither dynamic nor static
// attribute exist.
func (plug *ConnectedPlug) Attr(key string, val interface{}) error {
- return getAttribute(plug.Snap().Name(), plug.Interface(), plug.staticAttrs, plug.dynamicAttrs, key, val)
+ return getAttribute(plug.Snap().InstanceName(), plug.Interface(), plug.staticAttrs, plug.dynamicAttrs, key, val)
}
func (plug *ConnectedPlug) Lookup(path string) (interface{}, bool) {
@@ -189,7 +189,7 @@ func (plug *ConnectedPlug) SetAttr(key string, value interface{}) error {
// Ref returns the PlugRef for this plug.
func (plug *ConnectedPlug) Ref() *PlugRef {
- return &PlugRef{Snap: plug.Snap().Name(), Name: plug.Name()}
+ return &PlugRef{Snap: plug.Snap().InstanceName(), Name: plug.Name()}
}
// Interface returns the name of the interface for this slot.
@@ -224,7 +224,7 @@ func (slot *ConnectedSlot) SecurityTags() []string {
// StaticAttr returns a static attribute with the given key, or error if attribute doesn't exist.
func (slot *ConnectedSlot) StaticAttr(key string, val interface{}) error {
- return getAttribute(slot.Snap().Name(), slot.Interface(), slot.staticAttrs, nil, key, val)
+ return getAttribute(slot.Snap().InstanceName(), slot.Interface(), slot.staticAttrs, nil, key, val)
}
// StaticAttrs returns all static attributes.
@@ -241,7 +241,7 @@ func (slot *ConnectedSlot) DynamicAttrs() map[string]interface{} {
// attribute if dynamic one doesn't exist. Error is returned if neither dynamic nor static
// attribute exist.
func (slot *ConnectedSlot) Attr(key string, val interface{}) error {
- return getAttribute(slot.Snap().Name(), slot.Interface(), slot.staticAttrs, slot.dynamicAttrs, key, val)
+ return getAttribute(slot.Snap().InstanceName(), slot.Interface(), slot.staticAttrs, slot.dynamicAttrs, key, val)
}
func (slot *ConnectedSlot) Lookup(path string) (interface{}, bool) {
@@ -262,7 +262,7 @@ func (slot *ConnectedSlot) SetAttr(key string, value interface{}) error {
// Ref returns the SlotRef for this slot.
func (slot *ConnectedSlot) Ref() *SlotRef {
- return &SlotRef{Snap: slot.Snap().Name(), Name: slot.Name()}
+ return &SlotRef{Snap: slot.Snap().InstanceName(), Name: slot.Name()}
}
// Interface returns the name of the interface for this connection.
diff --git a/interfaces/core.go b/interfaces/core.go
index 81b9568687..9efffd78a1 100644
--- a/interfaces/core.go
+++ b/interfaces/core.go
@@ -31,7 +31,7 @@ import (
func BeforePreparePlug(iface Interface, plugInfo *snap.PlugInfo) error {
if iface.Name() != plugInfo.Interface {
return fmt.Errorf("cannot sanitize plug %q (interface %q) using interface %q",
- PlugRef{Snap: plugInfo.Snap.Name(), Name: plugInfo.Name}, plugInfo.Interface, iface.Name())
+ PlugRef{Snap: plugInfo.Snap.InstanceName(), Name: plugInfo.Name}, plugInfo.Interface, iface.Name())
}
var err error
if iface, ok := iface.(PlugSanitizer); ok {
@@ -55,7 +55,7 @@ func (ref PlugRef) String() string {
func BeforePrepareSlot(iface Interface, slotInfo *snap.SlotInfo) error {
if iface.Name() != slotInfo.Interface {
return fmt.Errorf("cannot sanitize slot %q (interface %q) using interface %q",
- SlotRef{Snap: slotInfo.Snap.Name(), Name: slotInfo.Name}, slotInfo.Interface, iface.Name())
+ SlotRef{Snap: slotInfo.Snap.InstanceName(), Name: slotInfo.Name}, slotInfo.Interface, iface.Name())
}
var err error
if iface, ok := iface.(SlotSanitizer); ok {
@@ -100,8 +100,8 @@ type ConnRef struct {
// NewConnRef creates a connection reference for given plug and slot
func NewConnRef(plug *snap.PlugInfo, slot *snap.SlotInfo) *ConnRef {
return &ConnRef{
- PlugRef: PlugRef{Snap: plug.Snap.Name(), Name: plug.Name},
- SlotRef: SlotRef{Snap: slot.Snap.Name(), Name: slot.Name},
+ PlugRef: PlugRef{Snap: plug.Snap.InstanceName(), Name: plug.Name},
+ SlotRef: SlotRef{Snap: slot.Snap.InstanceName(), Name: slot.Name},
}
}
diff --git a/interfaces/dbus/backend.go b/interfaces/dbus/backend.go
index 08477438e1..f59e61b75a 100644
--- a/interfaces/dbus/backend.go
+++ b/interfaces/dbus/backend.go
@@ -78,7 +78,7 @@ func setupDbusServiceForUserd(snapInfo *snap.Info) error {
//
// DBus has no concept of a complain mode so confinment type is ignored.
func (b *Backend) Setup(snapInfo *snap.Info, opts interfaces.ConfinementOptions, repo *interfaces.Repository) error {
- snapName := snapInfo.Name()
+ snapName := snapInfo.InstanceName()
// Get the snippets that apply to this snap
spec, err := repo.SnapSpecification(b.Name(), snapName)
if err != nil {
diff --git a/interfaces/ifacetest/backendtest.go b/interfaces/ifacetest/backendtest.go
index 091e5635b9..3aa33417e6 100644
--- a/interfaces/ifacetest/backendtest.go
+++ b/interfaces/ifacetest/backendtest.go
@@ -162,7 +162,7 @@ func (s *BackendSuite) UpdateSnap(c *C, oldSnapInfo *snap.Info, opts interfaces.
newSnapInfo := snaptest.MockInfo(c, snapYaml, &snap.SideInfo{
Revision: snap.R(revision),
})
- c.Assert(newSnapInfo.Name(), Equals, oldSnapInfo.Name())
+ c.Assert(newSnapInfo.InstanceName(), Equals, oldSnapInfo.InstanceName())
s.removePlugsSlots(c, oldSnapInfo)
s.addPlugsSlots(c, newSnapInfo)
err := s.Backend.Setup(newSnapInfo, opts, s.Repo)
@@ -172,7 +172,7 @@ func (s *BackendSuite) UpdateSnap(c *C, oldSnapInfo *snap.Info, opts interfaces.
// RemoveSnap "removes" an "installed" snap.
func (s *BackendSuite) RemoveSnap(c *C, snapInfo *snap.Info) {
- err := s.Backend.Remove(snapInfo.Name())
+ err := s.Backend.Remove(snapInfo.InstanceName())
c.Assert(err, IsNil)
s.removePlugsSlots(c, snapInfo)
}
@@ -189,12 +189,12 @@ func (s *BackendSuite) addPlugsSlots(c *C, snapInfo *snap.Info) {
}
func (s *BackendSuite) removePlugsSlots(c *C, snapInfo *snap.Info) {
- for _, plug := range s.Repo.Plugs(snapInfo.Name()) {
- err := s.Repo.RemovePlug(plug.Snap.Name(), plug.Name)
+ for _, plug := range s.Repo.Plugs(snapInfo.InstanceName()) {
+ err := s.Repo.RemovePlug(plug.Snap.InstanceName(), plug.Name)
c.Assert(err, IsNil)
}
- for _, slot := range s.Repo.Slots(snapInfo.Name()) {
- err := s.Repo.RemoveSlot(slot.Snap.Name(), slot.Name)
+ for _, slot := range s.Repo.Slots(snapInfo.InstanceName()) {
+ err := s.Repo.RemoveSlot(slot.Snap.InstanceName(), slot.Name)
c.Assert(err, IsNil)
}
}
diff --git a/interfaces/json.go b/interfaces/json.go
index bc9dce12d5..aceeda2741 100644
--- a/interfaces/json.go
+++ b/interfaces/json.go
@@ -59,7 +59,7 @@ func (info *Info) MarshalJSON() ([]byte, error) {
plugs := make([]*plugJSON, 0, len(info.Plugs))
for _, plug := range info.Plugs {
plugs = append(plugs, &plugJSON{
- Snap: plug.Snap.Name(),
+ Snap: plug.Snap.InstanceName(),
Name: plug.Name,
Attrs: plug.Attrs,
Label: plug.Label,
@@ -68,7 +68,7 @@ func (info *Info) MarshalJSON() ([]byte, error) {
slots := make([]*slotJSON, 0, len(info.Slots))
for _, slot := range info.Slots {
slots = append(slots, &slotJSON{
- Snap: slot.Snap.Name(),
+ Snap: slot.Snap.InstanceName(),
Name: slot.Name,
Attrs: slot.Attrs,
Label: slot.Label,
diff --git a/interfaces/kmod/backend.go b/interfaces/kmod/backend.go
index 3896b561ff..5a01fc0e95 100644
--- a/interfaces/kmod/backend.go
+++ b/interfaces/kmod/backend.go
@@ -67,7 +67,7 @@ func (b *Backend) Name() interfaces.SecuritySystem {
//
// If the method fails it should be re-tried (with a sensible strategy) by the caller.
func (b *Backend) Setup(snapInfo *snap.Info, confinement interfaces.ConfinementOptions, repo *interfaces.Repository) error {
- snapName := snapInfo.Name()
+ snapName := snapInfo.InstanceName()
// Get the snippets that apply to this snap
spec, err := repo.SnapSpecification(b.Name(), snapName)
if err != nil {
@@ -121,7 +121,7 @@ func deriveContent(spec *Specification, snapInfo *snap.Info) (map[string]*osutil
buffer.WriteString(module)
buffer.WriteRune('\n')
}
- content[fmt.Sprintf("%s.conf", snap.SecurityTag(snapInfo.Name()))] = &osutil.FileState{
+ content[fmt.Sprintf("%s.conf", snap.SecurityTag(snapInfo.InstanceName()))] = &osutil.FileState{
Content: buffer.Bytes(),
Mode: 0644,
}
diff --git a/interfaces/mount/backend.go b/interfaces/mount/backend.go
index 34cbccc211..7d18b0ce4a 100644
--- a/interfaces/mount/backend.go
+++ b/interfaces/mount/backend.go
@@ -56,7 +56,7 @@ func (b *Backend) Name() interfaces.SecuritySystem {
// Setup creates mount mount profile files specific to a given snap.
func (b *Backend) Setup(snapInfo *snap.Info, confinement interfaces.ConfinementOptions, repo *interfaces.Repository) error {
// Record all changes to the mount system for this snap.
- snapName := snapInfo.Name()
+ snapName := snapInfo.InstanceName()
spec, err := repo.SnapSpecification(b.Name(), snapName)
if err != nil {
return fmt.Errorf("cannot obtain mount security snippets for snap %q: %s", snapName, err)
@@ -107,7 +107,7 @@ func addMountProfile(content map[string]*osutil.FileState, fname string, entries
// deriveContent computes .fstab tables based on requests made to the specification.
func deriveContent(spec *Specification, snapInfo *snap.Info) map[string]*osutil.FileState {
content := make(map[string]*osutil.FileState, 2)
- snapName := snapInfo.Name()
+ snapName := snapInfo.InstanceName()
// Add the per-snap fstab file.
// This file is read by snap-update-ns in the global pass.
addMountProfile(content, fmt.Sprintf("snap.%s.fstab", snapName), spec.MountEntries())
diff --git a/interfaces/repo.go b/interfaces/repo.go
index 48172c7cce..5a6741847f 100644
--- a/interfaces/repo.go
+++ b/interfaces/repo.go
@@ -262,7 +262,7 @@ func (r *Repository) AddPlug(plug *snap.PlugInfo) error {
r.m.Lock()
defer r.m.Unlock()
- snapName := plug.Snap.Name()
+ snapName := plug.Snap.InstanceName()
// Reject snaps with invalid names
if err := snap.ValidateName(snapName); err != nil {
@@ -357,7 +357,7 @@ func (r *Repository) AddSlot(slot *snap.SlotInfo) error {
r.m.Lock()
defer r.m.Unlock()
- snapName := slot.Snap.Name()
+ snapName := slot.Snap.InstanceName()
// Reject snaps with invalid names
if err := snap.ValidateName(snapName); err != nil {
@@ -601,12 +601,12 @@ func (r *Repository) Connect(ref *ConnRef, plugDynamicAttrs, slotDynamicAttrs ma
if policyCheck != nil {
if i, ok := iface.(plugValidator); ok {
if err := i.BeforeConnectPlug(cplug); err != nil {
- return nil, fmt.Errorf("cannot connect plug %q of snap %q: %s", plug.Name, plug.Snap.Name(), err)
+ return nil, fmt.Errorf("cannot connect plug %q of snap %q: %s", plug.Name, plug.Snap.InstanceName(), err)
}
}
if i, ok := iface.(slotValidator); ok {
if err := i.BeforeConnectSlot(cslot); err != nil {
- return nil, fmt.Errorf("cannot connect slot %q of snap %q: %s", slot.Name, slot.Snap.Name(), err)
+ return nil, fmt.Errorf("cannot connect slot %q of snap %q: %s", slot.Name, slot.Snap.InstanceName(), err)
}
}
@@ -890,7 +890,7 @@ func (r *Repository) AddSnap(snapInfo *snap.Info) error {
r.m.Lock()
defer r.m.Unlock()
- snapName := snapInfo.Name()
+ snapName := snapInfo.InstanceName()
if r.plugs[snapName] != nil || r.slots[snapName] != nil {
return fmt.Errorf("cannot register interfaces for snap %q more than once", snapName)
@@ -980,7 +980,7 @@ func (r *Repository) DisconnectSnap(snapName string) ([]string, error) {
result := make([]string, 0, len(seen))
for info := range seen {
- result = append(result, info.Name())
+ result = append(result, info.InstanceName())
}
sort.Strings(result)
return result, nil
diff --git a/interfaces/repo_test.go b/interfaces/repo_test.go
index 8946306ba6..2102f6c216 100644
--- a/interfaces/repo_test.go
+++ b/interfaces/repo_test.go
@@ -217,7 +217,7 @@ func (s *RepositorySuite) TestAddPlug(c *C) {
err := s.testRepo.AddPlug(s.plug)
c.Assert(err, IsNil)
c.Assert(s.testRepo.AllPlugs(""), HasLen, 1)
- c.Assert(s.testRepo.Plug(s.plug.Snap.Name(), s.plug.Name), DeepEquals, s.plug)
+ c.Assert(s.testRepo.Plug(s.plug.Snap.InstanceName(), s.plug.Name), DeepEquals, s.plug)
}
func (s *RepositorySuite) TestAddPlugClashingPlug(c *C) {
@@ -226,7 +226,7 @@ func (s *RepositorySuite) TestAddPlugClashingPlug(c *C) {
err = s.testRepo.AddPlug(s.plug)
c.Assert(err, ErrorMatches, `snap "consumer" has plugs conflicting on name "plug"`)
c.Assert(s.testRepo.AllPlugs(""), HasLen, 1)
- c.Assert(s.testRepo.Plug(s.plug.Snap.Name(), s.plug.Name), DeepEquals, s.plug)
+ c.Assert(s.testRepo.Plug(s.plug.Snap.InstanceName(), s.plug.Name), DeepEquals, s.plug)
}
func (s *RepositorySuite) TestAddPlugClashingSlot(c *C) {
@@ -246,7 +246,7 @@ func (s *RepositorySuite) TestAddPlugClashingSlot(c *C) {
err = s.testRepo.AddPlug(plug)
c.Assert(err, ErrorMatches, `snap "snap" has plug and slot conflicting on name "clashing"`)
c.Assert(s.testRepo.AllSlots(""), HasLen, 1)
- c.Assert(s.testRepo.Slot(slot.Snap.Name(), slot.Name), DeepEquals, slot)
+ c.Assert(s.testRepo.Slot(slot.Snap.InstanceName(), slot.Name), DeepEquals, slot)
}
func (s *RepositorySuite) TestAddPlugFailsWithInvalidSnapName(c *C) {
@@ -282,8 +282,8 @@ func (s *RepositorySuite) TestAddPlugFailsWithUnknownInterface(c *C) {
func (s *RepositorySuite) TestPlug(c *C) {
err := s.testRepo.AddPlug(s.plug)
c.Assert(err, IsNil)
- c.Assert(s.emptyRepo.Plug(s.plug.Snap.Name(), s.plug.Name), IsNil)
- c.Assert(s.testRepo.Plug(s.plug.Snap.Name(), s.plug.Name), DeepEquals, s.plug)
+ c.Assert(s.emptyRepo.Plug(s.plug.Snap.InstanceName(), s.plug.Name), IsNil)
+ c.Assert(s.testRepo.Plug(s.plug.Snap.InstanceName(), s.plug.Name), DeepEquals, s.plug)
}
func (s *RepositorySuite) TestPlugSearch(c *C) {
@@ -316,13 +316,13 @@ plugs:
func (s *RepositorySuite) TestRemovePlugSucceedsWhenPlugExistsAndDisconnected(c *C) {
err := s.testRepo.AddPlug(s.plug)
c.Assert(err, IsNil)
- err = s.testRepo.RemovePlug(s.plug.Snap.Name(), s.plug.Name)
+ err = s.testRepo.RemovePlug(s.plug.Snap.InstanceName(), s.plug.Name)
c.Assert(err, IsNil)
c.Assert(s.testRepo.AllPlugs(""), HasLen, 0)
}
func (s *RepositorySuite) TestRemovePlugFailsWhenPlugDoesntExist(c *C) {
- err := s.emptyRepo.RemovePlug(s.plug.Snap.Name(), s.plug.Name)
+ err := s.emptyRepo.RemovePlug(s.plug.Snap.InstanceName(), s.plug.Name)
c.Assert(err, ErrorMatches, `cannot remove plug "plug" from snap "consumer", no such plug`)
}
@@ -335,10 +335,10 @@ func (s *RepositorySuite) TestRemovePlugFailsWhenPlugIsConnected(c *C) {
_, err = s.testRepo.Connect(connRef, nil, nil, nil)
c.Assert(err, IsNil)
// Removing a plug used by a slot returns an appropriate error
- err = s.testRepo.RemovePlug(s.plug.Snap.Name(), s.plug.Name)
+ err = s.testRepo.RemovePlug(s.plug.Snap.InstanceName(), s.plug.Name)
c.Assert(err, ErrorMatches, `cannot remove plug "plug" from snap "consumer", it is still connected`)
// The plug is still there
- slot := s.testRepo.Plug(s.plug.Snap.Name(), s.plug.Name)
+ slot := s.testRepo.Plug(s.plug.Snap.InstanceName(), s.plug.Name)
c.Assert(slot, Not(IsNil))
}
@@ -477,12 +477,12 @@ slots:
func (s *RepositorySuite) TestSlotSucceedsWhenSlotExists(c *C) {
err := s.testRepo.AddSlot(s.slot)
c.Assert(err, IsNil)
- slot := s.testRepo.Slot(s.slot.Snap.Name(), s.slot.Name)
+ slot := s.testRepo.Slot(s.slot.Snap.InstanceName(), s.slot.Name)
c.Assert(slot, DeepEquals, s.slot)
}
func (s *RepositorySuite) TestSlotFailsWhenSlotDoesntExist(c *C) {
- slot := s.testRepo.Slot(s.slot.Snap.Name(), s.slot.Name)
+ slot := s.testRepo.Slot(s.slot.Snap.InstanceName(), s.slot.Name)
c.Assert(slot, IsNil)
}
@@ -541,13 +541,13 @@ func (s *RepositorySuite) TestAddSlotClashingPlug(c *C) {
err = s.testRepo.AddSlot(slot)
c.Assert(err, ErrorMatches, `snap "snap" has plug and slot conflicting on name "clashing"`)
c.Assert(s.testRepo.AllPlugs(""), HasLen, 1)
- c.Assert(s.testRepo.Plug(plug.Snap.Name(), plug.Name), DeepEquals, plug)
+ c.Assert(s.testRepo.Plug(plug.Snap.InstanceName(), plug.Name), DeepEquals, plug)
}
func (s *RepositorySuite) TestAddSlotStoresCorrectData(c *C) {
err := s.testRepo.AddSlot(s.slot)
c.Assert(err, IsNil)
- slot := s.testRepo.Slot(s.slot.Snap.Name(), s.slot.Name)
+ slot := s.testRepo.Slot(s.slot.Snap.InstanceName(), s.slot.Name)
// The added slot has the same data
c.Assert(slot, DeepEquals, s.slot)
}
@@ -558,16 +558,16 @@ func (s *RepositorySuite) TestRemoveSlotSuccedsWhenSlotExistsAndDisconnected(c *
err := s.testRepo.AddSlot(s.slot)
c.Assert(err, IsNil)
// Removing a vacant slot simply works
- err = s.testRepo.RemoveSlot(s.slot.Snap.Name(), s.slot.Name)
+ err = s.testRepo.RemoveSlot(s.slot.Snap.InstanceName(), s.slot.Name)
c.Assert(err, IsNil)
// The slot is gone now
- slot := s.testRepo.Slot(s.slot.Snap.Name(), s.slot.Name)
+ slot := s.testRepo.Slot(s.slot.Snap.InstanceName(), s.slot.Name)
c.Assert(slot, IsNil)
}
func (s *RepositorySuite) TestRemoveSlotFailsWhenSlotDoesntExist(c *C) {
// Removing a slot that doesn't exist returns an appropriate error
- err := s.testRepo.RemoveSlot(s.slot.Snap.Name(), s.slot.Name)
+ err := s.testRepo.RemoveSlot(s.slot.Snap.InstanceName(), s.slot.Name)
c.Assert(err, Not(IsNil))
c.Assert(err, ErrorMatches, `cannot remove slot "slot" from snap "producer", no such slot`)
}
@@ -581,10 +581,10 @@ func (s *RepositorySuite) TestRemoveSlotFailsWhenSlotIsConnected(c *C) {
_, err = s.testRepo.Connect(connRef, nil, nil, nil)
c.Assert(err, IsNil)
// Removing a slot occupied by a plug returns an appropriate error
- err = s.testRepo.RemoveSlot(s.slot.Snap.Name(), s.slot.Name)
+ err = s.testRepo.RemoveSlot(s.slot.Snap.InstanceName(), s.slot.Name)
c.Assert(err, ErrorMatches, `cannot remove slot "slot" from snap "producer", it is still connected`)
// The slot is still there
- slot := s.testRepo.Slot(s.slot.Snap.Name(), s.slot.Name)
+ slot := s.testRepo.Slot(s.slot.Snap.InstanceName(), s.slot.Name)
c.Assert(slot, Not(IsNil))
}
@@ -1149,10 +1149,10 @@ func (s *RepositorySuite) TestConnectSucceeds(c *C) {
// Disconnect fails if any argument is empty
func (s *RepositorySuite) TestDisconnectFailsOnEmptyArgs(c *C) {
- err1 := s.testRepo.Disconnect(s.plug.Snap.Name(), s.plug.Name, s.slot.Snap.Name(), "")
- err2 := s.testRepo.Disconnect(s.plug.Snap.Name(), s.plug.Name, "", s.slot.Name)
- err3 := s.testRepo.Disconnect(s.plug.Snap.Name(), "", s.slot.Snap.Name(), s.slot.Name)
- err4 := s.testRepo.Disconnect("", s.plug.Name, s.slot.Snap.Name(), s.slot.Name)
+ err1 := s.testRepo.Disconnect(s.plug.Snap.InstanceName(), s.plug.Name, s.slot.Snap.InstanceName(), "")
+ err2 := s.testRepo.Disconnect(s.plug.Snap.InstanceName(), s.plug.Name, "", s.slot.Name)
+ err3 := s.testRepo.Disconnect(s.plug.Snap.InstanceName(), "", s.slot.Snap.InstanceName(), s.slot.Name)
+ err4 := s.testRepo.Disconnect("", s.plug.Name, s.slot.Snap.InstanceName(), s.slot.Name)
c.Assert(err1, ErrorMatches, `cannot disconnect, slot name is empty`)
c.Assert(err2, ErrorMatches, `cannot disconnect, slot snap name is empty`)
c.Assert(err3, ErrorMatches, `cannot disconnect, plug name is empty`)
@@ -1162,14 +1162,14 @@ func (s *RepositorySuite) TestDisconnectFailsOnEmptyArgs(c *C) {
// Disconnect fails if plug doesn't exist
func (s *RepositorySuite) TestDisconnectFailsWithoutPlug(c *C) {
c.Assert(s.testRepo.AddSlot(s.slot), IsNil)
- err := s.testRepo.Disconnect(s.plug.Snap.Name(), s.plug.Name, s.slot.Snap.Name(), s.slot.Name)
+ err := s.testRepo.Disconnect(s.plug.Snap.InstanceName(), s.plug.Name, s.slot.Snap.InstanceName(), s.slot.Name)
c.Assert(err, ErrorMatches, `snap "consumer" has no plug named "plug"`)
}
// Disconnect fails if slot doesn't exist
func (s *RepositorySuite) TestDisconnectFailsWithutSlot(c *C) {
c.Assert(s.testRepo.AddPlug(s.plug), IsNil)
- err := s.testRepo.Disconnect(s.plug.Snap.Name(), s.plug.Name, s.slot.Snap.Name(), s.slot.Name)
+ err := s.testRepo.Disconnect(s.plug.Snap.InstanceName(), s.plug.Name, s.slot.Snap.InstanceName(), s.slot.Name)
c.Assert(err, ErrorMatches, `snap "producer" has no slot named "slot"`)
}
@@ -1177,7 +1177,7 @@ func (s *RepositorySuite) TestDisconnectFailsWithutSlot(c *C) {
func (s *RepositorySuite) TestDisconnectFailsWhenNotConnected(c *C) {
c.Assert(s.testRepo.AddPlug(s.plug), IsNil)
c.Assert(s.testRepo.AddSlot(s.slot), IsNil)
- err := s.testRepo.Disconnect(s.plug.Snap.Name(), s.plug.Name, s.slot.Snap.Name(), s.slot.Name)
+ err := s.testRepo.Disconnect(s.plug.Snap.InstanceName(), s.plug.Name, s.slot.Snap.InstanceName(), s.slot.Name)
c.Assert(err, ErrorMatches, `cannot disconnect consumer:plug from producer:slot, it is not connected`)
}
@@ -1189,7 +1189,7 @@ func (s *RepositorySuite) TestDisconnectSucceeds(c *C) {
c.Assert(err, IsNil)
_, err = s.testRepo.Connect(NewConnRef(s.plug, s.slot), nil, nil, nil)
c.Assert(err, IsNil)
- err = s.testRepo.Disconnect(s.plug.Snap.Name(), s.plug.Name, s.slot.Snap.Name(), s.slot.Name)
+ err = s.testRepo.Disconnect(s.plug.Snap.InstanceName(), s.plug.Name, s.slot.Snap.InstanceName(), s.slot.Name)
c.Assert(err, IsNil)
c.Assert(s.testRepo.Interfaces(), DeepEquals, &Interfaces{
Plugs: []*snap.PlugInfo{s.plug},
@@ -1207,14 +1207,14 @@ func (s *RepositorySuite) TestConnectedFailsWithEmptySnapName(c *C) {
// Connected fails if plug or slot name is empty
func (s *RepositorySuite) TestConnectedFailsWithEmptyPlugSlotName(c *C) {
- _, err := s.testRepo.Connected(s.plug.Snap.Name(), "")
+ _, err := s.testRepo.Connected(s.plug.Snap.InstanceName(), "")
c.Check(err, ErrorMatches, "plug or slot name is empty")
}
// Connected fails if plug or slot doesn't exist
func (s *RepositorySuite) TestConnectedFailsWithoutPlugOrSlot(c *C) {
- _, err1 := s.testRepo.Connected(s.plug.Snap.Name(), s.plug.Name)
- _, err2 := s.testRepo.Connected(s.slot.Snap.Name(), s.slot.Name)
+ _, err1 := s.testRepo.Connected(s.plug.Snap.InstanceName(), s.plug.Name)
+ _, err2 := s.testRepo.Connected(s.slot.Snap.InstanceName(), s.slot.Name)
c.Check(err1, ErrorMatches, `snap "consumer" has no plug or slot named "plug"`)
c.Check(err2, ErrorMatches, `snap "producer" has no plug or slot named "slot"`)
}
@@ -1226,11 +1226,11 @@ func (s *RepositorySuite) TestConnectedFindsConnections(c *C) {
_, err := s.testRepo.Connect(NewConnRef(s.plug, s.slot), nil, nil, nil)
c.Assert(err, IsNil)
- conns, err := s.testRepo.Connected(s.plug.Snap.Name(), s.plug.Name)
+ conns, err := s.testRepo.Connected(s.plug.Snap.InstanceName(), s.plug.Name)
c.Assert(err, IsNil)
c.Check(conns, DeepEquals, []*ConnRef{NewConnRef(s.plug, s.slot)})
- conns, err = s.testRepo.Connected(s.slot.Snap.Name(), s.slot.Name)
+ conns, err = s.testRepo.Connected(s.slot.Snap.InstanceName(), s.slot.Name)
c.Assert(err, IsNil)
c.Check(conns, DeepEquals, []*ConnRef{NewConnRef(s.plug, s.slot)})
}
@@ -1259,11 +1259,11 @@ func (s *RepositorySuite) TestConnections(c *C) {
_, err := s.testRepo.Connect(NewConnRef(s.plug, s.slot), nil, nil, nil)
c.Assert(err, IsNil)
- conns, err := s.testRepo.Connections(s.plug.Snap.Name())
+ conns, err := s.testRepo.Connections(s.plug.Snap.InstanceName())
c.Assert(err, IsNil)
c.Check(conns, DeepEquals, []*ConnRef{NewConnRef(s.plug, s.slot)})
- conns, err = s.testRepo.Connections(s.slot.Snap.Name())
+ conns, err = s.testRepo.Connections(s.slot.Snap.InstanceName())
c.Assert(err, IsNil)
c.Check(conns, DeepEquals, []*ConnRef{NewConnRef(s.plug, s.slot)})
@@ -1306,7 +1306,7 @@ func (s *RepositorySuite) TestInterfacesSmokeTest(c *C) {
Connections: []*ConnRef{NewConnRef(s.plug, s.slot)},
})
// After disconnecting the connections become empty
- err = s.testRepo.Disconnect(s.plug.Snap.Name(), s.plug.Name, s.slot.Snap.Name(), s.slot.Name)
+ err = s.testRepo.Disconnect(s.plug.Snap.InstanceName(), s.plug.Name, s.slot.Snap.InstanceName(), s.slot.Name)
c.Assert(err, IsNil)
ifaces = s.testRepo.Interfaces()
c.Assert(ifaces, DeepEquals, &Interfaces{
@@ -1348,11 +1348,11 @@ func (s *RepositorySuite) TestSnapSpecification(c *C) {
c.Assert(repo.AddSlot(s.slot), IsNil)
// Snaps should get static security now
- spec, err := repo.SnapSpecification(testSecurity, s.plug.Snap.Name())
+ spec, err := repo.SnapSpecification(testSecurity, s.plug.Snap.InstanceName())
c.Assert(err, IsNil)
c.Check(spec.(*ifacetest.Specification).Snippets, DeepEquals, []string{"static plug snippet"})
- spec, err = repo.SnapSpecification(testSecurity, s.slot.Snap.Name())
+ spec, err = repo.SnapSpecification(testSecurity, s.slot.Snap.InstanceName())
c.Assert(err, IsNil)
c.Check(spec.(*ifacetest.Specification).Snippets, DeepEquals, []string{"static slot snippet"})
@@ -1362,14 +1362,14 @@ func (s *RepositorySuite) TestSnapSpecification(c *C) {
c.Assert(err, IsNil)
// Snaps should get static and connection-specific security now
- spec, err = repo.SnapSpecification(testSecurity, s.plug.Snap.Name())
+ spec, err = repo.SnapSpecification(testSecurity, s.plug.Snap.InstanceName())
c.Assert(err, IsNil)
c.Check(spec.(*ifacetest.Specification).Snippets, DeepEquals, []string{
"static plug snippet",
"connection-specific plug snippet",
})
- spec, err = repo.SnapSpecification(testSecurity, s.slot.Snap.Name())
+ spec, err = repo.SnapSpecification(testSecurity, s.slot.Snap.InstanceName())
c.Assert(err, IsNil)
c.Check(spec.(*ifacetest.Specification).Snippets, DeepEquals, []string{
"static slot snippet",
@@ -1399,11 +1399,11 @@ func (s *RepositorySuite) TestSnapSpecificationFailureWithConnectionSnippets(c *
_, err := repo.Connect(connRef, nil, nil, nil)
c.Assert(err, IsNil)
- spec, err := repo.SnapSpecification(testSecurity, s.plug.Snap.Name())
+ spec, err := repo.SnapSpecification(testSecurity, s.plug.Snap.InstanceName())
c.Assert(err, ErrorMatches, "cannot compute snippet for consumer")
c.Assert(spec, IsNil)
- spec, err = repo.SnapSpecification(testSecurity, s.slot.Snap.Name())
+ spec, err = repo.SnapSpecification(testSecurity, s.slot.Snap.InstanceName())
c.Assert(err, ErrorMatches, "cannot compute snippet for provider")
c.Assert(spec, IsNil)
}
@@ -1429,11 +1429,11 @@ func (s *RepositorySuite) TestSnapSpecificationFailureWithPermanentSnippets(c *C
_, err := repo.Connect(connRef, nil, nil, nil)
c.Assert(err, IsNil)
- spec, err := repo.SnapSpecification(testSecurity, s.plug.Snap.Name())
+ spec, err := repo.SnapSpecification(testSecurity, s.plug.Snap.InstanceName())
c.Assert(err, ErrorMatches, "cannot compute snippet for consumer")
c.Assert(spec, IsNil)
- spec, err = repo.SnapSpecification(testSecurity, s.slot.Snap.Name())
+ spec, err = repo.SnapSpecification(testSecurity, s.slot.Snap.InstanceName())
c.Assert(err, ErrorMatches, "cannot compute snippet for provider")
c.Assert(spec, IsNil)
}
@@ -1473,13 +1473,13 @@ slots:
candidateSlots := repo.AutoConnectCandidateSlots("consumer", "auto", policyCheck)
c.Assert(candidateSlots, HasLen, 1)
- c.Check(candidateSlots[0].Snap.Name(), Equals, "producer")
+ c.Check(candidateSlots[0].Snap.InstanceName(), Equals, "producer")
c.Check(candidateSlots[0].Interface, Equals, "auto")
c.Check(candidateSlots[0].Name, Equals, "auto")
candidatePlugs := repo.AutoConnectCandidatePlugs("producer", "auto", policyCheck)
c.Assert(candidatePlugs, HasLen, 1)
- c.Check(candidatePlugs[0].Snap.Name(), Equals, "consumer")
+ c.Check(candidatePlugs[0].Snap.InstanceName(), Equals, "consumer")
c.Check(candidatePlugs[0].Interface, Equals, "auto")
c.Check(candidatePlugs[0].Name, Equals, "auto")
}
@@ -1530,13 +1530,13 @@ plugs:
// Both can auto-connect
candidateSlots := repo.AutoConnectCandidateSlots("consumer1", "auto", policyCheck)
c.Assert(candidateSlots, HasLen, 1)
- c.Check(candidateSlots[0].Snap.Name(), Equals, "producer")
+ c.Check(candidateSlots[0].Snap.InstanceName(), Equals, "producer")
c.Check(candidateSlots[0].Interface, Equals, "auto")
c.Check(candidateSlots[0].Name, Equals, "auto")
candidateSlots = repo.AutoConnectCandidateSlots("consumer2", "auto", policyCheck)
c.Assert(candidateSlots, HasLen, 1)
- c.Check(candidateSlots[0].Snap.Name(), Equals, "producer")
+ c.Check(candidateSlots[0].Snap.InstanceName(), Equals, "producer")
c.Check(candidateSlots[0].Interface, Equals, "auto")
c.Check(candidateSlots[0].Name, Equals, "auto")
diff --git a/interfaces/seccomp/backend.go b/interfaces/seccomp/backend.go
index 40de971199..d71af0ab6f 100644
--- a/interfaces/seccomp/backend.go
+++ b/interfaces/seccomp/backend.go
@@ -93,7 +93,7 @@ func (b *Backend) Name() interfaces.SecuritySystem {
// This method should be called after changing plug, slots, connections between
// them or application present in the snap.
func (b *Backend) Setup(snapInfo *snap.Info, opts interfaces.ConfinementOptions, repo *interfaces.Repository) error {
- snapName := snapInfo.Name()
+ snapName := snapInfo.InstanceName()
// Get the snippets that apply to this snap
spec, err := repo.SnapSpecification(b.Name(), snapName)
if err != nil {
diff --git a/interfaces/sorting.go b/interfaces/sorting.go
index b4ce1e79fd..b344a0772b 100644
--- a/interfaces/sorting.go
+++ b/interfaces/sorting.go
@@ -69,8 +69,8 @@ type byPlugSnapAndName []*snap.PlugInfo
func (c byPlugSnapAndName) Len() int { return len(c) }
func (c byPlugSnapAndName) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c byPlugSnapAndName) Less(i, j int) bool {
- if c[i].Snap.Name() != c[j].Snap.Name() {
- return c[i].Snap.Name() < c[j].Snap.Name()
+ if c[i].Snap.InstanceName() != c[j].Snap.InstanceName() {
+ return c[i].Snap.InstanceName() < c[j].Snap.InstanceName()
}
return c[i].Name < c[j].Name
}
@@ -80,8 +80,8 @@ type bySlotSnapAndName []*snap.SlotInfo
func (c bySlotSnapAndName) Len() int { return len(c) }
func (c bySlotSnapAndName) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c bySlotSnapAndName) Less(i, j int) bool {
- if c[i].Snap.Name() != c[j].Snap.Name() {
- return c[i].Snap.Name() < c[j].Snap.Name()
+ if c[i].Snap.InstanceName() != c[j].Snap.InstanceName() {
+ return c[i].Snap.InstanceName() < c[j].Snap.InstanceName()
}
return c[i].Name < c[j].Name
}
@@ -143,8 +143,8 @@ type byPlugInfo []*snap.PlugInfo
func (c byPlugInfo) Len() int { return len(c) }
func (c byPlugInfo) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c byPlugInfo) Less(i, j int) bool {
- if c[i].Snap.Name() != c[j].Snap.Name() {
- return c[i].Snap.Name() < c[j].Snap.Name()
+ if c[i].Snap.InstanceName() != c[j].Snap.InstanceName() {
+ return c[i].Snap.InstanceName() < c[j].Snap.InstanceName()
}
return c[i].Name < c[j].Name
}
@@ -154,8 +154,8 @@ type bySlotInfo []*snap.SlotInfo
func (c bySlotInfo) Len() int { return len(c) }
func (c bySlotInfo) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c bySlotInfo) Less(i, j int) bool {
- if c[i].Snap.Name() != c[j].Snap.Name() {
- return c[i].Snap.Name() < c[j].Snap.Name()
+ if c[i].Snap.InstanceName() != c[j].Snap.InstanceName() {
+ return c[i].Snap.InstanceName() < c[j].Snap.InstanceName()
}
return c[i].Name < c[j].Name
}
diff --git a/interfaces/systemd/backend.go b/interfaces/systemd/backend.go
index 01c3b7c47f..3677618e14 100644
--- a/interfaces/systemd/backend.go
+++ b/interfaces/systemd/backend.go
@@ -54,7 +54,7 @@ func (b *Backend) Name() interfaces.SecuritySystem {
// them or application present in the snap.
func (b *Backend) Setup(snapInfo *snap.Info, confinement interfaces.ConfinementOptions, repo *interfaces.Repository) error {
// Record all the extra systemd services for this snap.
- snapName := snapInfo.Name()
+ snapName := snapInfo.InstanceName()
// Get the services that apply to this snap
spec, err := repo.SnapSpecification(b.Name(), snapName)
if err != nil {
diff --git a/interfaces/udev/backend.go b/interfaces/udev/backend.go
index b90070b494..2a9e026457 100644
--- a/interfaces/udev/backend.go
+++ b/interfaces/udev/backend.go
@@ -63,7 +63,7 @@ func snapRulesFilePath(snapName string) string {
//
// If the method fails it should be re-tried (with a sensible strategy) by the caller.
func (b *Backend) Setup(snapInfo *snap.Info, opts interfaces.ConfinementOptions, repo *interfaces.Repository) error {
- snapName := snapInfo.Name()
+ snapName := snapInfo.InstanceName()
spec, err := repo.SnapSpecification(b.Name(), snapName)
if err != nil {
return fmt.Errorf("cannot obtain udev specification for snap %q: %s", snapName, err)
@@ -75,7 +75,7 @@ func (b *Backend) Setup(snapInfo *snap.Info, opts interfaces.ConfinementOptions,
return fmt.Errorf("cannot create directory for udev rules %q: %s", dir, err)
}
- rulesFilePath := snapRulesFilePath(snapInfo.Name())
+ rulesFilePath := snapRulesFilePath(snapInfo.InstanceName())
if len(content) == 0 {
// Make sure that the rules file gets removed when we don't have any
diff --git a/overlord/assertstate/assertstate.go b/overlord/assertstate/assertstate.go
index deb46886dc..ef7b10ef0e 100644
--- a/overlord/assertstate/assertstate.go
+++ b/overlord/assertstate/assertstate.go
@@ -152,7 +152,7 @@ func RefreshSnapDeclarations(s *state.State, userID int) error {
continue
}
if err := snapasserts.FetchSnapDeclaration(f, info.SnapID); err != nil {
- return fmt.Errorf("cannot refresh snap-declaration for %q: %v", info.Name(), err)
+ return fmt.Errorf("cannot refresh snap-declaration for %q: %v", info.InstanceName(), err)
}
}
return nil
@@ -251,7 +251,7 @@ func ValidateRefreshes(s *state.State, snapInfos []*snap.Info, ignoreValidation
}
err := doFetch(s, userID, fetching)
if err != nil {
- errs = append(errs, fmt.Errorf("cannot refresh %q to revision %s: %v", candInfo.Name(), candInfo.Revision, err))
+ errs = append(errs, fmt.Errorf("cannot refresh %q to revision %s: %v", candInfo.InstanceName(), candInfo.Revision, err))
continue
}
@@ -267,7 +267,7 @@ func ValidateRefreshes(s *state.State, snapInfos []*snap.Info, ignoreValidation
}
}
if revoked != nil {
- errs = append(errs, fmt.Errorf("cannot refresh %q to revision %s: validation by %q (id %q) revoked", candInfo.Name(), candInfo.Revision, gatingNames[revoked.SnapID()], revoked.SnapID()))
+ errs = append(errs, fmt.Errorf("cannot refresh %q to revision %s: validation by %q (id %q) revoked", candInfo.InstanceName(), candInfo.Revision, gatingNames[revoked.SnapID()], revoked.SnapID()))
continue
}
@@ -346,7 +346,7 @@ func AutoAliases(s *state.State, info *snap.Info) (map[string]string, error) {
}
decl, err := SnapDeclaration(s, info.SnapID)
if err != nil {
- return nil, fmt.Errorf("internal error: cannot find snap-declaration for installed snap %q: %v", info.Name(), err)
+ return nil, fmt.Errorf("internal error: cannot find snap-declaration for installed snap %q: %v", info.InstanceName(), err)
}
explicitAliases := decl.Aliases()
if len(explicitAliases) != 0 {
diff --git a/overlord/devicestate/devicemgr.go b/overlord/devicestate/devicemgr.go
index 451dd36fec..8887ade766 100644
--- a/overlord/devicestate/devicemgr.go
+++ b/overlord/devicestate/devicemgr.go
@@ -281,7 +281,7 @@ func (m *DeviceManager) ensureOperational() error {
if gadgetInfo != nil && gadgetInfo.Hooks["prepare-device"] != nil {
summary := i18n.G("Run prepare-device hook")
hooksup := &hookstate.HookSetup{
- Snap: gadgetInfo.Name(),
+ Snap: gadgetInfo.InstanceName(),
Hook: "prepare-device",
}
prepareDevice = hookstate.HookTask(m.state, summary, hooksup, nil)
diff --git a/overlord/devicestate/devicestate.go b/overlord/devicestate/devicestate.go
index 4a3d41e0a3..1fd9a252a8 100644
--- a/overlord/devicestate/devicestate.go
+++ b/overlord/devicestate/devicestate.go
@@ -160,14 +160,14 @@ func checkGadgetOrKernel(st *state.State, snapInfo, curInfo *snap.Info, flags sn
if snapInfo.SnapID != "" {
snapDecl, err := assertstate.SnapDeclaration(st, snapInfo.SnapID)
if err != nil {
- return fmt.Errorf("internal error: cannot find snap declaration for %q: %v", snapInfo.Name(), err)
+ return fmt.Errorf("internal error: cannot find snap declaration for %q: %v", snapInfo.InstanceName(), err)
}
publisher := snapDecl.PublisherID()
if publisher != "canonical" && publisher != model.BrandID() {
- return fmt.Errorf("cannot install %s %q published by %q for model by %q", kind, snapInfo.Name(), publisher, model.BrandID())
+ return fmt.Errorf("cannot install %s %q published by %q for model by %q", kind, snapInfo.InstanceName(), publisher, model.BrandID())
}
} else {
- logger.Noticef("installing unasserted %s %q", kind, snapInfo.Name())
+ logger.Noticef("installing unasserted %s %q", kind, snapInfo.InstanceName())
}
currentSnap, err := currentInfo(st)
@@ -185,8 +185,9 @@ func checkGadgetOrKernel(st *state.State, snapInfo, curInfo *snap.Info, flags sn
return fmt.Errorf("cannot install %s snap on classic if not requested by the model", kind)
}
- if snapInfo.Name() != expectedName {
- return fmt.Errorf("cannot install %s %q, model assertion requests %q", kind, snapInfo.Name(), expectedName)
+ // TODO parallel-install: use instance name, instance name must match the store name
+ if snapInfo.InstanceName() != expectedName {
+ return fmt.Errorf("cannot install %s %q, model assertion requests %q", kind, snapInfo.InstanceName(), expectedName)
}
return nil
@@ -259,7 +260,7 @@ func CanManageRefreshes(st *state.State) bool {
for _, plugInfo := range info.Plugs {
if plugInfo.Interface == "snapd-control" && plugInfo.Attrs["refresh-schedule"] == "managed" {
- snapName := info.Name()
+ snapName := info.InstanceName()
plugName := plugInfo.Name
if interfaceConnected(st, snapName, plugName) {
return true
diff --git a/overlord/devicestate/devicestate_test.go b/overlord/devicestate/devicestate_test.go
index bec19018a0..c93d089c4e 100644
--- a/overlord/devicestate/devicestate_test.go
+++ b/overlord/devicestate/devicestate_test.go
@@ -2121,8 +2121,8 @@ func makeMockRepoWithConnectedSnaps(c *C, st *state.State, info11, core11 *snap.
err = repo.AddSnap(core11)
c.Assert(err, IsNil)
_, err = repo.Connect(&interfaces.ConnRef{
- PlugRef: interfaces.PlugRef{Snap: info11.Name(), Name: ifname},
- SlotRef: interfaces.SlotRef{Snap: core11.Name(), Name: ifname},
+ PlugRef: interfaces.PlugRef{Snap: info11.InstanceName(), Name: ifname},
+ SlotRef: interfaces.SlotRef{Snap: core11.InstanceName(), Name: ifname},
}, nil, nil, nil)
c.Assert(err, IsNil)
conns, err := repo.Connected("snap-with-snapd-control", "snapd-control")
@@ -2134,7 +2134,7 @@ func makeMockRepoWithConnectedSnaps(c *C, st *state.State, info11, core11 *snap.
func (s *deviceMgrSuite) makeSnapDeclaration(c *C, st *state.State, info *snap.Info) {
decl, err := s.storeSigning.Sign(asserts.SnapDeclarationType, map[string]interface{}{
"series": "16",
- "snap-name": info.Name(),
+ "snap-name": info.StoreName(),
"snap-id": info.SideInfo.SnapID,
"publisher-id": "canonical",
"timestamp": time.Now().UTC().Format(time.RFC3339),
diff --git a/overlord/devicestate/firstboot_test.go b/overlord/devicestate/firstboot_test.go
index 2130b02ba9..4bef3b9158 100644
--- a/overlord/devicestate/firstboot_test.go
+++ b/overlord/devicestate/firstboot_test.go
@@ -279,7 +279,7 @@ func (s *FirstBootTestSuite) TestPopulateFromSeedErrorsOnState(c *C) {
func (s *FirstBootTestSuite) makeAssertedSnap(c *C, snapYaml string, files [][]string, revision snap.Revision, developerID string) (snapFname string, snapDecl *asserts.SnapDeclaration, snapRev *asserts.SnapRevision) {
info, err := snap.InfoFromSnapYaml([]byte(snapYaml))
c.Assert(err, IsNil)
- snapName := info.Name()
+ snapName := info.InstanceName()
mockSnapFile := snaptest.MakeTestSnapWithFiles(c, snapYaml, files)
snapFname = filepath.Base(mockSnapFile)
@@ -1163,6 +1163,15 @@ snaps:
err = s.overlord.Settle(settleTimeout)
st.Lock()
c.Assert(err, IsNil)
+
+ // at this point snapd is "restarting", pretend the restart has
+ // happened
+ c.Assert(chg.Status(), Equals, state.DoingStatus)
+ state.MockRestarting(st, state.RestartUnset)
+ st.Unlock()
+ err = s.overlord.Settle(settleTimeout)
+ st.Lock()
+ c.Assert(err, IsNil)
c.Assert(chg.Status(), Equals, state.DoneStatus)
// verify
diff --git a/overlord/devicestate/handlers.go b/overlord/devicestate/handlers.go
index 6e296a8186..28050610ba 100644
--- a/overlord/devicestate/handlers.go
+++ b/overlord/devicestate/handlers.go
@@ -360,7 +360,7 @@ func getSerialRequestConfig(t *state.Task) (*serialRequestConfig, error) {
if err != nil {
return nil, fmt.Errorf("cannot find gadget snap and its name: %v", err)
}
- gadgetName = gadgetInfo.Name()
+ gadgetName = gadgetInfo.InstanceName()
tr = config.NewTransaction(t.State())
err = tr.GetMaybe(gadgetName, "device-service.url", &svcURL)
diff --git a/overlord/hookstate/ctlcmd/services_test.go b/overlord/hookstate/ctlcmd/services_test.go
index b8442bcf57..36f7d5fa85 100644
--- a/overlord/hookstate/ctlcmd/services_test.go
+++ b/overlord/hookstate/ctlcmd/services_test.go
@@ -143,22 +143,22 @@ func (s *servicectlSuite) SetUpTest(c *C) {
info2 := snaptest.MockSnap(c, string(otherSnapYaml), &snap.SideInfo{
Revision: snap.R(1),
})
- snapstate.Set(s.st, info1.Name(), &snapstate.SnapState{
+ snapstate.Set(s.st, info1.InstanceName(), &snapstate.SnapState{
Active: true,
Sequence: []*snap.SideInfo{
{
- RealName: info1.Name(),
+ RealName: info1.StoreName(),
Revision: info1.Revision,
SnapID: "test-snap-id",
},
},
Current: info1.Revision,
})
- snapstate.Set(s.st, info2.Name(), &snapstate.SnapState{
+ snapstate.Set(s.st, info2.InstanceName(), &snapstate.SnapState{
Active: true,
Sequence: []*snap.SideInfo{
{
- RealName: info2.Name(),
+ RealName: info2.StoreName(),
Revision: info2.Revision,
SnapID: "other-snap-id",
},
diff --git a/overlord/ifacestate/handlers.go b/overlord/ifacestate/handlers.go
index fcc1eaddf5..a8beb0b83b 100644
--- a/overlord/ifacestate/handlers.go
+++ b/overlord/ifacestate/handlers.go
@@ -103,7 +103,7 @@ func (m *InterfaceManager) doSetupProfiles(task *state.Task, tomb *tomb.Tomb) er
func (m *InterfaceManager) setupProfilesForSnap(task *state.Task, _ *tomb.Tomb, snapInfo *snap.Info, opts interfaces.ConfinementOptions) error {
addImplicitSlots(snapInfo)
- snapName := snapInfo.Name()
+ snapName := snapInfo.InstanceName()
// The snap may have been updated so perform the following operation to
// ensure that we are always working on the correct state:
@@ -146,7 +146,7 @@ func (m *InterfaceManager) setupProfilesForSnap(task *state.Task, _ *tomb.Tomb,
affectedSet[name] = true
}
// The principal snap was already handled above.
- delete(affectedSet, snapInfo.Name())
+ delete(affectedSet, snapInfo.InstanceName())
affectedSnaps := make([]string, 0, len(affectedSet))
for name := range affectedSet {
affectedSnaps = append(affectedSnaps, name)
@@ -611,9 +611,9 @@ func (m *InterfaceManager) doAutoConnect(task *state.Task, _ *tomb.Tomb) error {
// go with those from the new core snap.
if len(candidates) == 2 {
switch {
- case candidates[0].Snap.Name() == "ubuntu-core" && candidates[1].Snap.Name() == "core":
+ case candidates[0].Snap.InstanceName() == "ubuntu-core" && candidates[1].Snap.InstanceName() == "core":
candidates = candidates[1:2]
- case candidates[1].Snap.Name() == "ubuntu-core" && candidates[0].Snap.Name() == "core":
+ case candidates[1].Snap.InstanceName() == "ubuntu-core" && candidates[0].Snap.InstanceName() == "core":
candidates = candidates[0:1]
}
}
@@ -634,7 +634,7 @@ func (m *InterfaceManager) doAutoConnect(task *state.Task, _ *tomb.Tomb) error {
continue
}
- ignore, err := findSymmetricAutoconnect(st, plug.Snap.Name(), slot.Snap.Name(), task)
+ ignore, err := findSymmetricAutoconnect(st, plug.Snap.InstanceName(), slot.Snap.InstanceName(), task)
if err != nil {
return err
}
@@ -644,9 +644,9 @@ func (m *InterfaceManager) doAutoConnect(task *state.Task, _ *tomb.Tomb) error {
}
const auto = true
- if err := checkConnectConflicts(st, plug.Snap.Name(), slot.Snap.Name(), auto); err != nil {
+ if err := checkConnectConflicts(st, plug.Snap.InstanceName(), slot.Snap.InstanceName(), auto); err != nil {
if _, retry := err.(*state.Retry); retry {
- task.Logf("auto-connect of snap %q will be retried because of %q - %q conflict", snapName, plug.Snap.Name(), slot.Snap.Name())
+ task.Logf("auto-connect of snap %q will be retried because of %q - %q conflict", snapName, plug.Snap.InstanceName(), slot.Snap.InstanceName())
return err // will retry
}
return fmt.Errorf("auto-connect conflict check failed: %s", err)
@@ -664,7 +664,7 @@ func (m *InterfaceManager) doAutoConnect(task *state.Task, _ *tomb.Tomb) error {
// make sure slot is the only viable
// connection for plug, same check as if we were
// considering auto-connections from plug
- candSlots := m.repo.AutoConnectCandidateSlots(plug.Snap.Name(), plug.Name, autochecker.check)
+ candSlots := m.repo.AutoConnectCandidateSlots(plug.Snap.InstanceName(), plug.Name, autochecker.check)
if len(candSlots) != 1 || candSlots[0].String() != slot.String() {
crefs := make([]string, len(candSlots))
@@ -686,7 +686,7 @@ func (m *InterfaceManager) doAutoConnect(task *state.Task, _ *tomb.Tomb) error {
continue
}
- ignore, err := findSymmetricAutoconnect(st, plug.Snap.Name(), slot.Snap.Name(), task)
+ ignore, err := findSymmetricAutoconnect(st, plug.Snap.InstanceName(), slot.Snap.InstanceName(), task)
if err != nil {
return err
}
@@ -696,9 +696,9 @@ func (m *InterfaceManager) doAutoConnect(task *state.Task, _ *tomb.Tomb) error {
}
const auto = true
- if err := checkConnectConflicts(st, plug.Snap.Name(), slot.Snap.Name(), auto); err != nil {
+ if err := checkConnectConflicts(st, plug.Snap.InstanceName(), slot.Snap.InstanceName(), auto); err != nil {
if _, retry := err.(*state.Retry); retry {
- task.Logf("auto-connect of snap %q will be retried because of %q - %q conflict", snapName, plug.Snap.Name(), slot.Snap.Name())
+ task.Logf("auto-connect of snap %q will be retried because of %q - %q conflict", snapName, plug.Snap.InstanceName(), slot.Snap.InstanceName())
return err // will retry
}
return fmt.Errorf("auto-connect conflict check failed: %s", err)
diff --git a/overlord/ifacestate/helpers.go b/overlord/ifacestate/helpers.go
index 8e52a570ee..c5431989fb 100644
--- a/overlord/ifacestate/helpers.go
+++ b/overlord/ifacestate/helpers.go
@@ -107,7 +107,7 @@ func (m *InterfaceManager) addSnaps() error {
for _, snapInfo := range snaps {
addImplicitSlots(snapInfo)
if err := m.repo.AddSnap(snapInfo); err != nil {
- logger.Noticef("cannot add snap %q to interface repository: %s", snapInfo.Name(), err)
+ logger.Noticef("cannot add snap %q to interface repository: %s", snapInfo.InstanceName(), err)
}
}
return nil
@@ -139,7 +139,7 @@ func (m *InterfaceManager) regenerateAllSecurityProfiles() error {
// For each snap:
for _, snapInfo := range snaps {
- snapName := snapInfo.Name()
+ snapName := snapInfo.InstanceName()
// Get the state of the snap so we can compute the confinement option
var snapst snapstate.SnapState
if err := snapstate.Get(m.state, snapName, &snapst); err != nil {
@@ -285,7 +285,7 @@ func (m *InterfaceManager) reloadConnections(snapName string) ([]string, error)
func (m *InterfaceManager) setupSnapSecurity(task *state.Task, snapInfo *snap.Info, opts interfaces.ConfinementOptions) error {
st := task.State()
- snapName := snapInfo.Name()
+ snapName := snapInfo.InstanceName()
for _, backend := range m.repo.Backends() {
st.Unlock()
@@ -362,7 +362,7 @@ func (c *autoConnectChecker) check(plug *interfaces.ConnectedPlug, slot *interfa
var err error
plugDecl, err = c.snapDeclaration(plug.Snap().SnapID)
if err != nil {
- logger.Noticef("error: cannot find snap declaration for %q: %v", plug.Snap().Name(), err)
+ logger.Noticef("error: cannot find snap declaration for %q: %v", plug.Snap().InstanceName(), err)
return false, nil
}
}
@@ -372,7 +372,7 @@ func (c *autoConnectChecker) check(plug *interfaces.ConnectedPlug, slot *interfa
var err error
slotDecl, err = c.snapDeclaration(slot.Snap().SnapID)
if err != nil {
- logger.Noticef("error: cannot find snap declaration for %q: %v", slot.Snap().Name(), err)
+ logger.Noticef("error: cannot find snap declaration for %q: %v", slot.Snap().InstanceName(), err)
return false, nil
}
}
@@ -411,7 +411,7 @@ func (c *connectChecker) check(plug *interfaces.ConnectedPlug, slot *interfaces.
var err error
plugDecl, err = assertstate.SnapDeclaration(c.st, plug.Snap().SnapID)
if err != nil {
- return false, fmt.Errorf("cannot find snap declaration for %q: %v", plug.Snap().Name(), err)
+ return false, fmt.Errorf("cannot find snap declaration for %q: %v", plug.Snap().InstanceName(), err)
}
}
@@ -420,7 +420,7 @@ func (c *connectChecker) check(plug *interfaces.ConnectedPlug, slot *interfaces.
var err error
slotDecl, err = assertstate.SnapDeclaration(c.st, slot.Snap().SnapID)
if err != nil {
- return false, fmt.Errorf("cannot find snap declaration for %q: %v", slot.Snap().Name(), err)
+ return false, fmt.Errorf("cannot find snap declaration for %q: %v", slot.Snap().InstanceName(), err)
}
}
@@ -483,7 +483,7 @@ func snapsWithSecurityProfiles(st *state.State) ([]*snap.Info, error) {
}
seen := make(map[string]bool, len(infos))
for _, info := range infos {
- seen[info.Name()] = true
+ seen[info.InstanceName()] = true
}
for _, t := range st.Tasks() {
if t.Kind() != "link-snap" || t.Status().Ready() {
diff --git a/overlord/ifacestate/ifacestate.go b/overlord/ifacestate/ifacestate.go
index d1eda9a5e9..4eb8330dd8 100644
--- a/overlord/ifacestate/ifacestate.go
+++ b/overlord/ifacestate/ifacestate.go
@@ -296,7 +296,7 @@ func CheckInterfaces(st *state.State, snapInfo *snap.Info) error {
snapDecl, err := assertstate.SnapDeclaration(st, snapInfo.SnapID)
if err != nil {
- return fmt.Errorf("cannot find snap declaration for %q: %v", snapInfo.Name(), err)
+ return fmt.Errorf("cannot find snap declaration for %q: %v", snapInfo.InstanceName(), err)
}
ic := policy.InstallCandidate{
diff --git a/overlord/ifacestate/ifacestate_test.go b/overlord/ifacestate/ifacestate_test.go
index b1db199967..b20346e832 100644
--- a/overlord/ifacestate/ifacestate_test.go
+++ b/overlord/ifacestate/ifacestate_test.go
@@ -749,8 +749,8 @@ func (s *interfaceManagerSuite) testDisconnect(c *C, plugSnap, plugName, slotSna
// Ensure that the backend was used to setup security of both snaps
c.Assert(s.secBackend.SetupCalls, HasLen, 2)
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)
- c.Check(s.secBackend.SetupCalls[0].SnapInfo.Name(), Equals, "consumer")
- c.Check(s.secBackend.SetupCalls[1].SnapInfo.Name(), Equals, "producer")
+ c.Check(s.secBackend.SetupCalls[0].SnapInfo.InstanceName(), Equals, "consumer")
+ c.Check(s.secBackend.SetupCalls[1].SnapInfo.InstanceName(), Equals, "producer")
c.Check(s.secBackend.SetupCalls[0].Options, Equals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[1].Options, Equals, interfaces.ConfinementOptions{})
@@ -862,7 +862,7 @@ func (s *interfaceManagerSuite) mockSnap(c *C, yamlText string) *snap.Info {
Revision: snap.R(1),
}
snapInfo := snaptest.MockSnap(c, yamlText, sideInfo)
- sideInfo.RealName = snapInfo.Name()
+ sideInfo.RealName = snapInfo.StoreName()
a, err := s.db.FindMany(asserts.SnapDeclarationType, map[string]string{
"snap-name": sideInfo.RealName,
@@ -880,7 +880,7 @@ func (s *interfaceManagerSuite) mockSnap(c *C, yamlText string) *snap.Info {
defer s.state.Unlock()
// Put a side info into the state
- snapstate.Set(s.state, snapInfo.Name(), &snapstate.SnapState{
+ snapstate.Set(s.state, snapInfo.InstanceName(), &snapstate.SnapState{
Active: true,
Sequence: []*snap.SideInfo{sideInfo},
Current: sideInfo.Revision,
@@ -891,17 +891,17 @@ func (s *interfaceManagerSuite) mockSnap(c *C, yamlText string) *snap.Info {
func (s *interfaceManagerSuite) mockUpdatedSnap(c *C, yamlText string, revision int) *snap.Info {
sideInfo := &snap.SideInfo{Revision: snap.R(revision)}
snapInfo := snaptest.MockSnap(c, yamlText, sideInfo)
- sideInfo.RealName = snapInfo.Name()
+ sideInfo.RealName = snapInfo.StoreName()
s.state.Lock()
defer s.state.Unlock()
// Put the new revision (stored in SideInfo) into the state
var snapst snapstate.SnapState
- err := snapstate.Get(s.state, snapInfo.Name(), &snapst)
+ err := snapstate.Get(s.state, snapInfo.InstanceName(), &snapst)
c.Assert(err, IsNil)
snapst.Sequence = append(snapst.Sequence, sideInfo)
- snapstate.Set(s.state, snapInfo.Name(), &snapst)
+ snapstate.Set(s.state, snapInfo.InstanceName(), &snapst)
return snapInfo
}
@@ -1059,7 +1059,7 @@ func (s *interfaceManagerSuite) TestDoSetupSnapSecurityHonorsUndesiredFlag(c *C)
// Run the setup-snap-security task and let it finish.
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
Revision: snapInfo.Revision,
},
})
@@ -1103,7 +1103,7 @@ func (s *interfaceManagerSuite) TestDoSetupSnapSecurityAutoConnectsPlugs(c *C) {
// Run the setup-snap-security task and let it finish.
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
Revision: snapInfo.Revision,
},
})
@@ -1151,7 +1151,7 @@ func (s *interfaceManagerSuite) TestDoSetupSnapSecurityAutoConnectsSlots(c *C) {
// Run the setup-snap-security task and let it finish.
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
Revision: snapInfo.Revision,
},
})
@@ -1204,7 +1204,7 @@ func (s *interfaceManagerSuite) TestDoSetupSnapSecurityAutoConnectsSlotsMultiple
// Run the setup-snap-security task and let it finish.
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
Revision: snapInfo.Revision,
},
})
@@ -1266,7 +1266,7 @@ func (s *interfaceManagerSuite) TestDoSetupSnapSecurityNoAutoConnectSlotsIfAlter
// Run the setup-snap-security task and let it finish.
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
Revision: snapInfo.Revision,
},
})
@@ -1337,7 +1337,7 @@ slots:
// Run the setup-snap-security task and let it finish.
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
SnapID: snapInfo.SnapID,
Revision: snapInfo.Revision,
},
@@ -1384,7 +1384,7 @@ func (s *interfaceManagerSuite) TestDoSetupSnapSecuirtyKeepsExistingConnectionSt
// Run the setup-snap-security task and let it finish.
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
Revision: snapInfo.Revision,
},
})
@@ -1430,7 +1430,7 @@ func (s *interfaceManagerSuite) TestDoSetupSnapSecuirtyIgnoresStrayConnection(c
// Run the setup-snap-security task and let it finish.
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
Revision: snapInfo.Revision,
},
})
@@ -1459,7 +1459,7 @@ func (s *interfaceManagerSuite) TestDoSetupProfilesAddsImplicitSlots(c *C) {
// Run the setup-profiles task and let it finish.
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
Revision: snapInfo.Revision,
},
})
@@ -1473,7 +1473,7 @@ func (s *interfaceManagerSuite) TestDoSetupProfilesAddsImplicitSlots(c *C) {
// Ensure that we have slots on the OS snap.
repo := mgr.Repository()
- slots := repo.Slots(snapInfo.Name())
+ slots := repo.Slots(snapInfo.InstanceName())
// NOTE: This is not an exact test as it duplicates functionality elsewhere
// and is was a pain to update each time. This is correctly handled by the
// implicit slot tests in snap/implicit_test.go
@@ -1484,13 +1484,13 @@ func (s *interfaceManagerSuite) TestDoSetupSnapSecuirtyReloadsConnectionsWhenInv
s.mockIfaces(c, &ifacetest.TestInterface{InterfaceName: "test"}, &ifacetest.TestInterface{InterfaceName: "test2"})
snapInfo := s.mockSnap(c, consumerYaml)
s.mockSnap(c, producerYaml)
- s.testDoSetupSnapSecuirtyReloadsConnectionsWhenInvokedOn(c, snapInfo.Name(), snapInfo.Revision)
+ s.testDoSetupSnapSecuirtyReloadsConnectionsWhenInvokedOn(c, snapInfo.InstanceName(), snapInfo.Revision)
// Ensure that the backend was used to setup security of both snaps
c.Assert(s.secBackend.SetupCalls, HasLen, 2)
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)
- c.Check(s.secBackend.SetupCalls[0].SnapInfo.Name(), Equals, "consumer")
- c.Check(s.secBackend.SetupCalls[1].SnapInfo.Name(), Equals, "producer")
+ c.Check(s.secBackend.SetupCalls[0].SnapInfo.InstanceName(), Equals, "consumer")
+ c.Check(s.secBackend.SetupCalls[1].SnapInfo.InstanceName(), Equals, "producer")
c.Check(s.secBackend.SetupCalls[0].Options, Equals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[1].Options, Equals, interfaces.ConfinementOptions{})
@@ -1500,13 +1500,13 @@ func (s *interfaceManagerSuite) TestDoSetupSnapSecuirtyReloadsConnectionsWhenInv
s.mockIfaces(c, &ifacetest.TestInterface{InterfaceName: "test"}, &ifacetest.TestInterface{InterfaceName: "test2"})
s.mockSnap(c, consumerYaml)
snapInfo := s.mockSnap(c, producerYaml)
- s.testDoSetupSnapSecuirtyReloadsConnectionsWhenInvokedOn(c, snapInfo.Name(), snapInfo.Revision)
+ s.testDoSetupSnapSecuirtyReloadsConnectionsWhenInvokedOn(c, snapInfo.InstanceName(), snapInfo.Revision)
// Ensure that the backend was used to setup security of both snaps
c.Assert(s.secBackend.SetupCalls, HasLen, 2)
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)
- c.Check(s.secBackend.SetupCalls[0].SnapInfo.Name(), Equals, "producer")
- c.Check(s.secBackend.SetupCalls[1].SnapInfo.Name(), Equals, "consumer")
+ c.Check(s.secBackend.SetupCalls[0].SnapInfo.InstanceName(), Equals, "producer")
+ c.Check(s.secBackend.SetupCalls[1].SnapInfo.InstanceName(), Equals, "consumer")
c.Check(s.secBackend.SetupCalls[0].Options, Equals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[1].Options, Equals, interfaces.ConfinementOptions{})
@@ -1558,7 +1558,7 @@ func (s *interfaceManagerSuite) TestSetupProfilesHonorsDevMode(c *C) {
// Note that the task will see SnapSetup.Flags equal to DeveloperMode.
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
Revision: snapInfo.Revision,
},
Flags: snapstate.Flags{DevMode: true},
@@ -1574,7 +1574,7 @@ func (s *interfaceManagerSuite) TestSetupProfilesHonorsDevMode(c *C) {
// The snap was setup with DevModeConfinement
c.Assert(s.secBackend.SetupCalls, HasLen, 1)
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)
- c.Check(s.secBackend.SetupCalls[0].SnapInfo.Name(), Equals, "snap")
+ c.Check(s.secBackend.SetupCalls[0].SnapInfo.InstanceName(), Equals, "snap")
c.Check(s.secBackend.SetupCalls[0].Options, Equals, interfaces.ConfinementOptions{DevMode: true})
}
@@ -1609,7 +1609,7 @@ func (s *interfaceManagerSuite) TestSetupProfilesUsesFreshSnapInfo(c *C) {
// Run the setup-profiles task for the new revision and let it finish.
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: newSnapInfo.Name(),
+ RealName: newSnapInfo.StoreName(),
Revision: newSnapInfo.Revision,
},
})
@@ -1626,10 +1626,10 @@ func (s *interfaceManagerSuite) TestSetupProfilesUsesFreshSnapInfo(c *C) {
c.Assert(s.secBackend.SetupCalls, HasLen, 2)
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)
// The sample snap was setup, with the correct new revision.
- c.Check(s.secBackend.SetupCalls[0].SnapInfo.Name(), Equals, newSnapInfo.Name())
+ c.Check(s.secBackend.SetupCalls[0].SnapInfo.InstanceName(), Equals, newSnapInfo.InstanceName())
c.Check(s.secBackend.SetupCalls[0].SnapInfo.Revision, Equals, newSnapInfo.Revision)
// The OS snap was setup (because it was affected).
- c.Check(s.secBackend.SetupCalls[1].SnapInfo.Name(), Equals, coreSnapInfo.Name())
+ c.Check(s.secBackend.SetupCalls[1].SnapInfo.InstanceName(), Equals, coreSnapInfo.InstanceName())
c.Check(s.secBackend.SetupCalls[1].SnapInfo.Revision, Equals, coreSnapInfo.Revision)
}
@@ -1647,7 +1647,7 @@ func (s *interfaceManagerSuite) TestAutoConnectSetupSecurityForConnectedSlots(c
// Run the setup-snap-security task and let it finish.
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
Revision: snapInfo.Revision,
},
})
@@ -1664,10 +1664,10 @@ func (s *interfaceManagerSuite) TestAutoConnectSetupSecurityForConnectedSlots(c
c.Assert(s.secBackend.SetupCalls, HasLen, 3)
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)
// The sample snap was setup, with the correct new revision.
- c.Check(s.secBackend.SetupCalls[0].SnapInfo.Name(), Equals, snapInfo.Name())
+ c.Check(s.secBackend.SetupCalls[0].SnapInfo.InstanceName(), Equals, snapInfo.InstanceName())
c.Check(s.secBackend.SetupCalls[0].SnapInfo.Revision, Equals, snapInfo.Revision)
// The OS snap was setup (because its connected to sample snap).
- c.Check(s.secBackend.SetupCalls[1].SnapInfo.Name(), Equals, coreSnapInfo.Name())
+ c.Check(s.secBackend.SetupCalls[1].SnapInfo.InstanceName(), Equals, coreSnapInfo.InstanceName())
c.Check(s.secBackend.SetupCalls[1].SnapInfo.Revision, Equals, coreSnapInfo.Revision)
}
@@ -1823,7 +1823,7 @@ func (s *interfaceManagerSuite) TestDoRemove(c *C) {
// Security of the related snap was configured
c.Check(s.secBackend.SetupCalls, HasLen, 1)
- c.Check(s.secBackend.SetupCalls[0].SnapInfo.Name(), Equals, "producer")
+ c.Check(s.secBackend.SetupCalls[0].SnapInfo.InstanceName(), Equals, "producer")
// Connection state was left intact
var conns map[string]interface{}
@@ -1906,8 +1906,8 @@ func (s *interfaceManagerSuite) TestConnectSetsUpSecurity(c *C) {
c.Assert(s.secBackend.SetupCalls, HasLen, 2)
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)
- c.Check(s.secBackend.SetupCalls[0].SnapInfo.Name(), Equals, "producer")
- c.Check(s.secBackend.SetupCalls[1].SnapInfo.Name(), Equals, "consumer")
+ c.Check(s.secBackend.SetupCalls[0].SnapInfo.InstanceName(), Equals, "producer")
+ c.Check(s.secBackend.SetupCalls[1].SnapInfo.InstanceName(), Equals, "consumer")
c.Check(s.secBackend.SetupCalls[0].Options, Equals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[1].Options, Equals, interfaces.ConfinementOptions{})
@@ -1951,8 +1951,8 @@ func (s *interfaceManagerSuite) TestDisconnectSetsUpSecurity(c *C) {
c.Assert(s.secBackend.SetupCalls, HasLen, 2)
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)
- c.Check(s.secBackend.SetupCalls[0].SnapInfo.Name(), Equals, "consumer")
- c.Check(s.secBackend.SetupCalls[1].SnapInfo.Name(), Equals, "producer")
+ c.Check(s.secBackend.SetupCalls[0].SnapInfo.InstanceName(), Equals, "consumer")
+ c.Check(s.secBackend.SetupCalls[1].SnapInfo.InstanceName(), Equals, "producer")
c.Check(s.secBackend.SetupCalls[0].Options, Equals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[1].Options, Equals, interfaces.ConfinementOptions{})
@@ -2107,15 +2107,15 @@ func (s *interfaceManagerSuite) TestSetupProfilesDevModeMultiple(c *C) {
})
c.Assert(err, IsNil)
connRef := &interfaces.ConnRef{
- PlugRef: interfaces.PlugRef{Snap: siP.Name(), Name: "plug"},
- SlotRef: interfaces.SlotRef{Snap: siC.Name(), Name: "slot"},
+ PlugRef: interfaces.PlugRef{Snap: siP.InstanceName(), Name: "plug"},
+ SlotRef: interfaces.SlotRef{Snap: siC.InstanceName(), Name: "slot"},
}
_, err = repo.Connect(connRef, nil, nil, nil)
c.Assert(err, IsNil)
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: siC.Name(),
+ RealName: siC.StoreName(),
Revision: siC.Revision,
},
Flags: snapstate.Flags{DevMode: true},
@@ -2132,9 +2132,9 @@ func (s *interfaceManagerSuite) TestSetupProfilesDevModeMultiple(c *C) {
// The first snap is setup in devmode, the second is not
c.Assert(s.secBackend.SetupCalls, HasLen, 2)
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)
- c.Check(s.secBackend.SetupCalls[0].SnapInfo.Name(), Equals, siC.Name())
+ c.Check(s.secBackend.SetupCalls[0].SnapInfo.InstanceName(), Equals, siC.InstanceName())
c.Check(s.secBackend.SetupCalls[0].Options, Equals, interfaces.ConfinementOptions{DevMode: true})
- c.Check(s.secBackend.SetupCalls[1].SnapInfo.Name(), Equals, siP.Name())
+ c.Check(s.secBackend.SetupCalls[1].SnapInfo.InstanceName(), Equals, siP.InstanceName())
c.Check(s.secBackend.SetupCalls[1].Options, Equals, interfaces.ConfinementOptions{})
}
@@ -2223,13 +2223,13 @@ func (s *interfaceManagerSuite) TestUndoSetupProfilesOnInstall(c *C) {
// install.
snapInfo := s.mockSnap(c, sampleSnapYaml)
s.state.Lock()
- snapstate.Set(s.state, snapInfo.Name(), nil)
+ snapstate.Set(s.state, snapInfo.InstanceName(), nil)
s.state.Unlock()
// Add a change that undoes "setup-snap-security"
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
Revision: snapInfo.Revision,
},
})
@@ -2253,7 +2253,7 @@ func (s *interfaceManagerSuite) TestUndoSetupProfilesOnInstall(c *C) {
// undo task removed the security profile from the system.
c.Assert(s.secBackend.SetupCalls, HasLen, 0)
c.Assert(s.secBackend.RemoveCalls, HasLen, 1)
- c.Check(s.secBackend.RemoveCalls, DeepEquals, []string{snapInfo.Name()})
+ c.Check(s.secBackend.RemoveCalls, DeepEquals, []string{snapInfo.InstanceName()})
}
// Test that setup-snap-security gets undone correctly when a snap is refreshed
@@ -2269,7 +2269,7 @@ func (s *interfaceManagerSuite) TestUndoSetupProfilesOnRefresh(c *C) {
// Add a change that undoes "setup-snap-security"
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
Revision: snapInfo.Revision,
},
})
@@ -2292,7 +2292,7 @@ func (s *interfaceManagerSuite) TestUndoSetupProfilesOnRefresh(c *C) {
// setup the security of the snap we had in the state.
c.Assert(s.secBackend.SetupCalls, HasLen, 1)
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)
- c.Check(s.secBackend.SetupCalls[0].SnapInfo.Name(), Equals, snapInfo.Name())
+ c.Check(s.secBackend.SetupCalls[0].SnapInfo.InstanceName(), Equals, snapInfo.InstanceName())
c.Check(s.secBackend.SetupCalls[0].SnapInfo.Revision, Equals, snapInfo.Revision)
c.Check(s.secBackend.SetupCalls[0].Options, Equals, interfaces.ConfinementOptions{})
}
@@ -2459,7 +2459,7 @@ func (s *interfaceManagerSuite) TestAutoConnectDuringCoreTransition(c *C) {
// Run the setup-snap-security task and let it finish.
change := s.addSetupSnapSecurityChange(c, &snapstate.SnapSetup{
SideInfo: &snap.SideInfo{
- RealName: snapInfo.Name(),
+ RealName: snapInfo.StoreName(),
Revision: snapInfo.Revision,
},
})
@@ -2954,7 +2954,7 @@ func (s *interfaceManagerSuite) TestSnapsWithSecurityProfiles(c *C) {
c.Check(infos, HasLen, 3)
got := make(map[string]snap.Revision)
for _, info := range infos {
- got[info.Name()] = info.Revision
+ got[info.InstanceName()] = info.Revision
}
c.Check(got, DeepEquals, map[string]snap.Revision{
"snap0": snap.R(10),
diff --git a/overlord/managers_test.go b/overlord/managers_test.go
index c350689019..ce2a246218 100644
--- a/overlord/managers_test.go
+++ b/overlord/managers_test.go
@@ -449,7 +449,7 @@ func (ms *mgrsSuite) makeStoreTestSnap(c *C, snapYaml string, revno string) (pat
c.Assert(err, IsNil)
headers := map[string]interface{}{
- "snap-id": fakeSnapID(info.Name()),
+ "snap-id": fakeSnapID(info.StoreName()),
"snap-sha3-384": snapDigest,
"snap-size": fmt.Sprintf("%d", size),
"snap-revision": revno,
@@ -642,7 +642,7 @@ func (ms *mgrsSuite) serveSnap(snapPath, revno string) {
if err != nil {
panic(err)
}
- name := info.Name()
+ name := info.StoreName()
ms.serveIDtoName[fakeSnapID(name)] = name
ms.serveSnapPath[name] = snapPath
ms.serveRevision[name] = revno
@@ -1165,7 +1165,7 @@ func (ms *mgrsSuite) installLocalTestSnap(c *C, snapYamlContent string) *snap.In
c.Assert(err, IsNil)
// store current state
- snapName := info.Name()
+ snapName := info.InstanceName()
var snapst snapstate.SnapState
snapstate.Get(st, snapName, &snapst)
diff --git a/overlord/servicestate/servicestate.go b/overlord/servicestate/servicestate.go
index 51c8d064c2..965e13178c 100644
--- a/overlord/servicestate/servicestate.go
+++ b/overlord/servicestate/servicestate.go
@@ -79,7 +79,7 @@ func Control(st *state.State, appInfos []*snap.AppInfo, inst *Instruction, conte
names := make([]string, len(appInfos))
for i, svc := range appInfos {
svcs = append(svcs, svc.ServiceName())
- snapName := svc.Snap.Name()
+ snapName := svc.Snap.InstanceName()
names[i] = snapName + "." + svc.Name
if snapName != lastName {
snapNames = append(snapNames, snapName)
diff --git a/overlord/snapshotstate/backend/backend.go b/overlord/snapshotstate/backend/backend.go
index 7b2a9baa7a..8118084b3a 100644
--- a/overlord/snapshotstate/backend/backend.go
+++ b/overlord/snapshotstate/backend/backend.go
@@ -161,7 +161,7 @@ func Save(ctx context.Context, id uint64, si *snap.Info, cfg map[string]interfac
snapshot := &client.Snapshot{
SetID: id,
- Snap: si.Name(),
+ Snap: si.InstanceName(),
Revision: si.Revision,
Version: si.Version,
Time: time.Now(),
diff --git a/overlord/snapshotstate/backend/backend_test.go b/overlord/snapshotstate/backend/backend_test.go
index 12678e2699..50edecf3d3 100644
--- a/overlord/snapshotstate/backend/backend_test.go
+++ b/overlord/snapshotstate/backend/backend_test.go
@@ -445,7 +445,7 @@ func (s *snapshotSuite) TestHappyRoundtrip(c *check.C) {
shw, err := backend.Save(context.TODO(), shID, info, cfg, []string{"snapuser"})
c.Assert(err, check.IsNil)
c.Check(shw.SetID, check.Equals, shID)
- c.Check(shw.Snap, check.Equals, info.Name())
+ c.Check(shw.Snap, check.Equals, info.InstanceName())
c.Check(shw.Version, check.Equals, info.Version)
c.Check(shw.Revision, check.Equals, info.Revision)
c.Check(shw.Conf, check.DeepEquals, cfg)
@@ -461,7 +461,7 @@ func (s *snapshotSuite) TestHappyRoundtrip(c *check.C) {
defer shr.Close()
c.Check(shr.SetID, check.Equals, shID)
- c.Check(shr.Snap, check.Equals, info.Name())
+ c.Check(shr.Snap, check.Equals, info.InstanceName())
c.Check(shr.Version, check.Equals, info.Version)
c.Check(shr.Revision, check.Equals, info.Revision)
c.Check(shr.Conf, check.DeepEquals, cfg)
diff --git a/overlord/snapstate/aliasesv2.go b/overlord/snapstate/aliasesv2.go
index 762a186a41..e330335d0b 100644
--- a/overlord/snapstate/aliasesv2.go
+++ b/overlord/snapstate/aliasesv2.go
@@ -547,6 +547,7 @@ func Alias(st *state.State, snapName, app, alias string) (*state.TaskSet, error)
}
snapsup := &SnapSetup{
+ // TODO parallel-install: verify use of instance name
SideInfo: &snap.SideInfo{RealName: snapName},
}
@@ -568,7 +569,7 @@ func manualAlias(info *snap.Info, curAliases map[string]*AliasTarget, target, al
} else {
reason = fmt.Sprintf("target application %q is a daemon", target)
}
- return nil, fmt.Errorf("cannot enable alias %q for %q, %s", alias, info.Name(), reason)
+ return nil, fmt.Errorf("cannot enable alias %q for %q, %s", alias, info.InstanceName(), reason)
}
newAliases = make(map[string]*AliasTarget, len(curAliases))
for alias, aliasTarget := range curAliases {
@@ -603,6 +604,7 @@ func DisableAllAliases(st *state.State, snapName string) (*state.TaskSet, error)
}
snapsup := &SnapSetup{
+ // TODO parallel-install: verify use of instance name
SideInfo: &snap.SideInfo{RealName: snapName},
}
@@ -686,6 +688,7 @@ func Prefer(st *state.State, name string) (*state.TaskSet, error) {
}
snapsup := &SnapSetup{
+ // TODO parallel-install: verify use of instance name
SideInfo: &snap.SideInfo{RealName: name},
}
diff --git a/overlord/snapstate/aliasesv2_test.go b/overlord/snapstate/aliasesv2_test.go
index b14e5e6aa0..433168b1d3 100644
--- a/overlord/snapstate/aliasesv2_test.go
+++ b/overlord/snapstate/aliasesv2_test.go
@@ -145,7 +145,7 @@ func (s *snapmgrTestSuite) TestApplyAliasesChangeMulti(c *C) {
func (s *snapmgrTestSuite) TestAutoAliasesDelta(c *C) {
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -188,8 +188,8 @@ func (s *snapmgrTestSuite) TestAutoAliasesDelta(c *C) {
func (s *snapmgrTestSuite) TestAutoAliasesDeltaAll(c *C) {
seen := make(map[string]bool)
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- seen[info.Name()] = true
- if info.Name() == "alias-snap" {
+ seen[info.InstanceName()] = true
+ if info.InstanceName() == "alias-snap" {
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -237,7 +237,7 @@ func (s *snapmgrTestSuite) TestAutoAliasesDeltaAll(c *C) {
func (s *snapmgrTestSuite) TestAutoAliasesDeltaOverManual(c *C) {
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -274,7 +274,7 @@ func (s *snapmgrTestSuite) TestRefreshAliases(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
diff --git a/overlord/snapstate/backend/backend_test.go b/overlord/snapstate/backend/backend_test.go
index f06ca48276..9a62c76a94 100644
--- a/overlord/snapstate/backend/backend_test.go
+++ b/overlord/snapstate/backend/backend_test.go
@@ -72,7 +72,7 @@ apps:
c.Assert(err, IsNil)
c.Assert(snapf, FitsTypeOf, &squashfs.Snap{})
- c.Check(info.Name(), Equals, "hello")
+ c.Check(info.InstanceName(), Equals, "hello")
}
func (s *backendSuite) TestOpenSnapFilebSideInfo(c *C) {
@@ -93,7 +93,7 @@ slots:
c.Assert(err, IsNil)
// check side info
- c.Check(info.Name(), Equals, "blessed")
+ c.Check(info.InstanceName(), Equals, "blessed")
c.Check(info.Revision, Equals, snap.R(42))
c.Check(info.SideInfo, DeepEquals, si)
diff --git a/overlord/snapstate/backend/copydata.go b/overlord/snapstate/backend/copydata.go
index 471b798aaf..62670f2471 100644
--- a/overlord/snapstate/backend/copydata.go
+++ b/overlord/snapstate/backend/copydata.go
@@ -56,7 +56,7 @@ func (b Backend) UndoCopySnapData(newInfo *snap.Info, oldInfo *snap.Info, meter
}
err1 := b.RemoveSnapData(newInfo)
if err1 != nil {
- logger.Noticef("Cannot remove data directories for %q: %v", newInfo.Name(), err1)
+ logger.Noticef("Cannot remove data directories for %q: %v", newInfo.InstanceName(), err1)
}
var err2 error
@@ -64,12 +64,12 @@ func (b Backend) UndoCopySnapData(newInfo *snap.Info, oldInfo *snap.Info, meter
// first install, remove created common data dir
err2 = b.RemoveSnapCommonData(newInfo)
if err2 != nil {
- logger.Noticef("Cannot remove common data directories for %q: %v", newInfo.Name(), err2)
+ logger.Noticef("Cannot remove common data directories for %q: %v", newInfo.InstanceName(), err2)
}
} else {
err2 = b.untrashData(newInfo)
if err2 != nil {
- logger.Noticef("Cannot restore original data for %q while undoing: %v", newInfo.Name(), err2)
+ logger.Noticef("Cannot restore original data for %q while undoing: %v", newInfo.InstanceName(), err2)
}
}
@@ -80,7 +80,7 @@ func (b Backend) UndoCopySnapData(newInfo *snap.Info, oldInfo *snap.Info, meter
func (b Backend) ClearTrashedData(oldSnap *snap.Info) {
dirs, err := snapDataDirs(oldSnap)
if err != nil {
- logger.Noticef("Cannot remove previous data for %q: %v", oldSnap.Name(), err)
+ logger.Noticef("Cannot remove previous data for %q: %v", oldSnap.InstanceName(), err)
return
}
diff --git a/overlord/snapstate/backend/link.go b/overlord/snapstate/backend/link.go
index 77ed9c3062..6806d10701 100644
--- a/overlord/snapstate/backend/link.go
+++ b/overlord/snapstate/backend/link.go
@@ -61,7 +61,7 @@ func updateCurrentSymlinks(info *snap.Info) error {
// LinkSnap makes the snap available by generating wrappers and setting the current symlinks.
func (b Backend) LinkSnap(info *snap.Info, model *asserts.Model) error {
if info.Revision.Unset() {
- return fmt.Errorf("cannot link snap %q with unset revision", info.Name())
+ return fmt.Errorf("cannot link snap %q with unset revision", info.InstanceName())
}
if err := generateWrappers(info); err != nil {
@@ -74,7 +74,7 @@ func (b Backend) LinkSnap(info *snap.Info, model *asserts.Model) error {
if model.Base() != "" {
bootBase = model.Base()
}
- switch info.Name() {
+ switch info.InstanceName() {
case model.Kernel(), bootBase:
if err := boot.SetNextBoot(info); err != nil {
return err
@@ -116,17 +116,17 @@ func generateWrappers(s *snap.Info) error {
func removeGeneratedWrappers(s *snap.Info, meter progress.Meter) error {
err1 := wrappers.RemoveSnapBinaries(s)
if err1 != nil {
- logger.Noticef("Cannot remove binaries for %q: %v", s.Name(), err1)
+ logger.Noticef("Cannot remove binaries for %q: %v", s.InstanceName(), err1)
}
err2 := wrappers.RemoveSnapServices(s, meter)
if err2 != nil {
- logger.Noticef("Cannot remove services for %q: %v", s.Name(), err2)
+ logger.Noticef("Cannot remove services for %q: %v", s.InstanceName(), err2)
}
err3 := wrappers.RemoveSnapDesktopFiles(s)
if err3 != nil {
- logger.Noticef("Cannot remove desktop files for %q: %v", s.Name(), err3)
+ logger.Noticef("Cannot remove desktop files for %q: %v", s.InstanceName(), err3)
}
return firstErr(err1, err2, err3)
diff --git a/overlord/snapstate/backend/mountunit.go b/overlord/snapstate/backend/mountunit.go
index 41ca04dd99..af1b661b41 100644
--- a/overlord/snapstate/backend/mountunit.go
+++ b/overlord/snapstate/backend/mountunit.go
@@ -37,7 +37,7 @@ func addMountUnit(s *snap.Info, meter progress.Meter) error {
whereDir := dirs.StripRootDir(s.MountDir())
sysd := systemd.New(dirs.GlobalRootDir, meter)
- mountUnitName, err := sysd.WriteMountUnitFile(s.Name(), s.Revision.String(), squashfsPath, whereDir, "squashfs")
+ mountUnitName, err := sysd.WriteMountUnitFile(s.InstanceName(), s.Revision.String(), squashfsPath, whereDir, "squashfs")
if err != nil {
return err
}
diff --git a/overlord/snapstate/backend_test.go b/overlord/snapstate/backend_test.go
index 5f50cd6db6..56f49ed437 100644
--- a/overlord/snapstate/backend_test.go
+++ b/overlord/snapstate/backend_test.go
@@ -612,7 +612,7 @@ apps:
func (f *fakeSnappyBackend) ClearTrashedData(si *snap.Info) {
f.ops = append(f.ops, fakeOp{
op: "cleanup-trash",
- name: si.Name(),
+ name: si.InstanceName(),
revno: si.Revision,
})
}
diff --git a/overlord/snapstate/booted_test.go b/overlord/snapstate/booted_test.go
index d06d9b7ba1..3a02a64cb2 100644
--- a/overlord/snapstate/booted_test.go
+++ b/overlord/snapstate/booted_test.go
@@ -28,7 +28,6 @@ import (
. "gopkg.in/check.v1"
- "github.com/snapcore/snapd/asserts"
"github.com/snapcore/snapd/boot/boottest"
"github.com/snapcore/snapd/dirs"
"github.com/snapcore/snapd/overlord"
@@ -84,9 +83,7 @@ func (bs *bootedSuite) SetUpTest(c *C) {
snapstate.AutoAliases = func(*state.State, *snap.Info) (map[string]string, error) {
return nil, nil
}
- snapstate.Model = func(*state.State) (*asserts.Model, error) {
- return nil, nil
- }
+ snapstate.MockModel()
}
func (bs *bootedSuite) TearDownTest(c *C) {
diff --git a/overlord/snapstate/check_snap.go b/overlord/snapstate/check_snap.go
index d6583857ff..a041da5fc4 100644
--- a/overlord/snapstate/check_snap.go
+++ b/overlord/snapstate/check_snap.go
@@ -58,7 +58,7 @@ func checkAssumes(si *snap.Info) error {
if release.OnClassic {
hint = "try to update snapd and refresh the core snap"
}
- return fmt.Errorf("snap %q assumes unsupported features: %s (%s)", si.Name(), strings.Join(missing, ", "), hint)
+ return fmt.Errorf("snap %q assumes unsupported features: %s (%s)", si.InstanceName(), strings.Join(missing, ", "), hint)
}
return nil
}
@@ -137,11 +137,11 @@ func validateFlagsForInfo(info *snap.Info, snapst *SnapState, flags Flags) error
return nil
}
return &SnapNeedsDevModeError{
- Snap: info.Name(),
+ Snap: info.InstanceName(),
}
case snap.ClassicConfinement:
if !release.OnClassic {
- return &SnapNeedsClassicSystemError{Snap: info.Name()}
+ return &SnapNeedsClassicSystemError{Snap: info.InstanceName()}
}
if flags.Classic {
@@ -153,7 +153,7 @@ func validateFlagsForInfo(info *snap.Info, snapst *SnapState, flags Flags) error
}
return &SnapNeedsClassicError{
- Snap: info.Name(),
+ Snap: info.InstanceName(),
}
default:
return fmt.Errorf("unknown confinement %q", c)
@@ -170,7 +170,7 @@ func validateInfoAndFlags(info *snap.Info, snapst *SnapState, flags Flags) error
// verify we have a valid architecture
if !arch.IsSupportedArchitecture(info.Architectures) {
- return fmt.Errorf("snap %q supported architectures (%s) are incompatible with this system (%s)", info.Name(), strings.Join(info.Architectures, ", "), arch.UbuntuArchitecture())
+ return fmt.Errorf("snap %q supported architectures (%s) are incompatible with this system (%s)", info.InstanceName(), strings.Join(info.Architectures, ", "), arch.UbuntuArchitecture())
}
// check assumes
@@ -263,13 +263,14 @@ func checkCoreName(st *state.State, snapInfo, curInfo *snap.Info, flags Flags) e
// transition we will end up with not connected interface
// connections in the "core" snap. But the transition will
// kick in automatically quickly so an extra flag is overkill.
- if snapInfo.Name() == "core" && core.Name() == "ubuntu-core" {
+ // TODO parallel-install: use instance name
+ if snapInfo.InstanceName() == "core" && core.InstanceName() == "ubuntu-core" {
return nil
}
// but generally do not allow to have two cores installed
- if core.Name() != snapInfo.Name() {
- return fmt.Errorf("cannot install core snap %q when core snap %q is already present", snapInfo.Name(), core.Name())
+ if core.InstanceName() != snapInfo.InstanceName() {
+ return fmt.Errorf("cannot install core snap %q when core snap %q is already present", snapInfo.InstanceName(), core.InstanceName())
}
return nil
@@ -312,7 +313,7 @@ func checkGadgetOrKernel(st *state.State, snapInfo, curInfo *snap.Info, flags Fl
return fmt.Errorf("cannot replace signed %s snap with an unasserted one", kind)
}
- if currentSnap.Name() != snapInfo.Name() {
+ if currentSnap.InstanceName() != snapInfo.InstanceName() {
return fmt.Errorf("cannot replace %s snap with a different one", kind)
}
diff --git a/overlord/snapstate/check_snap_test.go b/overlord/snapstate/check_snap_test.go
index 2d189c0886..0c137a7a55 100644
--- a/overlord/snapstate/check_snap_test.go
+++ b/overlord/snapstate/check_snap_test.go
@@ -194,7 +194,7 @@ version: 1.0`
checkCbCalled := false
checkCb := func(st *state.State, s, cur *snap.Info, flags snapstate.Flags) error {
- c.Assert(s.Name(), Equals, "foo")
+ c.Assert(s.InstanceName(), Equals, "foo")
c.Assert(s.SnapID, Equals, "snap-id")
checkCbCalled = true
return nil
diff --git a/overlord/snapstate/export_test.go b/overlord/snapstate/export_test.go
index 6980cdff7d..6f3f8a821a 100644
--- a/overlord/snapstate/export_test.go
+++ b/overlord/snapstate/export_test.go
@@ -21,11 +21,13 @@ package snapstate
import (
"errors"
+ "fmt"
"sort"
"time"
"gopkg.in/tomb.v2"
+ "github.com/snapcore/snapd/asserts"
"github.com/snapcore/snapd/overlord/state"
"github.com/snapcore/snapd/snap"
)
@@ -193,3 +195,44 @@ func ByKindOrder(snaps ...*snap.Info) []*snap.Info {
sort.Sort(byKind(snaps))
return snaps
}
+
+func MockModelWithBase(baseName string) (restore func()) {
+ return mockModel(baseName)
+}
+
+func MockModel() (restore func()) {
+ return mockModel("")
+}
+
+func mockModel(baseName string) (restore func()) {
+ oldModel := Model
+
+ base := ""
+ if baseName != "" {
+ base = fmt.Sprintf("\nbase: %s", baseName)
+ }
+ mod := fmt.Sprintf(`type: model
+authority-id: brand
+series: 16
+brand-id: brand
+model: baz-3000
+architecture: armhf
+gadget: brand-gadget
+kernel: kernel%s
+timestamp: 2018-01-01T08:00:00+00:00
+sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
+
+AXNpZw==
+`, base)
+ a, err := asserts.Decode([]byte(mod))
+ if err != nil {
+ panic(err)
+ }
+
+ Model = func(*state.State) (*asserts.Model, error) {
+ return a.(*asserts.Model), nil
+ }
+ return func() {
+ Model = oldModel
+ }
+}
diff --git a/overlord/snapstate/handlers.go b/overlord/snapstate/handlers.go
index ae70ebae73..42971472ff 100644
--- a/overlord/snapstate/handlers.go
+++ b/overlord/snapstate/handlers.go
@@ -821,17 +821,39 @@ func (m *SnapManager) doLinkSnap(t *state.Task, _ *tomb.Tomb) error {
return nil
}
-// maybeRestart will schedule a reboot or restart as needed for the just linked
-// snap with info if it's a core or kernel snap.
+// maybeRestart will schedule a reboot or restart as needed for the
+// just linked snap with info if it's a core or snapd or kernel snap.
func maybeRestart(t *state.Task, info *snap.Info) {
st := t.State()
- if release.OnClassic && info.Type == snap.TypeOS {
- t.Logf("Requested daemon restart.")
- st.RequestRestart(state.RestartDaemon)
+
+ // TODO: once classic uses the snapd snap we need to restart
+ // here too
+ if release.OnClassic {
+ if info.Type == snap.TypeOS {
+ t.Logf("Requested daemon restart.")
+ st.RequestRestart(state.RestartDaemon)
+ }
+ return
}
- if !release.OnClassic && boot.KernelOsBaseRebootRequired(info) {
+
+ // On a core system we may need a full reboot if
+ // core/base or the kernel changes.
+ if boot.ChangeRequiresReboot(info) {
t.Logf("Requested system restart.")
st.RequestRestart(state.RestartSystem)
+ return
+ }
+
+ // On core systems that use a base snap we need to restart
+ // snapd when the snapd snap changes.
+ model, err := Model(st)
+ if err != nil {
+ logger.Noticef("cannot get model assertion: %v", model)
+ return
+ }
+ if model.Base() != "" && info.InstanceName() == "snapd" {
+ t.Logf("Requested daemon restart (snapd snap).")
+ st.RequestRestart(state.RestartDaemon)
}
}
diff --git a/overlord/snapstate/handlers_aliasesv2_test.go b/overlord/snapstate/handlers_aliasesv2_test.go
index 4c640b5ada..c131649a01 100644
--- a/overlord/snapstate/handlers_aliasesv2_test.go
+++ b/overlord/snapstate/handlers_aliasesv2_test.go
@@ -34,7 +34,7 @@ func (s *snapmgrTestSuite) TestDoSetAutoAliases(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -89,7 +89,7 @@ func (s *snapmgrTestSuite) TestDoSetAutoAliasesFirstInstall(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -139,7 +139,7 @@ func (s *snapmgrTestSuite) TestDoUndoSetAutoAliases(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -200,7 +200,7 @@ func (s *snapmgrTestSuite) TestDoSetAutoAliasesConflict(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -256,7 +256,7 @@ func (s *snapmgrTestSuite) TestDoUndoSetAutoAliasesConflict(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -353,7 +353,7 @@ func (s *snapmgrTestSuite) TestDoSetAutoAliasesFirstInstallUnaliased(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -404,7 +404,7 @@ func (s *snapmgrTestSuite) TestDoUndoSetAutoAliasesFirstInstallUnaliased(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -938,7 +938,7 @@ func (s *snapmgrTestSuite) TestDoRefreshAliases(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -1011,7 +1011,7 @@ func (s *snapmgrTestSuite) TestDoUndoRefreshAliases(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -1101,7 +1101,7 @@ func (s *snapmgrTestSuite) TestDoUndoRefreshAliasesFromEmpty(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -1176,7 +1176,7 @@ func (s *snapmgrTestSuite) TestDoRefreshAliasesPending(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -1235,7 +1235,7 @@ func (s *snapmgrTestSuite) TestDoUndoRefreshAliasesPending(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -1300,7 +1300,7 @@ func (s *snapmgrTestSuite) TestDoRefreshAliasesConflict(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
@@ -1354,7 +1354,7 @@ func (s *snapmgrTestSuite) TestDoUndoRefreshAliasesConflict(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- c.Check(info.Name(), Equals, "alias-snap")
+ c.Check(info.InstanceName(), Equals, "alias-snap")
return map[string]string{
"alias1": "cmd1",
"alias2": "cmd2",
diff --git a/overlord/snapstate/handlers_link_test.go b/overlord/snapstate/handlers_link_test.go
index 70a165d259..d4ad443131 100644
--- a/overlord/snapstate/handlers_link_test.go
+++ b/overlord/snapstate/handlers_link_test.go
@@ -82,6 +82,8 @@ func (s *linkSnapSuite) SetUpTest(c *C) {
resetReadInfo()
dirs.SetRootDir("/")
}
+
+ snapstate.MockModel()
}
func (s *linkSnapSuite) TearDownTest(c *C) {
@@ -359,6 +361,118 @@ func (s *linkSnapSuite) TestDoLinkSnapSuccessCoreRestarts(c *C) {
c.Check(t.Log()[0], Matches, `.*INFO Requested daemon restart\.`)
}
+func (s *linkSnapSuite) TestDoLinkSnapSuccessSnapdRestartsOnCoreWithBase(c *C) {
+ restore := release.MockOnClassic(false)
+ defer restore()
+
+ restore = snapstate.MockModelWithBase("core18")
+ defer restore()
+
+ s.state.Lock()
+ si := &snap.SideInfo{
+ RealName: "snapd",
+ Revision: snap.R(22),
+ }
+ t := s.state.NewTask("link-snap", "test")
+ t.Set("snap-setup", &snapstate.SnapSetup{
+ SideInfo: si,
+ })
+ s.state.NewChange("dummy", "...").AddTask(t)
+
+ s.state.Unlock()
+
+ s.snapmgr.Ensure()
+ s.snapmgr.Wait()
+
+ s.state.Lock()
+ defer s.state.Unlock()
+
+ var snapst snapstate.SnapState
+ err := snapstate.Get(s.state, "snapd", &snapst)
+ c.Assert(err, IsNil)
+
+ typ, err := snapst.Type()
+ c.Check(err, IsNil)
+ c.Check(typ, Equals, snap.TypeApp)
+
+ c.Check(t.Status(), Equals, state.DoneStatus)
+ c.Check(s.stateBackend.restartRequested, DeepEquals, []state.RestartType{state.RestartDaemon})
+ c.Check(t.Log(), HasLen, 1)
+ c.Check(t.Log()[0], Matches, `.*INFO Requested daemon restart \(snapd snap\)\.`)
+}
+
+func (s *linkSnapSuite) TestDoLinkSnapSuccessSnapdNoRestartWithoutBase(c *C) {
+ restore := release.MockOnClassic(false)
+ defer restore()
+
+ s.state.Lock()
+ si := &snap.SideInfo{
+ RealName: "snapd",
+ Revision: snap.R(22),
+ }
+ t := s.state.NewTask("link-snap", "test")
+ t.Set("snap-setup", &snapstate.SnapSetup{
+ SideInfo: si,
+ })
+ s.state.NewChange("dummy", "...").AddTask(t)
+
+ s.state.Unlock()
+
+ s.snapmgr.Ensure()
+ s.snapmgr.Wait()
+
+ s.state.Lock()
+ defer s.state.Unlock()
+
+ var snapst snapstate.SnapState
+ err := snapstate.Get(s.state, "snapd", &snapst)
+ c.Assert(err, IsNil)
+
+ typ, err := snapst.Type()
+ c.Check(err, IsNil)
+ c.Check(typ, Equals, snap.TypeApp)
+
+ c.Check(t.Status(), Equals, state.DoneStatus)
+ c.Check(s.stateBackend.restartRequested, IsNil)
+ c.Check(t.Log(), HasLen, 0)
+}
+
+func (s *linkSnapSuite) TestDoLinkSnapSuccessSnapdNoRestartOnClassic(c *C) {
+ restore := release.MockOnClassic(true)
+ defer restore()
+
+ s.state.Lock()
+ si := &snap.SideInfo{
+ RealName: "snapd",
+ Revision: snap.R(22),
+ }
+ t := s.state.NewTask("link-snap", "test")
+ t.Set("snap-setup", &snapstate.SnapSetup{
+ SideInfo: si,
+ })
+ s.state.NewChange("dummy", "...").AddTask(t)
+
+ s.state.Unlock()
+
+ s.snapmgr.Ensure()
+ s.snapmgr.Wait()
+
+ s.state.Lock()
+ defer s.state.Unlock()
+
+ var snapst snapstate.SnapState
+ err := snapstate.Get(s.state, "snapd", &snapst)
+ c.Assert(err, IsNil)
+
+ typ, err := snapst.Type()
+ c.Check(err, IsNil)
+ c.Check(typ, Equals, snap.TypeApp)
+
+ c.Check(t.Status(), Equals, state.DoneStatus)
+ c.Check(s.stateBackend.restartRequested, IsNil)
+ c.Check(t.Log(), HasLen, 0)
+}
+
func (s *linkSnapSuite) TestDoUndoLinkSnapSequenceDidNotHaveCandidate(c *C) {
s.state.Lock()
defer s.state.Unlock()
diff --git a/overlord/snapstate/snapstate.go b/overlord/snapstate/snapstate.go
index e978814b2f..e3ec6936ce 100644
--- a/overlord/snapstate/snapstate.go
+++ b/overlord/snapstate/snapstate.go
@@ -78,6 +78,9 @@ func doInstall(st *state.State, snapst *SnapState, snapsup *SnapSetup, flags int
}
}
+ // TODO parallel-install: block parallel installation of core, kernel,
+ // gadget and snapd snaps
+
if err := CheckChangeConflict(st, snapsup.Name(), nil, snapst); err != nil {
return nil, err
}
@@ -757,14 +760,14 @@ func doUpdate(st *state.State, names []string, updates []*snap.Info, params func
if err := validateInfoAndFlags(update, snapst, flags); err != nil {
if refreshAll {
- logger.Noticef("cannot update %q: %v", update.Name(), err)
+ logger.Noticef("cannot update %q: %v", update.InstanceName(), err)
continue
}
return nil, nil, err
}
if err := validateFeatureFlags(st, update); err != nil {
if refreshAll {
- logger.Noticef("cannot update %q: %v", update.Name(), err)
+ logger.Noticef("cannot update %q: %v", update.InstanceName(), err)
continue
}
return nil, nil, err
@@ -790,7 +793,7 @@ func doUpdate(st *state.State, names []string, updates []*snap.Info, params func
if err != nil {
if refreshAll {
// doing "refresh all", just skip this snap
- logger.Noticef("cannot refresh snap %q: %v", update.Name(), err)
+ logger.Noticef("cannot refresh snap %q: %v", update.InstanceName(), err)
continue
}
return nil, nil, err
@@ -804,7 +807,7 @@ func doUpdate(st *state.State, names []string, updates []*snap.Info, params func
// prereq types come first in updates, we
// also assume bases don't have hooks, otherwise
// they would need to wait on core
- prereqs[update.Name()] = ts
+ prereqs[update.InstanceName()] = ts
} else {
// prereqs were processed already, wait for
// them as necessary for the other kind of
@@ -815,7 +818,7 @@ func doUpdate(st *state.State, names []string, updates []*snap.Info, params func
}
}
- scheduleUpdate(update.Name(), ts)
+ scheduleUpdate(update.InstanceName(), ts)
tasksets = append(tasksets, ts)
}
@@ -934,7 +937,7 @@ func autoAliasesUpdate(st *state.State, names []string, updates []*snap.Info) (c
// snaps with updates
updating := make(map[string]bool, len(updates))
for _, info := range updates {
- updating[info.Name()] = true
+ updating[info.InstanceName()] = true
}
// add explicitly auto-aliases only for snaps that are not updated
@@ -1293,7 +1296,7 @@ func canRemove(si *snap.Info, snapst *SnapState, removeAll bool) bool {
//
// Once the ubuntu-core -> core transition has landed for some
// time we can remove the two lines below.
- if si.Name() == "ubuntu-core" && si.Type == snap.TypeOS {
+ if si.InstanceName() == "ubuntu-core" && si.Type == snap.TypeOS {
return true
}
@@ -1306,7 +1309,7 @@ func canRemove(si *snap.Info, snapst *SnapState, removeAll bool) bool {
// TODO: on classic likely let remove core even if active if it's only snap left.
// never remove anything that is used for booting
- if boot.InUse(si.Name(), si.Revision) {
+ if boot.InUse(si.InstanceName(), si.Revision) {
return false
}
@@ -1820,13 +1823,13 @@ func CoreInfo(st *state.State) (*snap.Info, error) {
// some systems have two cores: ubuntu-core/core
// we always return "core" in this case
if len(res) == 2 {
- if res[0].Name() == defaultCoreSnapName && res[1].Name() == "ubuntu-core" {
+ if res[0].InstanceName() == defaultCoreSnapName && res[1].InstanceName() == "ubuntu-core" {
return res[0], nil
}
- if res[0].Name() == "ubuntu-core" && res[1].Name() == defaultCoreSnapName {
+ if res[0].InstanceName() == "ubuntu-core" && res[1].InstanceName() == defaultCoreSnapName {
return res[1], nil
}
- return nil, fmt.Errorf("unexpected cores %q and %q", res[0].Name(), res[1].Name())
+ return nil, fmt.Errorf("unexpected cores %q and %q", res[0].InstanceName(), res[1].InstanceName())
}
return nil, fmt.Errorf("unexpected number of cores, got %d", len(res))
@@ -1850,7 +1853,7 @@ func ConfigDefaults(st *state.State, snapName string) (map[string]interface{}, e
if err != nil {
return nil, err
}
- isCoreDefaults := core.Name() == snapName
+ isCoreDefaults := core.InstanceName() == snapName
si := snapst.CurrentSideInfo()
// core snaps can be addressed even without a snap-id via the special
diff --git a/overlord/snapstate/snapstate_test.go b/overlord/snapstate/snapstate_test.go
index 74c158f103..bd42dcb7cc 100644
--- a/overlord/snapstate/snapstate_test.go
+++ b/overlord/snapstate/snapstate_test.go
@@ -3821,7 +3821,7 @@ func (s *snapmgrTestSuite) TestUpdateManyAutoAliasesScenarios(c *C) {
})
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- switch info.Name() {
+ switch info.InstanceName() {
case "some-snap":
return map[string]string{"aliasA": "cmdA"}, nil
case "other-snap":
@@ -3964,7 +3964,7 @@ func (s *snapmgrTestSuite) TestUpdateOneAutoAliasesScenarios(c *C) {
})
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- switch info.Name() {
+ switch info.InstanceName() {
case "some-snap":
return map[string]string{"aliasA": "cmdA"}, nil
case "other-snap":
@@ -6715,7 +6715,7 @@ func (s *snapmgrQuerySuite) TestInfo(c *C) {
info, err := snapstate.Info(st, "name1", snap.R(11))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "name1")
+ c.Check(info.InstanceName(), Equals, "name1")
c.Check(info.Revision, Equals, snap.R(11))
c.Check(info.Summary(), Equals, "s11")
c.Check(info.Version, Equals, "1.1")
@@ -6734,7 +6734,7 @@ func (s *snapmgrQuerySuite) TestSnapStateCurrentInfo(c *C) {
info, err := snapst.CurrentInfo()
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "name1")
+ c.Check(info.InstanceName(), Equals, "name1")
c.Check(info.Revision, Equals, snap.R(12))
c.Check(info.Summary(), Equals, "s12")
c.Check(info.Version, Equals, "1.2")
@@ -6756,7 +6756,7 @@ func (s *snapmgrQuerySuite) TestCurrentInfo(c *C) {
info, err := snapstate.CurrentInfo(st, "name1")
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "name1")
+ c.Check(info.InstanceName(), Equals, "name1")
c.Check(info.Revision, Equals, snap.R(12))
}
@@ -6779,7 +6779,7 @@ func (s *snapmgrQuerySuite) TestActiveInfos(c *C) {
c.Check(infos, HasLen, 1)
- c.Check(infos[0].Name(), Equals, "name1")
+ c.Check(infos[0].InstanceName(), Equals, "name1")
c.Check(infos[0].Revision, Equals, snap.R(12))
c.Check(infos[0].Summary(), Equals, "s12")
c.Check(infos[0].Version, Equals, "1.2")
@@ -6830,7 +6830,7 @@ func (s *snapmgrQuerySuite) TestTypeInfo(c *C) {
info, err := x.getInfo(st)
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, x.snapName)
+ c.Check(info.InstanceName(), Equals, x.snapName)
c.Check(info.Revision, Equals, snap.R(2))
c.Check(info.Version, Equals, x.snapName)
c.Check(info.Type, Equals, x.snapType)
@@ -6890,7 +6890,7 @@ func (s *snapmgrQuerySuite) TestTypeInfoCore(c *C) {
c.Assert(err, ErrorMatches, t.errMatcher)
} else {
c.Assert(info, NotNil)
- c.Check(info.Name(), Equals, t.expectedSnap, Commentf("(%d) test %q %v", testNr, t.expectedSnap, t.snapNames))
+ c.Check(info.InstanceName(), Equals, t.expectedSnap, Commentf("(%d) test %q %v", testNr, t.expectedSnap, t.snapNames))
c.Check(info.Type, Equals, snap.TypeOS)
}
}
@@ -6941,7 +6941,7 @@ func (s *snapmgrQuerySuite) TestAll(c *C) {
info12, err := snap.ReadInfo("name1", snapst.CurrentSideInfo())
c.Assert(err, IsNil)
- c.Check(info12.Name(), Equals, "name1")
+ c.Check(info12.InstanceName(), Equals, "name1")
c.Check(info12.Revision, Equals, snap.R(12))
c.Check(info12.Summary(), Equals, "s12")
c.Check(info12.Version, Equals, "1.2")
@@ -6950,7 +6950,7 @@ func (s *snapmgrQuerySuite) TestAll(c *C) {
info11, err := snap.ReadInfo("name1", snapst.Sequence[0])
c.Assert(err, IsNil)
- c.Check(info11.Name(), Equals, "name1")
+ c.Check(info11.InstanceName(), Equals, "name1")
c.Check(info11.Revision, Equals, snap.R(11))
c.Check(info11.Version, Equals, "1.1")
}
@@ -8587,7 +8587,7 @@ func (s *snapmgrTestSuite) TestEnsureAliasesV2(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- switch info.Name() {
+ switch info.InstanceName() {
case "alias-snap":
return map[string]string{
"alias1": "cmd1",
@@ -8655,7 +8655,7 @@ func (s *snapmgrTestSuite) TestEnsureAliasesV2SnapDisabled(c *C) {
defer s.state.Unlock()
snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) {
- switch info.Name() {
+ switch info.InstanceName() {
case "alias-snap":
return map[string]string{
"alias1": "cmd1",
@@ -9253,7 +9253,7 @@ func (s contentStore) SnapAction(ctx context.Context, currentSnaps []*store.Curr
panic("expected to be queried for install of only one snap at a time")
}
info := snaps[0]
- switch info.Name() {
+ switch info.InstanceName() {
case "snap-content-plug":
info.Plugs = map[string]*snap.PlugInfo{
"some-plug": {
diff --git a/overlord/snapstate/storehelpers.go b/overlord/snapstate/storehelpers.go
index 772148e5d9..5aa69c7485 100644
--- a/overlord/snapstate/storehelpers.go
+++ b/overlord/snapstate/storehelpers.go
@@ -89,7 +89,8 @@ func installInfo(st *state.State, name, channel string, revision snap.Revision,
action := &store.SnapAction{
Action: "install",
- Name: name,
+ // TODO parallel-install: verify use of correct name
+ Name: name,
// the desired channel
Channel: channel,
// the desired revision
@@ -153,7 +154,8 @@ func updateInfo(st *state.State, snapst *SnapState, opts *updateInfoOpts, userID
if curInfo.SnapID == "" { // amend
action.Action = "install"
- action.Name = curInfo.Name()
+ // TODO parallel-install: verify use of correct name
+ action.Name = curInfo.InstanceName()
}
theStore := Store(st)
@@ -161,7 +163,7 @@ func updateInfo(st *state.State, snapst *SnapState, opts *updateInfoOpts, userID
res, err := theStore.SnapAction(context.TODO(), curSnaps, []*store.SnapAction{action}, user, nil)
st.Lock()
- return singleActionResult(curInfo.Name(), action.Action, res, err)
+ return singleActionResult(curInfo.InstanceName(), action.Action, res, err)
}
func preUpdateInfo(st *state.State, snapst *SnapState, amend bool, userID int) (*snap.Info, *auth.UserState, error) {
@@ -248,7 +250,7 @@ func updateToRevisionInfo(st *state.State, snapst *SnapState, revision snap.Revi
res, err := theStore.SnapAction(context.TODO(), curSnaps, []*store.SnapAction{action}, user, nil)
st.Lock()
- return singleActionResult(curInfo.Name(), action.Action, res, err)
+ return singleActionResult(curInfo.InstanceName(), action.Action, res, err)
}
func currentSnaps(st *state.State) ([]*store.CurrentSnap, error) {
diff --git a/snap/broken.go b/snap/broken.go
index 21c8ef73ba..d9434e8565 100644
--- a/snap/broken.go
+++ b/snap/broken.go
@@ -74,7 +74,7 @@ func GuessAppsForBroken(info *Info) map[string]*AppInfo {
// was not validated before. To avoid a flag day and any potential issues,
// transparently rename the two clashing plugs by appending the "-plug" suffix.
func (info *Info) renameClashingCorePlugs() {
- if info.Name() == "core" && info.Type == TypeOS {
+ if info.InstanceName() == "core" && info.Type == TypeOS {
for _, plugName := range []string{"network-bind", "core-support"} {
info.renamePlug(plugName, plugName+"-plug")
}
diff --git a/snap/container.go b/snap/container.go
index a518d5b899..f6c019b783 100644
--- a/snap/container.go
+++ b/snap/container.go
@@ -201,7 +201,8 @@ func ValidateContainer(c Container, s *Info, logf func(format string, v ...inter
if needsrx[path] || mode.IsDir() {
if mode.Perm()&0555 != 0555 {
- logf("in snap %q: %q should be world-readable and executable, and isn't: %s", s.Name(), path, mode)
+ // TODO parallel-install: use of proper instance/store name
+ logf("in snap %q: %q should be world-readable and executable, and isn't: %s", s.InstanceName(), path, mode)
hasBadModes = true
}
} else {
@@ -213,19 +214,22 @@ func ValidateContainer(c Container, s *Info, logf func(format string, v ...inter
// more than anything else, not worth it IMHO (as I can't
// imagine this happening by accident).
if mode&(os.ModeDir|os.ModeNamedPipe|os.ModeSocket|os.ModeDevice) != 0 {
- logf("in snap %q: %q should be a regular file (or a symlink) and isn't", s.Name(), path)
+ // TODO parallel-install: use of proper instance/store name
+ logf("in snap %q: %q should be a regular file (or a symlink) and isn't", s.InstanceName(), path)
hasBadModes = true
}
}
if needsx[path] || strings.HasPrefix(path, "meta/hooks/") {
if mode.Perm()&0111 == 0 {
- logf("in snap %q: %q should be executable, and isn't: %s", s.Name(), path, mode)
+ // TODO parallel-install: use of proper instance/store name
+ logf("in snap %q: %q should be executable, and isn't: %s", s.InstanceName(), path, mode)
hasBadModes = true
}
} else {
// in needsr, or under meta but not a hook
if mode.Perm()&0444 != 0444 {
- logf("in snap %q: %q should be world-readable, and isn't: %s", s.Name(), path, mode)
+ // TODO parallel-install: use of proper instance/store name
+ logf("in snap %q: %q should be world-readable, and isn't: %s", s.InstanceName(), path, mode)
hasBadModes = true
}
}
@@ -239,7 +243,8 @@ func ValidateContainer(c Container, s *Info, logf func(format string, v ...inter
for _, needs := range []map[string]bool{needsx, needsrx, needsr} {
for path := range needs {
if !seen[path] {
- logf("in snap %q: path %q does not exist", s.Name(), path)
+ // TODO parallel-install: use of proper instance/store name
+ logf("in snap %q: path %q does not exist", s.InstanceName(), path)
}
}
}
diff --git a/snap/info.go b/snap/info.go
index 8f52ca4d45..344f4012d1 100644
--- a/snap/info.go
+++ b/snap/info.go
@@ -38,8 +38,8 @@ import (
// PlaceInfo offers all the information about where a snap and its data are located and exposed in the filesystem.
type PlaceInfo interface {
- // Name returns the name of the snap.
- Name() string
+ // InstanceName returns the name of the snap.
+ InstanceName() string
// MountDir returns the base directory of the snap.
MountDir() string
@@ -253,8 +253,15 @@ type ChannelSnapInfo struct {
Size int64 `json:"size"`
}
-// Name returns the blessed name for the snap.
-func (s *Info) Name() string {
+// InstanceName returns the blessed name of the snap decorated with instance
+// key, if any.
+func (s *Info) InstanceName() string {
+ // TODO parallel-install: include instance key
+ return s.StoreName()
+}
+
+// StoreName returns the global blessed name of the snap.
+func (s *Info) StoreName() string {
if s.RealName != "" {
return s.RealName
}
@@ -287,12 +294,12 @@ func (s *Info) Description() string {
// MountDir returns the base directory of the snap where it gets mounted.
func (s *Info) MountDir() string {
- return MountDir(s.Name(), s.Revision)
+ return MountDir(s.InstanceName(), s.Revision)
}
// MountFile returns the path where the snap file that is mounted is installed.
func (s *Info) MountFile() string {
- return MountFile(s.Name(), s.Revision)
+ return MountFile(s.InstanceName(), s.Revision)
}
// HooksDir returns the directory containing the snap's hooks.
@@ -302,42 +309,42 @@ func (s *Info) HooksDir() string {
// DataDir returns the data directory of the snap.
func (s *Info) DataDir() string {
- return filepath.Join(dirs.SnapDataDir, s.Name(), s.Revision.String())
+ return filepath.Join(dirs.SnapDataDir, s.InstanceName(), s.Revision.String())
}
// UserDataDir returns the user-specific data directory of the snap.
func (s *Info) UserDataDir(home string) string {
- return filepath.Join(home, dirs.UserHomeSnapDir, s.Name(), s.Revision.String())
+ return filepath.Join(home, dirs.UserHomeSnapDir, s.InstanceName(), s.Revision.String())
}
// UserCommonDataDir returns the user-specific data directory common across revision of the snap.
func (s *Info) UserCommonDataDir(home string) string {
- return filepath.Join(home, dirs.UserHomeSnapDir, s.Name(), "common")
+ return filepath.Join(home, dirs.UserHomeSnapDir, s.InstanceName(), "common")
}
// CommonDataDir returns the data directory common across revisions of the snap.
func (s *Info) CommonDataDir() string {
- return filepath.Join(dirs.SnapDataDir, s.Name(), "common")
+ return filepath.Join(dirs.SnapDataDir, s.InstanceName(), "common")
}
// DataHomeDir returns the per user data directory of the snap.
func (s *Info) DataHomeDir() string {
- return filepath.Join(dirs.SnapDataHomeGlob, s.Name(), s.Revision.String())
+ return filepath.Join(dirs.SnapDataHomeGlob, s.InstanceName(), s.Revision.String())
}
// CommonDataHomeDir returns the per user data directory common across revisions of the snap.
func (s *Info) CommonDataHomeDir() string {
- return filepath.Join(dirs.SnapDataHomeGlob, s.Name(), "common")
+ return filepath.Join(dirs.SnapDataHomeGlob, s.InstanceName(), "common")
}
// UserXdgRuntimeDir returns the XDG_RUNTIME_DIR directory of the snap for a particular user.
func (s *Info) UserXdgRuntimeDir(euid sys.UserID) string {
- return filepath.Join("/run/user", fmt.Sprintf("%d/snap.%s", euid, s.Name()))
+ return filepath.Join("/run/user", fmt.Sprintf("%d/snap.%s", euid, s.InstanceName()))
}
// XdgRuntimeDirs returns the XDG_RUNTIME_DIR directories for all users of the snap.
func (s *Info) XdgRuntimeDirs() string {
- return filepath.Join(dirs.XdgRuntimeDirGlob, fmt.Sprintf("snap.%s", s.Name()))
+ return filepath.Join(dirs.XdgRuntimeDirGlob, fmt.Sprintf("snap.%s", s.InstanceName()))
}
// NeedsDevMode returns whether the snap needs devmode.
@@ -372,7 +379,8 @@ func (s *Info) ExpandSnapVariables(path string) string {
// inside the mount namespace snap-confine creates and there we will
// always have a /snap directory available regardless if the system
// we're running on supports this or not.
- return filepath.Join(dirs.CoreSnapMountDir, s.Name(), s.Revision.String())
+ // TODO parallel-install: use of proper instance/store name
+ return filepath.Join(dirs.CoreSnapMountDir, s.InstanceName(), s.Revision.String())
case "SNAP_DATA":
return s.DataDir()
case "SNAP_COMMON":
@@ -406,7 +414,7 @@ func BadInterfacesSummary(snapInfo *Info) string {
inverted[reason] = append(inverted[reason], name)
}
var buf bytes.Buffer
- fmt.Fprintf(&buf, "snap %q has bad plugs or slots: ", snapInfo.Name())
+ fmt.Fprintf(&buf, "snap %q has bad plugs or slots: ", snapInfo.InstanceName())
reasons := make([]string, 0, len(inverted))
for reason := range inverted {
reasons = append(reasons, reason)
@@ -511,7 +519,7 @@ func getAttribute(snapName string, ifaceName string, attrs map[string]interface{
}
func (plug *PlugInfo) Attr(key string, val interface{}) error {
- return getAttribute(plug.Snap.Name(), plug.Interface, plug.Attrs, key, val)
+ return getAttribute(plug.Snap.InstanceName(), plug.Interface, plug.Attrs, key, val)
}
func (plug *PlugInfo) Lookup(key string) (interface{}, bool) {
@@ -533,11 +541,11 @@ func (plug *PlugInfo) SecurityTags() []string {
// String returns the representation of the plug as snap:plug string.
func (plug *PlugInfo) String() string {
- return fmt.Sprintf("%s:%s", plug.Snap.Name(), plug.Name)
+ return fmt.Sprintf("%s:%s", plug.Snap.InstanceName(), plug.Name)
}
func (slot *SlotInfo) Attr(key string, val interface{}) error {
- return getAttribute(slot.Snap.Name(), slot.Interface, slot.Attrs, key, val)
+ return getAttribute(slot.Snap.InstanceName(), slot.Interface, slot.Attrs, key, val)
}
func (slot *SlotInfo) Lookup(key string) (interface{}, bool) {
@@ -559,7 +567,7 @@ func (slot *SlotInfo) SecurityTags() []string {
// String returns the representation of the slot as snap:slot string.
func (slot *SlotInfo) String() string {
- return fmt.Sprintf("%s:%s", slot.Snap.Name(), slot.Name)
+ return fmt.Sprintf("%s:%s", slot.Snap.InstanceName(), slot.Name)
}
// SlotInfo provides information about a slot.
@@ -685,7 +693,7 @@ func (timer *TimerInfo) File() string {
}
func (app *AppInfo) String() string {
- return JoinSnapApp(app.Snap.Name(), app.Name)
+ return JoinSnapApp(app.Snap.InstanceName(), app.Name)
}
// SecurityTag returns application-specific security tag.
@@ -693,32 +701,33 @@ func (app *AppInfo) String() string {
// Security tags are used by various security subsystems as "profile names" and
// sometimes also as a part of the file name.
func (app *AppInfo) SecurityTag() string {
- return AppSecurityTag(app.Snap.Name(), app.Name)
+ return AppSecurityTag(app.Snap.InstanceName(), app.Name)
}
// DesktopFile returns the path to the installed optional desktop file for the application.
func (app *AppInfo) DesktopFile() string {
- return filepath.Join(dirs.SnapDesktopFilesDir, fmt.Sprintf("%s_%s.desktop", app.Snap.Name(), app.Name))
+ return filepath.Join(dirs.SnapDesktopFilesDir, fmt.Sprintf("%s_%s.desktop", app.Snap.InstanceName(), app.Name))
}
// WrapperPath returns the path to wrapper invoking the app binary.
func (app *AppInfo) WrapperPath() string {
- return filepath.Join(dirs.SnapBinariesDir, JoinSnapApp(app.Snap.Name(), app.Name))
+ return filepath.Join(dirs.SnapBinariesDir, JoinSnapApp(app.Snap.InstanceName(), app.Name))
}
// CompleterPath returns the path to the completer snippet for the app binary.
func (app *AppInfo) CompleterPath() string {
- return filepath.Join(dirs.CompletersDir, JoinSnapApp(app.Snap.Name(), app.Name))
+ return filepath.Join(dirs.CompletersDir, JoinSnapApp(app.Snap.InstanceName(), app.Name))
}
func (app *AppInfo) launcherCommand(command string) string {
if command != "" {
command = " " + command
}
- if app.Name == app.Snap.Name() {
+ // TODO parallel-install: use of proper instance/store name
+ if app.Name == app.Snap.InstanceName() {
return fmt.Sprintf("/usr/bin/snap run%s %s", command, app.Name)
}
- return fmt.Sprintf("/usr/bin/snap run%s %s.%s", command, app.Snap.Name(), app.Name)
+ return fmt.Sprintf("/usr/bin/snap run%s %s.%s", command, app.Snap.InstanceName(), app.Name)
}
// LauncherCommand returns the launcher command line to use when invoking the app binary.
@@ -774,7 +783,7 @@ func (app *AppInfo) IsService() bool {
// Security tags are used by various security subsystems as "profile names" and
// sometimes also as a part of the file name.
func (hook *HookInfo) SecurityTag() string {
- return HookSecurityTag(hook.Snap.Name(), hook.Name)
+ return HookSecurityTag(hook.Snap.InstanceName(), hook.Name)
}
// Env returns the hook-specific environment overrides
diff --git a/snap/info_snap_yaml_test.go b/snap/info_snap_yaml_test.go
index 138ccd9d08..5e4598e816 100644
--- a/snap/info_snap_yaml_test.go
+++ b/snap/info_snap_yaml_test.go
@@ -59,7 +59,7 @@ func (s *InfoSnapYamlTestSuite) TearDownTest(c *C) {
func (s *InfoSnapYamlTestSuite) TestSimple(c *C) {
info, err := snap.InfoFromSnapYaml(mockYaml)
c.Assert(err, IsNil)
- c.Assert(info.Name(), Equals, "foo")
+ c.Assert(info.InstanceName(), Equals, "foo")
c.Assert(info.Version, Equals, "1.0")
c.Assert(info.Type, Equals, snap.TypeApp)
}
@@ -111,7 +111,7 @@ plugs:
network-client:
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Assert(info.Plugs["network-client"], DeepEquals, &snap.PlugInfo{
@@ -129,7 +129,7 @@ plugs:
net: network-client
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Assert(info.Plugs["net"], DeepEquals, &snap.PlugInfo{
@@ -148,7 +148,7 @@ plugs:
interface: network-client
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Assert(info.Plugs["net"], DeepEquals, &snap.PlugInfo{
@@ -168,7 +168,7 @@ plugs:
ipv6-aware: true
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Assert(info.Plugs["net"], DeepEquals, &snap.PlugInfo{
@@ -193,7 +193,7 @@ plugs:
b: B
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Assert(info.Plugs["iface"], DeepEquals, &snap.PlugInfo{
@@ -221,7 +221,7 @@ plugs:
attr: 2
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Assert(info.Plugs["net"], DeepEquals, &snap.PlugInfo{
@@ -242,7 +242,7 @@ apps:
app:
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Check(info.Apps, HasLen, 1)
@@ -274,7 +274,7 @@ apps:
without-plug:
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Check(info.Apps, HasLen, 2)
@@ -311,7 +311,7 @@ apps:
plugs: ["net"]
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Check(info.Apps, HasLen, 1)
@@ -339,7 +339,7 @@ apps:
plugs: ["network-client"]
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Check(info.Apps, HasLen, 1)
@@ -367,7 +367,7 @@ plugs:
ipv6-aware: true
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Check(info.Apps, HasLen, 0)
@@ -388,7 +388,7 @@ plugs:
label: Disk I/O indicator
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Check(info.Apps, HasLen, 0)
@@ -492,7 +492,7 @@ slots:
network-client:
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 1)
c.Assert(info.Slots["network-client"], DeepEquals, &snap.SlotInfo{
@@ -510,7 +510,7 @@ slots:
net: network-client
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 1)
c.Assert(info.Slots["net"], DeepEquals, &snap.SlotInfo{
@@ -529,7 +529,7 @@ slots:
interface: network-client
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 1)
c.Assert(info.Slots["net"], DeepEquals, &snap.SlotInfo{
@@ -549,7 +549,7 @@ slots:
ipv6-aware: true
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 1)
c.Assert(info.Slots["net"], DeepEquals, &snap.SlotInfo{
@@ -573,7 +573,7 @@ slots:
a: "A"
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 1)
c.Assert(info.Slots["iface"], DeepEquals, &snap.SlotInfo{
@@ -601,7 +601,7 @@ slots:
attr: 2
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 1)
c.Assert(info.Slots["net"], DeepEquals, &snap.SlotInfo{
@@ -622,7 +622,7 @@ apps:
app:
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 1)
c.Check(info.Apps, HasLen, 1)
@@ -652,7 +652,7 @@ apps:
slots: ["net"]
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 1)
c.Check(info.Apps, HasLen, 1)
@@ -680,7 +680,7 @@ apps:
slots: ["network-client"]
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 1)
c.Check(info.Apps, HasLen, 1)
@@ -708,7 +708,7 @@ slots:
ipv6-aware: true
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 1)
c.Check(info.Apps, HasLen, 0)
@@ -730,7 +730,7 @@ slots:
label: Front panel LED (red)
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 1)
c.Check(info.Apps, HasLen, 0)
@@ -752,7 +752,7 @@ hooks:
test-hook:
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 1)
c.Check(info.Apps, HasLen, 0)
@@ -785,7 +785,7 @@ hooks:
slots: [test-slot]
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 1)
c.Check(info.Apps, HasLen, 0)
@@ -885,7 +885,7 @@ hooks:
test-hook:
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 0)
c.Check(info.Apps, HasLen, 0)
@@ -913,7 +913,7 @@ hooks:
test-hook:
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 0)
c.Check(info.Apps, HasLen, 0)
@@ -933,7 +933,7 @@ hooks:
foo-hook:
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 0)
c.Check(info.Slots, HasLen, 0)
c.Check(info.Apps, HasLen, 0)
@@ -958,7 +958,7 @@ hooks:
plugs: [test-plug]
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Check(info.Apps, HasLen, 0)
@@ -992,7 +992,7 @@ hooks:
test-hook:
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Check(info.Apps, HasLen, 0)
@@ -1028,7 +1028,7 @@ hooks:
without-plug:
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Check(info.Apps, HasLen, 0)
@@ -1066,7 +1066,7 @@ hooks:
plugs: ["test-plug"]
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Check(info.Apps, HasLen, 0)
@@ -1103,7 +1103,7 @@ apps:
test-app:
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "snap")
+ c.Check(info.InstanceName(), Equals, "snap")
c.Check(info.Plugs, HasLen, 1)
c.Check(info.Slots, HasLen, 0)
c.Check(info.Apps, HasLen, 1)
@@ -1171,7 +1171,7 @@ slots:
interface: ptrace
`))
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "foo")
+ c.Check(info.InstanceName(), Equals, "foo")
c.Check(info.Version, Equals, "1.2")
c.Check(info.Type, Equals, snap.TypeApp)
c.Check(info.Epoch.String(), Equals, "1*")
diff --git a/snap/info_test.go b/snap/info_test.go
index 8761490022..9030a93186 100644
--- a/snap/info_test.go
+++ b/snap/info_test.go
@@ -88,7 +88,7 @@ func (s *infoSuite) TestSideInfoOverrides(c *C) {
SnapID: "snapidsnapidsnapidsnapidsnapidsn",
}
- c.Check(info.Name(), Equals, "newname")
+ c.Check(info.InstanceName(), Equals, "newname")
c.Check(info.Summary(), Equals, "fixed summary")
c.Check(info.Description(), Equals, "fixed desc")
c.Check(info.Revision, Equals, snap.R(1))
@@ -186,7 +186,7 @@ func (s *infoSuite) TestReadInfo(c *C) {
snapInfo2, err := snap.ReadInfo("sample", si)
c.Assert(err, IsNil)
- c.Check(snapInfo2.Name(), Equals, "sample")
+ c.Check(snapInfo2.InstanceName(), Equals, "sample")
c.Check(snapInfo2.Revision, Equals, snap.R(42))
c.Check(snapInfo2.Summary(), Equals, "esummary")
@@ -203,7 +203,7 @@ func (s *infoSuite) TestReadCurrentInfo(c *C) {
snapInfo2, err := snap.ReadCurrentInfo("sample")
c.Assert(err, IsNil)
- c.Check(snapInfo2.Name(), Equals, "sample")
+ c.Check(snapInfo2.InstanceName(), Equals, "sample")
c.Check(snapInfo2.Revision, Equals, snap.R(42))
c.Check(snapInfo2, DeepEquals, snapInfo1)
@@ -217,7 +217,7 @@ func (s *infoSuite) TestInstallDate(c *C) {
info := snaptest.MockSnap(c, sampleYaml, si)
// not current -> Zero
c.Check(info.InstallDate().IsZero(), Equals, true)
- c.Check(snap.InstallDate(info.Name()).IsZero(), Equals, true)
+ c.Check(snap.InstallDate(info.InstanceName()).IsZero(), Equals, true)
mountdir := info.MountDir()
dir, rev := filepath.Split(mountdir)
@@ -231,7 +231,7 @@ func (s *infoSuite) TestInstallDate(c *C) {
c.Check(instTime.IsZero(), Equals, false)
c.Check(info.InstallDate().Equal(instTime), Equals, true)
- c.Check(snap.InstallDate(info.Name()).Equal(instTime), Equals, true)
+ c.Check(snap.InstallDate(info.InstanceName()).Equal(instTime), Equals, true)
}
func (s *infoSuite) TestReadInfoNotFound(c *C) {
@@ -321,7 +321,7 @@ confinement: devmode`
info, err := snap.ReadInfoFromSnapFile(snapf, nil)
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "foo")
+ c.Check(info.InstanceName(), Equals, "foo")
c.Check(info.Version, Equals, "1.0")
c.Check(info.Type, Equals, snap.TypeApp)
c.Check(info.Revision, Equals, snap.R(0))
@@ -343,7 +343,7 @@ confinement: classic`
info, err := snap.ReadInfoFromSnapFile(snapf, nil)
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "foo")
+ c.Check(info.InstanceName(), Equals, "foo")
c.Check(info.Version, Equals, "1.0")
c.Check(info.Type, Equals, snap.TypeApp)
c.Check(info.Revision, Equals, snap.R(0))
@@ -363,7 +363,7 @@ type: app`
info, err := snap.ReadInfoFromSnapFile(snapf, nil)
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "foo")
+ c.Check(info.InstanceName(), Equals, "foo")
c.Check(info.Version, Equals, "1.0")
c.Check(info.Type, Equals, snap.TypeApp)
c.Check(info.Revision, Equals, snap.R(0))
@@ -386,7 +386,7 @@ type: app`
Revision: snap.R(42),
})
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "baz")
+ c.Check(info.InstanceName(), Equals, "baz")
c.Check(info.Version, Equals, "1.0")
c.Check(info.Type, Equals, snap.TypeApp)
c.Check(info.Revision, Equals, snap.R(42))
@@ -570,7 +570,7 @@ func (s *infoSuite) checkInstalledSnapAndSnapFile(c *C, yaml string, contents st
sideInfo := &snap.SideInfo{Revision: snap.R(42)}
info0 := snaptest.MockSnap(c, yaml, sideInfo)
snaptest.PopulateDir(info0.MountDir(), emptyHooks(hooks...))
- info, err := snap.ReadInfo(info0.Name(), sideInfo)
+ info, err := snap.ReadInfo(info0.InstanceName(), sideInfo)
c.Check(err, IsNil)
checker(c, info)
@@ -731,7 +731,7 @@ func (s *infoSuite) TestAppDesktopFile(c *C) {
snapInfo, err := snap.ReadInfo("sample", &snap.SideInfo{})
c.Assert(err, IsNil)
- c.Check(snapInfo.Name(), Equals, "sample")
+ c.Check(snapInfo.InstanceName(), Equals, "sample")
c.Check(snapInfo.Apps["app"].DesktopFile(), Matches, `.*/var/lib/snapd/desktop/applications/sample_app.desktop`)
c.Check(snapInfo.Apps["sample"].DesktopFile(), Matches, `.*/var/lib/snapd/desktop/applications/sample_sample.desktop`)
}
diff --git a/snap/pack/pack.go b/snap/pack/pack.go
index 5bf9e6e6a7..02bc470d07 100644
--- a/snap/pack/pack.go
+++ b/snap/pack/pack.go
@@ -250,7 +250,7 @@ func prepare(sourceDir, targetDir, buildDir string) (snapName string, err error)
}
// build the package
- snapName = fmt.Sprintf("%s_%s_%v.snap", info.Name(), info.Version, debArchitecture(info))
+ snapName = fmt.Sprintf("%s_%s_%v.snap", info.InstanceName(), info.Version, debArchitecture(info))
if targetDir != "" {
snapName = filepath.Join(targetDir, snapName)
diff --git a/snap/snapenv/snapenv.go b/snap/snapenv/snapenv.go
index 6e021656b1..395b5bc3f3 100644
--- a/snap/snapenv/snapenv.go
+++ b/snap/snapenv/snapenv.go
@@ -93,16 +93,17 @@ func snapEnv(info *snap.Info) map[string]string {
// used by so many other modules, we run into circular dependencies if it's
// somewhere more reasonable like the snappy module.
func basicEnv(info *snap.Info) map[string]string {
+ // TODO parallel-install: use of proper instance/store name
return map[string]string{
// This uses CoreSnapMountDir because the computed environment
// variables are conveyed to the started application process which
// shall *either* execute with the new mount namespace where snaps are
// always mounted on /snap OR it is a classically confined snap where
// /snap is a part of the distribution package.
- "SNAP": filepath.Join(dirs.CoreSnapMountDir, info.Name(), info.Revision.String()),
+ "SNAP": filepath.Join(dirs.CoreSnapMountDir, info.InstanceName(), info.Revision.String()),
"SNAP_COMMON": info.CommonDataDir(),
"SNAP_DATA": info.DataDir(),
- "SNAP_NAME": info.Name(),
+ "SNAP_NAME": info.InstanceName(),
"SNAP_VERSION": info.Version,
"SNAP_REVISION": info.Revision.String(),
"SNAP_ARCH": arch.UbuntuArchitecture(),
@@ -117,6 +118,7 @@ func basicEnv(info *snap.Info) map[string]string {
// used by so many other modules, we run into circular dependencies if it's
// somewhere more reasonable like the snappy module.
func userEnv(info *snap.Info, home string) map[string]string {
+ // TODO parallel-install: use of proper instance/store name
result := map[string]string{
"SNAP_USER_COMMON": info.UserCommonDataDir(home),
"SNAP_USER_DATA": info.UserDataDir(home),
diff --git a/snap/snaptest/snaptest_test.go b/snap/snaptest/snaptest_test.go
index 5ad3ff5817..8c44798430 100644
--- a/snap/snaptest/snaptest_test.go
+++ b/snap/snaptest/snaptest_test.go
@@ -60,7 +60,7 @@ func (s *snapTestSuite) TearDownTest(c *C) {
func (s *snapTestSuite) TestMockSnap(c *C) {
snapInfo := snaptest.MockSnap(c, sampleYaml, &snap.SideInfo{Revision: snap.R(42)})
// Data from YAML is used
- c.Check(snapInfo.Name(), Equals, "sample")
+ c.Check(snapInfo.InstanceName(), Equals, "sample")
// Data from SideInfo is used
c.Check(snapInfo.Revision, Equals, snap.R(42))
// The YAML is placed on disk
@@ -75,7 +75,7 @@ func (s *snapTestSuite) TestMockSnap(c *C) {
func (s *snapTestSuite) TestMockSnapCurrent(c *C) {
snapInfo := snaptest.MockSnapCurrent(c, sampleYaml, &snap.SideInfo{Revision: snap.R(42)})
// Data from YAML is used
- c.Check(snapInfo.Name(), Equals, "sample")
+ c.Check(snapInfo.InstanceName(), Equals, "sample")
// Data from SideInfo is used
c.Check(snapInfo.Revision, Equals, snap.R(42))
// The YAML is placed on disk
@@ -89,7 +89,7 @@ func (s *snapTestSuite) TestMockSnapCurrent(c *C) {
func (s *snapTestSuite) TestMockInfo(c *C) {
snapInfo := snaptest.MockInfo(c, sampleYaml, &snap.SideInfo{Revision: snap.R(42)})
// Data from YAML is used
- c.Check(snapInfo.Name(), Equals, "sample")
+ c.Check(snapInfo.InstanceName(), Equals, "sample")
// Data from SideInfo is used
c.Check(snapInfo.Revision, Equals, snap.R(42))
// The YAML is *not* placed on disk
@@ -103,7 +103,7 @@ func (s *snapTestSuite) TestMockInfo(c *C) {
func (s *snapTestSuite) TestMockInvalidInfo(c *C) {
snapInfo := snaptest.MockInvalidInfo(c, sampleYaml+"\nslots:\n network:\n", &snap.SideInfo{Revision: snap.R(42)})
// Data from YAML is used
- c.Check(snapInfo.Name(), Equals, "sample")
+ c.Check(snapInfo.InstanceName(), Equals, "sample")
// Data from SideInfo is used
c.Check(snapInfo.Revision, Equals, snap.R(42))
// The YAML is *not* placed on disk
diff --git a/snap/validate.go b/snap/validate.go
index 84a91f003b..f51e253fb7 100644
--- a/snap/validate.go
+++ b/snap/validate.go
@@ -213,7 +213,8 @@ func validateSocketAddrPath(socket *SocketInfo, fieldName string, path string) e
}
func validateSocketAddrAbstract(socket *SocketInfo, fieldName string, path string) error {
- prefix := fmt.Sprintf("@snap.%s.", socket.App.Snap.Name())
+ // TODO parallel-install: use of proper instance/store name, discuss socket activation in parallel install world
+ prefix := fmt.Sprintf("@snap.%s.", socket.App.Snap.InstanceName())
if !strings.HasPrefix(path, prefix) {
return fmt.Errorf("socket %q path for %q must be prefixed with %q", socket.Name, fieldName, prefix)
}
@@ -258,11 +259,12 @@ func validateSocketAddrNetPort(socket *SocketInfo, fieldName string, port string
// Validate verifies the content in the info.
func Validate(info *Info) error {
- name := info.Name()
+ name := info.InstanceName()
if name == "" {
return fmt.Errorf("snap name cannot be empty")
}
+ // TODO parallel-install: use of proper instance/store name, validate instance key
if err := ValidateName(name); err != nil {
return err
}
@@ -315,7 +317,7 @@ func Validate(info *Info) error {
// validate that bases do not have base fields
if info.Type == TypeOS || info.Type == TypeBase {
if info.Base != "" {
- return fmt.Errorf(`cannot have "base" field on %q snap %q`, info.Type, info.Name())
+ return fmt.Errorf(`cannot have "base" field on %q snap %q`, info.Type, info.InstanceName())
}
}
diff --git a/spread.yaml b/spread.yaml
index d5076f4141..39b466c931 100644
--- a/spread.yaml
+++ b/spread.yaml
@@ -291,6 +291,8 @@ debug-each: |
if [ "$SPREAD_DEBUG_EACH" = 1 ]; then
# shellcheck source=tests/lib/journalctl.sh
. "$TESTSLIB/journalctl.sh"
+ #shellcheck source=tests/lib/state.sh
+ . "$TESTSLIB/state.sh"
echo '# journal messages for snapd'
get_journalctl_log -u snapd
@@ -300,6 +302,8 @@ debug-each: |
dmesg --ctime | grep type=1326 || true
echo '# snap interfaces'
snap interfaces || true
+ echo '# tasks executed on system'
+ cat "$RUNTIME_STATE_PATH/runs" || true
fi
rename:
diff --git a/store/details.go b/store/details.go
index 6812e20dff..d8a35785f7 100644
--- a/store/details.go
+++ b/store/details.go
@@ -68,24 +68,6 @@ type snapDetails struct {
CommonIDs []string `json:"common_ids,omitempty"`
}
-// channelMap contains
-type channelMap struct {
- Track string `json:"track"`
- SnapDetails []channelSnapInfoDetails `json:"map,omitempty"`
-}
-
-// channelSnapInfoDetails is the subset of snapDetails we need to get
-// information about the snaps in the various channels
-type channelSnapInfoDetails struct {
- Revision int `json:"revision"` // store revisions are ints starting at 1
- Confinement string `json:"confinement"`
- Version string `json:"version"`
- Channel string `json:"channel"`
- Epoch snap.Epoch `json:"epoch"`
- DownloadSize int64 `json:"binary_filesize"`
- Info string `json:"info"`
-}
-
func infoFromRemote(d *snapDetails) *snap.Info {
info := &snap.Info{}
info.Architectures = d.Architectures
diff --git a/store/store.go b/store/store.go
index 51c152cf10..193b9ebe58 100644
--- a/store/store.go
+++ b/store/store.go
@@ -1453,6 +1453,7 @@ var download = func(ctx context.Context, name, sha3_384, downloadURL string, use
}
var finalErr error
+ var dlSize float64
startTime := time.Now()
for attempt := retry.Start(defaultRetryStrategy, nil); attempt.Next(); {
reqOptions := downloadOptions(storeURL, cdnHeader)
@@ -1511,7 +1512,8 @@ var download = func(ctx context.Context, name, sha3_384, downloadURL string, use
if pbar == nil {
pbar = progress.Null
}
- pbar.Start(name, float64(resp.ContentLength))
+ dlSize = float64(resp.ContentLength)
+ pbar.Start(name, dlSize)
mw := io.MultiWriter(w, h, pbar)
_, finalErr = io.Copy(mw, resp.Body)
pbar.Finished()
@@ -1538,6 +1540,20 @@ var download = func(ctx context.Context, name, sha3_384, downloadURL string, use
}
break
}
+ if finalErr == nil {
+ // not using quantity.FormatFoo as this is just for debug
+ dt := time.Since(startTime)
+ r := dlSize / dt.Seconds()
+ var p rune
+ for _, p = range " kMGTPEZY" {
+ if r < 1000 {
+ break
+ }
+ r /= 1000
+ }
+
+ logger.Debugf("Download succeeded in %.03fs (%.0f%cB/s).", dt.Seconds(), r, p)
+ }
return finalErr
}
@@ -2120,6 +2136,7 @@ func (s *Store) snapAction(ctx context.Context, currentSnaps []*CurrentSnap, act
}
}
+ // TODO parallel-install: use of proper instance/store name
aJSON := &snapActionJSON{
Action: a.Action,
InstanceKey: instanceKey,
diff --git a/store/store_test.go b/store/store_test.go
index f3ebb70725..e15490210b 100644
--- a/store/store_test.go
+++ b/store/store_test.go
@@ -1908,103 +1908,6 @@ const (
helloWorldDeveloperID = "canonical"
)
-/* acquired via
-
-http --pretty=format --print b https://api.snapcraft.io/api/v1/snaps/details/hello-world X-Ubuntu-Series:16 fields==anon_download_url,architecture,channel,download_sha3_384,summary,description,binary_filesize,download_url,icon_url,last_updated,license,package_name,prices,publisher,ratings_average,revision,screenshot_urls,snap_id,support_url,title,content,version,origin,developer_id,private,confinement,snap_yaml_raw channel==edge | xsel -b
-
-on 2016-07-03. Then, by hand:
- * set prices to {"EUR": 0.99, "USD": 1.23}.
- * Screenshot URLS set manually.
- * Set "private" to true.
-
-on 2017-11-20. Then, by hand:
- * add "snap_yaml_raw" from "test-snapd-content-plug"
-
-On Ubuntu, apt install httpie xsel (although you could get http from
-the http snap instead).
-
-*/
-const MockDetailsJSON = `{
- "_links": {
- "self": {
- "href": "https://api.snapcraft.io/api/v1/snaps/details/hello-world?fields=anon_download_url%2Carchitecture%2Cchannel%2Cdownload_sha3_384%2Csummary%2Cdescription%2Cbinary_filesize%2Cdownload_url%2Cicon_url%2Clast_updated%2Clicense%2Cpackage_name%2Cprices%2Cpublisher%2Cratings_average%2Crevision%2Cscreenshot_urls%2Csnap_id%2Csupport_url%2Ctitle%2Ccontent%2Cversion%2Corigin%2Cdeveloper_id%2Cprivate%2Cconfinement&channel=edge"
- }
- },
- "anon_download_url": "https://public.apps.ubuntu.com/anon/download-snap/buPKUD3TKqCOgLEjjHx5kSiCpIs5cMuQ_27.snap",
- "architecture": [
- "all"
- ],
- "base": "bare-base",
- "binary_filesize": 20480,
- "channel": "edge",
- "confinement": "strict",
- "content": "application",
- "description": "This is a simple hello world example.",
- "developer_id": "canonical",
- "download_sha3_384": "eed62063c04a8c3819eb71ce7d929cc8d743b43be9e7d86b397b6d61b66b0c3a684f3148a9dbe5821360ae32105c1bd9",
- "download_url": "https://public.apps.ubuntu.com/download-snap/buPKUD3TKqCOgLEjjHx5kSiCpIs5cMuQ_27.snap",
- "icon_url": "https://myapps.developer.ubuntu.com/site_media/appmedia/2015/03/hello.svg_NZLfWbh.png",
- "last_updated": "2016-07-12T16:37:23.960632Z",
- "license": "GPL-3.0",
- "origin": "canonical",
- "package_name": "hello-world",
- "prices": {"EUR": 0.99, "USD": 1.23},
- "publisher": "Canonical",
- "ratings_average": 0.0,
- "revision": 27,
- "screenshot_urls": ["https://myapps.developer.ubuntu.com/site_media/appmedia/2015/03/screenshot.png"],
- "snap_id": "buPKUD3TKqCOgLEjjHx5kSiCpIs5cMuQ",
- "summary": "The 'hello-world' of snaps",
- "support_url": "mailto:snappy-devel@lists.ubuntu.com",
- "title": "Hello World",
- "version": "6.3",
- "snap_yaml_raw": "name: test-snapd-content-plug\nversion: 1.0\napps:\n content-plug:\n command: bin/content-plug\n plugs: [shared-content-plug]\nplugs:\n shared-content-plug:\n interface: content\n target: import\n content: mylib\n default-provider: test-snapd-content-slot\nslots:\n shared-content-slot:\n interface: content\n content: mylib\n read:\n - /\n",
- "channel_maps_list": [
- {
- "track": "latest",
- "map": [
- {
- "info": "released",
- "version": "v1",
- "binary_filesize": 12345,
- "epoch": "0",
- "confinement": "strict",
- "channel": "stable",
- "revision": 1
- },
- {
- "info": "released",
- "version": "v2",
- "binary_filesize": 12345,
- "epoch": "0",
- "confinement": "strict",
- "channel": "candidate",
- "revision": 2
- },
- {
- "info": "released",
- "version": "v8",
- "binary_filesize": 12345,
- "epoch": "0",
- "confinement": "devmode",
- "channel": "beta",
- "revision": 8
- },
- {
- "info": "released",
- "version": "v9",
- "binary_filesize": 12345,
- "epoch": "0",
- "confinement": "devmode",
- "channel": "edge",
- "revision": 9
- }
- ]
- }
- ]
-}
-`
-
const mockOrdersJSON = `{
"orders": [
{
@@ -2285,7 +2188,8 @@ func (s *storeTestSuite) TestInfo(c *C) {
}
result, err := sto.SnapInfo(spec, nil)
c.Assert(err, IsNil)
- c.Check(result.Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Check(result.InstanceName(), Equals, "hello-world")
c.Check(result.Architectures, DeepEquals, []string{"all"})
c.Check(result.Revision, Equals, snap.R(27))
c.Check(result.SnapID, Equals, helloWorldSnapID)
@@ -2367,7 +2271,7 @@ func (s *storeTestSuite) TestInfoBadResponses(c *C) {
info, err := sto.SnapInfo(SnapSpec{Name: "hello"}, nil)
c.Assert(err, IsNil)
- c.Check(info.Name(), Equals, "hello")
+ c.Check(info.InstanceName(), Equals, "hello")
info, err = sto.SnapInfo(SnapSpec{Name: "hello"}, nil)
c.Check(err, Equals, ErrSnapNotFound)
@@ -2411,7 +2315,8 @@ func (s *storeTestSuite) TestInfoDefaultChannelIsStable(c *C) {
}
result, err := sto.SnapInfo(spec, nil)
c.Assert(err, IsNil)
- c.Check(result.Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Check(result.InstanceName(), Equals, "hello-world")
c.Check(result.SnapID, Equals, helloWorldSnapID)
c.Check(result.Channel, Equals, "stable")
}
@@ -2475,7 +2380,8 @@ func (s *storeTestSuite) TestInfo500once(c *C) {
}
result, err := sto.SnapInfo(spec, nil)
c.Assert(err, IsNil)
- c.Check(result.Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Check(result.InstanceName(), Equals, "hello-world")
c.Assert(n, Equals, 2)
}
@@ -2514,7 +2420,8 @@ func (s *storeTestSuite) TestInfoAndChannels(c *C) {
result, err := sto.SnapInfo(spec, nil)
c.Assert(err, IsNil)
c.Assert(n, Equals, 1)
- c.Check(result.Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Check(result.InstanceName(), Equals, "hello-world")
expected := map[string]*snap.ChannelSnapInfo{
"latest/stable": {
Revision: snap.R(27),
@@ -2636,7 +2543,8 @@ func (s *storeTestSuite) TestInfoNonDefaults(c *C) {
}
result, err := sto.SnapInfo(spec, nil)
c.Assert(err, IsNil)
- c.Check(result.Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Check(result.InstanceName(), Equals, "hello-world")
}
func (s *storeTestSuite) TestStoreIDFromAuthContext(c *C) {
@@ -2666,7 +2574,8 @@ func (s *storeTestSuite) TestStoreIDFromAuthContext(c *C) {
}
result, err := sto.SnapInfo(spec, nil)
c.Assert(err, IsNil)
- c.Check(result.Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Check(result.InstanceName(), Equals, "hello-world")
}
func (s *storeTestSuite) TestProxyStoreFromAuthContext(c *C) {
@@ -2698,7 +2607,8 @@ func (s *storeTestSuite) TestProxyStoreFromAuthContext(c *C) {
}
result, err := sto.SnapInfo(spec, nil)
c.Assert(err, IsNil)
- c.Check(result.Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Check(result.InstanceName(), Equals, "hello-world")
}
func (s *storeTestSuite) TestProxyStoreFromAuthContextURLFallback(c *C) {
@@ -2729,7 +2639,8 @@ func (s *storeTestSuite) TestProxyStoreFromAuthContextURLFallback(c *C) {
}
result, err := sto.SnapInfo(spec, nil)
c.Assert(err, IsNil)
- c.Check(result.Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Check(result.InstanceName(), Equals, "hello-world")
}
func (s *storeTestSuite) TestInfoOopses(c *C) {
@@ -2805,51 +2716,53 @@ func (s *storeTestSuite) TestNoInfo(c *C) {
}
/* acquired via:
-curl -s -H "accept: application/hal+json" -H "X-Ubuntu-Release: 16" -H "X-Ubuntu-Device-Channel: edge" -H "X-Ubuntu-Wire-Protocol: 1" -H "X-Ubuntu-Architecture: amd64" 'https://api.snapcraft.io/api/v1/snaps/search?fields=anon_download_url%2Carchitecture%2Cchannel%2Cdownload_sha512%2Csummary%2Cdescription%2Cbinary_filesize%2Cdownload_url%2Cicon_url%2Clast_updated%2Clicense%2Cpackage_name%2Cprices%2Cpublisher%2Cratings_average%2Crevision%2Cscreenshot_urls%2Csnap_id%2Csupport_url%2Ctitle%2Ccontent%2Cversion%2Corigin%2Ccommon_ids&q=hello' | python -m json.tool | xsel -b
-Screenshot URLS set manually.
+curl -s -H "accept: application/hal+json" -H "X-Ubuntu-Release: 16" -H "X-Ubuntu-Device-Channel: edge" -H "X-Ubuntu-Wire-Protocol: 1" -H "X-Ubuntu-Architecture: amd64" 'https://api.snapcraft.io/api/v1/snaps/search?fields=anon_download_url%2Carchitecture%2Cchannel%2Cdownload_sha3_384%2Csummary%2Cdescription%2Cbinary_filesize%2Cdownload_url%2Cepoch%2Cicon_url%2Clast_updated%2Cpackage_name%2Cprices%2Cpublisher%2Cratings_average%2Crevision%2Cscreenshot_urls%2Csnap_id%2Clicense%2Cbase%2Csupport_url%2Ccontact%2Ctitle%2Ccontent%2Cversion%2Corigin%2Cdeveloper_id%2Cprivate%2Cconfinement%2Ccommon_ids&q=hello' | python -m json.tool | xsel -b
+Add base and prices.
*/
const MockSearchJSON = `{
"_embedded": {
"clickindex:package": [
{
- "anon_download_url": "https://public.apps.ubuntu.com/anon/download-snap/buPKUD3TKqCOgLEjjHx5kSiCpIs5cMuQ_25.snap",
+ "anon_download_url": "https://api.snapcraft.io/api/v1/snaps/download/buPKUD3TKqCOgLEjjHx5kSiCpIs5cMuQ_27.snap",
"architecture": [
"all"
],
+ "base": "bare-base",
"binary_filesize": 20480,
- "channel": "edge",
+ "channel": "stable",
"common_ids": [],
+ "confinement": "strict",
+ "contact": "mailto:snappy-devel@lists.ubuntu.com",
"content": "application",
"description": "This is a simple hello world example.",
- "download_sha512": "4bf23ce93efa1f32f0aeae7ec92564b7b0f9f8253a0bd39b2741219c1be119bb676c21208c6845ccf995e6aabe791d3f28a733ebcbbc3171bb23f67981f4068e",
- "download_url": "https://public.apps.ubuntu.com/download-snap/buPKUD3TKqCOgLEjjHx5kSiCpIs5cMuQ_25.snap",
- "icon_url": "https://myapps.developer.ubuntu.com/site_media/appmedia/2015/03/hello.svg_NZLfWbh.png",
- "last_updated": "2016-04-19T19:50:50.435291Z",
- "license": "GPL-3.0",
+ "developer_id": "canonical",
+ "download_sha3_384": "eed62063c04a8c3819eb71ce7d929cc8d743b43be9e7d86b397b6d61b66b0c3a684f3148a9dbe5821360ae32105c1bd9",
+ "download_url": "https://api.snapcraft.io/api/v1/snaps/download/buPKUD3TKqCOgLEjjHx5kSiCpIs5cMuQ_27.snap",
+ "epoch": "0",
+ "icon_url": "https://dashboard.snapcraft.io/site_media/appmedia/2015/03/hello.svg_NZLfWbh.png",
+ "last_updated": "2016-07-12T16:37:23.960632+00:00",
+ "license": "MIT",
"origin": "canonical",
"package_name": "hello-world",
"prices": {"EUR": 2.99, "USD": 3.49},
+ "private": false,
"publisher": "Canonical",
"ratings_average": 0.0,
- "revision": 25,
- "screenshot_urls": ["https://myapps.developer.ubuntu.com/site_media/appmedia/2015/03/screenshot.png"],
+ "revision": 27,
+ "screenshot_urls": [
+ "https://dashboard.snapcraft.io/site_media/appmedia/2018/06/Screenshot_from_2018-06-14_09-33-31.png"
+ ],
"snap_id": "buPKUD3TKqCOgLEjjHx5kSiCpIs5cMuQ",
- "summary": "Hello world example",
- "support_url": "mailto:snappy-devel@lists.ubuntu.com",
+ "summary": "The 'hello-world' of snaps",
+ "support_url": "",
"title": "Hello World",
- "version": "6.0"
+ "version": "6.3"
}
]
},
"_links": {
- "first": {
- "href": "https://api.snapcraft.io/api/v1/snaps/search?q=hello&fields=anon_download_url%2Carchitecture%2Cchannel%2Cdownload_sha512%2Csummary%2Cdescription%2Cbinary_filesize%2Cdownload_url%2Cicon_url%2Clast_updated%2Clicense%2Cpackage_name%2Cprices%2Cpublisher%2Cratings_average%2Crevision%2Cscreenshot_urls%2Csnap_id%2Csupport_url%2Ctitle%2Ccontent%2Cversion%2Corigin&page=1"
- },
- "last": {
- "href": "https://api.snapcraft.io/api/v1/snaps/search?q=hello&fields=anon_download_url%2Carchitecture%2Cchannel%2Cdownload_sha512%2Csummary%2Cdescription%2Cbinary_filesize%2Cdownload_url%2Cicon_url%2Clast_updated%2Clicense%2Cpackage_name%2Cprices%2Cpublisher%2Cratings_average%2Crevision%2Cscreenshot_urls%2Csnap_id%2Csupport_url%2Ctitle%2Ccontent%2Cversion%2Corigin&page=1"
- },
"self": {
- "href": "https://api.snapcraft.io/api/v1/snaps/search?q=hello&fields=anon_download_url%2Carchitecture%2Cchannel%2Cdownload_sha512%2Csummary%2Cdescription%2Cbinary_filesize%2Cdownload_url%2Cicon_url%2Clast_updated%2Clicense%2Cpackage_name%2Cprices%2Cpublisher%2Cratings_average%2Crevision%2Cscreenshot_urls%2Csnap_id%2Csupport_url%2Ctitle%2Ccontent%2Cversion%2Corigin&page=1"
+ "href": "http://api.snapcraft.io/api/v1/snaps/search?fields=anon_download_url%2Carchitecture%2Cchannel%2Cdownload_sha3_384%2Csummary%2Cdescription%2Cbinary_filesize%2Cdownload_url%2Cepoch%2Cicon_url%2Clast_updated%2Cpackage_name%2Cprices%2Cpublisher%2Cratings_average%2Crevision%2Cscreenshot_urls%2Csnap_id%2Clicense%2Cbase%2Csupport_url%2Ccontact%2Ctitle%2Ccontent%2Cversion%2Corigin%2Cdeveloper_id%2Cprivate%2Cconfinement%2Ccommon_ids&q=hello"
}
}
}
@@ -3100,6 +3013,88 @@ func (s *storeTestSuite) testSnapCommands(c *C, onClassic bool) {
})
}
+func (s *storeTestSuite) TestFind(c *C) {
+ restore := release.MockOnClassic(false)
+ defer restore()
+
+ mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ assertRequest(c, r, "GET", searchPath)
+ query := r.URL.Query()
+
+ q := query.Get("q")
+ c.Check(q, Equals, "hello")
+
+ c.Check(r.UserAgent(), Equals, userAgent)
+
+ // check device authorization is set, implicitly checking doRequest was used
+ c.Check(r.Header.Get("X-Device-Authorization"), Equals, `Macaroon root="device-macaroon"`)
+
+ // no store ID by default
+ storeID := r.Header.Get("X-Ubuntu-Store")
+ c.Check(storeID, Equals, "")
+
+ c.Check(r.URL.Query().Get("fields"), Equals, "abc,def")
+
+ c.Check(r.Header.Get("X-Ubuntu-Series"), Equals, release.Series)
+ c.Check(r.Header.Get("X-Ubuntu-Architecture"), Equals, arch.UbuntuArchitecture())
+ c.Check(r.Header.Get("X-Ubuntu-Classic"), Equals, "false")
+
+ c.Check(r.Header.Get("X-Ubuntu-Confinement"), Equals, "")
+
+ w.Header().Set("X-Suggested-Currency", "GBP")
+
+ w.Header().Set("Content-Type", "application/hal+json")
+ w.WriteHeader(200)
+
+ io.WriteString(w, MockSearchJSON)
+ }))
+
+ c.Assert(mockServer, NotNil)
+ defer mockServer.Close()
+
+ mockServerURL, _ := url.Parse(mockServer.URL)
+ cfg := Config{
+ StoreBaseURL: mockServerURL,
+ DetailFields: []string{"abc", "def"},
+ }
+ authContext := &testAuthContext{c: c, device: s.device}
+ sto := New(&cfg, authContext)
+
+ snaps, err := sto.Find(&Search{Query: "hello"}, nil)
+ c.Assert(err, IsNil)
+ c.Assert(snaps, HasLen, 1)
+ snp := snaps[0]
+ c.Check(snp.InstanceName(), Equals, "hello-world")
+ c.Check(snp.Architectures, DeepEquals, []string{"all"})
+ c.Check(snp.Revision, Equals, snap.R(27))
+ c.Check(snp.SnapID, Equals, helloWorldSnapID)
+ c.Check(snp.Publisher, Equals, "canonical")
+ c.Check(snp.PublisherID, Equals, "canonical")
+ c.Check(snp.Version, Equals, "6.3")
+ c.Check(snp.Sha3_384, Matches, `[[:xdigit:]]{96}`)
+ c.Check(snp.Size, Equals, int64(20480))
+ c.Check(snp.Channel, Equals, "stable")
+ c.Check(snp.Description(), Equals, "This is a simple hello world example.")
+ c.Check(snp.Summary(), Equals, "The 'hello-world' of snaps")
+ c.Check(snp.Title(), Equals, "Hello World")
+ c.Check(snp.License, Equals, "MIT")
+ c.Assert(snp.Prices, DeepEquals, map[string]float64{"EUR": 2.99, "USD": 3.49})
+ c.Assert(snp.Paid, Equals, true)
+ c.Assert(snp.Screenshots, DeepEquals, []snap.ScreenshotInfo{
+ {
+ URL: "https://dashboard.snapcraft.io/site_media/appmedia/2018/06/Screenshot_from_2018-06-14_09-33-31.png",
+ },
+ })
+ c.Check(snp.MustBuy, Equals, true)
+ c.Check(snp.Contact, Equals, "mailto:snappy-devel@lists.ubuntu.com")
+ c.Check(snp.Base, Equals, "bare-base")
+
+ // Make sure the epoch (currently not sent by the store) defaults to "0"
+ c.Check(snp.Epoch.String(), Equals, "0")
+
+ c.Check(sto.SuggestedCurrency(), Equals, "GBP")
+}
+
func (s *storeTestSuite) TestFindPrivate(c *C) {
n := 0
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -4615,7 +4610,8 @@ func (s *storeTestSuite) TestSnapAction(c *C) {
}, nil, nil)
c.Assert(err, IsNil)
c.Assert(results, HasLen, 1)
- c.Assert(results[0].Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Assert(results[0].InstanceName(), Equals, "hello-world")
c.Assert(results[0].Revision, Equals, snap.R(26))
c.Assert(results[0].Version, Equals, "6.1")
c.Assert(results[0].SnapID, Equals, helloWorldSnapID)
@@ -4983,7 +4979,8 @@ func (s *storeTestSuite) TestSnapActionRetryOnEOF(c *C) {
c.Assert(err, IsNil)
c.Assert(n, Equals, 4)
c.Assert(results, HasLen, 1)
- c.Assert(results[0].Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Assert(results[0].InstanceName(), Equals, "hello-world")
}
func (s *storeTestSuite) TestSnapActionIgnoreValidation(c *C) {
@@ -5070,7 +5067,8 @@ func (s *storeTestSuite) TestSnapActionIgnoreValidation(c *C) {
}, nil, nil)
c.Assert(err, IsNil)
c.Assert(results, HasLen, 1)
- c.Assert(results[0].Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Assert(results[0].InstanceName(), Equals, "hello-world")
c.Assert(results[0].Revision, Equals, snap.R(26))
}
@@ -5151,7 +5149,8 @@ func (s *storeTestSuite) TestInstallFallbackChannelIsStable(c *C) {
}, nil, nil)
c.Assert(err, IsNil)
c.Assert(results, HasLen, 1)
- c.Assert(results[0].Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Assert(results[0].InstanceName(), Equals, "hello-world")
c.Assert(results[0].Revision, Equals, snap.R(26))
c.Assert(results[0].SnapID, Equals, helloWorldSnapID)
}
@@ -5246,7 +5245,8 @@ func (s *storeTestSuite) TestSnapActionNonDefaultsHeaders(c *C) {
}, nil, nil)
c.Assert(err, IsNil)
c.Assert(results, HasLen, 1)
- c.Assert(results[0].Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Assert(results[0].InstanceName(), Equals, "hello-world")
c.Assert(results[0].Revision, Equals, snap.R(26))
c.Assert(results[0].Version, Equals, "6.1")
c.Assert(results[0].SnapID, Equals, helloWorldSnapID)
@@ -5337,7 +5337,8 @@ func (s *storeTestSuite) TestSnapActionWithDeltas(c *C) {
}, nil, nil)
c.Assert(err, IsNil)
c.Assert(results, HasLen, 1)
- c.Assert(results[0].Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Assert(results[0].InstanceName(), Equals, "hello-world")
c.Assert(results[0].Revision, Equals, snap.R(26))
}
@@ -5423,7 +5424,8 @@ func (s *storeTestSuite) TestSnapActionOptions(c *C) {
}, nil, &RefreshOptions{RefreshManaged: true})
c.Assert(err, IsNil)
c.Assert(results, HasLen, 1)
- c.Assert(results[0].Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Assert(results[0].InstanceName(), Equals, "hello-world")
c.Assert(results[0].Revision, Equals, snap.R(26))
}
@@ -5514,7 +5516,8 @@ func (s *storeTestSuite) testSnapActionGet(action string, c *C) {
}, nil, nil)
c.Assert(err, IsNil)
c.Assert(results, HasLen, 1)
- c.Assert(results[0].Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Assert(results[0].InstanceName(), Equals, "hello-world")
c.Assert(results[0].Revision, Equals, snap.R(26))
c.Assert(results[0].Version, Equals, "6.1")
c.Assert(results[0].SnapID, Equals, helloWorldSnapID)
@@ -5612,7 +5615,8 @@ func (s *storeTestSuite) testSnapActionGetWithRevision(action string, c *C) {
}, nil, nil)
c.Assert(err, IsNil)
c.Assert(results, HasLen, 1)
- c.Assert(results[0].Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Assert(results[0].InstanceName(), Equals, "hello-world")
c.Assert(results[0].Revision, Equals, snap.R(28))
c.Assert(results[0].Version, Equals, "6.1")
c.Assert(results[0].SnapID, Equals, helloWorldSnapID)
@@ -6201,7 +6205,8 @@ func (s *storeTestSuite) TestSnapActionRefreshesBothAuths(c *C) {
}, s.user, nil)
c.Assert(err, IsNil)
c.Assert(results, HasLen, 1)
- c.Assert(results[0].Name(), Equals, "hello-world")
+ // TODO parallel-install: use of proper instance/store name
+ c.Assert(results[0].InstanceName(), Equals, "hello-world")
c.Check(refreshDischargeEndpointHit, Equals, true)
c.Check(refreshSessionRequested, Equals, true)
c.Check(n, Equals, 2)
diff --git a/tests/lib/fakestore/store/store.go b/tests/lib/fakestore/store/store.go
index baf67acaf8..24190723b4 100644
--- a/tests/lib/fakestore/store/store.go
+++ b/tests/lib/fakestore/store/store.go
@@ -218,7 +218,7 @@ func snapEssentialInfo(w http.ResponseWriter, fn, snapID string, bs asserts.Back
}
return &essentialInfo{
- Name: info.Name(),
+ Name: info.StoreName(),
SnapID: snapID,
DeveloperID: develID,
DevelName: devel,
@@ -329,7 +329,7 @@ func (s *Store) collectSnaps() (map[string]string, error) {
if err != nil {
return nil, err
}
- snaps[info.Name()] = fn
+ snaps[info.StoreName()] = fn
}
return snaps, err
diff --git a/tests/lib/prepare-restore.sh b/tests/lib/prepare-restore.sh
index 434b7ab32f..ca2f7eeccb 100755
--- a/tests/lib/prepare-restore.sh
+++ b/tests/lib/prepare-restore.sh
@@ -411,6 +411,9 @@ prepare_suite_each() {
if is_classic_system; then
prepare_each_classic
fi
+ #shellcheck source=tests/lib/state.sh
+ . "$TESTSLIB"/state.sh
+ echo -n "$SPREAD_JOB " >> "$RUNTIME_STATE_PATH/runs"
}
restore_suite_each() {
diff --git a/tests/lib/state.sh b/tests/lib/state.sh
index 2e31e0d98b..65d273bbb0 100755
--- a/tests/lib/state.sh
+++ b/tests/lib/state.sh
@@ -1,7 +1,8 @@
#!/bin/bash
SNAPD_STATE_PATH="$SPREAD_PATH/tests/snapd-state"
-SNAPD_STATE_FILE="$SPREAD_PATH/tests/snapd-state.tar"
+SNAPD_STATE_FILE="$SPREAD_PATH/tests/snapd-state/snapd-state.tar"
+RUNTIME_STATE_PATH="$SPREAD_PATH/tests/runtime-state"
# shellcheck source=tests/lib/dirs.sh
. "$TESTSLIB/dirs.sh"
@@ -13,19 +14,16 @@ SNAPD_STATE_FILE="$SPREAD_PATH/tests/snapd-state.tar"
. "$TESTSLIB/systems.sh"
delete_snapd_state() {
- if is_core_system; then
- rm -rf "$SNAPD_STATE_PATH"
- else
- rm -f "$SNAPD_STATE_FILE"
- fi
+ rm -rf "$SNAPD_STATE_PATH"
}
save_snapd_state() {
+ mkdir -p "$SNAPD_STATE_PATH" "$RUNTIME_STATE_PATH"
if is_core_system; then
boot_path="$(get_boot_path)"
test -n "$boot_path" || return 1
- mkdir -p "$SNAPD_STATE_PATH" "$SNAPD_STATE_PATH"/system-units
+ mkdir -p "$SNAPD_STATE_PATH"/system-units
# Copy the state preserving the timestamps
cp -a /var/lib/snapd "$SNAPD_STATE_PATH"/snapd-lib
diff --git a/tests/main/econnreset/task.yaml b/tests/main/econnreset/task.yaml
index 66085801d4..4ed2b4682c 100644
--- a/tests/main/econnreset/task.yaml
+++ b/tests/main/econnreset/task.yaml
@@ -1,5 +1,8 @@
summary: Ensure that ECONNRESET is handled
restore: |
+ echo "Stop the snap download command"
+ kill -9 "$(pgrep -f 'snap download')" || true
+
echo "Remove the firewall rule again"
iptables -D OUTPUT -m owner --uid-owner "$(id -u test)" -j REJECT -p tcp --reject-with tcp-reset || true
@@ -14,6 +17,8 @@ debug: |
ls -lh test-snapd-huge_* || true
echo "other dir content"
ls -lh
+ echo "download log:"
+ cat snap-download.log
execute: |
echo "Downloading a large snap in the background"
@@ -22,17 +27,17 @@ execute: |
echo "Wait until the download started and downloaded more than 1 MB"
echo "starting: $(date)"
- for _ in $(seq 400); do
+ for _ in $(seq 120); do
partial=$(find . -name 'test-snapd-huge_*.snap.partial' | head -1)
if [ -n "$partial" ] && [ "$(stat -c%s "$partial")" -gt "$(( 1024 * 1024 ))" ]; then
break
fi
- sleep 0.1
+ sleep 0.5
done
if [ ! -f "$partial" ] || [ "$(stat -c%s "$partial")" -eq 0 ]; then
echo "Partial file $partial did not start downloading, test broken"
- kill -9 "$(pidof snap)"
+ kill -9 "$(pgrep -f 'snap download')" || true
exit 1
fi
@@ -40,6 +45,7 @@ execute: |
echo "File fully downloaded before the test could act"
echo "Test broken"
echo "end: $(date)"
+ kill -9 "$(pgrep -f 'snap download')" || true
exit 1
fi
@@ -53,10 +59,16 @@ execute: |
fi
sleep .5
done
+
+ if [ -n "$(find . -name 'test-snapd-huge_*.snap')" ]; then
+ echo "File fully downloaded even after iptables was applied"
+ echo "Test broken"
+ echo "end: $(date)"
+ exit 1
+ fi
+
MATCH 'Retrying.*\.snap, attempt 2' < snap-download.log
# Note that the download will not be successful because of the nature of
# the netfilter testbed. When snap download retries the next attempt will
# end up with a "connection refused" error, something we do not retry
-debug: |
- cat snap-download.log
diff --git a/tests/main/security-setuid-root/task.yaml b/tests/main/security-setuid-root/task.yaml
index a8e619879f..c44160af13 100644
--- a/tests/main/security-setuid-root/task.yaml
+++ b/tests/main/security-setuid-root/task.yaml
@@ -16,12 +16,12 @@ prepare: |
. $TESTSLIB/snaps.sh
install_local test-snapd-tools
echo "Ensure the snap-confine profiles on core are not loaded"
- for p in /etc/apparmor.d/snap.core.*.usr.lib.snapd.snap-confine; do
+ for p in /var/lib/snapd/apparmor/profiles/snap-confine.*; do
apparmor_parser -R "$p"
done
restore: |
echo "Ensure the snap-confine profiles are restored"
- for p in /etc/apparmor.d/snap.core.*.usr.lib.snapd.snap-confine; do
+ for p in /var/lib/snapd/apparmor/profiles/snap-confine.*; do
apparmor_parser -r $p
done
execute: |
diff --git a/tests/main/snap-confine-from-core/task.yaml b/tests/main/snap-confine-from-core/task.yaml
index 47ed34fbe2..a98e7f2f52 100644
--- a/tests/main/snap-confine-from-core/task.yaml
+++ b/tests/main/snap-confine-from-core/task.yaml
@@ -50,23 +50,23 @@ execute: |
fi
echo "Ensure snapd generates the right apparmor profile on restart"
- PROFILES="$(find /etc/apparmor.d/ -maxdepth 1 -name "snap.core.*.snap-confine")"
+ PROFILES="$(find /var/lib/snapd/apparmor/profiles/ -maxdepth 1 -name "snap-confine.*")"
if [ -z "$PROFILES" ]; then
echo "cannot find apparmor profiles for snap-confine from core"
echo "test broken"
- ls -al /etc/apparmor.d
+ ls -al /var/lib/snapd/apparmor/profiles
exit 1
fi
echo "Force system-key change"
systemd_stop_units snapd.service snapd.socket
printf '{"version":1}' > /var/lib/snapd/system-key
- rm -f /etc/apparmor.d/snap.core.*.snap-confine
+ rm -f /var/lib/snapd/apparmor/profiles/snap-confine.*
systemctl start snapd.service snapd.socket
wait_for_service snapd.service
echo "Ensure this also re-generates the snap-confine from core profile"
- PROFILES="$(find /etc/apparmor.d/ -maxdepth 1 -name "snap.core.*.snap-confine")"
+ PROFILES="$(find /var/lib/snapd/apparmor/profiles/ -maxdepth 1 -name "snap-confine.*")"
if [ -z "$PROFILES" ]; then
echo "apparmor profiles for snap-confine from core were not re-generated"
echo "test broken"
diff --git a/wrappers/desktop.go b/wrappers/desktop.go
index 93426e30aa..0c8328a6d7 100644
--- a/wrappers/desktop.go
+++ b/wrappers/desktop.go
@@ -108,6 +108,8 @@ func rewriteExecLine(s *snap.Info, desktopFile, line string) (string, error) {
cmd := strings.SplitN(line, "=", 2)[1]
for _, app := range s.Apps {
+ // TODO parallel-install: adjust valid command checks to account
+ // for instance name
wrapper := app.WrapperPath()
validCmd := filepath.Base(wrapper)
// check the prefix to allow %flag style args
@@ -120,7 +122,7 @@ func rewriteExecLine(s *snap.Info, desktopFile, line string) (string, error) {
}
}
- logger.Noticef("cannot use line %q for desktop file %q (snap %s)", line, desktopFile, s.Name())
+ logger.Noticef("cannot use line %q for desktop file %q (snap %s)", line, desktopFile, s.InstanceName())
// The Exec= line in the desktop file is invalid. Instead of failing
// hard we rewrite the Exec= line. The convention is that the desktop
// file has the same name as the application we can use this fact here.
@@ -214,7 +216,7 @@ func AddSnapDesktopFiles(s *snap.Info) (err error) {
return err
}
- installedDesktopFileName := filepath.Join(dirs.SnapDesktopFilesDir, fmt.Sprintf("%s_%s", s.Name(), filepath.Base(df)))
+ installedDesktopFileName := filepath.Join(dirs.SnapDesktopFilesDir, fmt.Sprintf("%s_%s", s.InstanceName(), filepath.Base(df)))
content = sanitizeDesktopFile(s, installedDesktopFileName, content)
if err := osutil.AtomicWriteFile(installedDesktopFileName, content, 0755, 0); err != nil {
return err
@@ -232,7 +234,8 @@ func AddSnapDesktopFiles(s *snap.Info) (err error) {
// RemoveSnapDesktopFiles removes the added desktop files for the applications in the snap.
func RemoveSnapDesktopFiles(s *snap.Info) error {
- glob := filepath.Join(dirs.SnapDesktopFilesDir, s.Name()+"_*.desktop")
+ // TODO parallel-install: verify use of instance names here
+ glob := filepath.Join(dirs.SnapDesktopFilesDir, s.InstanceName()+"_*.desktop")
activeDesktopFiles, err := filepath.Glob(glob)
if err != nil {
return fmt.Errorf("cannot get desktop files for %v: %s", glob, err)
diff --git a/wrappers/services.go b/wrappers/services.go
index fbb61068ec..8407849689 100644
--- a/wrappers/services.go
+++ b/wrappers/services.go
@@ -372,7 +372,7 @@ func genServiceNames(snap *snap.Info, appNames []string) []string {
func genServiceFile(appInfo *snap.AppInfo) []byte {
serviceTemplate := `[Unit]
# Auto-generated, DO NOT EDIT
-Description=Service for snap application {{.App.Snap.Name}}.{{.App.Name}}
+Description=Service for snap application {{.App.Snap.InstanceName}}.{{.App.Name}}
Requires={{.MountUnit}}
Wants={{.PrerequisiteTarget}}
After={{.MountUnit}} {{.PrerequisiteTarget}}{{range .After}} {{.}}{{end}}
@@ -383,7 +383,7 @@ X-Snappy=yes
[Service]
ExecStart={{.App.LauncherCommand}}
-SyslogIdentifier={{.App.Snap.Name}}.{{.App.Name}}
+SyslogIdentifier={{.App.Snap.InstanceName}}.{{.App.Name}}
Restart={{.Restart}}
WorkingDirectory={{.App.Snap.DataDir}}
{{- if .App.StopCommand}}
@@ -489,7 +489,7 @@ WantedBy={{.ServicesTarget}}
func genServiceSocketFile(appInfo *snap.AppInfo, socketName string) []byte {
socketTemplate := `[Unit]
# Auto-generated, DO NO EDIT
-Description=Socket {{.SocketName}} for snap application {{.App.Snap.Name}}.{{.App.Name}}
+Description=Socket {{.SocketName}} for snap application {{.App.Snap.InstanceName}}.{{.App.Name}}
Requires={{.MountUnit}}
Wants={{.PrerequisiteTarget}}
After={{.MountUnit}} {{.PrerequisiteTarget}}
@@ -558,7 +558,7 @@ func renderListenStream(socket *snap.SocketInfo) string {
func generateSnapTimerFile(app *snap.AppInfo) ([]byte, error) {
timerTemplate := `[Unit]
# Auto-generated, DO NOT EDIT
-Description=Timer {{.TimerName}} for snap application {{.App.Snap.Name}}.{{.App.Name}}
+Description=Timer {{.TimerName}} for snap application {{.App.Snap.InstanceName}}.{{.App.Name}}
Requires={{.MountUnit}}
After={{.MountUnit}}
X-Snappy=yes