Beispiel #1
0
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`)
}
Beispiel #2
0
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"`)

}
Beispiel #3
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
	}
}
Beispiel #4
0
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",
		},
	})
}
Beispiel #5
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
	}
}