Skip to content

Commit

Permalink
Ensure snap try installs core if its missing
Browse files Browse the repository at this point in the history
LP: #1643888
  • Loading branch information
mvo5 committed Nov 28, 2016
1 parent 2fb1c7f commit a00572a
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 40 deletions.
12 changes: 10 additions & 2 deletions daemon/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1122,13 +1122,21 @@ func trySnap(c *Command, r *http.Request, user *auth.UserState, trydir string, f
return BadRequest("cannot read snap info for %s: %s", trydir, err)
}

tsets, err := snapstateTryPath(st, info.Name(), trydir, flags)
var userID int
if user != nil {
userID = user.ID
}
tsets, err := withEnsureUbuntuCore(st, info.Name(), userID,
func() (*state.TaskSet, error) {
return snapstateTryPath(st, info.Name(), 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{tsets}, []string{info.Name()})
chg := newChange(st, "try-snap", msg, tsets, []string{info.Name()})
chg.Set("api-data", map[string]string{"snap-name": info.Name()})

ensureStateSoon(st)
Expand Down
99 changes: 61 additions & 38 deletions daemon/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1879,12 +1879,6 @@ func (s *apiSuite) TestTrySnap(c *check.C) {
d.overlord.Loop()
defer d.overlord.Stop()

soon := 0
ensureStateSoon = func(st *state.State) {
soon++
ensureStateSoonImpl(st)
}

req, err := http.NewRequest("POST", "/v2/snaps", nil)
c.Assert(err, check.IsNil)

Expand All @@ -1896,44 +1890,73 @@ func (s *apiSuite) TestTrySnap(c *check.C) {
err = ioutil.WriteFile(snapYaml, []byte("name: foo\nversion: 1.0\n"), 0644)
c.Assert(err, check.IsNil)

tryWasCalled := true
snapstateTryPath = func(s *state.State, name, path string, flags snapstate.Flags) (*state.TaskSet, error) {
tryWasCalled = true
t := s.NewTask("fake-install-snap", "Doing a fake install")
return state.NewTaskSet(t), nil
}
for _, t := range []struct {
coreInfoErr error
nTasks int
installSnap string
}{
// core installed
{nil, 1, ""},
// no-core-installed
{state.ErrNoState, 2, "core"},
} {
soon := 0
ensureStateSoon = func(st *state.State) {
soon++
ensureStateSoonImpl(st)
}

// try the snap
rsp := trySnap(snapsCmd, req, nil, tryDir, snapstate.Flags{}).(*resp)
c.Assert(rsp.Type, check.Equals, ResponseTypeAsync)
c.Assert(tryWasCalled, check.Equals, true)
tryWasCalled := true
snapstateTryPath = func(s *state.State, name, path string, flags snapstate.Flags) (*state.TaskSet, error) {
tryWasCalled = true
t := s.NewTask("fake-install-snap", "Doing a fake try")
return state.NewTaskSet(t), nil
}

st := d.overlord.State()
st.Lock()
defer st.Unlock()
chg := st.Change(rsp.Change)
c.Assert(chg, check.NotNil)
installSnap := ""
snapstateInstall = func(s *state.State, name, channel string, revision snap.Revision, userID int, flags snapstate.Flags) (*state.TaskSet, error) {
installSnap = name
t := s.NewTask("fake-install-snap", "Doing a fake install")
return state.NewTaskSet(t), nil
}

snapstateCoreInfo = func(s *state.State) (*snap.Info, error) {
return nil, t.coreInfoErr
}

c.Assert(chg.Tasks(), check.HasLen, 1)
// try the snap (without an installed core)
rsp := trySnap(snapsCmd, req, nil, tryDir, snapstate.Flags{}).(*resp)
c.Assert(rsp.Type, check.Equals, ResponseTypeAsync)
c.Assert(tryWasCalled, check.Equals, true)

st.Unlock()
<-chg.Ready()
st.Lock()
st := d.overlord.State()
st.Lock()
chg := st.Change(rsp.Change)
c.Assert(chg, check.NotNil)

c.Check(chg.Kind(), check.Equals, "try-snap")
c.Check(chg.Summary(), check.Equals, fmt.Sprintf(`Try "%s" snap from %s`, "foo", tryDir))
var names []string
err = chg.Get("snap-names", &names)
c.Assert(err, check.IsNil)
c.Check(names, check.DeepEquals, []string{"foo"})
var apiData map[string]interface{}
err = chg.Get("api-data", &apiData)
c.Assert(err, check.IsNil)
c.Check(apiData, check.DeepEquals, map[string]interface{}{
"snap-name": "foo",
})
c.Assert(chg.Tasks(), check.HasLen, t.nTasks)
c.Check(installSnap, check.Equals, t.installSnap)

c.Check(soon, check.Equals, 1)
st.Unlock()
<-chg.Ready()
st.Lock()

c.Check(chg.Kind(), check.Equals, "try-snap")
c.Check(chg.Summary(), check.Equals, fmt.Sprintf(`Try "%s" snap from %s`, "foo", tryDir))
var names []string
err = chg.Get("snap-names", &names)
c.Assert(err, check.IsNil)
c.Check(names, check.DeepEquals, []string{"foo"})
var apiData map[string]interface{}
err = chg.Get("api-data", &apiData)
c.Assert(err, check.IsNil)
c.Check(apiData, check.DeepEquals, map[string]interface{}{
"snap-name": "foo",
})

c.Check(soon, check.Equals, 1)
st.Unlock()
}
}

func (s *apiSuite) TestTrySnapRelative(c *check.C) {
Expand Down

0 comments on commit a00572a

Please sign in to comment.