Skip to content

Commit

Permalink
Merge pull request #2605 from pedronis/orthog-alias-refresh
Browse files Browse the repository at this point in the history
overlord,overlord/snapstate: have UpdateMany retire/enable auto-aliases even without new revision
  • Loading branch information
mvo5 committed Jan 12, 2017
2 parents 8923092 + fa67181 commit e7a61bd
Show file tree
Hide file tree
Showing 4 changed files with 529 additions and 54 deletions.
157 changes: 157 additions & 0 deletions overlord/managers_test.go
Expand Up @@ -32,6 +32,7 @@ import (
"net/url" "net/url"
"os" "os"
"path/filepath" "path/filepath"
"sort"
"strings" "strings"
"time" "time"


Expand Down Expand Up @@ -1321,6 +1322,162 @@ apps:
c.Check(dest, Equals, "foo.app2") c.Check(dest, Equals, "foo.app2")
} }


func (ms *mgrsSuite) TestHappyOrthogonalRefreshAutoAliases(c *C) {
ms.prereqSnapAssertions(c, map[string]interface{}{
"snap-name": "foo",
"auto-aliases": []interface{}{"app1"},
}, map[string]interface{}{
"snap-name": "bar",
})

fooYaml := `name: foo
version: @VERSION@
apps:
app1:
command: bin/app1
aliases: [app1]
app2:
command: bin/app2
aliases: [app2]
`

barYaml := `name: bar
version: @VERSION@
apps:
app1:
command: bin/app1
aliases: [app1]
app3:
command: bin/app3
aliases: [app3]
`

fooPath, _ := ms.makeStoreTestSnap(c, strings.Replace(fooYaml, "@VERSION@", "1.0", -1), "10")
ms.serveSnap(fooPath, "10")

barPath, _ := ms.makeStoreTestSnap(c, strings.Replace(barYaml, "@VERSION@", "2.0", -1), "20")
ms.serveSnap(barPath, "20")

mockServer := ms.mockStore(c)
defer mockServer.Close()

st := ms.o.State()
st.Lock()
defer st.Unlock()

ts, err := snapstate.Install(st, "foo", "stable", snap.R(0), 0, snapstate.Flags{})
c.Assert(err, IsNil)
chg := st.NewChange("install-snap", "...")
chg.AddAll(ts)

st.Unlock()
err = ms.o.Settle()
st.Lock()
c.Assert(err, IsNil)

c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("install-snap change failed with: %v", chg.Err()))

c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("install-snap change failed with: %v", chg.Err()))

ts, err = snapstate.Install(st, "bar", "stable", snap.R(0), 0, snapstate.Flags{})
c.Assert(err, IsNil)
chg = st.NewChange("install-snap", "...")
chg.AddAll(ts)

st.Unlock()
err = ms.o.Settle()
st.Lock()
c.Assert(err, IsNil)

c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("install-snap change failed with: %v", chg.Err()))

info, err := snapstate.CurrentInfo(st, "foo")
c.Assert(err, IsNil)
c.Check(info.Revision, Equals, snap.R(10))
c.Check(info.Version, Equals, "1.0")

info, err = snapstate.CurrentInfo(st, "bar")
c.Assert(err, IsNil)
c.Check(info.Revision, Equals, snap.R(20))
c.Check(info.Version, Equals, "2.0")

var allAliases map[string]map[string]string
err = st.Get("aliases", &allAliases)
c.Check(err, IsNil)
c.Check(allAliases, DeepEquals, map[string]map[string]string{
"foo": {
"app1": "auto",
},
})

ms.prereqSnapAssertions(c, map[string]interface{}{
"snap-name": "foo",
"auto-aliases": []interface{}{"app2"},
"revision": "1",
}, map[string]interface{}{
"snap-name": "bar",
"auto-aliases": []interface{}{"app1", "app3"},
"revision": "1",
})

// new foo version/revision
fooPath, _ = ms.makeStoreTestSnap(c, strings.Replace(fooYaml, "@VERSION@", "1.5", -1), "15")
ms.serveSnap(fooPath, "15")

// refresh all
err = assertstate.RefreshSnapDeclarations(st, 0)
c.Assert(err, IsNil)

updated, tss, err := snapstate.UpdateMany(st, nil, 0)
c.Assert(err, IsNil)
sort.Strings(updated)
c.Assert(updated, DeepEquals, []string{"bar", "foo"})
c.Assert(tss, HasLen, 3)
chg = st.NewChange("upgrade-snaps", "...")
chg.AddAll(tss[0])
chg.AddAll(tss[1])
chg.AddAll(tss[2])

st.Unlock()
err = ms.o.Settle()
st.Lock()
c.Assert(err, IsNil)

c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("upgrade-snap change failed with: %v", chg.Err()))

info, err = snapstate.CurrentInfo(st, "foo")
c.Assert(err, IsNil)
c.Check(info.Revision, Equals, snap.R(15))
c.Check(info.Version, Equals, "1.5")

allAliases = nil
err = st.Get("aliases", &allAliases)
c.Check(err, IsNil)
c.Check(allAliases, DeepEquals, map[string]map[string]string{
"foo": {
"app2": "auto",
},
"bar": {
"app1": "auto",
"app3": "auto",
},
})

app2Alias := filepath.Join(dirs.SnapBinariesDir, "app2")
dest, err := os.Readlink(app2Alias)
c.Assert(err, IsNil)
c.Check(dest, Equals, "foo.app2")

app1Alias := filepath.Join(dirs.SnapBinariesDir, "app1")
dest, err = os.Readlink(app1Alias)
c.Assert(err, IsNil)
c.Check(dest, Equals, "bar.app1")
app3Alias := filepath.Join(dirs.SnapBinariesDir, "app3")
dest, err = os.Readlink(app3Alias)
c.Assert(err, IsNil)
c.Check(dest, Equals, "bar.app3")
}

type authContextSetupSuite struct { type authContextSetupSuite struct {
o *overlord.Overlord o *overlord.Overlord
ac auth.AuthContext ac auth.AuthContext
Expand Down
107 changes: 55 additions & 52 deletions overlord/snapstate/backend_test.go
Expand Up @@ -148,71 +148,74 @@ func (f *fakeStore) ListRefresh(cands []*store.RefreshCandidate, _ *auth.UserSta
if len(cands) == 0 { if len(cands) == 0 {
return nil, nil return nil, nil
} }
if len(cands) != 1 { if len(cands) > 2 {
panic("ListRefresh unexpectedly called with more than one candidate") panic("ListRefresh unexpectedly called with more than two candidates")
} }
cand := cands[0]


snapID := cand.SnapID var res []*snap.Info
for _, cand := range cands {
snapID := cand.SnapID


if snapID == "" { if snapID == "" || snapID == "other-snap-id" {
return nil, nil continue
} }


if snapID == "fakestore-please-error-on-refresh" { if snapID == "fakestore-please-error-on-refresh" {
return nil, fmt.Errorf("failing as requested") return nil, fmt.Errorf("failing as requested")
} }


var name string var name string
if snapID == "some-snap-id" { if snapID == "some-snap-id" {
name = "some-snap" name = "some-snap"
} else { } else {
panic(fmt.Sprintf("ListRefresh: unknown snap-id: %s", snapID)) panic(fmt.Sprintf("ListRefresh: unknown snap-id: %s", snapID))
} }


revno := snap.R(11) revno := snap.R(11)
confinement := snap.StrictConfinement confinement := snap.StrictConfinement
switch cand.Channel { switch cand.Channel {
case "channel-for-7": case "channel-for-7":
revno = snap.R(7) revno = snap.R(7)
case "channel-for-classic": case "channel-for-classic":
confinement = snap.ClassicConfinement confinement = snap.ClassicConfinement
case "channel-for-devmode": case "channel-for-devmode":
confinement = snap.DevModeConfinement confinement = snap.DevModeConfinement
} }


info := &snap.Info{ info := &snap.Info{
SideInfo: snap.SideInfo{ SideInfo: snap.SideInfo{
RealName: name, RealName: name,
Channel: cand.Channel, Channel: cand.Channel,
SnapID: cand.SnapID, SnapID: cand.SnapID,
Revision: revno, Revision: revno,
}, },
Version: name, Version: name,
DownloadInfo: snap.DownloadInfo{ DownloadInfo: snap.DownloadInfo{
DownloadURL: "https://some-server.com/some/path.snap", DownloadURL: "https://some-server.com/some/path.snap",
}, },
Confinement: confinement, Confinement: confinement,
} }


var hit snap.Revision var hit snap.Revision
if cand.Revision != revno { if cand.Revision != revno {
hit = revno hit = revno
} }
for _, blocked := range cand.Block { for _, blocked := range cand.Block {
if blocked == revno { if blocked == revno {
hit = snap.Revision{} hit = snap.Revision{}
break break
}
} }
}


f.fakeBackend.ops = append(f.fakeBackend.ops, fakeOp{op: "storesvc-list-refresh", cand: *cand, revno: hit}) f.fakeBackend.ops = append(f.fakeBackend.ops, fakeOp{op: "storesvc-list-refresh", cand: *cand, revno: hit})


if hit.Unset() { if !hit.Unset() {
return nil, nil
res = append(res, info)
}
} }


return []*snap.Info{info}, nil return res, nil
} }


func (f *fakeStore) SuggestedCurrency() string { func (f *fakeStore) SuggestedCurrency() string {
Expand Down

0 comments on commit e7a61bd

Please sign in to comment.