func (ss *stateSuite) TestCheckpointPreserveCleanStatus(c *C) { b := new(fakeStateBackend) st := state.New(b) st.Lock() chg := st.NewChange("install", "...") t := st.NewTask("download", "...") chg.AddTask(t) t.SetStatus(state.DoneStatus) t.SetClean() // implicit checkpoint st.Unlock() c.Assert(b.checkpoints, HasLen, 1) buf := bytes.NewBuffer(b.checkpoints[0]) st2, err := state.ReadState(nil, buf) c.Assert(err, IsNil) st2.Lock() defer st2.Unlock() chg2 := st2.Change(chg.ID()) t2 := st2.Task(t.ID()) c.Assert(chg2.IsClean(), Equals, true) c.Assert(t2.IsClean(), Equals, true) }
func (ss *stateSuite) TestEmptyTaskAndChangeDataAndCheckpointReadAndSet(c *C) { b := new(fakeStateBackend) st := state.New(b) st.Lock() t1 := st.NewTask("1...", "...") t1ID := t1.ID() chg := st.NewChange("chg", "...") chgID := chg.ID() chg.AddTask(t1) // implicit checkpoint st.Unlock() c.Assert(b.checkpoints, HasLen, 1) buf := bytes.NewBuffer(b.checkpoints[0]) st2, err := state.ReadState(nil, buf) c.Assert(err, IsNil) c.Assert(st2, NotNil) st2.Lock() defer st2.Unlock() chg2 := st2.Change(chgID) t1_2 := st2.Task(t1ID) c.Assert(t1_2, NotNil) // no crash chg2.Set("c", 1) // no crash either t1_2.Set("t", 1) }
func (ss *stateSuite) TestCheckpointPreserveLastIds(c *C) { b := new(fakeStateBackend) st := state.New(b) st.Lock() st.NewChange("install", "...") st.NewTask("download", "...") st.NewTask("download", "...") c.Assert(st.NewLane(), Equals, 1) // implicit checkpoint st.Unlock() c.Assert(b.checkpoints, HasLen, 1) buf := bytes.NewBuffer(b.checkpoints[0]) st2, err := state.ReadState(nil, buf) c.Assert(err, IsNil) st2.Lock() defer st2.Unlock() c.Assert(st2.NewTask("download", "...").ID(), Equals, "3") c.Assert(st2.NewChange("install", "...").ID(), Equals, "2") c.Assert(st2.NewLane(), Equals, 2) }
func loadState(backend state.Backend) (*state.State, error) { if !osutil.FileExists(dirs.SnapStateFile) { // fail fast, mostly interesting for tests, this dir is setup // by the snapd package stateDir := filepath.Dir(dirs.SnapStateFile) if !osutil.IsDirectory(stateDir) { return nil, fmt.Errorf("fatal: directory %q must be present", stateDir) } s := state.New(backend) patch.Init(s) return s, nil } r, err := os.Open(dirs.SnapStateFile) if err != nil { return nil, fmt.Errorf("cannot read the state file: %s", err) } defer r.Close() s, err := state.ReadState(backend, r) if err != nil { return nil, err } // one-shot migrations err = patch.Apply(s) if err != nil { return nil, err } return s, nil }
func (ss *stateSuite) TestEmptyStateDataAndCheckpointReadAndSet(c *C) { b := new(fakeStateBackend) st := state.New(b) st.Lock() chg := st.NewChange("install", "summary") c.Assert(chg, NotNil) // implicit checkpoint st.Unlock() c.Assert(b.checkpoints, HasLen, 1) buf := bytes.NewBuffer(b.checkpoints[0]) st2, err := state.ReadState(nil, buf) c.Assert(err, IsNil) c.Assert(st2, NotNil) st2.Lock() defer st2.Unlock() // no crash st2.Set("a", 1) }
func (ss *stateSuite) TestReadStateInitsCache(c *C) { st, err := state.ReadState(nil, bytes.NewBufferString("{}")) c.Assert(err, IsNil) st.Lock() defer st.Unlock() st.Cache("key", "value") c.Assert(st.Cached("key"), Equals, "value") }
func (s *patch4Suite) TestPatch4OnRefreshes(c *C) { restorer := patch.MockLevel(4) defer restorer() r, err := os.Open(dirs.SnapStateFile) c.Assert(err, IsNil) defer r.Close() st, err := state.ReadState(nil, r) c.Assert(err, IsNil) func() { st.Lock() defer st.Unlock() task := st.Task("16") c.Assert(task, NotNil) // simulate that the task was running (but the change // is not fully done yet) task.SetStatus(state.DoneStatus) snapsup, err := patch.Patch4TaskSnapSetup(task) c.Assert(err, IsNil) c.Check(snapsup.Flags.Revert(), Equals, false) var had bool var idx int c.Check(task.Get("had-candidate", &had), IsNil) c.Check(had, Equals, false) c.Check(task.Get("old-candidate-index", &idx), Equals, state.ErrNoState) c.Check(len(task.Change().Tasks()), Equals, 7) }() // go from patch level 3 -> 4 err = patch.Apply(st) c.Assert(err, IsNil) st.Lock() defer st.Unlock() task := st.Task("16") c.Assert(task, NotNil) snapsup, err := patch.Patch4TaskSnapSetup(task) c.Assert(err, IsNil) c.Check(snapsup.Flags.Revert(), Equals, false) var had bool var idx int c.Check(task.Get("had-candidate", &had), Equals, state.ErrNoState) c.Check(task.Get("old-candidate-index", &idx), IsNil) c.Check(idx, Equals, 1) // we added cleanup c.Check(len(task.Change().Tasks()), Equals, 7+1) }
func (s *patch2Suite) TestPatch2(c *C) { restorer := patch.MockLevel(2) defer restorer() r, err := os.Open(dirs.SnapStateFile) c.Assert(err, IsNil) defer r.Close() st, err := state.ReadState(nil, r) c.Assert(err, IsNil) // go from patch level 1 -> 2 err = patch.Apply(st) c.Assert(err, IsNil) st.Lock() defer st.Unlock() // our mocks are correct c.Assert(st.Changes(), HasLen, 2) c.Assert(st.Tasks(), HasLen, 2) var snapsup snapstate.SnapSetup // transition of: // - SnapSetup.{Name,Revision} -> SnapSetup.SideInfo.{RealName,Revision} t := st.Task("1") err = t.Get("snap-setup", &snapsup) c.Assert(err, IsNil) c.Assert(snapsup.SideInfo, DeepEquals, &snap.SideInfo{ RealName: "foo", Revision: snap.R("x3"), }) // transition of: // - SnapState.Sequence is backfilled with "RealName" (if missing) var snapst snapstate.SnapState err = snapstate.Get(st, "foo", &snapst) c.Assert(err, IsNil) c.Check(snapst.Sequence[0].RealName, Equals, "foo") c.Check(snapst.Sequence[1].RealName, Equals, "foo") // transition of: // - Candidate for "bar" -> tasks SnapSetup.SideInfo t = st.Task("2") err = t.Get("snap-setup", &snapsup) c.Assert(err, IsNil) c.Assert(snapsup.SideInfo, DeepEquals, &snap.SideInfo{ RealName: "bar", Revision: snap.R("x1"), }) // FIXME: bar is now empty and should no longer be there? err = snapstate.Get(st, "bar", &snapst) c.Assert(err, IsNil) }
// This test simulates a link-snap task that is scheduled but has not // run yet. It has no "had-candidate" data set yet. func (s *patch4Suite) TestPatch4OnRefreshesNoHadCandidateYet(c *C) { restorer := patch.MockLevel(4) defer restorer() r, err := os.Open(dirs.SnapStateFile) c.Assert(err, IsNil) defer r.Close() st, err := state.ReadState(nil, r) c.Assert(err, IsNil) func() { st.Lock() defer st.Unlock() task := st.Task("16") c.Assert(task, NotNil) // its ready to run but has not run yet task.Clear("had-candidate") task.SetStatus(state.DoStatus) ss, err := snapstate.TaskSnapSetup(task) c.Assert(err, IsNil) c.Check(ss.Flags.Revert(), Equals, false) var had bool var idx int c.Check(task.Get("had-candidate", &had), Equals, state.ErrNoState) c.Check(task.Get("old-candidate-index", &idx), Equals, state.ErrNoState) c.Check(len(task.Change().Tasks()), Equals, 7) }() // go from patch level 3 -> 4 err = patch.Apply(st) c.Assert(err, IsNil) st.Lock() defer st.Unlock() task := st.Task("16") c.Assert(task, NotNil) ss, err := snapstate.TaskSnapSetup(task) c.Assert(err, IsNil) c.Check(ss.Flags.Revert(), Equals, false) var had bool var idx int c.Check(task.Get("had-candidate", &had), Equals, state.ErrNoState) c.Check(task.Get("old-candidate-index", &idx), IsNil) c.Check(idx, Equals, 1) // we added cleanup c.Check(len(task.Change().Tasks()), Equals, 7+1) }
func (ss *stateSuite) TestNewChangeAndCheckpoint(c *C) { b := new(fakeStateBackend) st := state.New(b) st.Lock() chg := st.NewChange("install", "summary") c.Assert(chg, NotNil) chgID := chg.ID() chg.Set("a", 1) chg.SetStatus(state.ErrorStatus) spawnTime := chg.SpawnTime() readyTime := chg.ReadyTime() // implicit checkpoint st.Unlock() c.Assert(b.checkpoints, HasLen, 1) buf := bytes.NewBuffer(b.checkpoints[0]) st2, err := state.ReadState(nil, buf) c.Assert(err, IsNil) c.Assert(st2, NotNil) st2.Lock() defer st2.Unlock() chgs := st2.Changes() c.Assert(chgs, HasLen, 1) chg0 := chgs[0] c.Check(chg0.ID(), Equals, chgID) c.Check(chg0.Kind(), Equals, "install") c.Check(chg0.Summary(), Equals, "summary") c.Check(chg0.SpawnTime().Equal(spawnTime), Equals, true) c.Check(chg0.ReadyTime().Equal(readyTime), Equals, true) var v int err = chg0.Get("a", &v) c.Check(err, IsNil) c.Check(v, Equals, 1) c.Check(chg0.Status(), Equals, state.ErrorStatus) select { case <-chg0.Ready(): default: c.Errorf("Change didn't preserve Ready channel closed after deserialization") } }
func (s *patch1Suite) TestPatch1(c *C) { restore := patch.MockReadInfo(s.readInfo) defer restore() r, err := os.Open(dirs.SnapStateFile) c.Assert(err, IsNil) defer r.Close() st, err := state.ReadState(nil, r) c.Assert(err, IsNil) // go from patch-level 0 to patch-level 1 restorer := patch.MockLevel(1) defer restorer() err = patch.Apply(st) c.Assert(err, IsNil) st.Lock() defer st.Unlock() expected := []struct { name string typ snap.Type cur snap.Revision }{ {"foo", snap.TypeApp, snap.R(22)}, {"core", snap.TypeOS, snap.R(111)}, {"borken", snap.TypeApp, snap.R(-2)}, {"wip", "", snap.R(0)}, } for _, exp := range expected { var snapst snapstate.SnapState err := snapstate.Get(st, exp.name, &snapst) c.Assert(err, IsNil) c.Check(snap.Type(snapst.SnapType), Equals, exp.typ) c.Check(snapst.Current, Equals, exp.cur) } // ensure we only moved forward to patch-level 1 var patchLevel int err = st.Get("patch-level", &patchLevel) c.Assert(err, IsNil) c.Assert(patchLevel, Equals, 1) }
func (ss *stateSuite) TestImplicitCheckpointAndRead(c *C) { b := new(fakeStateBackend) st := state.New(b) st.Lock() st.Set("v", 1) mSt1 := &mgrState1{A: "foo"} st.Set("mgr1", mSt1) mSt2 := &mgrState2{C: &Count2{B: 42}} st.Set("mgr2", mSt2) // implicit checkpoint st.Unlock() c.Assert(b.checkpoints, HasLen, 1) buf := bytes.NewBuffer(b.checkpoints[0]) st2, err := state.ReadState(nil, buf) c.Assert(err, IsNil) c.Assert(st2.Modified(), Equals, false) st2.Lock() defer st2.Unlock() var v int err = st2.Get("v", &v) c.Assert(err, IsNil) c.Check(v, Equals, 1) var mSt1B mgrState1 err = st2.Get("mgr1", &mSt1B) c.Assert(err, IsNil) c.Check(&mSt1B, DeepEquals, mSt1) var mSt2B mgrState2 err = st2.Get("mgr2", &mSt2B) c.Assert(err, IsNil) c.Check(&mSt2B, DeepEquals, mSt2) }
func (ss *stateSuite) TestNewChangeAndCheckpointTaskDerivedStatus(c *C) { b := new(fakeStateBackend) st := state.New(b) st.Lock() chg := st.NewChange("install", "summary") c.Assert(chg, NotNil) chgID := chg.ID() t1 := st.NewTask("download", "1...") t1.SetStatus(state.DoneStatus) chg.AddTask(t1) // implicit checkpoint st.Unlock() c.Assert(b.checkpoints, HasLen, 1) buf := bytes.NewBuffer(b.checkpoints[0]) st2, err := state.ReadState(nil, buf) c.Assert(err, IsNil) st2.Lock() defer st2.Unlock() chgs := st2.Changes() c.Assert(chgs, HasLen, 1) chg0 := chgs[0] c.Check(chg0.ID(), Equals, chgID) c.Check(chg0.Status(), Equals, state.DoneStatus) select { case <-chg0.Ready(): default: c.Errorf("Change didn't preserve Ready channel closed after deserialization") } }
func (ss *stateSuite) TestNewTaskAndCheckpoint(c *C) { b := new(fakeStateBackend) st := state.New(b) st.Lock() chg := st.NewChange("install", "summary") c.Assert(chg, NotNil) t1 := st.NewTask("download", "1...") chg.AddTask(t1) t1ID := t1.ID() t1.Set("a", 1) t1.SetStatus(state.DoneStatus) t1.SetProgress("snap", 5, 10) t1.JoinLane(42) t1.JoinLane(43) t2 := st.NewTask("inst", "2...") chg.AddTask(t2) t2ID := t2.ID() t2.WaitFor(t1) schedule := time.Now().Add(time.Hour) t2.At(schedule) // implicit checkpoint st.Unlock() c.Assert(b.checkpoints, HasLen, 1) buf := bytes.NewBuffer(b.checkpoints[0]) st2, err := state.ReadState(nil, buf) c.Assert(err, IsNil) c.Assert(st2, NotNil) st2.Lock() defer st2.Unlock() chgs := st2.Changes() c.Assert(chgs, HasLen, 1) chg0 := chgs[0] tasks0 := make(map[string]*state.Task) for _, t := range chg0.Tasks() { tasks0[t.ID()] = t } c.Assert(tasks0, HasLen, 2) task0_1 := tasks0[t1ID] c.Check(task0_1.ID(), Equals, t1ID) c.Check(task0_1.Kind(), Equals, "download") c.Check(task0_1.Summary(), Equals, "1...") c.Check(task0_1.Change(), Equals, chg0) var v int err = task0_1.Get("a", &v) c.Check(v, Equals, 1) c.Check(task0_1.Status(), Equals, state.DoneStatus) _, cur, tot := task0_1.Progress() c.Check(cur, Equals, 5) c.Check(tot, Equals, 10) c.Assert(task0_1.Lanes(), DeepEquals, []int{42, 43}) task0_2 := tasks0[t2ID] c.Check(task0_2.WaitTasks(), DeepEquals, []*state.Task{task0_1}) c.Check(task0_1.HaltTasks(), DeepEquals, []*state.Task{task0_2}) tasks2 := make(map[string]*state.Task) for _, t := range st2.Tasks() { tasks2[t.ID()] = t } c.Assert(tasks2, HasLen, 2) c.Check(task0_1.AtTime().IsZero(), Equals, true) c.Check(task0_2.AtTime().Equal(schedule), Equals, true) }
func (s *FirstBootTestSuite) TestPopulateFromSeedHappyMultiAssertsFiles(c *C) { // put a firstboot snap into the SnapBlobDir snapYaml := `name: foo version: 1.0` mockSnapFile := snaptest.MakeTestSnapWithFiles(c, snapYaml, nil) fooSnapFile := filepath.Join(dirs.SnapSeedDir, "snaps", filepath.Base(mockSnapFile)) err := os.Rename(mockSnapFile, fooSnapFile) c.Assert(err, IsNil) // put a 2nd firstboot snap into the SnapBlobDir snapYaml = `name: bar version: 1.0` mockSnapFile = snaptest.MakeTestSnapWithFiles(c, snapYaml, nil) barSnapFile := filepath.Join(dirs.SnapSeedDir, "snaps", filepath.Base(mockSnapFile)) err = os.Rename(mockSnapFile, barSnapFile) c.Assert(err, IsNil) devAcct := assertstest.NewAccount(s.storeSigning, "developer", map[string]interface{}{ "account-id": "developerid", }, "") snapDeclFoo, err := s.storeSigning.Sign(asserts.SnapDeclarationType, map[string]interface{}{ "series": "16", "snap-id": "foosnapidsnapid", "publisher-id": "developerid", "snap-name": "foo", "timestamp": time.Now().UTC().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) sha3_384, size, err := asserts.SnapFileSHA3_384(fooSnapFile) c.Assert(err, IsNil) snapRevFoo, err := s.storeSigning.Sign(asserts.SnapRevisionType, map[string]interface{}{ "snap-sha3-384": sha3_384, "snap-size": fmt.Sprintf("%d", size), "snap-id": "foosnapidsnapid", "developer-id": "developerid", "snap-revision": "128", "timestamp": time.Now().UTC().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) writeAssertionsToFile("foo.asserts", []asserts.Assertion{devAcct, snapRevFoo, snapDeclFoo}) snapDeclBar, err := s.storeSigning.Sign(asserts.SnapDeclarationType, map[string]interface{}{ "series": "16", "snap-id": "barsnapidsnapid", "publisher-id": "developerid", "snap-name": "bar", "timestamp": time.Now().UTC().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) sha3_384, size, err = asserts.SnapFileSHA3_384(barSnapFile) c.Assert(err, IsNil) snapRevBar, err := s.storeSigning.Sign(asserts.SnapRevisionType, map[string]interface{}{ "snap-sha3-384": sha3_384, "snap-size": fmt.Sprintf("%d", size), "snap-id": "barsnapidsnapid", "developer-id": "developerid", "snap-revision": "65", "timestamp": time.Now().UTC().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) writeAssertionsToFile("bar.asserts", []asserts.Assertion{devAcct, snapDeclBar, snapRevBar}) // add a model assertion and its chain assertsChain := s.makeModelAssertionChain(c) writeAssertionsToFile("model.asserts", assertsChain) // create a seed.yaml content := []byte(fmt.Sprintf(` snaps: - name: foo file: %s - name: bar file: %s `, filepath.Base(fooSnapFile), filepath.Base(barSnapFile))) err = ioutil.WriteFile(filepath.Join(dirs.SnapSeedDir, "seed.yaml"), content, 0644) c.Assert(err, IsNil) // run the firstboot stuff st := s.overlord.State() st.Lock() defer st.Unlock() tsAll, err := devicestate.PopulateStateFromSeedImpl(st) c.Assert(err, IsNil) chg := st.NewChange("run-it", "run the populate from seed changes") for _, ts := range tsAll { chg.AddAll(ts) } c.Assert(st.Changes(), HasLen, 1) st.Unlock() s.overlord.Settle() st.Lock() c.Assert(chg.Err(), IsNil) // and check the snap got correctly installed c.Check(osutil.FileExists(filepath.Join(dirs.SnapMountDir, "foo", "128", "meta", "snap.yaml")), Equals, true) // and check the snap got correctly installed c.Check(osutil.FileExists(filepath.Join(dirs.SnapMountDir, "bar", "65", "meta", "snap.yaml")), Equals, true) // verify r, err := os.Open(dirs.SnapStateFile) c.Assert(err, IsNil) state, err := state.ReadState(nil, r) c.Assert(err, IsNil) state.Lock() defer state.Unlock() // check foo info, err := snapstate.CurrentInfo(state, "foo") c.Assert(err, IsNil) c.Assert(info.SnapID, Equals, "foosnapidsnapid") c.Assert(info.Revision, Equals, snap.R(128)) c.Assert(info.DeveloperID, Equals, "developerid") // check bar info, err = snapstate.CurrentInfo(state, "bar") c.Assert(err, IsNil) c.Assert(info.SnapID, Equals, "barsnapidsnapid") c.Assert(info.Revision, Equals, snap.R(65)) c.Assert(info.DeveloperID, Equals, "developerid") }
func (s *FirstBootTestSuite) TestPopulateFromSeedHappy(c *C) { // put a firstboot snap into the SnapBlobDir snapYaml := `name: foo version: 1.0` mockSnapFile := snaptest.MakeTestSnapWithFiles(c, snapYaml, nil) targetSnapFile := filepath.Join(dirs.SnapSeedDir, "snaps", filepath.Base(mockSnapFile)) err := os.Rename(mockSnapFile, targetSnapFile) c.Assert(err, IsNil) // put a firstboot local snap into the SnapBlobDir snapYaml = `name: local version: 1.0` mockSnapFile = snaptest.MakeTestSnapWithFiles(c, snapYaml, nil) targetSnapFile2 := filepath.Join(dirs.SnapSeedDir, "snaps", filepath.Base(mockSnapFile)) err = os.Rename(mockSnapFile, targetSnapFile2) c.Assert(err, IsNil) devAcct := assertstest.NewAccount(s.storeSigning, "developer", map[string]interface{}{ "account-id": "developerid", }, "") devAcctFn := filepath.Join(dirs.SnapSeedDir, "assertions", "developer.account") err = ioutil.WriteFile(devAcctFn, asserts.Encode(devAcct), 0644) c.Assert(err, IsNil) snapDecl, err := s.storeSigning.Sign(asserts.SnapDeclarationType, map[string]interface{}{ "series": "16", "snap-id": "snapidsnapid", "publisher-id": "developerid", "snap-name": "foo", "timestamp": time.Now().UTC().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) declFn := filepath.Join(dirs.SnapSeedDir, "assertions", "foo.snap-declaration") err = ioutil.WriteFile(declFn, asserts.Encode(snapDecl), 0644) c.Assert(err, IsNil) sha3_384, size, err := asserts.SnapFileSHA3_384(targetSnapFile) c.Assert(err, IsNil) snapRev, err := s.storeSigning.Sign(asserts.SnapRevisionType, map[string]interface{}{ "snap-sha3-384": sha3_384, "snap-size": fmt.Sprintf("%d", size), "snap-id": "snapidsnapid", "developer-id": "developerid", "snap-revision": "128", "timestamp": time.Now().UTC().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) revFn := filepath.Join(dirs.SnapSeedDir, "assertions", "foo.snap-revision") err = ioutil.WriteFile(revFn, asserts.Encode(snapRev), 0644) c.Assert(err, IsNil) // add a model assertion and its chain assertsChain := s.makeModelAssertionChain(c) for i, as := range assertsChain { fn := filepath.Join(dirs.SnapSeedDir, "assertions", strconv.Itoa(i)) err := ioutil.WriteFile(fn, asserts.Encode(as), 0644) c.Assert(err, IsNil) } // create a seed.yaml content := []byte(fmt.Sprintf(` snaps: - name: foo file: %s devmode: true - name: local unasserted: true file: %s `, filepath.Base(targetSnapFile), filepath.Base(targetSnapFile2))) err = ioutil.WriteFile(filepath.Join(dirs.SnapSeedDir, "seed.yaml"), content, 0644) c.Assert(err, IsNil) // run the firstboot stuff st := s.overlord.State() st.Lock() defer st.Unlock() tsAll, err := devicestate.PopulateStateFromSeedImpl(st) c.Assert(err, IsNil) // the last task of the last taskset must be mark-seeded markSeededTask := tsAll[len(tsAll)-1].Tasks()[0] c.Check(markSeededTask.Kind(), Equals, "mark-seeded") // and the markSeededTask must wait for the other tasks prevTasks := tsAll[len(tsAll)-2].Tasks() otherTask := prevTasks[len(prevTasks)-1] c.Check(markSeededTask.WaitTasks(), testutil.Contains, otherTask) // now run the change and check the result chg := st.NewChange("run-it", "run the populate from seed changes") for _, ts := range tsAll { chg.AddAll(ts) } c.Assert(st.Changes(), HasLen, 1) st.Unlock() s.overlord.Settle() st.Lock() c.Assert(chg.Err(), IsNil) // and check the snap got correctly installed c.Check(osutil.FileExists(filepath.Join(dirs.SnapMountDir, "foo", "128", "meta", "snap.yaml")), Equals, true) c.Check(osutil.FileExists(filepath.Join(dirs.SnapMountDir, "local", "x1", "meta", "snap.yaml")), Equals, true) // verify r, err := os.Open(dirs.SnapStateFile) c.Assert(err, IsNil) state, err := state.ReadState(nil, r) c.Assert(err, IsNil) state.Lock() defer state.Unlock() // check foo info, err := snapstate.CurrentInfo(state, "foo") c.Assert(err, IsNil) c.Assert(info.SnapID, Equals, "snapidsnapid") c.Assert(info.Revision, Equals, snap.R(128)) c.Assert(info.DeveloperID, Equals, "developerid") var snapst snapstate.SnapState err = snapstate.Get(state, "foo", &snapst) c.Assert(err, IsNil) c.Assert(snapst.DevMode, Equals, true) // check local info, err = snapstate.CurrentInfo(state, "local") c.Assert(err, IsNil) c.Assert(info.SnapID, Equals, "") c.Assert(info.Revision, Equals, snap.R("x1")) c.Assert(info.DeveloperID, Equals, "") // and ensure state is now considered seeded var seeded bool err = state.Get("seeded", &seeded) c.Assert(err, IsNil) c.Check(seeded, Equals, true) }
func (s *patch6Suite) TestPatch6(c *C) { restorer := patch.MockLevel(6) defer restorer() r, err := os.Open(dirs.SnapStateFile) c.Assert(err, IsNil) defer r.Close() st, err := state.ReadState(nil, r) c.Assert(err, IsNil) func() { st.Lock() defer st.Unlock() stateMap, err := patch.Patch4StateMap(st) c.Assert(err, IsNil) c.Check(int(stateMap["a"].Flags), Equals, 1) c.Check(int(stateMap["b"].Flags), Equals, 2) c.Check(int(stateMap["c"].Flags), Equals, 4) }() c.Assert(patch.Apply(st), IsNil) st.Lock() defer st.Unlock() stateMap, err := patch.Patch6StateMap(st) c.Assert(err, IsNil) c.Check(stateMap["a"].DevMode, Equals, true) c.Check(stateMap["a"].TryMode, Equals, false) c.Check(stateMap["a"].JailMode, Equals, false) c.Check(stateMap["b"].DevMode, Equals, false) c.Check(stateMap["b"].TryMode, Equals, true) c.Check(stateMap["b"].JailMode, Equals, false) c.Check(stateMap["c"].DevMode, Equals, false) c.Check(stateMap["c"].TryMode, Equals, false) c.Check(stateMap["c"].JailMode, Equals, true) for _, task := range st.Tasks() { ss, err := patch.Patch6SnapSetup(task) if err == state.ErrNoState { continue } c.Assert(err, IsNil) var snaps []string c.Assert(task.Change().Get("snap-names", &snaps), IsNil) c.Assert(snaps, HasLen, 1) switch snaps[0] { case "a": c.Check(ss.DevMode, Equals, true, Commentf("a")) c.Check(ss.TryMode, Equals, false, Commentf("a")) c.Check(ss.JailMode, Equals, false, Commentf("a")) c.Check(ss.Revert, Equals, false, Commentf("a")) case "b": c.Check(ss.DevMode, Equals, false, Commentf("b")) c.Check(ss.TryMode, Equals, true, Commentf("b")) c.Check(ss.JailMode, Equals, false, Commentf("b")) c.Check(ss.Revert, Equals, false, Commentf("b")) case "c": c.Check(ss.DevMode, Equals, false, Commentf("c")) c.Check(ss.TryMode, Equals, false, Commentf("c")) c.Check(ss.JailMode, Equals, true, Commentf("c")) c.Check(ss.Revert, Equals, true, Commentf("c")) } } }
func (s *FirstBootTestSuite) TestPopulateFromSeedHappy(c *C) { // put a firstboot snap into the SnapBlobDir snapYaml := `name: foo version: 1.0` mockSnapFile := snaptest.MakeTestSnapWithFiles(c, snapYaml, nil) targetSnapFile := filepath.Join(dirs.SnapSeedDir, "snaps", filepath.Base(mockSnapFile)) err := os.Rename(mockSnapFile, targetSnapFile) c.Assert(err, IsNil) // put a firstboot local snap into the SnapBlobDir snapYaml = `name: local version: 1.0` mockSnapFile = snaptest.MakeTestSnapWithFiles(c, snapYaml, nil) targetSnapFile2 := filepath.Join(dirs.SnapSeedDir, "snaps", filepath.Base(mockSnapFile)) err = os.Rename(mockSnapFile, targetSnapFile2) c.Assert(err, IsNil) devAcct := assertstest.NewAccount(s.storeSigning, "developer", map[string]interface{}{ "account-id": "developerid", }, "") devAcctFn := filepath.Join(dirs.SnapSeedDir, "assertions", "developer.account") err = ioutil.WriteFile(devAcctFn, asserts.Encode(devAcct), 0644) c.Assert(err, IsNil) snapDecl, err := s.storeSigning.Sign(asserts.SnapDeclarationType, map[string]interface{}{ "series": "16", "snap-id": "snapidsnapid", "publisher-id": "developerid", "snap-name": "foo", "timestamp": time.Now().UTC().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) declFn := filepath.Join(dirs.SnapSeedDir, "assertions", "foo.snap-declaration") err = ioutil.WriteFile(declFn, asserts.Encode(snapDecl), 0644) c.Assert(err, IsNil) sha3_384, size, err := asserts.SnapFileSHA3_384(targetSnapFile) c.Assert(err, IsNil) snapRev, err := s.storeSigning.Sign(asserts.SnapRevisionType, map[string]interface{}{ "snap-sha3-384": sha3_384, "snap-size": fmt.Sprintf("%d", size), "snap-id": "snapidsnapid", "developer-id": "developerid", "snap-revision": "128", "timestamp": time.Now().UTC().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) revFn := filepath.Join(dirs.SnapSeedDir, "assertions", "foo.snap-revision") err = ioutil.WriteFile(revFn, asserts.Encode(snapRev), 0644) c.Assert(err, IsNil) // add a model assertion and its chain assertsChain := s.makeModelAssertionChain(c) for i, as := range assertsChain { fn := filepath.Join(dirs.SnapSeedDir, "assertions", strconv.Itoa(i)) err := ioutil.WriteFile(fn, asserts.Encode(as), 0644) c.Assert(err, IsNil) } // create a seed.yaml content := []byte(fmt.Sprintf(` snaps: - name: foo file: %s devmode: true - name: local unasserted: true file: %s `, filepath.Base(targetSnapFile), filepath.Base(targetSnapFile2))) err = ioutil.WriteFile(filepath.Join(dirs.SnapSeedDir, "seed.yaml"), content, 0644) c.Assert(err, IsNil) // run the firstboot stuff err = boot.PopulateStateFromSeed() c.Assert(err, IsNil) // and check the snap got correctly installed c.Check(osutil.FileExists(filepath.Join(dirs.SnapMountDir, "foo", "128", "meta", "snap.yaml")), Equals, true) c.Check(osutil.FileExists(filepath.Join(dirs.SnapMountDir, "local", "x1", "meta", "snap.yaml")), Equals, true) // verify r, err := os.Open(dirs.SnapStateFile) c.Assert(err, IsNil) state, err := state.ReadState(nil, r) c.Assert(err, IsNil) state.Lock() defer state.Unlock() // check foo info, err := snapstate.CurrentInfo(state, "foo") c.Assert(err, IsNil) c.Assert(info.SnapID, Equals, "snapidsnapid") c.Assert(info.Revision, Equals, snap.R(128)) c.Assert(info.DeveloperID, Equals, "developerid") var snapst snapstate.SnapState err = snapstate.Get(state, "foo", &snapst) c.Assert(err, IsNil) c.Assert(snapst.DevMode(), Equals, true) // check local info, err = snapstate.CurrentInfo(state, "local") c.Assert(err, IsNil) c.Assert(info.SnapID, Equals, "") c.Assert(info.Revision, Equals, snap.R("x1")) c.Assert(info.DeveloperID, Equals, "") }