summaryrefslogtreecommitdiff
diff options
authorMichael Vogt <mvo@ubuntu.com>2018-07-19 19:04:50 +0200
committerMichael Vogt <mvo@ubuntu.com>2018-07-19 19:04:50 +0200
commit99a0c4e19350eed194ea46102391ab02ac939160 (patch)
treec1a6eeadb28d80de2d122e83d377d872c75e19d5
parent68b834b8520342bf3e32cc14af60ab0261e35f12 (diff)
parentf95fcbd8d1a6f7e0882529a90ff0cc5b38615536 (diff)
Merge remote-tracking branch 'upstream/master' into no-degraded-bootno-degraded-boot
-rw-r--r--client/client.go6
-rw-r--r--cmd/snap/cmd_interface.go9
-rw-r--r--cmd/snap/cmd_interface_test.go2
-rw-r--r--cmd/snap/cmd_interfaces.go9
-rw-r--r--cmd/snap/cmd_interfaces_test.go12
-rw-r--r--cmd/snap/main.go26
-rw-r--r--daemon/api.go43
-rw-r--r--daemon/api_test.go178
-rw-r--r--overlord/configstate/configstate.go16
-rw-r--r--overlord/configstate/configstate_test.go17
-rw-r--r--overlord/ifacestate/export_test.go10
-rw-r--r--overlord/ifacestate/helpers.go193
-rw-r--r--overlord/ifacestate/helpers_test.go162
-rw-r--r--packaging/arch/PKGBUILD2
-rw-r--r--packaging/fedora/snapd.spec16
-rw-r--r--packaging/opensuse/snapd.changes12
-rw-r--r--packaging/opensuse/snapd.spec2
-rw-r--r--packaging/ubuntu-14.04/changelog20
-rw-r--r--packaging/ubuntu-16.04/changelog20
-rw-r--r--snap/info.go18
-rw-r--r--snap/info_test.go10
-rw-r--r--tests/lib/snaps/test-snapd-policy-app-provider-classic/meta/snap.yaml4
-rw-r--r--tests/lib/snaps/test-snapd-policy-app-provider-core/meta/snap.yaml8
-rw-r--r--tests/main/install-errors/task.yaml7
-rw-r--r--tests/main/snap-info/check.py12
-rw-r--r--tests/main/snap-run-hook/task.yaml9
26 files changed, 629 insertions, 194 deletions
diff --git a/client/client.go b/client/client.go
index 264285f97c..193ca6bb44 100644
--- a/client/client.go
+++ b/client/client.go
@@ -374,6 +374,7 @@ const (
ErrorKindTwoFactorRequired = "two-factor-required"
ErrorKindTwoFactorFailed = "two-factor-failed"
ErrorKindLoginRequired = "login-required"
+ ErrorKindInvalidAuthData = "invalid-auth-data"
ErrorKindTermsNotAccepted = "terms-not-accepted"
ErrorKindNoPaymentMethods = "no-payment-methods"
ErrorKindPaymentDeclined = "payment-declined"
@@ -382,6 +383,7 @@ const (
ErrorKindSnapAlreadyInstalled = "snap-already-installed"
ErrorKindSnapNotInstalled = "snap-not-installed"
ErrorKindSnapNotFound = "snap-not-found"
+ ErrorKindAppNotFound = "app-not-found"
ErrorKindSnapLocal = "snap-local"
ErrorKindSnapNeedsDevMode = "snap-needs-devmode"
ErrorKindSnapNeedsClassic = "snap-needs-classic"
@@ -396,9 +398,11 @@ const (
ErrorKindNotSnap = "snap-not-a-snap"
- ErrorKindNetworkTimeout = "network-timeout"
+ ErrorKindNetworkTimeout = "network-timeout"
+
ErrorKindInterfacesUnchanged = "interfaces-unchanged"
+ ErrorKindBadQuery = "bad-query"
ErrorKindConfigNoSuchOption = "option-not-found"
ErrorKindSystemRestart = "system-restart"
diff --git a/cmd/snap/cmd_interface.go b/cmd/snap/cmd_interface.go
index 2a171f72c0..acb249c306 100644
--- a/cmd/snap/cmd_interface.go
+++ b/cmd/snap/cmd_interface.go
@@ -28,7 +28,6 @@ import (
"github.com/snapcore/snapd/client"
"github.com/snapcore/snapd/i18n"
- "github.com/snapcore/snapd/snap"
"github.com/jessevdk/go-flags"
)
@@ -122,9 +121,9 @@ func (x *cmdInterface) showOneInterface(iface *client.Interface) {
labelPart = fmt.Sprintf(" (%s)", plug.Label)
}
if plug.Name == iface.Name {
- fmt.Fprintf(w, " - %s%s", snap.UseNick(plug.Snap), labelPart)
+ fmt.Fprintf(w, " - %s%s", plug.Snap, labelPart)
} else {
- fmt.Fprintf(w, ` - %s:%s%s`, snap.UseNick(plug.Snap), plug.Name, labelPart)
+ fmt.Fprintf(w, ` - %s:%s%s`, plug.Snap, plug.Name, labelPart)
}
// Print a colon which will make the snap:plug element a key-value
// yaml object so that we can write the attributes.
@@ -144,9 +143,9 @@ func (x *cmdInterface) showOneInterface(iface *client.Interface) {
labelPart = fmt.Sprintf(" (%s)", slot.Label)
}
if slot.Name == iface.Name {
- fmt.Fprintf(w, " - %s%s", snap.UseNick(slot.Snap), labelPart)
+ fmt.Fprintf(w, " - %s%s", slot.Snap, labelPart)
} else {
- fmt.Fprintf(w, ` - %s:%s%s`, snap.UseNick(slot.Snap), slot.Name, labelPart)
+ fmt.Fprintf(w, ` - %s:%s%s`, slot.Snap, slot.Name, labelPart)
}
// Print a colon which will make the snap:slot element a key-value
// yaml object so that we can write the attributes.
diff --git a/cmd/snap/cmd_interface_test.go b/cmd/snap/cmd_interface_test.go
index 043ddd3577..27ebb2011f 100644
--- a/cmd/snap/cmd_interface_test.go
+++ b/cmd/snap/cmd_interface_test.go
@@ -174,7 +174,7 @@ func (s *SnapSuite) TestInterfaceDetails(c *C) {
{Snap: "deepin-music", Name: "network"},
{Snap: "http", Name: "network"},
},
- Slots: []client.Slot{{Snap: "core", Name: "network"}},
+ Slots: []client.Slot{{Snap: "system", Name: "network"}},
}},
})
})
diff --git a/cmd/snap/cmd_interfaces.go b/cmd/snap/cmd_interfaces.go
index ca0260738d..5946f84ee2 100644
--- a/cmd/snap/cmd_interfaces.go
+++ b/cmd/snap/cmd_interfaces.go
@@ -23,7 +23,6 @@ import (
"fmt"
"github.com/snapcore/snapd/i18n"
- "github.com/snapcore/snapd/snap"
"github.com/jessevdk/go-flags"
)
@@ -89,12 +88,12 @@ func (x *cmdInterfaces) Execute(args []string) error {
for _, slot := range ifaces.Slots {
if wantedSnap != "" {
var ok bool
- if wantedSnap == slot.Snap || wantedSnap == snap.UseNick(slot.Snap) {
+ if wantedSnap == slot.Snap {
ok = true
}
for i := 0; i < len(slot.Connections) && !ok; i++ {
- if wantedSnap == slot.Connections[i].Snap || wantedSnap == snap.UseNick(slot.Connections[i].Snap) {
+ if wantedSnap == slot.Connections[i].Snap {
ok = true
}
}
@@ -110,7 +109,7 @@ func (x *cmdInterfaces) Execute(args []string) error {
}
// The OS snap is special and enable abbreviated
// display syntax on the slot-side of the connection.
- if slot.Snap == "core" || slot.Snap == "ubuntu-core" || slot.Snap == snap.UseNick("core") {
+ if slot.Snap == "system" {
fmt.Fprintf(w, ":%s\t", slot.Name)
} else {
fmt.Fprintf(w, "%s:%s\t", slot.Snap, slot.Name)
@@ -135,7 +134,7 @@ func (x *cmdInterfaces) Execute(args []string) error {
// plug, the loop below focuses on printing just the disconnected plugs.
for _, plug := range ifaces.Plugs {
if wantedSnap != "" {
- if wantedSnap != plug.Snap && wantedSnap != snap.UseNick(plug.Snap) {
+ if wantedSnap != plug.Snap {
continue
}
}
diff --git a/cmd/snap/cmd_interfaces_test.go b/cmd/snap/cmd_interfaces_test.go
index d58b2317b2..be70c107c3 100644
--- a/cmd/snap/cmd_interfaces_test.go
+++ b/cmd/snap/cmd_interfaces_test.go
@@ -278,7 +278,7 @@ func (s *SnapSuite) TestConnectionsOsSnapSlots(c *C) {
"result": client.Connections{
Slots: []client.Slot{
{
- Snap: "core",
+ Snap: "system",
Name: "network-listening",
Interface: "network-listening",
Label: "Ability to be a network service",
@@ -302,7 +302,7 @@ func (s *SnapSuite) TestConnectionsOsSnapSlots(c *C) {
Label: "Ability to be a network service",
Connections: []client.SlotRef{
{
- Snap: "core",
+ Snap: "system",
Name: "network-listening",
},
},
@@ -314,7 +314,7 @@ func (s *SnapSuite) TestConnectionsOsSnapSlots(c *C) {
Label: "Ability to be a network service",
Connections: []client.SlotRef{
{
- Snap: "core",
+ Snap: "system",
Name: "network-listening",
},
},
@@ -438,7 +438,7 @@ func (s *SnapSuite) TestConnectionsOfSystemNicknameSnap(c *C) {
"result": client.Connections{
Slots: []client.Slot{
{
- Snap: "core",
+ Snap: "system",
Name: "core-support",
Interface: "some-iface",
Connections: []client.PlugRef{{Snap: "core", Name: "core-support-plug"}},
@@ -453,13 +453,13 @@ func (s *SnapSuite) TestConnectionsOfSystemNicknameSnap(c *C) {
Snap: "core",
Name: "core-support-plug",
Interface: "some-iface",
- Connections: []client.SlotRef{{Snap: "core", Name: "core-support"}},
+ Connections: []client.SlotRef{{Snap: "system", Name: "core-support"}},
},
},
},
})
})
- rest, err := Parser().ParseArgs([]string{"interfaces", "core"})
+ rest, err := Parser().ParseArgs([]string{"interfaces", "system"})
c.Assert(err, IsNil)
c.Assert(rest, DeepEquals, []string{})
expectedStdout := "" +
diff --git a/cmd/snap/main.go b/cmd/snap/main.go
index 3fdf107f92..f6da78a05a 100644
--- a/cmd/snap/main.go
+++ b/cmd/snap/main.go
@@ -386,6 +386,19 @@ func (e *exitStatus) Error() string {
return fmt.Sprintf("internal error: exitStatus{%d} being handled as normal error", e.code)
}
+var wrongDashes = string([]rune{
+ 0x2010, // hyphen
+ 0x2011, // non-breaking hyphen
+ 0x2012, // figure dash
+ 0x2013, // en dash
+ 0x2014, // em dash
+ 0x2015, // horizontal bar
+ 0xfe58, // small em dash
+ 0x2015, // figure dash
+ 0x2e3a, // two-em dash
+ 0x2e3b, // three-em dash
+})
+
func run() error {
parser := Parser()
_, err := parser.Parse()
@@ -404,6 +417,19 @@ func run() error {
}
msg, err := errorToCmdMessage("", err, nil)
+
+ if cmdline := strings.Join(os.Args, " "); strings.ContainsAny(cmdline, wrongDashes) {
+ // TRANSLATORS: the %+q is the commandline (+q means quoted, with any non-ascii character called out). Please keep the lines to at most 80 characters.
+ fmt.Fprintf(Stderr, i18n.G(`Your command included some characters that look like dashes but are not:
+ %+q
+in some situations you might find that when copying from an online source such
+as a blog you need to replace “typographic” dashes and quotes with their ASCII
+equivalent. Dashes in particular are homoglyphs on most terminals and in most
+fixed-width fonts, so it can be hard to tell.
+
+`), cmdline)
+ }
+
if err != nil {
return err
}
diff --git a/daemon/api.go b/daemon/api.go
index 9a1ea19891..8b5823fb69 100644
--- a/daemon/api.go
+++ b/daemon/api.go
@@ -1649,7 +1649,7 @@ func splitQS(qs string) []string {
func getSnapConf(c *Command, r *http.Request, user *auth.UserState) Response {
vars := muxVars(r)
- snapName := snap.DropNick(vars["name"])
+ snapName := configstate.RemapSnapFromRequest(vars["name"])
keys := splitQS(r.URL.Query().Get("keys"))
@@ -1700,7 +1700,7 @@ func getSnapConf(c *Command, r *http.Request, user *auth.UserState) Response {
func setSnapConf(c *Command, r *http.Request, user *auth.UserState) Response {
vars := muxVars(r)
- snapName := snap.DropNick(vars["name"])
+ snapName := configstate.RemapSnapFromRequest(vars["name"])
var patchValues map[string]interface{}
if err := jsonutil.DecodeWithNumber(r.Body, &patchValues); err != nil {
@@ -1745,7 +1745,7 @@ func getInterfaces(c *Command, r *http.Request, user *auth.UserState) Response {
if pselect != "all" && pselect != "connected" {
return BadRequest("unsupported select qualifier")
}
- var names []string
+ var names []string // Interface names
namesStr := q.Get("names")
if namesStr != "" {
names = strings.Split(namesStr, ",")
@@ -1760,12 +1760,13 @@ func getInterfaces(c *Command, r *http.Request, user *auth.UserState) Response {
// Query the interface repository (this returns []*interface.Info).
infos := c.d.overlord.InterfaceManager().Repository().Info(opts)
infoJSONs := make([]*interfaceJSON, 0, len(infos))
+
for _, info := range infos {
// Convert interfaces.Info into interfaceJSON
plugs := make([]*plugJSON, 0, len(info.Plugs))
for _, plug := range info.Plugs {
plugs = append(plugs, &plugJSON{
- Snap: plug.Snap.InstanceName(),
+ Snap: ifacestate.RemapSnapToResponse(plug.Snap.InstanceName()),
Name: plug.Name,
Attrs: plug.Attrs,
Label: plug.Label,
@@ -1774,7 +1775,7 @@ func getInterfaces(c *Command, r *http.Request, user *auth.UserState) Response {
slots := make([]*slotJSON, 0, len(info.Slots))
for _, slot := range info.Slots {
slots = append(slots, &slotJSON{
- Snap: slot.Snap.InstanceName(),
+ Snap: ifacestate.RemapSnapToResponse(slot.Snap.InstanceName()),
Name: slot.Name,
Attrs: slot.Attrs,
Label: slot.Label,
@@ -1796,15 +1797,16 @@ func getLegacyConnections(c *Command, r *http.Request, user *auth.UserState) Res
ifaces := repo.Interfaces()
var ifjson interfaceJSON
-
plugConns := map[string][]interfaces.SlotRef{}
slotConns := map[string][]interfaces.PlugRef{}
- for _, conn := range ifaces.Connections {
- plugRef := conn.PlugRef.String()
- slotRef := conn.SlotRef.String()
- plugConns[plugRef] = append(plugConns[plugRef], conn.SlotRef)
- slotConns[slotRef] = append(slotConns[slotRef], conn.PlugRef)
+ for _, cref := range ifaces.Connections {
+ plugRef := interfaces.PlugRef{Snap: ifacestate.RemapSnapToResponse(cref.PlugRef.Snap), Name: cref.PlugRef.Name}
+ slotRef := interfaces.SlotRef{Snap: ifacestate.RemapSnapToResponse(cref.SlotRef.Snap), Name: cref.SlotRef.Name}
+ plugID := plugRef.String()
+ slotID := slotRef.String()
+ plugConns[plugID] = append(plugConns[plugID], slotRef)
+ slotConns[slotID] = append(slotConns[slotID], plugRef)
}
for _, plug := range ifaces.Plugs {
@@ -1812,14 +1814,15 @@ func getLegacyConnections(c *Command, r *http.Request, user *auth.UserState) Res
for _, app := range plug.Apps {
apps = append(apps, app.Name)
}
+ plugRef := interfaces.PlugRef{Snap: ifacestate.RemapSnapToResponse(plug.Snap.InstanceName()), Name: plug.Name}
pj := &plugJSON{
- Snap: plug.Snap.InstanceName(),
- Name: plug.Name,
+ Snap: plugRef.Snap,
+ Name: plugRef.Name,
Interface: plug.Interface,
Attrs: plug.Attrs,
Apps: apps,
Label: plug.Label,
- Connections: plugConns[plug.String()],
+ Connections: plugConns[plugRef.String()],
}
ifjson.Plugs = append(ifjson.Plugs, pj)
}
@@ -1828,15 +1831,15 @@ func getLegacyConnections(c *Command, r *http.Request, user *auth.UserState) Res
for _, app := range slot.Apps {
apps = append(apps, app.Name)
}
-
+ slotRef := interfaces.SlotRef{Snap: ifacestate.RemapSnapToResponse(slot.Snap.InstanceName()), Name: slot.Name}
sj := &slotJSON{
- Snap: slot.Snap.InstanceName(),
- Name: slot.Name,
+ Snap: slotRef.Snap,
+ Name: slotRef.Name,
Interface: slot.Interface,
Attrs: slot.Attrs,
Apps: apps,
Label: slot.Label,
- Connections: slotConns[slot.String()],
+ Connections: slotConns[slotRef.String()],
}
ifjson.Slots = append(ifjson.Slots, sj)
}
@@ -1895,10 +1898,10 @@ func changeInterfaces(c *Command, r *http.Request, user *auth.UserState) Respons
defer st.Unlock()
for i := range a.Plugs {
- a.Plugs[i].Snap = snap.DropNick(a.Plugs[i].Snap)
+ a.Plugs[i].Snap = ifacestate.RemapSnapFromRequest(a.Plugs[i].Snap)
}
for i := range a.Slots {
- a.Slots[i].Snap = snap.DropNick(a.Slots[i].Snap)
+ a.Slots[i].Snap = ifacestate.RemapSnapFromRequest(a.Slots[i].Snap)
}
switch a.Action {
diff --git a/daemon/api_test.go b/daemon/api_test.go
index eff7965beb..e0582317e1 100644
--- a/daemon/api_test.go
+++ b/daemon/api_test.go
@@ -3665,11 +3665,28 @@ func snapList(rawSnaps interface{}) []map[string]interface{} {
return snaps
}
+// inverseCaseMapper implements SnapMapper to use lower case internally and upper case externally.
+type inverseCaseMapper struct {
+ ifacestate.IdentityMapper // Embed the identity mapper to reuse empty state mapping functions.
+}
+
+func (m *inverseCaseMapper) RemapSnapFromRequest(snapName string) string {
+ return strings.ToLower(snapName)
+}
+
+func (m *inverseCaseMapper) RemapSnapToResponse(snapName string) string {
+ return strings.ToUpper(snapName)
+}
+
// Tests for GET /v2/interfaces
-func (s *apiSuite) TestInterfaces(c *check.C) {
- revert := builtin.MockInterface(&ifacetest.TestInterface{InterfaceName: "test"})
- defer revert()
+func (s *apiSuite) TestInterfacesLegacy(c *check.C) {
+ restore := builtin.MockInterface(&ifacetest.TestInterface{InterfaceName: "test"})
+ defer restore()
+ // Install an inverse case mapper to exercise the interface mapping at the same time.
+ restore = ifacestate.MockSnapMapper(&inverseCaseMapper{})
+ defer restore()
+
d := s.daemon(c)
s.mockSnap(c, consumerYaml)
@@ -3695,27 +3712,27 @@ func (s *apiSuite) TestInterfaces(c *check.C) {
"result": map[string]interface{}{
"plugs": []interface{}{
map[string]interface{}{
- "snap": "consumer",
+ "snap": "CONSUMER",
"plug": "plug",
"interface": "test",
"attrs": map[string]interface{}{"key": "value"},
"apps": []interface{}{"app"},
"label": "label",
"connections": []interface{}{
- map[string]interface{}{"snap": "producer", "slot": "slot"},
+ map[string]interface{}{"snap": "PRODUCER", "slot": "slot"},
},
},
},
"slots": []interface{}{
map[string]interface{}{
- "snap": "producer",
+ "snap": "PRODUCER",
"slot": "slot",
"interface": "test",
"attrs": map[string]interface{}{"key": "value"},
"apps": []interface{}{"app"},
"label": "label",
"connections": []interface{}{
- map[string]interface{}{"snap": "consumer", "plug": "plug"},
+ map[string]interface{}{"snap": "CONSUMER", "plug": "plug"},
},
},
},
@@ -3726,93 +3743,58 @@ func (s *apiSuite) TestInterfaces(c *check.C) {
})
}
-/**
-// Tests for GET /v2/interface (note: singular!)
+func (s *apiSuite) TestInterfacesModern(c *check.C) {
+ restore := builtin.MockInterface(&ifacetest.TestInterface{InterfaceName: "test"})
+ defer restore()
+ // Install an inverse case mapper to exercise the interface mapping at the same time.
+ restore = ifacestate.MockSnapMapper(&inverseCaseMapper{})
+ defer restore()
-func (s *apiSuite) TestInterfaceIndex(c *check.C) {
d := s.daemon(c)
- s.mockIface(c, &ifacetest.TestInterface{
- InterfaceName: "test",
- InterfaceStaticInfo: interfaces.StaticInfo{
- Summary: "summary",
- },
- })
s.mockSnap(c, consumerYaml)
s.mockSnap(c, producerYaml)
repo := d.overlord.InterfaceManager().Repository()
- connRef := interfaces.ConnRef{
+ connRef := &interfaces.ConnRef{
PlugRef: interfaces.PlugRef{Snap: "consumer", Name: "plug"},
SlotRef: interfaces.SlotRef{Snap: "producer", Name: "slot"},
}
- c.Assert(repo.Connect(connRef), check.IsNil)
-
- req, err := http.NewRequest("GET", "/v2/interface", nil)
+ _, err := repo.Connect(connRef, nil, nil, nil)
c.Assert(err, check.IsNil)
- rec := httptest.NewRecorder()
- interfaceIndexCmd.GET(interfaceIndexCmd, req, nil).ServeHTTP(rec, req)
- c.Check(rec.Code, check.Equals, 200)
- var body map[string]interface{}
- err = json.Unmarshal(rec.Body.Bytes(), &body)
- c.Check(err, check.IsNil)
- // The body contains large number of interface names, ensure that just the
- // test one, added above, exists.
- c.Check(body["result"], testutil.DeepContains, map[string]interface{}{
- "name": "test",
- "summary": "summary",
- "used": true,
- })
- c.Check(body["status"], check.Equals, "OK")
- c.Check(body["status-code"], check.Equals, 200.0)
- c.Check(body["type"], check.Equals, "sync")
-}
-
-// Tests for GET /v2/interface/test
-
-func (s *apiSuite) TestInterfaceDetail(c *check.C) {
- _ = s.daemon(c)
- s.mockIface(c, &ifacetest.TestInterface{
- InterfaceName: "test",
- InterfaceStaticInfo: interfaces.StaticInfo{
- Summary: "summary",
- },
- })
- s.mockSnap(c, consumerYaml)
- s.mockSnap(c, producerYaml)
-
- // NOTE: this is confusing, we must set s.vars manually,
- s.vars = map[string]string{"name": "test"}
- req, err := http.NewRequest("GET", "/v2/interface/test", nil)
+ req, err := http.NewRequest("GET", "/v2/interfaces?select=connected&doc=true&plugs=true&slots=true", nil)
c.Assert(err, check.IsNil)
rec := httptest.NewRecorder()
- interfaceDetailCmd.GET(interfaceDetailCmd, req, nil).ServeHTTP(rec, req)
+ interfacesCmd.GET(interfacesCmd, req, nil).ServeHTTP(rec, req)
c.Check(rec.Code, check.Equals, 200)
var body map[string]interface{}
err = json.Unmarshal(rec.Body.Bytes(), &body)
c.Check(err, check.IsNil)
c.Check(body, check.DeepEquals, map[string]interface{}{
- "result": map[string]interface{}{
- "name": "test",
- "summary": "summary",
- "plugs": []interface{}{
- map[string]interface{}{
- "snap": "consumer",
- "plug": "plug",
- "label": "label",
- "attrs": map[string]interface{}{"key": "value"},
- },
- },
- "slots": []interface{}{
- map[string]interface{}{
- "snap": "producer",
- "slot": "slot",
- "label": "label",
- "attrs": map[string]interface{}{"key": "value"},
+ "result": []interface{}{
+ map[string]interface{}{
+ "name": "test",
+ "plugs": []interface{}{
+ map[string]interface{}{
+ "snap": "CONSUMER",
+ "plug": "plug",
+ "label": "label",
+ "attrs": map[string]interface{}{
+ "key": "value",
+ },
+ }},
+ "slots": []interface{}{
+ map[string]interface{}{
+ "snap": "PRODUCER",
+ "slot": "slot",
+ "label": "label",
+ "attrs": map[string]interface{}{
+ "key": "value",
+ },
+ },
},
},
- "used": true,
},
"status": "OK",
"status-code": 200.0,
@@ -3820,36 +3802,15 @@ func (s *apiSuite) TestInterfaceDetail(c *check.C) {
})
}
-func (s *apiSuite) TestInterfaceDetail404(c *check.C) {
- _ = s.daemon(c)
-
- // NOTE: this is confusing, we must set s.vars manually,
- s.vars = map[string]string{"name": "test"}
- req, err := http.NewRequest("GET", "/v2/interface/test", nil)
- c.Assert(err, check.IsNil)
- rec := httptest.NewRecorder()
- interfaceDetailCmd.GET(interfaceDetailCmd, req, nil).ServeHTTP(rec, req)
- c.Check(rec.Code, check.Equals, 404)
- var body map[string]interface{}
- err = json.Unmarshal(rec.Body.Bytes(), &body)
- c.Check(err, check.IsNil)
- c.Check(body, check.DeepEquals, map[string]interface{}{
- "result": map[string]interface{}{
- "message": `cannot find interface named "test"`,
- },
- "status": "Not Found",
- "status-code": 404.0,
- "type": "error",
- })
-}
-
-**/
-
// Test for POST /v2/interfaces
func (s *apiSuite) TestConnectPlugSuccess(c *check.C) {
- revert := builtin.MockInterface(&ifacetest.TestInterface{InterfaceName: "test"})
- defer revert()
+ restore := builtin.MockInterface(&ifacetest.TestInterface{InterfaceName: "test"})
+ defer restore()
+ // Install an inverse case mapper to exercise the interface mapping at the same time.
+ restore = ifacestate.MockSnapMapper(&inverseCaseMapper{})
+ defer restore()
+
d := s.daemon(c)
s.mockSnap(c, consumerYaml)
@@ -3860,8 +3821,8 @@ func (s *apiSuite) TestConnectPlugSuccess(c *check.C) {
action := &interfaceAction{
Action: "connect",
- Plugs: []plugJSON{{Snap: "consumer", Name: "plug"}},
- Slots: []slotJSON{{Snap: "producer", Name: "slot"}},
+ Plugs: []plugJSON{{Snap: "CONSUMER", Name: "plug"}},
+ Slots: []slotJSON{{Snap: "PRODUCER", Name: "slot"}},
}
text, err := json.Marshal(action)
c.Assert(err, check.IsNil)
@@ -4059,8 +4020,11 @@ func (s *apiSuite) TestConnectCoreSystemAlias(c *check.C) {
}
func (s *apiSuite) testDisconnect(c *check.C, plugSnap, plugName, slotSnap, slotName string) {
- revert := builtin.MockInterface(&ifacetest.TestInterface{InterfaceName: "test"})
- defer revert()
+ restore := builtin.MockInterface(&ifacetest.TestInterface{InterfaceName: "test"})
+ defer restore()
+ // Install an inverse case mapper to exercise the interface mapping at the same time.
+ restore = ifacestate.MockSnapMapper(&inverseCaseMapper{})
+ defer restore()
d := s.daemon(c)
s.mockSnap(c, consumerYaml)
@@ -4113,15 +4077,15 @@ func (s *apiSuite) testDisconnect(c *check.C, plugSnap, plugName, slotSnap, slot
}
func (s *apiSuite) TestDisconnectPlugSuccess(c *check.C) {
- s.testDisconnect(c, "consumer", "plug", "producer", "slot")
+ s.testDisconnect(c, "CONSUMER", "plug", "PRODUCER", "slot")
}
func (s *apiSuite) TestDisconnectPlugSuccessWithEmptyPlug(c *check.C) {
- s.testDisconnect(c, "", "", "producer", "slot")
+ s.testDisconnect(c, "", "", "PRODUCER", "slot")
}
func (s *apiSuite) TestDisconnectPlugSuccessWithEmptySlot(c *check.C) {
- s.testDisconnect(c, "consumer", "plug", "", "")
+ s.testDisconnect(c, "CONSUMER", "plug", "", "")
}
func (s *apiSuite) TestDisconnectPlugFailureNoSuchPlug(c *check.C) {
diff --git a/overlord/configstate/configstate.go b/overlord/configstate/configstate.go
index 8cd49fab2a..a5281d91eb 100644
--- a/overlord/configstate/configstate.go
+++ b/overlord/configstate/configstate.go
@@ -120,3 +120,19 @@ func Configure(st *state.State, snapName string, patch map[string]interface{}, f
task := hookstate.HookTask(st, summary, hooksup, contextData)
return state.NewTaskSet(task)
}
+
+// RemapSnapFromRequest renames a snap as received from an API request
+func RemapSnapFromRequest(snapName string) string {
+ if snapName == "system" {
+ return "core"
+ }
+ return snapName
+}
+
+// RemapSnapToResponse renames a snap as about to be sent from an API response
+func RemapSnapToResponse(snapName string) string {
+ if snapName == "core" {
+ return "system"
+ }
+ return snapName
+}
diff --git a/overlord/configstate/configstate_test.go b/overlord/configstate/configstate_test.go
index 51f5b6cc6b..d78effb5b4 100644
--- a/overlord/configstate/configstate_test.go
+++ b/overlord/configstate/configstate_test.go
@@ -302,3 +302,20 @@ func (s *configcoreHijackSuite) TestHijack(c *C) {
c.Check(chg.Err(), IsNil)
c.Check(configcoreRan, Equals, true)
}
+
+type miscSuite struct{}
+
+var _ = Suite(&miscSuite{})
+
+func (s *miscSuite) TestRemappingFuncs(c *C) {
+ // We don't change those.
+ c.Assert(configstate.RemapSnapFromRequest("foo"), Equals, "foo")
+ c.Assert(configstate.RemapSnapFromRequest("snapd"), Equals, "snapd")
+ c.Assert(configstate.RemapSnapFromRequest("core"), Equals, "core")
+ c.Assert(configstate.RemapSnapToResponse("foo"), Equals, "foo")
+ c.Assert(configstate.RemapSnapToResponse("snapd"), Equals, "snapd")
+
+ // This is the one we alter.
+ c.Assert(configstate.RemapSnapFromRequest("system"), Equals, "core")
+ c.Assert(configstate.RemapSnapToResponse("core"), Equals, "system")
+}
diff --git a/overlord/ifacestate/export_test.go b/overlord/ifacestate/export_test.go
index 57eebed295..3f824f4ac4 100644
--- a/overlord/ifacestate/export_test.go
+++ b/overlord/ifacestate/export_test.go
@@ -32,6 +32,8 @@ var (
CheckConnectConflicts = checkConnectConflicts
FindSymmetricAutoconnect = findSymmetricAutoconnect
ConnectPriv = connect
+ GetConns = getConns
+ SetConns = setConns
)
// AddForeignTaskHandlers registers handlers for tasks handled outside of the
@@ -55,3 +57,11 @@ func MockContentLinkRetryTimeout(d time.Duration) (restore func()) {
contentLinkRetryTimeout = d
return func() { contentLinkRetryTimeout = old }
}
+
+// UpperCaseConnState returns a canned connection state map.
+// This allows us to keep connState private and still write some tests for it.
+func UpperCaseConnState() map[string]connState {
+ return map[string]connState{
+ "APP:network CORE:network": {Auto: true, Interface: "network"},
+ }
+}
diff --git a/overlord/ifacestate/helpers.go b/overlord/ifacestate/helpers.go
index e92fd5e81a..d19bc0660e 100644
--- a/overlord/ifacestate/helpers.go
+++ b/overlord/ifacestate/helpers.go
@@ -457,7 +457,9 @@ func getPlugAndSlotRefs(task *state.Task) (interfaces.PlugRef, interfaces.SlotRe
return plugRef, slotRef, nil
}
-// Get information about connections from the state
+// getConns returns information about connections from the state.
+//
+// Connections are transparently re-mapped according to remapIncomingConnRef
func getConns(st *state.State) (conns map[string]connState, err error) {
err = st.Get("conns", &conns)
if err != nil && err != state.ErrNoState {
@@ -466,11 +468,35 @@ func getConns(st *state.State) (conns map[string]connState, err error) {
if conns == nil {
conns = make(map[string]connState)
}
- return conns, nil
+ remapped := make(map[string]connState, len(conns))
+ for id, cstate := range conns {
+ cref, err := interfaces.ParseConnRef(id)
+ if err != nil {
+ return nil, err
+ }
+ cref.PlugRef.Snap = RemapSnapFromState(cref.PlugRef.Snap)
+ cref.SlotRef.Snap = RemapSnapFromState(cref.SlotRef.Snap)
+ remapped[cref.ID()] = cstate
+ }
+ return remapped, nil
}
+// setConns sets information about connections in the state.
+//
+// Connections are transparently re-mapped according to remapOutgoingConnRef
func setConns(st *state.State, conns map[string]connState) {
- st.Set("conns", conns)
+ remapped := make(map[string]connState, len(conns))
+ for id, cstate := range conns {
+ cref, err := interfaces.ParseConnRef(id)
+ if err != nil {
+ // We cannot fail here
+ panic(err)
+ }
+ cref.PlugRef.Snap = RemapSnapToState(cref.PlugRef.Snap)
+ cref.SlotRef.Snap = RemapSnapToState(cref.SlotRef.Snap)
+ remapped[cref.ID()] = cstate
+ }
+ st.Set("conns", remapped)
}
// snapsWithSecurityProfiles returns all snaps that have active
@@ -529,7 +555,8 @@ func snapsWithSecurityProfiles(st *state.State) ([]*snap.Info, error) {
func resolveSnapIDToName(st *state.State, snapID string) (name string, err error) {
if snapID == "system" {
- return snap.DropNick(snapID), nil
+ // Resolve the system nickname to a concrete snap.
+ return mapper.RemapSnapFromRequest(snapID), nil
}
decl, err := assertstate.SnapDeclaration(st, snapID)
if asserts.IsNotFound(err) {
@@ -541,6 +568,164 @@ func resolveSnapIDToName(st *state.State, snapID string) (name string, err error
return decl.SnapName(), nil
}
+// SnapMapper offers APIs for re-mapping snap names in interfaces and the
+// configuration system. The mapper is designed to apply transformations around
+// the edges of snapd (state interactions and API interactions) to offer one
+// view on the inside of snapd and another view on the outside.
+type SnapMapper interface {
+ // re-map functions for loading and saving objects in the state.
+ RemapSnapFromState(snapName string) string
+ RemapSnapToState(snapName string) string
+ // re-map functions for API requests/responses.
+ RemapSnapFromRequest(snapName string) string
+ RemapSnapToResponse(snapName string) string
+}
+
+// IdentityMapper implements SnapMapper and performs no transformations at all.
+type IdentityMapper struct{}
+
+// RemapSnapFromState doesn't change the snap name in any way.
+func (m *IdentityMapper) RemapSnapFromState(snapName string) string {
+ return snapName
+}
+
+// RemapSnapToState doesn't change the snap name in any way.
+func (m *IdentityMapper) RemapSnapToState(snapName string) string {
+ return snapName
+}
+
+// RemapSnapFromRequest doesn't change the snap name in any way.
+func (m *IdentityMapper) RemapSnapFromRequest(snapName string) string {
+ return snapName
+}
+
+// RemapSnapToResponse doesn't change the snap name in any way.
+func (m *IdentityMapper) RemapSnapToResponse(snapName string) string {
+ return snapName
+}
+
+// CoreCoreSystemMapper implements SnapMapper and makes implicit slots
+// appear to be on "core" in the state and in memory but as "system" in the API.
+//
+// NOTE: This mapper can be used to prepare, as an intermediate step, for the
+// transition to "snapd" mapper. Using it the state and API layer will look
+// exactly the same as with the "snapd" mapper. This can be used to make any
+// necessary adjustments the test suite.
+type CoreCoreSystemMapper struct {
+ IdentityMapper // Embedding the identity mapper allows us to cut on boilerplate.
+}
+
+// RemapSnapFromRequest renames the "system" snap to the "core" snap.
+//
+// This allows us to accept connection and disconnection requests that
+// explicitly refer to "core" or using the "system" nickname.
+func (m *CoreCoreSystemMapper) RemapSnapFromRequest(snapName string) string {
+ if snapName == "system" {
+ return "core"
+ }
+ return snapName
+}
+
+// RemapSnapToResponse renames the "core" snap to the "system" snap.
+//
+// This allows us to make all the implicitly defined slots, that are really
+// associated with the "core" snap to seemingly occupy the "system" snap
+// instead.
+func (m *CoreCoreSystemMapper) RemapSnapToResponse(snapName string) string {
+ if snapName == "core" {
+ return "system"
+ }
+ return snapName
+}
+
+// CoreSnapdSystemMapper implements SnapMapper and makes implicit slots
+// appear to be on "core" in the state and on "system" in the API while they
+// are on "snapd" in memory.
+type CoreSnapdSystemMapper struct {
+ IdentityMapper // Embedding the identity mapper allows us to cut on boilerplate.
+}
+
+// RemapSnapFromState renames the "core" snap to the "snapd" snap.
+//
+// This allows modern snapd to load an old state that remembers connections
+// between slots on the "core" snap and other snaps. In memory we are actually
+// using "snapd" snap for hosting those slots and this lets us stay compatible.
+func (m *CoreSnapdSystemMapper) RemapSnapFromState(snapName string) string {
+ if snapName == "core" {
+ return "snapd"
+ }
+ return snapName
+}
+
+// RemapSnapToState renames the "snapd" snap to the "core" snap.
+//
+// This allows the state to stay backwards compatible as all the connections
+// seem to refer to the "core" snap, as in pre core{16,18} days where there was
+// only one core snap.
+func (m *CoreSnapdSystemMapper) RemapSnapToState(snapName string) string {
+ if snapName == "snapd" {
+ return "core"
+ }
+ return snapName
+}
+
+// RemapSnapFromRequest renames the "core" or "system" snaps to the "snapd" snap.
+//
+// This allows us to accept connection and disconnection requests that
+// explicitly refer to "core" or "system" even though we really want them to
+// refer to "snapd". Note that this is not fully symmetric with
+// RemapSnapToResponse as we explicitly always talk about "system" snap,
+// even if the request used "core".
+func (m *CoreSnapdSystemMapper) RemapSnapFromRequest(snapName string) string {
+ if snapName == "system" || snapName == "core" {
+ return "snapd"
+ }
+ return snapName
+}
+
+// RemapSnapToResponse renames the "snapd" snap to the "system" snap.
+//
+// This allows us to make all the implicitly defined slots, that are really
+// associated with the "snapd" snap to seemingly occupy the "system" snap
+// instead. This ties into the concept of using "system" as a nickname (e.g. in
+// gadget snap connections).
+func (m *CoreSnapdSystemMapper) RemapSnapToResponse(snapName string) string {
+ if snapName == "snapd" {
+ return "system"
+ }
+ return snapName
+}
+
+// mapper contains the currently active snap mapper.
+var mapper SnapMapper = &CoreCoreSystemMapper{}
+
+// MockSnapMapper mocks the currently used snap mapper.
+func MockSnapMapper(new SnapMapper) (restore func()) {
+ old := mapper
+ mapper = new
+ return func() { mapper = old }
+}
+
+// RemapSnapFromState renames a snap when loaded from state according to the current mapper.
+func RemapSnapFromState(snapName string) string {
+ return mapper.RemapSnapFromState(snapName)
+}
+
+// RemapSnapToState renames a snap when saving to state according to the current mapper.
+func RemapSnapToState(snapName string) string {
+ return mapper.RemapSnapToState(snapName)
+}
+
+// RemapSnapFromRequest renames a snap as received from an API request according to the current mapper.
+func RemapSnapFromRequest(snapName string) string {
+ return mapper.RemapSnapFromRequest(snapName)
+}
+
+// RemapSnapToResponse renames a snap as about to be sent from an API response according to the current mapper.
+func RemapSnapToResponse(snapName string) string {
+ return mapper.RemapSnapToResponse(snapName)
+}
+
func connectDisconnectAffectedSnaps(t *state.Task) ([]string, error) {
plugRef, slotRef, err := getPlugAndSlotRefs(t)
if err != nil {
diff --git a/overlord/ifacestate/helpers_test.go b/overlord/ifacestate/helpers_test.go
new file mode 100644
index 0000000000..5d99913d7b
--- /dev/null
+++ b/overlord/ifacestate/helpers_test.go
@@ -0,0 +1,162 @@
+// -*- Mode: Go; indent-tabs-mode: t -*-
+
+/*
+ * Copyright (C) 2018 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package ifacestate_test
+
+import (
+ "strings"
+
+ . "gopkg.in/check.v1"
+
+ "github.com/snapcore/snapd/overlord/ifacestate"
+ "github.com/snapcore/snapd/overlord/state"
+)
+
+type helpersSuite struct {
+ st *state.State
+}
+
+var _ = Suite(&helpersSuite{})
+
+func (s *helpersSuite) SetUpTest(c *C) {
+ s.st = state.New(nil)
+}
+
+func (s *helpersSuite) TestIdentityMapper(c *C) {
+ var m ifacestate.SnapMapper = &ifacestate.IdentityMapper{}
+
+ // Nothing is altered.
+ c.Assert(m.RemapSnapFromState("example"), Equals, "example")
+ c.Assert(m.RemapSnapToState("example"), Equals, "example")
+ c.Assert(m.RemapSnapFromRequest("example"), Equals, "example")
+ c.Assert(m.RemapSnapToResponse("example"), Equals, "example")
+}
+
+func (s *helpersSuite) TestCoreCoreSystemMapper(c *C) {
+ var m ifacestate.SnapMapper = &ifacestate.CoreCoreSystemMapper{}
+
+ // Snaps are not renamed when interacting with the state.
+ c.Assert(m.RemapSnapFromState("core"), Equals, "core")
+ c.Assert(m.RemapSnapToState("core"), Equals, "core")
+
+ // The "core" snap is renamed to the "system" in API response
+ // and back in the API requests.
+ c.Assert(m.RemapSnapFromRequest("system"), Equals, "core")
+ c.Assert(m.RemapSnapToResponse("core"), Equals, "system")
+
+ // Other snap names are unchanged.
+ c.Assert(m.RemapSnapFromState("potato"), Equals, "potato")
+ c.Assert(m.RemapSnapToState("potato"), Equals, "potato")
+ c.Assert(m.RemapSnapFromRequest("potato"), Equals, "potato")
+ c.Assert(m.RemapSnapToResponse("potato"), Equals, "potato")
+}
+
+func (s *helpersSuite) TestCoreSnapdSystemMapper(c *C) {
+ var m ifacestate.SnapMapper = &ifacestate.CoreSnapdSystemMapper{}
+
+ // The "snapd" snap is renamed to the "core" in when saving the state
+ // and back when loading the state.
+ c.Assert(m.RemapSnapFromState("core"), Equals, "snapd")
+ c.Assert(m.RemapSnapToState("snapd"), Equals, "core")
+
+ // The "snapd" snap is renamed to the "system" in API response and back in
+ // the API requests.
+ c.Assert(m.RemapSnapFromRequest("system"), Equals, "snapd")
+ c.Assert(m.RemapSnapToResponse("snapd"), Equals, "system")
+
+ // The "core" snap is also renamed to "snapd" in API requests, for
+ // compatibility.
+ c.Assert(m.RemapSnapFromRequest("core"), Equals, "snapd")
+
+ // Other snap names are unchanged.
+ c.Assert(m.RemapSnapFromState("potato"), Equals, "potato")
+ c.Assert(m.RemapSnapToState("potato"), Equals, "potato")
+ c.Assert(m.RemapSnapFromRequest("potato"), Equals, "potato")
+ c.Assert(m.RemapSnapToResponse("potato"), Equals, "potato")
+}
+
+// caseMapper implements SnapMapper to use upper case internally and lower case externally.
+type caseMapper struct{}
+
+func (m *caseMapper) RemapSnapFromState(snapName string) string {
+ return strings.ToUpper(snapName)
+}
+
+func (m *caseMapper) RemapSnapToState(snapName string) string {
+ return strings.ToLower(snapName)
+}
+
+func (m *caseMapper) RemapSnapFromRequest(snapName string) string {
+ return strings.ToUpper(snapName)
+}
+
+func (m *caseMapper) RemapSnapToResponse(snapName string) string {
+ return strings.ToLower(snapName)
+}
+
+func (s *helpersSuite) TestMappingFunctions(c *C) {
+ restore := ifacestate.MockSnapMapper(&caseMapper{})
+ defer restore()
+
+ c.Assert(ifacestate.RemapSnapFromState("example"), Equals, "EXAMPLE")
+ c.Assert(ifacestate.RemapSnapToState("EXAMPLE"), Equals, "example")
+ c.Assert(ifacestate.RemapSnapFromRequest("example"), Equals, "EXAMPLE")
+ c.Assert(ifacestate.RemapSnapToResponse("EXAMPLE"), Equals, "example")
+}
+
+func (s *helpersSuite) TestGetConns(c *C) {
+ s.st.Lock()
+ defer s.st.Unlock()
+ s.st.Set("conns", map[string]interface{}{
+ "app:network core:network": map[string]interface{}{
+ "auto": true,
+ "interface": "network",
+ },
+ })
+
+ restore := ifacestate.MockSnapMapper(&caseMapper{})
+ defer restore()
+
+ conns, err := ifacestate.GetConns(s.st)
+ c.Assert(err, IsNil)
+ for id, connState := range conns {
+ c.Assert(id, Equals, "APP:network CORE:network")
+ c.Assert(connState.Auto, Equals, true)
+ c.Assert(connState.Interface, Equals, "network")
+ }
+}
+
+func (s *helpersSuite) TestSetConns(c *C) {
+ s.st.Lock()
+ defer s.st.Unlock()
+
+ restore := ifacestate.MockSnapMapper(&caseMapper{})
+ defer restore()
+
+ // This has upper-case data internally, see export_test.go
+ ifacestate.SetConns(s.st, ifacestate.UpperCaseConnState())
+ var conns map[string]interface{}
+ err := s.st.Get("conns", &conns)
+ c.Assert(err, IsNil)
+ c.Assert(conns, DeepEquals, map[string]interface{}{
+ "app:network core:network": map[string]interface{}{
+ "auto": true,
+ "interface": "network",
+ }})
+}
diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD
index 239ba7f2d9..2a8b4e4b12 100644
--- a/packaging/arch/PKGBUILD
+++ b/packaging/arch/PKGBUILD
@@ -10,7 +10,7 @@ pkgname=snapd
pkgdesc="Service and tools for management of snap packages."
depends=('squashfs-tools' 'libseccomp' 'libsystemd')
optdepends=('bash-completion: bash completion support')
-pkgver=2.34
+pkgver=2.34.2
pkgrel=1
arch=('x86_64')
url="https://github.com/snapcore/snapd"
diff --git a/packaging/fedora/snapd.spec b/packaging/fedora/snapd.spec
index f59848f33f..84c44906bb 100644
--- a/packaging/fedora/snapd.spec
+++ b/packaging/fedora/snapd.spec
@@ -73,7 +73,7 @@
%endif
Name: snapd
-Version: 2.34
+Version: 2.34.2
Release: 0%{?dist}
Summary: A transactional software package manager
Group: System Environment/Base
@@ -733,6 +733,18 @@ fi
%changelog
+* Thu Jul 19 2018 Michael Vogt <mvo@ubuntu.com>
+ - packaging: fix bogus date in fedora snapd.spec
+ - tests: fix tests expecting old email address
+
+* Tue Jul 17 2018 Michael Vogt <mvo@ubuntu.com>
+ - tests: cherry-pick test fixes from master for 2.34
+ - coreconfig: add support for `snap set system network.disable-
+ ipv6`
+ - debian: do not ship snapd.apparmor.service on ubuntu
+ - overlord/snapstate: dedupe default content providers
+ - interfaces/builtin: create can-bus interface
+
* Fri Jul 06 2018 Michael Vogt <mvo@ubuntu.com>
- New upstream release 2.34
- store, daemon, client, cmd/snap: expose "scope", default to wide*
@@ -1392,7 +1404,7 @@ fi
UbuntuStore(Repository)? references
- store: reorg auth refresh
-* Tue May 16 2018 Michael Vogt <mvo@ubuntu.com>
+* Wed May 16 2018 Michael Vogt <mvo@ubuntu.com>
- New upstream release 2.32.9
- tests: run all spread tests inside GCE
- tests: build spread in the autopkgtests with a more recent go
diff --git a/packaging/opensuse/snapd.changes b/packaging/opensuse/snapd.changes
index e809da5edf..573e91660c 100644
--- a/packaging/opensuse/snapd.changes
+++ b/packaging/opensuse/snapd.changes
@@ -1,4 +1,14 @@
-------------------------------------------------------------------
+Thu Jul 19 12:05:50 UTC 2018 - mvo@fastmail.fm
+
+- Update to upstream release 2.34.2
+
+-------------------------------------------------------------------
+Wed Jul 17 19:46:56 UTC 2018 - mvo@fastmail.fm
+
+- Update to upstream release 2.34.1
+
+-------------------------------------------------------------------
Fri Jul 06 16:08:17 UTC 2018 - mvo@fastmail.fm
- Update to upstream release 2.34
@@ -17,7 +27,7 @@ Fri Jun 22 14:25:35 UTC 2018 - me@zygoon.pl
- Load snap-confine apparmor profile in post, if apparmor is enabled
- Adjust badness of polkit-untracked-privlege
-------------------------------------------------------------------
-Fri Jun 21 17:37:56 UTC 2018 - mvo@fastmail.fm
+Thu Jun 21 17:37:56 UTC 2018 - mvo@fastmail.fm
- Update to upstream release 2.33.1
diff --git a/packaging/opensuse/snapd.spec b/packaging/opensuse/snapd.spec
index 8db9b790a9..d502ef0a98 100644
--- a/packaging/opensuse/snapd.spec
+++ b/packaging/opensuse/snapd.spec
@@ -61,7 +61,7 @@
%global snap_mount_dir /snap
Name: snapd
-Version: 2.34
+Version: 2.34.2
Release: 0
Summary: Tools enabling systems to work with .snap files
License: GPL-3.0
diff --git a/packaging/ubuntu-14.04/changelog b/packaging/ubuntu-14.04/changelog
index 86ac5dda00..e62339ad5d 100644
--- a/packaging/ubuntu-14.04/changelog
+++ b/packaging/ubuntu-14.04/changelog
@@ -1,3 +1,23 @@
+snapd (2.34.2~14.04) trusty; urgency=medium
+
+ * New upstream release, LP: #1779403
+ - packaging: fix bogus date in fedora snapd.spec
+ - tests: fix tests expecting old email address
+
+ -- Michael Vogt <michael.vogt@ubuntu.com> Thu, 19 Jul 2018 12:05:50 +0200
+
+snapd (2.34.1~14.04) trusty; urgency=medium
+
+ * New upstream release, LP: #1779403
+ - tests: cherry-pick test fixes from master for 2.34
+ - coreconfig: add support for `snap set system network.disable-
+ ipv6`
+ - debian: do not ship snapd.apparmor.service on ubuntu
+ - overlord/snapstate: dedupe default content providers
+ - interfaces/builtin: create can-bus interface
+
+ -- Michael Vogt <michael.vogt@ubuntu.com> Tue, 17 Jul 2018 19:46:56 +0200
+
snapd (2.34~14.04) trusty; urgency=medium
* New upstream release, LP: #1779403
diff --git a/packaging/ubuntu-16.04/changelog b/packaging/ubuntu-16.04/changelog
index a54c56598c..cdea1c6785 100644
--- a/packaging/ubuntu-16.04/changelog
+++ b/packaging/ubuntu-16.04/changelog
@@ -1,3 +1,23 @@
+snapd (2.34.2) xenial; urgency=medium
+
+ * New upstream release, LP: #1779403
+ - packaging: fix bogus date in fedora snapd.spec
+ - tests: fix tests expecting old email address
+
+ -- Michael Vogt <michael.vogt@ubuntu.com> Thu, 19 Jul 2018 12:05:50 +0200
+
+snapd (2.34.1) xenial; urgency=medium
+
+ * New upstream release, LP: #1779403
+ - tests: cherry-pick test fixes from master for 2.34
+ - coreconfig: add support for `snap set system network.disable-
+ ipv6`
+ - debian: do not ship snapd.apparmor.service on ubuntu
+ - overlord/snapstate: dedupe default content providers
+ - interfaces/builtin: create can-bus interface
+
+ -- Michael Vogt <michael.vogt@ubuntu.com> Tue, 17 Jul 2018 19:46:56 +0200
+
snapd (2.34) xenial; urgency=medium
* New upstream release, LP: #1779403
diff --git a/snap/info.go b/snap/info.go
index b1ba386bf7..143e0969ea 100644
--- a/snap/info.go
+++ b/snap/info.go
@@ -999,24 +999,6 @@ func JoinSnapApp(snap, app string) string {
return fmt.Sprintf("%s.%s", snap, app)
}
-// UseNick returns the nickname for given snap name. If there is none, returns
-// the original name.
-func UseNick(snapName string) string {
- if snapName == "core" {
- return "system"
- }
- return snapName
-}
-
-// DropNick returns the snap name for given nickname. If there is none, returns
-// the original name.
-func DropNick(nick string) string {
- if nick == "system" {
- return "core"
- }
- return nick
-}
-
// InstanceSnap splits the instance name and returns the name of the snap.
func InstanceSnap(instanceName string) string {
snapName, _ := SplitInstanceName(instanceName)
diff --git a/snap/info_test.go b/snap/info_test.go
index 35eaa78277..2856144c9b 100644
--- a/snap/info_test.go
+++ b/snap/info_test.go
@@ -1206,16 +1206,6 @@ func (s *infoSuite) TestStopModeTypeKillSignal(c *C) {
}
}
-func (s *infoSuite) TestNickname(c *C) {
- c.Check(snap.UseNick("core"), Equals, "system")
- c.Check(snap.UseNick("system"), Equals, "system")
- c.Check(snap.UseNick("foo"), Equals, "foo")
-
- c.Check(snap.DropNick("core"), Equals, "core")
- c.Check(snap.DropNick("system"), Equals, "core")
- c.Check(snap.DropNick("foo"), Equals, "foo")
-}
-
func (s *infoSuite) TestSplitInstanceName(c *C) {
snapName, instanceKey := snap.SplitInstanceName("foo_bar")
c.Check(snapName, Equals, "foo")
diff --git a/tests/lib/snaps/test-snapd-policy-app-provider-classic/meta/snap.yaml b/tests/lib/snaps/test-snapd-policy-app-provider-classic/meta/snap.yaml
index d5d56f6562..37f2abbcaf 100644
--- a/tests/lib/snaps/test-snapd-policy-app-provider-classic/meta/snap.yaml
+++ b/tests/lib/snaps/test-snapd-policy-app-provider-classic/meta/snap.yaml
@@ -18,6 +18,7 @@ slots:
interface: dbus
bus: system
name: test.system
+ fwupd: null
location-control: null
location-observe: null
lxd: null
@@ -48,6 +49,9 @@ apps:
docker:
command: bin/run
slots: [ docker ]
+ fwupd:
+ command: bin/run
+ slots: [ fwupd ]
location-control:
command: bin/run
slots: [ location-control ]
diff --git a/tests/lib/snaps/test-snapd-policy-app-provider-core/meta/snap.yaml b/tests/lib/snaps/test-snapd-policy-app-provider-core/meta/snap.yaml
index 9a46426528..9eed9f1a63 100644
--- a/tests/lib/snaps/test-snapd-policy-app-provider-core/meta/snap.yaml
+++ b/tests/lib/snaps/test-snapd-policy-app-provider-core/meta/snap.yaml
@@ -43,6 +43,8 @@ slots:
unity8-calendar: null
unity8-contacts: null
upower-observe: null
+ wayland: null
+ x11: null
apps:
avahi-control:
@@ -129,3 +131,9 @@ apps:
upower-observe:
command: bin/run
slots: [ upower-observe ]
+ wayland:
+ command: bin/run
+ slots: [ wayland ]
+ x11:
+ command: bin/run
+ slots: [ x11 ]
diff --git a/tests/main/install-errors/task.yaml b/tests/main/install-errors/task.yaml
index aba8928ce2..399ff877f4 100644
--- a/tests/main/install-errors/task.yaml
+++ b/tests/main/install-errors/task.yaml
@@ -81,3 +81,10 @@ execute: |
fi
MATCH 'error: snap "pi2-kernel" is not available on stable for this architecture' < stderr.out
fi
+
+ echo "Install a snap with suspicious characters in its name"
+ if snap install atom ––classic 2>stderr.out; then
+ echo "snap install atom ––classic should have failed but did not"
+ exit 1
+ fi
+ MATCH 'characters that look like dashes but are not' < stderr.out
diff --git a/tests/main/snap-info/check.py b/tests/main/snap-info/check.py
index 501ac2eaff..b406a2624b 100644
--- a/tests/main/snap-info/check.py
+++ b/tests/main/snap-info/check.py
@@ -73,7 +73,7 @@ check("basic-desktop", res[1],
check("test-snapd-tools", res[2],
("name", equals, "test-snapd-tools"),
("publisher", equals, "canonical"),
- ("contact", equals, "snappy-canonical-storeaccount@canonical.com"),
+ ("contact", equals, "snaps@canonical.com"),
("summary", equals, "Tools for testing the snapd application"),
("description", equals, "A tool to test snapd\n"),
("commands", exists),
@@ -87,13 +87,13 @@ check("test-snapd-tools", res[2],
("edge", matches, verRevNotesRx("-")),
),
("snap-id", equals, snap_ids["test-snapd-tools"]),
- ("license", equals, "unset"), # TODO: update once snap.yaml contains the right license
+ ("license", matches, r"(unknown|unset)"), # TODO: update once snap.yaml contains the right license
)
check("test-snapd-devmode", res[3],
("name", equals, "test-snapd-devmode"),
("publisher", equals, "canonical"),
- ("contact", equals, "snappy-canonical-storeaccount@canonical.com"),
+ ("contact", equals, "snaps@canonical.com"),
("summary", equals, "Basic snap with devmode confinement"),
("description", equals, "A basic buildable snap that asks for devmode confinement\n"),
("tracking", equals, "beta"),
@@ -106,7 +106,7 @@ check("test-snapd-devmode", res[3],
("edge", matches, verRevNotesRx("devmode")),
),
("snap-id", equals, snap_ids["test-snapd-devmode"]),
- ("license", equals, "unset"), # TODO: update once snap.yaml contains the right license
+ ("license", matches, r"(unknown|unset)"), # TODO: update once snap.yaml contains the right license
)
check("core", res[4],
@@ -124,7 +124,7 @@ check("core", res[4],
# sideload "core"
("contact", maybe),
("snap-id", maybe),
- ("license", equals, "unset"), # TODO: update once snap.yaml contains the right license
+ ("license", matches, r"(unknown|unset)"), # TODO: update once snap.yaml contains the right license
)
check("error", res[5],
@@ -135,7 +135,7 @@ check("error", res[5],
check("test-snapd-python-webserver", res[6],
("name", equals, "test-snapd-python-webserver"),
("publisher", equals, "canonical"),
- ("contact", equals, "snappy-canonical-storeaccount@canonical.com"),
+ ("contact", equals, "snaps@canonical.com"),
("summary", exists),
("description", exists),
("channels", exists),
diff --git a/tests/main/snap-run-hook/task.yaml b/tests/main/snap-run-hook/task.yaml
index 8616fcb9a8..37ebcb38b1 100644
--- a/tests/main/snap-run-hook/task.yaml
+++ b/tests/main/snap-run-hook/task.yaml
@@ -8,12 +8,9 @@ environment:
ENVDUMP: /var/snap/basic-hooks/current/hooks-env
prepare: |
- echo "Build test hooks package"
- snap pack $TESTSLIB/snaps/basic-hooks
- snap install --dangerous basic-hooks_1.0_all.snap
-
-restore: |
- rm -f basic-hooks_1.0_all.snap
+ #shellcheck source=tests/lib/snaps.sh
+ . $TESTSLIB/snaps.sh
+ install_local basic-hooks
execute: |
# Note that `snap run` doesn't exit non-zero if the hook is missing, so we