func (ms *mgrsSuite) TestHappyLocalInstall(c *C) { snapYamlContent := `name: foo apps: bar: command: bin/bar ` snapPath := makeTestSnap(c, snapYamlContent+"version: 1.0") st := ms.o.State() st.Lock() defer st.Unlock() ts, err := snapstate.InstallPath(st, &snap.SideInfo{RealName: "foo"}, 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.Status(), Equals, state.DoneStatus, Commentf("install-snap change failed with: %v", chg.Err())) snap, err := snapstate.CurrentInfo(st, "foo") c.Assert(err, IsNil) // ensure that the binary wrapper file got generated with the right // name binaryWrapper := filepath.Join(dirs.SnapBinariesDir, "foo.bar") c.Assert(osutil.IsSymlink(binaryWrapper), Equals, true) // data dirs c.Assert(osutil.IsDirectory(snap.DataDir()), Equals, true) c.Assert(osutil.IsDirectory(snap.CommonDataDir()), Equals, true) // snap file and its mounting // after install the snap file is in the right dir c.Assert(osutil.FileExists(filepath.Join(dirs.SnapBlobDir, "foo_x1.snap")), Equals, true) // ensure the right unit is created mup := systemd.MountUnitPath("/snap/foo/x1") content, err := ioutil.ReadFile(mup) c.Assert(err, IsNil) c.Assert(string(content), Matches, "(?ms).*^Where=/snap/foo/x1") c.Assert(string(content), Matches, "(?ms).*^What=/var/lib/snapd/snaps/foo_x1.snap") }
func (s *systemd) WriteMountUnitFile(name, what, where, fstype string) (string, error) { extra := "" if osutil.IsDirectory(what) { extra = "Options=bind\n" fstype = "none" } if fstype == "squashfs" && useFuse() { fstype = "fuse.squashfuse" } c := fmt.Sprintf(`[Unit] Description=Mount unit for %s [Mount] What=%s Where=%s Type=%s %s [Install] WantedBy=multi-user.target `, name, what, where, fstype, extra) mu := MountUnitPath(where) return filepath.Base(mu), osutil.AtomicWriteFile(mu, []byte(c), 0644, 0) }
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 trySnap(c *Command, r *http.Request, user *auth.UserState, trydir string, flags snapstate.Flags) Response { st := c.d.overlord.State() st.Lock() defer st.Unlock() if !filepath.IsAbs(trydir) { return BadRequest("cannot try %q: need an absolute path", trydir) } if !osutil.IsDirectory(trydir) { return BadRequest("cannot try %q: not a snap directory", trydir) } // the developer asked us to do this with a trusted snap dir info, err := unsafeReadSnapInfo(trydir) if err != nil { return BadRequest("cannot read snap info for %s: %s", trydir, err) } tsets, err := snapstateTryPath(st, info.Name(), trydir, flags) if err != nil { return BadRequest("cannot try %s: %s", trydir, err) } msg := fmt.Sprintf(i18n.G("Try %q snap from %q"), info.Name(), trydir) chg := newChange(st, "try-snap", msg, []*state.TaskSet{tsets}, []string{info.Name()}) chg.Set("api-data", map[string]string{"snap-name": info.Name()}) ensureStateSoon(st) return AsyncResponse(nil, &Meta{Change: chg.ID()}) }
func norm(path string) string { path = filepath.Clean(path) if osutil.IsDirectory(path) { path = path + "/" } return path }
// addImplicitHooks adds hooks from the installed snap's hookdir to the snap info. // // Existing hooks (i.e. ones defined in the YAML) are not changed; only missing // hooks are added. func addImplicitHooks(snapInfo *Info) error { // First of all, check to ensure the hooks directory exists. If it doesn't, // it's not an error-- there's just nothing to do. hooksDir := snapInfo.HooksDir() if !osutil.IsDirectory(hooksDir) { return nil } fileInfos, err := ioutil.ReadDir(hooksDir) if err != nil { return fmt.Errorf("unable to read hooks directory: %s", err) } for _, fileInfo := range fileInfos { addHookIfValid(snapInfo, fileInfo.Name()) } return nil }
func (x *cmdTry) Execute([]string) error { if err := x.validateMode(); err != nil { return err } cli := Client() name := x.Positional.SnapDir opts := &client.SnapOptions{ DevMode: x.DevMode, JailMode: x.JailMode, } if name == "" { if osutil.FileExists("snapcraft.yaml") && osutil.IsDirectory("prime") { name = "prime" } else { if osutil.FileExists("meta/snap.yaml") { name = "./" } } if name == "" { return fmt.Errorf(i18n.G("error: the `<snap-dir>` argument was not provided and couldn't be inferred")) } } path, err := filepath.Abs(name) if err != nil { // TRANSLATORS: %q gets what the user entered, %v gets the resulting error message return fmt.Errorf(i18n.G("cannot get full path for %q: %v"), name, err) } changeID, err := cli.Try(path, opts) if err != nil { return err } chg, err := wait(cli, changeID) if err != nil { return err } // extract the snap name var snapName string if err := chg.Get("snap-name", &snapName); err != nil { // TRANSLATORS: %q gets the snap name, %v gets the resulting error message return fmt.Errorf(i18n.G("cannot extract the snap-name from local file %q: %v"), name, err) } name = snapName // show output as speced snaps, err := cli.List([]string{name}, nil) if err != nil { return err } if len(snaps) != 1 { // TRANSLATORS: %q gets the snap name, %v the list of things found when trying to list it return fmt.Errorf(i18n.G("cannot get data for %q: %v"), name, snaps) } snap := snaps[0] // TRANSLATORS: 1. snap name, 2. snap version (keep those together please). the 3rd %s is a path (where it's mounted from). fmt.Fprintf(Stdout, i18n.G("%s %s mounted from %s\n"), name, snap.Version, path) return nil }
func (ms *mgrsSuite) TestHappyLocalInstallWithStoreMetadata(c *C) { snapDecl := ms.prereqSnapAssertions(c) snapYamlContent := `name: foo apps: bar: command: bin/bar ` snapPath := makeTestSnap(c, snapYamlContent+"version: 1.5") si := &snap.SideInfo{ RealName: "foo", SnapID: fooSnapID, Revision: snap.R(55), DeveloperID: "devdevdevID", Developer: "devdevdev", } st := ms.o.State() st.Lock() defer st.Unlock() // have the snap-declaration in the system db err := assertstate.Add(st, ms.storeSigning.StoreAccountKey("")) c.Assert(err, IsNil) err = assertstate.Add(st, ms.devAcct) c.Assert(err, IsNil) err = assertstate.Add(st, snapDecl) c.Assert(err, IsNil) ts, err := snapstate.InstallPath(st, si, 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.Status(), Equals, state.DoneStatus, Commentf("install-snap change failed with: %v", chg.Err())) info, err := snapstate.CurrentInfo(st, "foo") c.Assert(err, IsNil) c.Check(info.Revision, Equals, snap.R(55)) c.Check(info.SnapID, Equals, fooSnapID) c.Check(info.DeveloperID, Equals, "devdevdevID") c.Check(info.Developer, Equals, "devdevdev") c.Check(info.Version, Equals, "1.5") // ensure that the binary wrapper file got generated with the right // name binaryWrapper := filepath.Join(dirs.SnapBinariesDir, "foo.bar") c.Assert(osutil.IsSymlink(binaryWrapper), Equals, true) // data dirs c.Assert(osutil.IsDirectory(info.DataDir()), Equals, true) c.Assert(osutil.IsDirectory(info.CommonDataDir()), Equals, true) // snap file and its mounting // after install the snap file is in the right dir c.Assert(osutil.FileExists(filepath.Join(dirs.SnapBlobDir, "foo_55.snap")), Equals, true) // ensure the right unit is created mup := systemd.MountUnitPath("/snap/foo/55") content, err := ioutil.ReadFile(mup) c.Assert(err, IsNil) c.Assert(string(content), Matches, "(?ms).*^Where=/snap/foo/55") c.Assert(string(content), Matches, "(?ms).*^What=/var/lib/snapd/snaps/foo_55.snap") }