func (s *snapmgrTestSuite) TestAliasSnapCommandSpaceConflict(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, }) // the command namespace of this one will conflict snapstate.Set(s.state, "alias1", &snapstate.SnapState{ Sequence: []*snap.SideInfo{ {RealName: "alias1", Revision: snap.R(3)}, }, Current: snap.R(3), }) chg := s.state.NewChange("alias", "enable an alias") ts, err := snapstate.Alias(s.state, "alias-snap", []string{"alias1.cmd1"}) c.Assert(err, IsNil) chg.AddAll(ts) s.state.Unlock() s.snapmgr.Ensure() s.snapmgr.Wait() s.state.Lock() c.Check(chg.Status(), Equals, state.ErrorStatus) c.Check(chg.Err(), ErrorMatches, `(?s).*cannot enable alias "alias1.cmd1" for "alias-snap", it conflicts with the command namespace of installed snap "alias1".*`) }
func (s *snapmgrTestSuite) TestAliasNoAlias(c *C) { s.state.Lock() defer s.state.Unlock() snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ Sequence: []*snap.SideInfo{ {RealName: "some-snap", Revision: snap.R(11)}, }, Current: snap.R(11), Active: true, }) chg := s.state.NewChange("alias", "enable an alias") ts, err := snapstate.Alias(s.state, "some-snap", []string{"alias1"}) c.Assert(err, IsNil) chg.AddAll(ts) s.state.Unlock() s.snapmgr.Ensure() s.snapmgr.Wait() s.state.Lock() c.Check(chg.Status(), Equals, state.ErrorStatus) c.Check(chg.Err(), ErrorMatches, `(?s).*cannot enable alias "alias1" for "some-snap", no such alias.*`) }
func (s *snapmgrTestSuite) TestAliasAutoAliasConflict(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, }) s.state.Set("aliases", map[string]map[string]string{ "other-snap": {"alias1": "auto"}, }) chg := s.state.NewChange("alias", "enable an alias") ts, err := snapstate.Alias(s.state, "alias-snap", []string{"alias1"}) c.Assert(err, IsNil) chg.AddAll(ts) s.state.Unlock() s.snapmgr.Ensure() s.snapmgr.Wait() s.state.Lock() c.Check(chg.Status(), Equals, state.ErrorStatus) c.Check(chg.Err(), ErrorMatches, `(?s).*cannot enable alias "alias1" for "alias-snap", already enabled for "other-snap".*`) }
func (s *snapmgrTestSuite) TestAliasUpdateChangeConflict(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.Alias(s.state, "some-snap", []string{"alias1"}) c.Assert(err, IsNil) // need a change to make the tasks visible s.state.NewChange("alias", "...").AddAll(ts) _, err = snapstate.Update(s.state, "some-snap", "some-channel", snap.R(0), s.user.ID, snapstate.Flags{}) c.Assert(err, ErrorMatches, `snap "some-snap" has changes in progress`) }
func (s *snapmgrTestSuite) TestAliasTasks(c *C) { s.state.Lock() defer s.state.Unlock() snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ Sequence: []*snap.SideInfo{ {RealName: "some-snap", Revision: snap.R(11)}, }, Current: snap.R(11), Active: true, }) ts, err := snapstate.Alias(s.state, "some-snap", []string{"alias"}) c.Assert(err, IsNil) c.Assert(s.state.TaskCount(), Equals, len(ts.Tasks())) c.Assert(taskKinds(ts.Tasks()), DeepEquals, []string{ "alias", }) }
func (s *snapmgrTestSuite) TestAliasRunThrough(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, }) chg := s.state.NewChange("alias", "enable an alias") ts, err := snapstate.Alias(s.state, "alias-snap", []string{"alias1"}) c.Assert(err, IsNil) chg.AddAll(ts) s.state.Unlock() defer s.snapmgr.Stop() s.settle() s.state.Lock() c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("%v", chg.Err())) expected := fakeOps{ { op: "update-aliases", aliases: []*backend.Alias{{"alias1", "alias-snap.cmd1"}}, }, } // 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{ "alias-snap": {"alias1": "enabled"}, }) }
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) TestHappyAlias(c *C) { st := ms.o.State() st.Lock() defer st.Unlock() fooYaml := `name: foo version: 1.0 apps: foo: command: bin/foo aliases: [foo_] bar: command: bin/bar aliases: [bar,bar1] ` ms.installLocalTestSnap(c, fooYaml) ts, err := snapstate.Alias(st, "foo", []string{"foo_", "bar", "bar1"}) 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") barAlias := filepath.Join(dirs.SnapBinariesDir, "bar") dest, err = os.Readlink(barAlias) c.Assert(err, IsNil) c.Check(dest, Equals, "foo.bar") bar1Alias := filepath.Join(dirs.SnapBinariesDir, "bar1") dest, err = os.Readlink(bar1Alias) c.Assert(err, IsNil) c.Check(dest, Equals, "foo.bar") 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", "bar": "enabled", "bar1": "enabled", }, }) ms.removeSnap(c, "foo") c.Check(osutil.IsSymlink(foo_Alias), Equals, false) c.Check(osutil.IsSymlink(barAlias), Equals, false) c.Check(osutil.IsSymlink(bar1Alias), Equals, false) allAliases = nil err = st.Get("aliases", &allAliases) c.Assert(err, IsNil) c.Check(allAliases, HasLen, 0) }
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 } }