Example #1
0
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".*`)
}
Example #2
0
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.*`)
}
Example #3
0
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".*`)
}
Example #4
0
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`)
}
Example #5
0
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",
	})
}
Example #6
0
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"},
	})
}
Example #7
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,
	})

	// 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
	}
}
Example #8
0
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)
}
Example #9
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
	}
}