func (s *snapmgrTestSuite) TestUpdateUnaliasChangeConflict(c *C) { s.state.Lock() defer s.state.Unlock() snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ Active: true, Sequence: []*snap.SideInfo{{RealName: "some-snap", SnapID: "some-snap-id", Revision: snap.R(7)}}, Current: snap.R(7), SnapType: "app", }) ts, err := snapstate.Update(s.state, "some-snap", "some-channel", snap.R(0), s.user.ID, snapstate.Flags{}) c.Assert(err, IsNil) // need a change to make the tasks visible s.state.NewChange("update", "...").AddAll(ts) _, err = snapstate.Unalias(s.state, "some-snap", []string{"alias1"}) c.Assert(err, ErrorMatches, `snap "some-snap" has changes in progress`) }
func (s *snapmgrTestSuite) TestUnliasTotalUndoRunThroughAliasConflict(c *C) { s.state.Lock() defer s.state.Unlock() snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ Sequence: []*snap.SideInfo{ {RealName: "alias-snap", Revision: snap.R(11)}, }, Current: snap.R(11), Active: true, }) defer s.snapmgr.Stop() s.state.Set("aliases", map[string]map[string]string{ "alias-snap": { "alias1": "enabled", }, }) chg := s.state.NewChange("scenario", "...") ts, err := snapstate.Unalias(s.state, "alias-snap", []string{"alias1"}) c.Assert(err, IsNil) chg.AddAll(ts) tasks := ts.Tasks() last := tasks[len(tasks)-1] grabAlias1 := func(t *state.Task, _ *tomb.Tomb) error { st := t.State() st.Lock() defer st.Unlock() var allAliases map[string]map[string]string err := st.Get("aliases", &allAliases) c.Assert(err, IsNil) c.Assert(allAliases, DeepEquals, map[string]map[string]string{ "alias-snap": { "alias1": "disabled", }, }) st.Set("aliases", map[string]map[string]string{ "alias-snap": { "alias1": "disabled", }, "other-snap": { "alias1": "enabled", }, }) return nil } s.snapmgr.AddAdhocTaskHandler("grab-alias1", grabAlias1, nil) tgrab1 := s.state.NewTask("grab-alias1", "grab alias1 for other-snap") tgrab1.WaitFor(last) chg.AddTask(tgrab1) terr := s.state.NewTask("error-trigger", "provoking total undo") terr.WaitFor(tgrab1) chg.AddTask(terr) s.state.Unlock() for i := 0; i < 5; i++ { s.snapmgr.Ensure() s.snapmgr.Wait() } s.state.Lock() c.Assert(chg.Status(), Equals, state.ErrorStatus, Commentf("%v", chg.Err())) rmAliases := []*backend.Alias{{"alias1", "alias-snap.cmd1"}} expected := fakeOps{ { op: "update-aliases", rmAliases: rmAliases, }, { op: "matching-aliases", }, { op: "missing-aliases", }, { op: "update-aliases", }, } // start with an easier-to-read error if this fails: c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops()) c.Assert(s.fakeBackend.ops, DeepEquals, expected) var allAliases map[string]map[string]string err = s.state.Get("aliases", &allAliases) c.Assert(err, IsNil) c.Check(allAliases, DeepEquals, map[string]map[string]string{ "other-snap": { "alias1": "enabled", }, }) c.Check(last.Log(), HasLen, 1) c.Check(last.Log()[0], Matches, `.* ERROR cannot enable alias "alias1" for "alias-snap", already enabled for "other-snap"`) }
func (s *snapmgrTestSuite) TestAliasMatrixTotalUndoRunThrough(c *C) { s.state.Lock() defer s.state.Unlock() snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ Sequence: []*snap.SideInfo{ {RealName: "alias-snap", Revision: snap.R(11)}, }, Current: snap.R(11), Active: true, }) // alias1 is a non auto-alias // alias5 is an auto-alias // alias1lost is a non auto-alias and doesn't have an entry in the snap anymore // alias5lost is an auto-alias and doesn't have an entry in the snap any snapstate.AutoAliases = func(st *state.State, info *snap.Info) ([]string, error) { c.Check(info.Name(), Equals, "alias-snap") return []string{"alias5", "alias5lost"}, nil } cmds := map[string]string{ "alias1": "cmd1", "alias5": "cmd5", } defer s.snapmgr.Stop() for _, scenario := range statusesMatrix { scenAlias := scenario.alias if scenario.beforeStatus != "" { s.state.Set("aliases", map[string]map[string]string{ "alias-snap": { scenAlias: scenario.beforeStatus, }, }) } else { s.state.Set("aliases", nil) } chg := s.state.NewChange("scenario", "...") var err error var ts *state.TaskSet targets := []string{scenAlias} switch scenario.action { case "alias": ts, err = snapstate.Alias(s.state, "alias-snap", targets) case "unalias": ts, err = snapstate.Unalias(s.state, "alias-snap", targets) case "reset": ts, err = snapstate.ResetAliases(s.state, "alias-snap", targets) } c.Assert(err, IsNil) chg.AddAll(ts) tasks := ts.Tasks() last := tasks[len(tasks)-1] terr := s.state.NewTask("error-trigger", "provoking total undo") terr.WaitFor(last) chg.AddTask(terr) s.state.Unlock() for i := 0; i < 3; i++ { s.snapmgr.Ensure() s.snapmgr.Wait() } s.state.Lock() c.Assert(chg.Status(), Equals, state.ErrorStatus, Commentf("%#v: %v", scenario, chg.Err())) var aliases []*backend.Alias var rmAliases []*backend.Alias beAlias := &backend.Alias{scenAlias, fmt.Sprintf("alias-snap.%s", cmds[scenAlias])} switch scenario.mutation { case "-": case "add": aliases = []*backend.Alias{beAlias} case "rm": rmAliases = []*backend.Alias{beAlias} } comm := Commentf("%#v", scenario) expected := fakeOps{ { op: "update-aliases", aliases: aliases, rmAliases: rmAliases, }, { op: "matching-aliases", aliases: aliases, }, { op: "missing-aliases", aliases: rmAliases, }, { op: "update-aliases", aliases: rmAliases, rmAliases: aliases, }, } // start with an easier-to-read error if this fails: c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops(), comm) c.Assert(s.fakeBackend.ops, DeepEquals, expected, comm) var allAliases map[string]map[string]string err = s.state.Get("aliases", &allAliases) c.Assert(err, IsNil) if scenario.beforeStatus != "" { c.Check(allAliases, DeepEquals, map[string]map[string]string{ "alias-snap": {scenAlias: scenario.beforeStatus}, }, comm) } else { c.Check(allAliases, HasLen, 0, comm) } s.fakeBackend.ops = nil } }
func (ms *mgrsSuite) TestHappyUnalias(c *C) { st := ms.o.State() st.Lock() defer st.Unlock() fooYaml := `name: foo version: 1.0 apps: foo: command: bin/foo aliases: [foo_] ` ms.installLocalTestSnap(c, fooYaml) ts, err := snapstate.Alias(st, "foo", []string{"foo_"}) c.Assert(err, IsNil) chg := st.NewChange("alias", "...") chg.AddAll(ts) st.Unlock() err = ms.o.Settle() st.Lock() c.Assert(err, IsNil) c.Assert(chg.Err(), IsNil) c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("alias change failed with: %v", chg.Err())) foo_Alias := filepath.Join(dirs.SnapBinariesDir, "foo_") dest, err := os.Readlink(foo_Alias) c.Assert(err, IsNil) c.Check(dest, Equals, "foo") var allAliases map[string]map[string]string err = st.Get("aliases", &allAliases) c.Assert(err, IsNil) c.Check(allAliases, DeepEquals, map[string]map[string]string{ "foo": { "foo_": "enabled", }, }) ts, err = snapstate.Unalias(st, "foo", []string{"foo_"}) c.Assert(err, IsNil) chg = st.NewChange("unalias", "...") chg.AddAll(ts) st.Unlock() err = ms.o.Settle() st.Lock() c.Assert(err, IsNil) c.Assert(chg.Err(), IsNil) c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("unalias change failed with: %v", chg.Err())) c.Check(osutil.IsSymlink(foo_Alias), Equals, false) allAliases = nil err = st.Get("aliases", &allAliases) c.Assert(err, IsNil) c.Check(allAliases, DeepEquals, map[string]map[string]string{ "foo": { "foo_": "disabled", }, }) }
func (s *snapmgrTestSuite) TestAliasMatrixTotalUndoRunThrough(c *C) { s.state.Lock() defer s.state.Unlock() snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ Sequence: []*snap.SideInfo{ {RealName: "alias-snap", Revision: snap.R(11)}, }, Current: snap.R(11), Active: true, }) defer s.snapmgr.Stop() for _, scenario := range statusesMatrix { if scenario.beforeStatus != "" { s.state.Set("aliases", map[string]map[string]string{ "alias-snap": { "alias1": scenario.beforeStatus, }, }) } else { s.state.Set("aliases", nil) } chg := s.state.NewChange("scenario", "...") var err error var ts *state.TaskSet switch scenario.action { case "alias": ts, err = snapstate.Alias(s.state, "alias-snap", []string{"alias1"}) case "unalias": ts, err = snapstate.Unalias(s.state, "alias-snap", []string{"alias1"}) } c.Assert(err, IsNil) chg.AddAll(ts) tasks := ts.Tasks() last := tasks[len(tasks)-1] terr := s.state.NewTask("error-trigger", "provoking total undo") terr.WaitFor(last) chg.AddTask(terr) s.state.Unlock() for i := 0; i < 3; i++ { s.snapmgr.Ensure() s.snapmgr.Wait() } s.state.Lock() c.Assert(chg.Status(), Equals, state.ErrorStatus, Commentf("%#v: %v", scenario, chg.Err())) var aliases []*backend.Alias var rmAliases []*backend.Alias switch scenario.mutation { case "-": case "add": aliases = []*backend.Alias{{"alias1", "alias-snap.cmd1"}} case "rm": rmAliases = []*backend.Alias{{"alias1", "alias-snap.cmd1"}} } comm := Commentf("%#v", scenario) expected := fakeOps{ { op: "update-aliases", aliases: aliases, rmAliases: rmAliases, }, { op: "matching-aliases", aliases: aliases, }, { op: "missing-aliases", aliases: rmAliases, }, { op: "update-aliases", aliases: rmAliases, rmAliases: aliases, }, } // start with an easier-to-read error if this fails: c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops(), comm) c.Assert(s.fakeBackend.ops, DeepEquals, expected, comm) var allAliases map[string]map[string]string err = s.state.Get("aliases", &allAliases) c.Assert(err, IsNil) if scenario.beforeStatus != "" { c.Check(allAliases, DeepEquals, map[string]map[string]string{ "alias-snap": {"alias1": scenario.beforeStatus}, }, comm) } else { c.Check(allAliases, HasLen, 0, comm) } s.fakeBackend.ops = nil } }