func (s *SnapTestSuite) TestLocalSnapSimple(c *C) { snapYaml, err := s.makeInstalledMockSnap() c.Assert(err, IsNil) snap, err := NewInstalledSnapPart(snapYaml, testOrigin) c.Assert(err, IsNil) c.Assert(snap, NotNil) c.Check(snap.Name(), Equals, "hello-app") c.Check(snap.Version(), Equals, "1.10") c.Check(snap.IsActive(), Equals, false) c.Check(snap.Description(), Equals, "Hello") c.Check(snap.IsInstalled(), Equals, true) services := snap.ServiceYamls() c.Assert(services, HasLen, 1) c.Assert(services[0].Name, Equals, "svc1") // ensure we get valid Date() st, err := os.Stat(snap.basedir) c.Assert(err, IsNil) c.Assert(snap.Date(), Equals, st.ModTime()) c.Assert(snap.basedir, Equals, filepath.Join(s.tempdir, "snaps", helloAppComposedName, "1.10")) c.Assert(snap.InstalledSize(), Not(Equals), -1) }
func (s *SnapTestSuite) TestServicesWithPorts(c *C) { const packageHello = `name: hello-app version: 1.10 icon: meta/hello.svg binaries: - name: bin/hello services: - name: svc1 description: "Service #1" ports: external: ui: port: 8080/tcp nothing: port: 8081/tcp negotiable: yes - name: svc2 description: "Service #2" ` yamlFile, err := makeInstalledMockSnap(s.tempdir, packageHello) c.Assert(err, IsNil) snap, err := NewInstalledSnapPart(yamlFile, testOrigin) c.Assert(err, IsNil) c.Assert(snap, NotNil) c.Assert(snap.Name(), Equals, "hello-app") c.Assert(snap.Origin(), Equals, testOrigin) c.Assert(snap.Version(), Equals, "1.10") c.Assert(snap.IsActive(), Equals, false) services := snap.ServiceYamls() c.Assert(services, HasLen, 2) c.Assert(services[0].Name, Equals, "svc1") c.Assert(services[0].Description, Equals, "Service #1") external1Ui, ok := services[0].Ports.External["ui"] c.Assert(ok, Equals, true) c.Assert(external1Ui.Port, Equals, "8080/tcp") c.Assert(external1Ui.Negotiable, Equals, false) external1Nothing, ok := services[0].Ports.External["nothing"] c.Assert(ok, Equals, true) c.Assert(external1Nothing.Port, Equals, "8081/tcp") c.Assert(external1Nothing.Negotiable, Equals, true) c.Assert(services[1].Name, Equals, "svc2") c.Assert(services[1].Description, Equals, "Service #2") // ensure we get valid Date() st, err := os.Stat(snap.basedir) c.Assert(err, IsNil) c.Assert(snap.Date(), Equals, st.ModTime()) c.Assert(snap.basedir, Equals, filepath.Join(s.tempdir, "snaps", helloAppComposedName, "1.10")) c.Assert(snap.InstalledSize(), Not(Equals), -1) }
func doInstall(name, channel string, flags InstallFlags, meter progress.Meter) (snapName string, err error) { defer func() { if err != nil { err = &ErrInstallFailed{Snap: name, OrigErr: err} } }() // consume local snaps if fi, err := os.Stat(name); err == nil && fi.Mode().IsRegular() { // we allow unauthenticated package when in developer // mode if provisioning.InDeveloperMode() { flags |= AllowUnauthenticated } snap, err := (&Overlord{}).Install(name, flags, meter) if err != nil { return "", err } return snap.Name(), nil } // check repos next mStore := NewConfiguredUbuntuStoreSnapRepository() installed, err := (&Overlord{}).Installed() if err != nil { return "", err } snap, err := mStore.Snap(name, channel, nil) if err != nil { return "", err } cur := FindSnapsByNameAndVersion(snap.Name(), snap.Version, installed) if len(cur) != 0 { return "", ErrAlreadyInstalled } if PackageNameActive(snap.Name()) { return "", ErrPackageNameAlreadyInstalled } return installRemote(mStore, snap, flags, meter) }
// Search searches the repository for the given searchTerm func (s *SnapUbuntuStoreRepository) Search(searchTerm string) (SharedNames, error) { u := *s.searchURI // make a copy, so we can mutate it q := u.Query() q.Set("q", searchTerm) u.RawQuery = q.Encode() req, err := http.NewRequest("GET", u.String(), nil) if err != nil { return nil, err } // set headers setUbuntuStoreHeaders(req) client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() var searchData searchResults dec := json.NewDecoder(resp.Body) if err := dec.Decode(&searchData); err != nil { return nil, err } sharedNames := make(SharedNames, len(searchData.Payload.Packages)) for _, pkg := range searchData.Payload.Packages { snap := NewRemoteSnapPart(pkg) pkgName := snap.Name() if _, ok := sharedNames[snap.Name()]; !ok { sharedNames[pkgName] = new(SharedName) } sharedNames[pkgName].Parts = append(sharedNames[pkgName].Parts, snap) if pkg.Alias != "" { sharedNames[pkgName].Alias = snap } } return sharedNames, nil }
// FindSnapsByName returns all snaps with the given name in the "haystack" // slice of snaps (useful for filtering) func FindSnapsByName(needle string, haystack []*Snap) (res []*Snap) { name, developer := SplitDeveloper(needle) ignorens := developer == "" for _, snap := range haystack { if snap.Name() == name && (ignorens || snap.Developer() == developer) { res = append(res, snap) } } return res }
// FindSnapsByNameAndRevision returns the snaps with the name/version in the // given slice of snaps func FindSnapsByNameAndRevision(needle string, revision int, haystack []*Snap) []*Snap { name, developer := SplitDeveloper(needle) ignorens := developer == "" var found []*Snap for _, snap := range haystack { if snap.Name() == name && snap.Revision() == revision && (ignorens || snap.Developer() == developer) { found = append(found, snap) } } return found }
func (s *SnapTestSuite) TestLocalSnapInstallWithBlessedMetadataOverridingName(c *C) { snapPath := makeTestSnapPackage(c, "") si := &snap.SideInfo{ OfficialName: "bar", Revision: 55, } snap, err := (&Overlord{}).InstallWithSideInfo(snapPath, si, 0, nil) c.Assert(err, IsNil) c.Check(snap.Name(), Equals, "bar") c.Check(snap.Revision, Equals, 55) baseDir := filepath.Join(dirs.SnapSnapsDir, "bar", "55") c.Assert(osutil.FileExists(baseDir), Equals, true) }
// ActiveSnapByName returns all active snaps with the given name func ActiveSnapByName(needle string) *Snap { installed, err := (&Overlord{}).Installed() if err != nil { return nil } for _, snap := range installed { if !snap.IsActive() { continue } if snap.Name() == needle { return snap } } return nil }
// FIXME: This needs to go (and will go). We will have something // like: // remoteSnapType = GetUpdatesFromServer() // localSnapType = DoUpdate(remoteSnaps) // ShowUpdates(localSnaps) // By using the different types (instead of the same interface) // it will not be possilbe to pass remote snaps into the // ShowUpdates() output. // // // convertToInstalledSnaps takes a slice of remote snaps that got // updated and returns the corresponding local snaps func convertToInstalledSnaps(remoteUpdates []*snap.Info) ([]*Snap, error) { installed, err := (&Overlord{}).Installed() if err != nil { return nil, err } installedUpdates := make([]*Snap, 0, len(remoteUpdates)) for _, snap := range remoteUpdates { for _, installed := range installed { if snap.Name() == installed.Name() && snap.Version == installed.Version() { installedUpdates = append(installedUpdates, installed) } } } return installedUpdates, nil }
func (s *SnapTestSuite) TestLocalSnapInstall(c *C) string { snapPath := makeTestSnapPackage(c, "") // revision will be 0 snap, err := (&Overlord{}).Install(snapPath, 0, nil) c.Assert(err, IsNil) c.Check(snap.Name(), Equals, "foo") baseDir := filepath.Join(dirs.SnapSnapsDir, fooComposedName, "0") c.Assert(osutil.FileExists(baseDir), Equals, true) snapEntries := listDir(c, filepath.Join(dirs.SnapSnapsDir, fooComposedName)) c.Check(snapEntries, DeepEquals, []string{"0", "current"}) snapDataEntries := listDir(c, filepath.Join(dirs.SnapDataDir, fooComposedName)) c.Check(snapDataEntries, DeepEquals, []string{"0", "current"}) return snapPath }
func (s *SnapTestSuite) TestServicesWithPorts(c *C) { const packageHello = `name: hello-snap version: 1.10 apps: hello: command: bin/hello svc1: command: svc1 type: forking description: "Service #1" ports: external: ui: port: 8080/tcp nothing: port: 8081/tcp negotiable: yes svc2: command: svc2 type: forking description: "Service #2" ` yamlFile, err := makeInstalledMockSnap(packageHello, 11) c.Assert(err, IsNil) snap, err := NewInstalledSnap(yamlFile) c.Assert(err, IsNil) c.Assert(snap, NotNil) c.Assert(snap.Name(), Equals, "hello-snap") c.Assert(snap.Developer(), Equals, testDeveloper) c.Assert(snap.Version(), Equals, "1.10") c.Assert(snap.IsActive(), Equals, false) apps := snap.Info().Apps c.Assert(apps, HasLen, 3) c.Assert(apps["svc1"].Name, Equals, "svc1") c.Assert(apps["svc2"].Name, Equals, "svc2") }
func (s *SnapTestSuite) TestLocalSnapSimple(c *C) { snapYaml, err := makeInstalledMockSnap("", 15) c.Assert(err, IsNil) snap, err := NewInstalledSnap(snapYaml) c.Assert(err, IsNil) c.Assert(snap, NotNil) c.Check(snap.Name(), Equals, "hello-snap") c.Check(snap.Version(), Equals, "1.10") c.Check(snap.IsActive(), Equals, false) c.Check(snap.Info().Summary(), Equals, "hello in summary") c.Check(snap.Info().Description(), Equals, "Hello...") c.Check(snap.Info().Revision, Equals, 15) mountDir := snap.Info().MountDir() _, err = os.Stat(mountDir) c.Assert(err, IsNil) c.Assert(mountDir, Equals, filepath.Join(dirs.SnapSnapsDir, helloSnapComposedName, "15")) }
// UpdateAll the installed snappy packages, it returns the updated Snaps // if updates where available and an error and nil if any of the updates // fail to apply. func UpdateAll(flags InstallFlags, meter progress.Meter) ([]*Snap, error) { mStore := NewConfiguredUbuntuStoreSnapRepository() updates, err := snapUpdates(mStore) if err != nil { return nil, err } for _, snap := range updates { meter.Notify(fmt.Sprintf("Updating %s (%s)", snap.Name(), snap.Version)) if err := doUpdate(mStore, snap, flags, meter); err != nil { return nil, err } } installedUpdates, err := convertToInstalledSnaps(updates) if err != nil { return nil, err } return installedUpdates, nil }
func (s *SnapTestSuite) TestLocalSnapInstallWithBlessedMetadata(c *C) { snapPath := makeTestSnapPackage(c, "") si := &snap.SideInfo{ OfficialName: "foo", Revision: 40, } snap, err := (&Overlord{}).InstallWithSideInfo(snapPath, si, 0, nil) c.Assert(err, IsNil) c.Check(snap.Name(), Equals, "foo") c.Check(snap.Revision, Equals, 40) baseDir := filepath.Join(dirs.SnapSnapsDir, fooComposedName, "40") c.Assert(osutil.FileExists(baseDir), Equals, true) snapEntries := listDir(c, filepath.Join(dirs.SnapSnapsDir, fooComposedName)) c.Check(snapEntries, DeepEquals, []string{"40", "current"}) snapDataEntries := listDir(c, filepath.Join(dirs.SnapDataDir, fooComposedName)) c.Check(snapDataEntries, DeepEquals, []string{"40", "current"}) }
func (s *SquashfsTestSuite) TestName(c *C) { snap := New("/path/to/foo.snap") c.Assert(snap.Name(), Equals, "foo.snap") }
// plural! func getSnapsInfo(c *Command, r *http.Request) Response { route := c.d.router.Get(snapCmd.Path) if route == nil { return InternalError("router can't find route for snaps") } sources := make([]string, 0, 2) query := r.URL.Query() var includeStore, includeLocal bool if len(query["sources"]) > 0 { for _, v := range strings.Split(query["sources"][0], ",") { if v == "store" { includeStore = true } else if v == "local" { includeLocal = true } } } else { includeStore = true includeLocal = true } searchTerm := query.Get("q") var includeTypes []string if len(query["types"]) > 0 { includeTypes = strings.Split(query["types"][0], ",") } var aboutSnaps []aboutSnap var remoteSnapMap map[string]*snap.Info if includeLocal { sources = append(sources, "local") aboutSnaps, _ = allLocalSnapInfos(c.d.overlord.State()) } var suggestedCurrency string if includeStore { remoteSnapMap = make(map[string]*snap.Info) remoteRepo := newRemoteRepo() auther, err := c.d.auther(r) if err != nil && err != auth.ErrInvalidAuth { return InternalError("%v", err) } // repo.Find("") finds all // // TODO: Instead of ignoring the error from Find: // * if there are no results, return an error response. // * If there are results at all (perhaps local), include a // warning in the response found, _ := remoteRepo.FindSnaps(searchTerm, "", auther) suggestedCurrency = remoteRepo.SuggestedCurrency() sources = append(sources, "store") for _, snap := range found { remoteSnapMap[snap.Name()] = snap } } seen := make(map[string]bool) results := make([]*json.RawMessage, 0, len(aboutSnaps)+len(remoteSnapMap)) addResult := func(name string, m map[string]interface{}) { if seen[name] { return } seen[name] = true // TODO Search the store for "content" with multiple values. See: // https://wiki.ubuntu.com/AppStore/Interfaces/ClickPackageIndex#Search if len(includeTypes) > 0 && !resultHasType(m, includeTypes) { return } resource := "" url, err := route.URL("name", name) if err == nil { resource = url.String() } data, err := json.Marshal(webify(m, resource)) if err != nil { return } raw := json.RawMessage(data) results = append(results, &raw) } for _, about := range aboutSnaps { info := about.info name := info.Name() // strings.Contains(name, "") is true if strings.Contains(name, searchTerm) { active := about.snapst.Active addResult(name, mapSnap(info, active, remoteSnapMap[name])) } } for name, remoteSnap := range remoteSnapMap { addResult(name, mapSnap(nil, false, remoteSnap)) } meta := &Meta{ Sources: sources, Paging: &Paging{ Page: 1, Pages: 1, }, SuggestedCurrency: suggestedCurrency, } return SyncResponse(results, meta) }