func (ms *mgrsSuite) installLocalTestSnap(c *C, snapYamlContent string) *snap.Info { st := ms.o.State() snapPath := makeTestSnap(c, snapYamlContent) snapf, err := snap.Open(snapPath) c.Assert(err, IsNil) info, err := snap.ReadInfoFromSnapFile(snapf, nil) c.Assert(err, IsNil) // store current state snapName := info.Name() var snapst snapstate.SnapState snapstate.Get(st, snapName, &snapst) ts, err := snapstate.InstallPath(st, &snap.SideInfo{RealName: snapName}, snapPath, "", snapstate.Flags{DevMode: true}) 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.Err(), IsNil) c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("install-snap change failed with: %v", chg.Err())) return info }
func tryDirect(w io.Writer, path string, verbose bool) bool { path = norm(path) snapf, err := snap.Open(path) if err != nil { return false } info, err := snap.ReadInfoFromSnapFile(snapf, nil) if err != nil { return false } fmt.Fprintf(w, "path:\t%q\n", path) fmt.Fprintf(w, "name:\t%s\n", info.Name()) fmt.Fprintf(w, "summary:\t%q\n", info.Summary()) var notes *Notes if verbose { fmt.Fprintln(w, "notes:\t") fmt.Fprintf(w, " confinement:\t%s\n", info.Confinement) if info.Broken == "" { fmt.Fprintln(w, " broken:\tfalse") } else { fmt.Fprintf(w, " broken:\ttrue (%s)\n", info.Broken) } } else { notes = NotesFromInfo(info) } fmt.Fprintf(w, "version:\t%s %s\n", info.Version, notes) maybePrintType(w, string(info.Type)) return true }
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 unsafeReadSnapInfoImpl(snapPath string) (*snap.Info, error) { // Condider using DeriveSideInfo before falling back to this! snapf, err := snap.Open(snapPath) if err != nil { return nil, err } return snap.ReadInfoFromSnapFile(snapf, nil) }
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 extractKernelAssets(snapPath string, info *snap.Info) error { snapf, err := snap.Open(snapPath) if err != nil { return err } if err := boot.ExtractKernelAssets(info, snapf); err != nil { return err } return nil }
func (s *infoSuite) TestReadInfoFromSnapFileValidates(c *C) { yaml := `name: foo.bar version: 1.0 type: app` snapPath := makeTestSnap(c, yaml) snapf, err := snap.Open(snapPath) c.Assert(err, IsNil) _, err = snap.ReadInfoFromSnapFile(snapf, nil) c.Assert(err, ErrorMatches, "invalid snap name.*") }
func (s *FileSuite) TestFileOpenForSnapDir(c *C) { sd := c.MkDir() snapYaml := filepath.Join(sd, "meta", "snap.yaml") err := os.MkdirAll(filepath.Dir(snapYaml), 0755) c.Assert(err, IsNil) err = ioutil.WriteFile(snapYaml, []byte(`name: foo`), 0644) c.Assert(err, IsNil) f, err := snap.Open(sd) c.Assert(err, IsNil) c.Assert(f, FitsTypeOf, &snapdir.SnapDir{}) }
func (s *infoSuite) TestReadInfoFromSnapFileCatchesInvalidConfinement(c *C) { yaml := `name: foo version: 1.0 confinement: foo` snapPath := makeTestSnap(c, yaml) snapf, err := snap.Open(snapPath) c.Assert(err, IsNil) _, err = snap.ReadInfoFromSnapFile(snapf, nil) c.Assert(err, ErrorMatches, ".*invalid confinement type.*") }
// OpenSnapFile opens a snap blob returning both a snap.Info completed // with sideInfo (if not nil) and a corresponding snap.Container. // Assumes the file was verified beforehand or the user asked for --dangerous. func OpenSnapFile(snapPath string, sideInfo *snap.SideInfo) (*snap.Info, snap.Container, error) { snapf, err := snap.Open(snapPath) if err != nil { return nil, nil, err } info, err := snap.ReadInfoFromSnapFile(snapf, sideInfo) if err != nil { return nil, nil, err } return info, snapf, nil }
func (s *infoSuite) TestReadInfoFromSnapFileCatchesInvalidHook(c *C) { yaml := `name: foo version: 1.0 hooks: 123abc:` snapPath := makeTestSnap(c, yaml) snapf, err := snap.Open(snapPath) c.Assert(err, IsNil) _, err = snap.ReadInfoFromSnapFile(snapf, nil) c.Assert(err, ErrorMatches, ".*invalid hook name.*") }
func (ms *mgrsSuite) serveSnap(snapPath, revno string) { snapf, err := snap.Open(snapPath) if err != nil { panic(err) } info, err := snap.ReadInfoFromSnapFile(snapf, nil) if err != nil { panic(err) } name := info.Name() ms.serveIDtoName[fakeSnapID(name)] = name ms.serveSnapPath[name] = snapPath ms.serveRevision[name] = revno }
func snapEssentialInfo(w http.ResponseWriter, fn, snapID string, bs asserts.Backstore) (*essentialInfo, error) { snapFile, err := snap.Open(fn) if err != nil { http.Error(w, fmt.Sprintf("cannot read: %v: %v", fn, err), http.StatusBadRequest) return nil, errInfo } info, err := snap.ReadInfoFromSnapFile(snapFile, nil) if err != nil { http.Error(w, fmt.Sprintf("can get info for: %v: %v", fn, err), http.StatusBadRequest) return nil, errInfo } snapDigest, size, err := asserts.SnapFileSHA3_384(fn) if err != nil { http.Error(w, fmt.Sprintf("can get digest for: %v: %v", fn, err), http.StatusBadRequest) return nil, errInfo } snapRev, devAcct, err := findSnapRevision(snapDigest, bs) if err != nil && err != asserts.ErrNotFound { http.Error(w, fmt.Sprintf("can get info for: %v: %v", fn, err), http.StatusBadRequest) return nil, errInfo } var devel, develID string var revision int if snapRev != nil { snapID = snapRev.SnapID() develID = snapRev.DeveloperID() devel = devAcct.Username() revision = snapRev.SnapRevision() } else { // XXX: fallback until we are always assertion based develID = defaultDeveloperID devel = defaultDeveloper revision = makeRevision(info) } return &essentialInfo{ Name: info.Name(), SnapID: snapID, DeveloperID: develID, DevelName: devel, Revision: revision, Version: info.Version, Digest: snapDigest, Size: size, }, nil }
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) 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 *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 (s *Store) collectSnaps() (map[string]string, error) { snapFns, err := filepath.Glob(filepath.Join(s.blobDir, "*.snap")) if err != nil { return nil, err } snaps := map[string]string{} for _, fn := range snapFns { snapFile, err := snap.Open(fn) if err != nil { return nil, err } info, err := snap.ReadInfoFromSnapFile(snapFile, nil) if err != nil { return nil, err } snaps[info.Name()] = fn } return snaps, err }
func localSnaps(opts *Options) (*localInfos, error) { local := make(map[string]*snap.Info) nameToPath := make(map[string]string) for _, snapName := range opts.Snaps { if strings.HasSuffix(snapName, ".snap") && osutil.FileExists(snapName) { snapFile, err := snap.Open(snapName) if err != nil { return nil, err } info, err := snap.ReadInfoFromSnapFile(snapFile, nil) if err != nil { return nil, err } // local snap gets local revision info.Revision = snap.R(-1) nameToPath[info.Name()] = snapName local[snapName] = info } } return &localInfos{ pathToInfo: local, nameToPath: nameToPath, }, nil }
func (ms *mgrsSuite) mockStore(c *C) *httptest.Server { var baseURL string fillHit := func() string { snapf, err := snap.Open(ms.serveSnapPath) if err != nil { panic(err) } info, err := snap.ReadInfoFromSnapFile(snapf, nil) if err != nil { panic(err) } hit := strings.Replace(fooSearchHit, "@URL@", baseURL+"/snap", -1) hit = strings.Replace(hit, "@ICON@", baseURL+"/icon", -1) hit = strings.Replace(hit, "@VERSION@", info.Version, -1) hit = strings.Replace(hit, "@REVISION@", ms.serveRevision, -1) return hit } mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if strings.HasPrefix(r.URL.Path, "/assertions/") { comps := strings.Split(r.URL.Path, "/") ref := &asserts.Ref{ Type: asserts.Type(comps[2]), PrimaryKey: comps[3:], } a, err := ref.Resolve(ms.storeSigning.Find) if err == asserts.ErrNotFound { w.Header().Set("Content-Type", "application/json") w.WriteHeader(404) w.Write([]byte(`{"status": 404}`)) return } if err != nil { panic(err) } w.Header().Set("Content-Type", asserts.MediaType) w.WriteHeader(200) w.Write(asserts.Encode(a)) return } switch r.URL.Path { case "/details/foo": w.WriteHeader(http.StatusOK) io.WriteString(w, fillHit()) case "/metadata": w.WriteHeader(http.StatusOK) output := `{ "_embedded": { "clickindex:package": [@HIT@] } }` output = strings.Replace(output, "@HIT@", fillHit(), 1) io.WriteString(w, output) case "/snap": snapR, err := os.Open(ms.serveSnapPath) if err != nil { panic(err) } io.Copy(w, snapR) default: panic("unexpected url path: " + r.URL.Path) } })) c.Assert(mockServer, NotNil) baseURL = mockServer.URL detailsURL, err := url.Parse(baseURL + "/details/") c.Assert(err, IsNil) bulkURL, err := url.Parse(baseURL + "/metadata") c.Assert(err, IsNil) assertionsURL, err := url.Parse(baseURL + "/assertions/") c.Assert(err, IsNil) storeCfg := store.Config{ DetailsURI: detailsURL, BulkURI: bulkURL, AssertionsURI: assertionsURL, } mStore := store.New(&storeCfg, nil) st := ms.o.State() st.Lock() snapstate.ReplaceStore(ms.o.State(), mStore) st.Unlock() return mockServer }
func (ms *mgrsSuite) mockStore(c *C) *httptest.Server { var baseURL string fillHit := func(name string) string { snapf, err := snap.Open(ms.serveSnapPath[name]) if err != nil { panic(err) } info, err := snap.ReadInfoFromSnapFile(snapf, nil) if err != nil { panic(err) } hit := strings.Replace(searchHit, "@URL@", baseURL+"/snap/"+name, -1) hit = strings.Replace(hit, "@NAME@", name, -1) hit = strings.Replace(hit, "@SNAPID@", fakeSnapID(name), -1) hit = strings.Replace(hit, "@ICON@", baseURL+"/icon", -1) hit = strings.Replace(hit, "@VERSION@", info.Version, -1) hit = strings.Replace(hit, "@REVISION@", ms.serveRevision[name], -1) return hit } mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { comps := strings.Split(r.URL.Path, "/") if len(comps) == 0 { panic("unexpected url path: " + r.URL.Path) } switch comps[1] { case "assertions": ref := &asserts.Ref{ Type: asserts.Type(comps[2]), PrimaryKey: comps[3:], } a, err := ref.Resolve(ms.storeSigning.Find) if err == asserts.ErrNotFound { w.Header().Set("Content-Type", "application/json") w.WriteHeader(404) w.Write([]byte(`{"status": 404}`)) return } if err != nil { panic(err) } w.Header().Set("Content-Type", asserts.MediaType) w.WriteHeader(200) w.Write(asserts.Encode(a)) return case "details": w.WriteHeader(http.StatusOK) io.WriteString(w, fillHit(comps[2])) case "metadata": dec := json.NewDecoder(r.Body) var input struct { Snaps []struct { SnapID string `json:"snap_id"` Revision int `json:"revision"` } `json:"snaps"` } err := dec.Decode(&input) if err != nil { panic(err) } var hits []json.RawMessage for _, s := range input.Snaps { name := ms.serveIDtoName[s.SnapID] if snap.R(s.Revision) == snap.R(ms.serveRevision[name]) { continue } hits = append(hits, json.RawMessage(fillHit(name))) } w.WriteHeader(http.StatusOK) output, err := json.Marshal(map[string]interface{}{ "_embedded": map[string]interface{}{ "clickindex:package": hits, }, }) if err != nil { panic(err) } w.Write(output) case "snap": snapR, err := os.Open(ms.serveSnapPath[comps[2]]) if err != nil { panic(err) } io.Copy(w, snapR) default: panic("unexpected url path: " + r.URL.Path) } })) c.Assert(mockServer, NotNil) baseURL = mockServer.URL detailsURL, err := url.Parse(baseURL + "/details/") c.Assert(err, IsNil) bulkURL, err := url.Parse(baseURL + "/metadata") c.Assert(err, IsNil) assertionsURL, err := url.Parse(baseURL + "/assertions/") c.Assert(err, IsNil) storeCfg := store.Config{ DetailsURI: detailsURL, BulkURI: bulkURL, AssertionsURI: assertionsURL, } mStore := store.New(&storeCfg, nil) st := ms.o.State() st.Lock() snapstate.ReplaceStore(ms.o.State(), mStore) st.Unlock() return mockServer }