func iconGet(name, origin string) Response { lock, err := lockfile.Lock(dirs.SnapLockFile, true) if err != nil { return InternalError("unable to acquire lock: %v", err) } defer lock.Unlock() bag := lightweight.PartBagByName(name, origin) if bag == nil || len(bag.Versions) == 0 { return NotFound("unable to find snap with name %q and origin %q", name, origin) } part := bag.LoadBest() if part == nil { return NotFound("unable to load snap with name %q and origin %q", name, origin) } path := filepath.Clean(part.Icon()) if !strings.HasPrefix(path, dirs.SnapSnapsDir) { // XXX: how could this happen? return BadRequest("requested icon is not in snap path") } return FileResponse(path) }
func snapConfig(c *Command, r *http.Request) Response { vars := muxVars(r) name := vars["name"] origin := vars["origin"] if name == "" || origin == "" { return BadRequest("missing name or origin") } pkgName := name + "." + origin lock, err := lockfile.Lock(dirs.SnapLockFile, true) if err != nil { return InternalError("unable to acquire lock: %v", err) } defer lock.Unlock() bag := lightweight.PartBagByName(name, origin) if bag == nil { return NotFound("no snap found with name %q and origin %q", name, origin) } idx := bag.ActiveIndex() if idx < 0 { return BadRequest("unable to configure non-active snap") } part, err := bag.Load(idx) if err != nil { return InternalError("unable to load active snap: %v", err) } bs, err := ioutil.ReadAll(r.Body) if err != nil { return BadRequest("reading config request body gave %v", err) } overlord := getConfigurator() config, err := overlord.Configure(part.(*snappy.SnapPart), bs) if err != nil { return InternalError("unable to retrieve config for %s: %v", pkgName, err) } return SyncResponse(config) }
func getSnapInfo(c *Command, r *http.Request) Response { vars := muxVars(r) name := vars["name"] origin := vars["origin"] lock, err := lockfile.Lock(dirs.SnapLockFile, true) if err != nil { return InternalError("unable to acquire lock: %v", err) } defer lock.Unlock() repo := newRemoteRepo() var part snappy.Part if parts, _ := repo.Details(name, origin); len(parts) > 0 { part = parts[0] } bag := lightweight.PartBagByName(name, origin) if bag == nil && part == nil { return NotFound("unable to find snap with name %q and origin %q", name, origin) } route := c.d.router.Get(c.Path) if route == nil { return InternalError("router can't find route for snap %s.%s", name, origin) } url, err := route.URL("name", name, "origin", origin) if err != nil { return InternalError("route can't build URL for snap %s.%s: %v", name, origin, err) } result := webify(bag.Map(part), url.String()) return SyncResponse(result) }
func snapService(c *Command, r *http.Request) Response { route := c.d.router.Get(operationCmd.Path) if route == nil { return InternalError("router can't find route for operation") } vars := muxVars(r) name := vars["name"] origin := vars["origin"] if name == "" || origin == "" { return BadRequest("missing name or origin") } appName := vars["service"] pkgName := name + "." + origin action := "status" if r.Method != "GET" { decoder := json.NewDecoder(r.Body) var cmd map[string]string if err := decoder.Decode(&cmd); err != nil { return BadRequest("can't decode request body into service command: %v", err) } action = cmd["action"] } var lock lockfile.LockedFile reachedAsync := false switch action { case "status", "start", "stop", "restart", "enable", "disable": var err error lock, err = lockfile.Lock(dirs.SnapLockFile, true) if err != nil { return InternalError("unable to acquire lock: %v", err) } defer func() { if !reachedAsync { lock.Unlock() } }() default: return BadRequest("unknown action %s", action) } bag := lightweight.PartBagByName(name, origin) idx := bag.ActiveIndex() if idx < 0 { return NotFound("unable to find snap with name %q and origin %q", name, origin) } ipart, err := bag.Load(idx) if err != nil { return InternalError("unable to load active snap: %v", err) } part, ok := ipart.(*snappy.SnapPart) if !ok { return InternalError("active snap is not a *snappy.SnapPart: %T", ipart) } apps := part.Apps() if len(apps) == 0 { return NotFound("snap %q has no services", pkgName) } appmap := make(map[string]*appDesc, len(apps)) for i := range apps { if apps[i].Daemon == "" { continue } appmap[apps[i].Name] = &appDesc{Spec: apps[i], Op: action} } if appName != "" && appmap[appName] == nil { return NotFound("snap %q has no service %q", pkgName, appName) } // note findServices takes the *bare* name actor, err := findServices(name, appName, &progress.NullProgress{}) if err != nil { return InternalError("no services for %q [%q] found: %v", pkgName, appName, err) } f := func() interface{} { status, err := actor.ServiceStatus() if err != nil { logger.Noticef("unable to get status for %q [%q]: %v", pkgName, appName, err) return err } for i := range status { if desc, ok := appmap[status[i].ServiceName]; ok { desc.Status = status[i] } else { // shouldn't really happen, but can't hurt appmap[status[i].ServiceName] = &appDesc{Status: status[i]} } } if appName == "" { return appmap } return appmap[appName] } if action == "status" { return SyncResponse(f()) } reachedAsync = true return AsyncResponse(c.d.AddTask(func() interface{} { defer lock.Unlock() switch action { case "start": err = actor.Start() case "stop": err = actor.Stop() case "enable": err = actor.Enable() case "disable": err = actor.Disable() case "restart": err = actor.Restart() } if err != nil { logger.Noticef("unable to %s %q [%q]: %v\n", action, pkgName, appName, err) return err } return f() }).Map(route)) }