func (s *mountSnapSuite) TestDoUndoMountSnap(c *C) { v1 := "name: core\nversion: 1.0\n" testSnap := snaptest.MakeTestSnapWithFiles(c, v1, nil) s.state.Lock() defer s.state.Unlock() si1 := &snap.SideInfo{ RealName: "core", Revision: snap.R(1), } si2 := &snap.SideInfo{ RealName: "core", Revision: snap.R(2), } snapstate.Set(s.state, "core", &snapstate.SnapState{ Sequence: []*snap.SideInfo{si1}, Current: si1.Revision, SnapType: "os", }) t := s.state.NewTask("mount-snap", "test") t.Set("snap-setup", &snapstate.SnapSetup{ SideInfo: si2, SnapPath: testSnap, }) chg := s.state.NewChange("dummy", "...") chg.AddTask(t) terr := s.state.NewTask("error-trigger", "provoking total undo") terr.WaitFor(t) chg.AddTask(terr) s.state.Unlock() for i := 0; i < 3; i++ { s.snapmgr.Ensure() s.snapmgr.Wait() } s.state.Lock() // ensure undo was called the right way c.Check(s.fakeBackend.ops, DeepEquals, fakeOps{ { op: "current", old: "/snap/core/1", }, { op: "setup-snap", name: testSnap, revno: snap.R(2), }, { op: "undo-setup-snap", name: "/snap/core/2", stype: "os", }, }) }
func (s *imageSuite) TestDownloadUnpackGadget(c *C) { files := [][]string{ {"subdir/canary.txt", "I'm a canary"}, } s.downloadedSnaps["pc"] = snaptest.MakeTestSnapWithFiles(c, packageGadget, files) s.storeSnapInfo["pc"] = infoFromSnapYaml(c, packageGadget, snap.R(99)) gadgetUnpackDir := filepath.Join(c.MkDir(), "gadget-unpack-dir") opts := &image.Options{ GadgetUnpackDir: gadgetUnpackDir, } local, err := image.LocalSnaps(opts) c.Assert(err, IsNil) err = image.DownloadUnpackGadget(s, s.model, opts, local) c.Assert(err, IsNil) // verify the right data got unpacked for _, t := range []struct{ file, content string }{ {"meta/snap.yaml", packageGadget}, {files[0][0], files[0][1]}, } { fn := filepath.Join(gadgetUnpackDir, t.file) content, err := ioutil.ReadFile(fn) c.Assert(err, IsNil) c.Check(content, DeepEquals, []byte(t.content)) } }
func (s *kernelOSSuite) TestExtractKernelAssetsNoUnpacksKernelForGrub(c *C) { // pretend to be a grub system mockGrub := boottest.NewMockBootloader("grub", c.MkDir()) partition.ForceBootloader(mockGrub) files := [][]string{ {"kernel.img", "I'm a kernel"}, {"initrd.img", "...and I'm an initrd"}, {"meta/kernel.yaml", "version: 4.2"}, } si := &snap.SideInfo{ RealName: "ubuntu-kernel", Revision: snap.R(42), } fn := snaptest.MakeTestSnapWithFiles(c, packageKernel, files) snapf, err := snap.Open(fn) c.Assert(err, IsNil) info, err := snap.ReadInfoFromSnapFile(snapf, si) c.Assert(err, IsNil) err = boot.ExtractKernelAssets(info, snapf) c.Assert(err, IsNil) // kernel is *not* here kernimg := filepath.Join(mockGrub.Dir(), "ubuntu-kernel_42.snap", "kernel.img") c.Assert(osutil.FileExists(kernimg), Equals, false) }
func (s *storeTestSuite) makeTestSnap(c *C, snapYamlContent string) string { fn := snaptest.MakeTestSnapWithFiles(c, snapYamlContent, nil) dst := filepath.Join(s.store.blobDir, filepath.Base(fn)) err := osutil.CopyFile(fn, dst, 0) c.Assert(err, IsNil) return dst }
func (s *infoSuite) TestReadInfoFromSnapFileCatchesInvalidImplicitHook(c *C) { yaml := `name: foo version: 1.0` snapPath := snaptest.MakeTestSnapWithFiles(c, yaml, emptyHooks("123abc")) snapf, err := snap.Open(snapPath) c.Assert(err, IsNil) _, err = snap.ReadInfoFromSnapFile(snapf, nil) c.Assert(err, ErrorMatches, ".*invalid hook name.*") }
func (s *imageSuite) setupSnaps(c *C, gadgetUnpackDir string) { err := os.MkdirAll(gadgetUnpackDir, 0755) c.Assert(err, IsNil) err = ioutil.WriteFile(filepath.Join(gadgetUnpackDir, "grub.conf"), nil, 0644) c.Assert(err, IsNil) s.downloadedSnaps["pc"] = snaptest.MakeTestSnapWithFiles(c, packageGadget, [][]string{{"grub.cfg", "I'm a grub.cfg"}}) s.storeSnapInfo["pc"] = infoFromSnapYaml(c, packageGadget, snap.R(1)) s.addSystemSnapAssertions(c, "pc") s.downloadedSnaps["pc-kernel"] = snaptest.MakeTestSnapWithFiles(c, packageKernel, nil) s.storeSnapInfo["pc-kernel"] = infoFromSnapYaml(c, packageKernel, snap.R(2)) s.addSystemSnapAssertions(c, "pc-kernel") s.downloadedSnaps["core"] = snaptest.MakeTestSnapWithFiles(c, packageCore, nil) s.storeSnapInfo["core"] = infoFromSnapYaml(c, packageCore, snap.R(3)) s.addSystemSnapAssertions(c, "core") s.downloadedSnaps["required-snap1"] = snaptest.MakeTestSnapWithFiles(c, requiredSnap1, nil) s.storeSnapInfo["required-snap1"] = infoFromSnapYaml(c, requiredSnap1, snap.R(3)) s.addSystemSnapAssertions(c, "required-snap1") }
func (s *setupSuite) TestSetupUndoIdempotent(c *C) { // make sure that a retry wouldn't stumble on partial work // use a kernel because that does and need to do strictly more // this cannot check systemd own behavior though around mounts! bootloader := boottest.NewMockBootloader("mock", c.MkDir()) partition.ForceBootloader(bootloader) // we don't get real mounting os.Setenv("SNAPPY_SQUASHFS_UNPACK_FOR_TESTS", "1") defer os.Unsetenv("SNAPPY_SQUASHFS_UNPACK_FOR_TESTS") testFiles := [][]string{ {"kernel.img", "kernel"}, {"initrd.img", "initrd"}, {"modules/4.4.0-14-generic/foo.ko", "a module"}, {"firmware/bar.bin", "some firmware"}, {"meta/kernel.yaml", "version: 4.2"}, } snapPath := snaptest.MakeTestSnapWithFiles(c, `name: kernel version: 1.0 type: kernel `, testFiles) si := snap.SideInfo{ RealName: "kernel", Revision: snap.R(140), } err := s.be.SetupSnap(snapPath, &si, &s.nullProgress) c.Assert(err, IsNil) minInfo := snap.MinimalPlaceInfo("kernel", snap.R(140)) err = s.be.UndoSetupSnap(minInfo, "kernel", &s.nullProgress) c.Assert(err, IsNil) // retry run err = s.be.UndoSetupSnap(minInfo, "kernel", &s.nullProgress) c.Assert(err, IsNil) // sanity checks l, _ := filepath.Glob(filepath.Join(dirs.SnapServicesDir, "*.mount")) c.Assert(l, HasLen, 0) c.Assert(osutil.FileExists(minInfo.MountDir()), Equals, false) c.Assert(osutil.FileExists(minInfo.MountFile()), Equals, false) l, _ = filepath.Glob(filepath.Join(bootloader.Dir(), "*")) c.Assert(l, HasLen, 0) }
func (s *infoSuite) TestReadInfoFromSnapFileMissingEpoch(c *C) { yaml := `name: foo version: 1.0 type: app` snapPath := snaptest.MakeTestSnapWithFiles(c, yaml, nil) snapf, err := snap.Open(snapPath) c.Assert(err, IsNil) info, err := snap.ReadInfoFromSnapFile(snapf, nil) c.Assert(err, IsNil) c.Check(info.Name(), Equals, "foo") c.Check(info.Version, Equals, "1.0") c.Check(info.Type, Equals, snap.TypeApp) c.Check(info.Revision, Equals, snap.R(0)) c.Check(info.Epoch, Equals, "0") // Defaults to 0 }
func (s *kernelOSSuite) TestExtractKernelAssetsAndRemove(c *C) { files := [][]string{ {"kernel.img", "I'm a kernel"}, {"initrd.img", "...and I'm an initrd"}, {"dtbs/foo.dtb", "g'day, I'm foo.dtb"}, {"dtbs/bar.dtb", "hello, I'm bar.dtb"}, // must be last {"meta/kernel.yaml", "version: 4.2"}, } si := &snap.SideInfo{ RealName: "ubuntu-kernel", Revision: snap.R(42), } fn := snaptest.MakeTestSnapWithFiles(c, packageKernel, files) snapf, err := snap.Open(fn) c.Assert(err, IsNil) info, err := snap.ReadInfoFromSnapFile(snapf, si) c.Assert(err, IsNil) err = boot.ExtractKernelAssets(info, snapf) c.Assert(err, IsNil) // this is where the kernel/initrd is unpacked bootdir := s.bootloader.Dir() kernelAssetsDir := filepath.Join(bootdir, "ubuntu-kernel_42.snap") for _, def := range files { if def[0] == "meta/kernel.yaml" { break } fullFn := filepath.Join(kernelAssetsDir, def[0]) content, err := ioutil.ReadFile(fullFn) c.Assert(err, IsNil) c.Assert(string(content), Equals, def[1]) } // remove err = boot.RemoveKernelAssets(info) c.Assert(err, IsNil) c.Check(osutil.FileExists(kernelAssetsDir), Equals, false) }
func (s *infoSuite) checkInstalledSnapAndSnapFile(c *C, yaml string, contents string, hooks []string, checker func(c *C, info *snap.Info)) { // First check installed snap sideInfo := &snap.SideInfo{Revision: snap.R(42)} info0 := snaptest.MockSnap(c, yaml, contents, sideInfo) snaptest.PopulateDir(info0.MountDir(), emptyHooks(hooks...)) info, err := snap.ReadInfo(info0.Name(), sideInfo) c.Check(err, IsNil) checker(c, info) // Now check snap file snapPath := snaptest.MakeTestSnapWithFiles(c, yaml, emptyHooks(hooks...)) snapf, err := snap.Open(snapPath) c.Assert(err, IsNil) info, err = snap.ReadInfoFromSnapFile(snapf, nil) c.Check(err, IsNil) checker(c, info) }
func (s *infoSuite) TestReadInfoFromSnapFileWithSideInfo(c *C) { yaml := `name: foo version: 1.0 type: app` snapPath := snaptest.MakeTestSnapWithFiles(c, yaml, nil) snapf, err := snap.Open(snapPath) c.Assert(err, IsNil) info, err := snap.ReadInfoFromSnapFile(snapf, &snap.SideInfo{ RealName: "baz", Revision: snap.R(42), }) c.Assert(err, IsNil) c.Check(info.Name(), Equals, "baz") c.Check(info.Version, Equals, "1.0") c.Check(info.Type, Equals, snap.TypeApp) c.Check(info.Revision, Equals, snap.R(42)) }
func (s *infoSuite) TestReadInfoFromSnapFile(c *C) { yaml := `name: foo version: 1.0 type: app epoch: 1* confinement: devmode` snapPath := snaptest.MakeTestSnapWithFiles(c, yaml, nil) snapf, err := snap.Open(snapPath) c.Assert(err, IsNil) info, err := snap.ReadInfoFromSnapFile(snapf, nil) c.Assert(err, IsNil) c.Check(info.Name(), Equals, "foo") c.Check(info.Version, Equals, "1.0") c.Check(info.Type, Equals, snap.TypeApp) c.Check(info.Revision, Equals, snap.R(0)) c.Check(info.Epoch, Equals, "1*") c.Check(info.Confinement, Equals, snap.DevModeConfinement) }
func (ms *mgrsSuite) TestInstallKernelSnapUpdatesBootloader(c *C) { bootloader := boottest.NewMockBootloader("mock", c.MkDir()) partition.ForceBootloader(bootloader) defer partition.ForceBootloader(nil) restore := release.MockOnClassic(false) defer restore() const packageKernel = ` name: krnl version: 4.0-1 type: kernel` files := [][]string{ {"kernel.img", "I'm a kernel"}, {"initrd.img", "...and I'm an initrd"}, {"meta/kernel.yaml", "version: 4.2"}, } snapPath := snaptest.MakeTestSnapWithFiles(c, packageKernel, files) st := ms.o.State() st.Lock() defer st.Unlock() ts, err := snapstate.InstallPath(st, &snap.SideInfo{RealName: "krnl"}, snapPath, "", 0) c.Assert(err, IsNil) chg := st.NewChange("install-snap", "...") chg.AddAll(ts) st.Unlock() err = ms.o.Settle() st.Lock() c.Assert(err, IsNil) c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("install-snap change failed with: %v", chg.Err())) c.Assert(bootloader.BootVars, DeepEquals, map[string]string{ "snap_try_kernel": "krnl_x1.snap", "snap_mode": "try", }) }
func (s *setupSuite) TestSetupDoUndoKernelUboot(c *C) { bootloader := boottest.NewMockBootloader("mock", c.MkDir()) partition.ForceBootloader(bootloader) // we don't get real mounting os.Setenv("SNAPPY_SQUASHFS_UNPACK_FOR_TESTS", "1") defer os.Unsetenv("SNAPPY_SQUASHFS_UNPACK_FOR_TESTS") testFiles := [][]string{ {"kernel.img", "kernel"}, {"initrd.img", "initrd"}, {"modules/4.4.0-14-generic/foo.ko", "a module"}, {"firmware/bar.bin", "some firmware"}, {"meta/kernel.yaml", "version: 4.2"}, } snapPath := snaptest.MakeTestSnapWithFiles(c, `name: kernel version: 1.0 type: kernel `, testFiles) si := snap.SideInfo{ RealName: "kernel", Revision: snap.R(140), } err := s.be.SetupSnap(snapPath, &si, &s.nullProgress) c.Assert(err, IsNil) l, _ := filepath.Glob(filepath.Join(bootloader.Dir(), "*")) c.Assert(l, HasLen, 1) minInfo := snap.MinimalPlaceInfo("kernel", snap.R(140)) // undo deletes the kernel assets again err = s.be.UndoSetupSnap(minInfo, "kernel", &s.nullProgress) c.Assert(err, IsNil) l, _ = filepath.Glob(filepath.Join(bootloader.Dir(), "*")) c.Assert(l, HasLen, 0) }
func (s *mountSnapSuite) TestDoMountSnapRemovesSnaps(c *C) { v1 := "name: mock\nversion: 1.0\n" testSnap := snaptest.MakeTestSnapWithFiles(c, v1, nil) s.state.Lock() t := s.state.NewTask("mount-snap", "test") t.Set("snap-setup", &snapstate.SnapSetup{ SideInfo: &snap.SideInfo{ RealName: "foo", Revision: snap.R(33), }, SnapPath: testSnap, DownloadInfo: &snap.DownloadInfo{DownloadURL: "https://some"}, }) s.state.NewChange("dummy", "...").AddTask(t) s.state.Unlock() s.snapmgr.Ensure() s.snapmgr.Wait() c.Assert(osutil.FileExists(testSnap), Equals, false) }
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, "") }
func (s *imageSuite) TestBootstrapToRootDirDevmodeSnap(c *C) { restore := sysdb.InjectTrusted(s.storeSigning.Trusted) defer restore() rootdir := filepath.Join(c.MkDir(), "imageroot") // FIXME: bootstrapToRootDir needs an unpacked gadget yaml gadgetUnpackDir := filepath.Join(c.MkDir(), "gadget") err := os.MkdirAll(gadgetUnpackDir, 0755) c.Assert(err, IsNil) err = ioutil.WriteFile(filepath.Join(gadgetUnpackDir, "grub.conf"), nil, 0644) c.Assert(err, IsNil) s.setupSnaps(c, gadgetUnpackDir) s.downloadedSnaps["devmode-snap"] = snaptest.MakeTestSnapWithFiles(c, devmodeSnap, nil) s.storeSnapInfo["devmode-snap"] = infoFromSnapYaml(c, devmodeSnap, snap.R(0)) // mock the mount cmds (for the extract kernel assets stuff) c1 := testutil.MockCommand(c, "mount", "") defer c1.Restore() c2 := testutil.MockCommand(c, "umount", "") defer c2.Restore() opts := &image.Options{ Snaps: []string{s.downloadedSnaps["devmode-snap"]}, RootDir: rootdir, GadgetUnpackDir: gadgetUnpackDir, } local, err := image.LocalSnaps(opts) c.Assert(err, IsNil) err = image.BootstrapToRootDir(s, s.model, opts, local) c.Assert(err, IsNil) // check seed yaml seed, err := snap.ReadSeedYaml(filepath.Join(rootdir, "var/lib/snapd/seed/seed.yaml")) c.Assert(err, IsNil) c.Check(seed.Snaps, HasLen, 5) // check devmode-snap info := &snap.Info{ SideInfo: snap.SideInfo{ RealName: "devmode-snap", Revision: snap.R("x1"), }, } fn := filepath.Base(info.MountFile()) p := filepath.Join(rootdir, "var/lib/snapd/seed/snaps", fn) c.Check(osutil.FileExists(p), Equals, true) // ensure local snaps are put last in seed.yaml last := len(seed.Snaps) - 1 c.Check(seed.Snaps[last], DeepEquals, &snap.SeedSnap{ Name: "devmode-snap", File: fn, DevMode: true, Unasserted: true, }) }
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 *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 makeTestSnap(c *C, snapYamlContent string) string { return snaptest.MakeTestSnapWithFiles(c, snapYamlContent, nil) }
func (ms *mgrsSuite) TestInstallKernelSnapUpdatesBootloader(c *C) { bootloader := boottest.NewMockBootloader("mock", c.MkDir()) partition.ForceBootloader(bootloader) defer partition.ForceBootloader(nil) restore := release.MockOnClassic(false) defer restore() brandAcct := assertstest.NewAccount(ms.storeSigning, "my-brand", map[string]interface{}{ "account-id": "my-brand", "verification": "certified", }, "") brandAccKey := assertstest.NewAccountKey(ms.storeSigning, brandAcct, nil, brandPrivKey.PublicKey(), "") brandSigning := assertstest.NewSigningDB("my-brand", brandPrivKey) model, err := brandSigning.Sign(asserts.ModelType, map[string]interface{}{ "series": "16", "authority-id": "my-brand", "brand-id": "my-brand", "model": "my-model", "architecture": "amd64", "store": "my-brand-store-id", "gadget": "gadget", "kernel": "krnl", "timestamp": time.Now().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) const packageKernel = ` name: krnl version: 4.0-1 type: kernel` files := [][]string{ {"kernel.img", "I'm a kernel"}, {"initrd.img", "...and I'm an initrd"}, {"meta/kernel.yaml", "version: 4.2"}, } snapPath := snaptest.MakeTestSnapWithFiles(c, packageKernel, files) st := ms.o.State() st.Lock() defer st.Unlock() // setup model assertion err = assertstate.Add(st, ms.storeSigning.StoreAccountKey("")) c.Assert(err, IsNil) err = assertstate.Add(st, brandAcct) c.Assert(err, IsNil) err = assertstate.Add(st, brandAccKey) c.Assert(err, IsNil) auth.SetDevice(st, &auth.DeviceState{ Brand: "my-brand", Model: "my-model", }) err = assertstate.Add(st, model) c.Assert(err, IsNil) ts, err := snapstate.InstallPath(st, &snap.SideInfo{RealName: "krnl"}, snapPath, "", snapstate.Flags{}) c.Assert(err, IsNil) chg := st.NewChange("install-snap", "...") chg.AddAll(ts) st.Unlock() err = ms.o.Settle() st.Lock() c.Assert(err, IsNil) c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("install-snap change failed with: %v", chg.Err())) c.Assert(bootloader.BootVars, DeepEquals, map[string]string{ "snap_try_kernel": "krnl_x1.snap", "snap_mode": "try", }) }