func snapsOp(c *Command, r *http.Request, user *auth.UserState) Response { route := c.d.router.Get(stateChangeCmd.Path) if route == nil { return InternalError("cannot find route for change") } decoder := json.NewDecoder(r.Body) var inst snapInstruction if err := decoder.Decode(&inst); err != nil { return BadRequest("cannot decode request body into snap instruction: %v", err) } if inst.Channel != "" || !inst.Revision.Unset() || inst.DevMode || inst.JailMode { return BadRequest("unsupported option provided for multi-snap operation") } st := c.d.overlord.State() st.Lock() defer st.Unlock() if user != nil { inst.userID = user.ID } var msg string var affected []string var tsets []*state.TaskSet var err error switch inst.Action { case "refresh": msg, affected, tsets, err = snapUpdateMany(&inst, st) case "install": msg, affected, tsets, err = snapInstallMany(&inst, st) case "remove": msg, affected, tsets, err = snapRemoveMany(&inst, st) default: return BadRequest("unsupported multi-snap operation %q", inst.Action) } if err != nil { return InternalError("cannot %s %q: %v", inst.Action, inst.Snaps, err) } var chg *state.Change if len(tsets) == 0 { chg = st.NewChange(inst.Action+"-snap", msg) chg.SetStatus(state.DoneStatus) } else { chg = newChange(st, inst.Action+"-snap", msg, tsets, affected) ensureStateSoon(st) } chg.Set("api-data", map[string]interface{}{"snap-names": affected}) return AsyncResponse(nil, &Meta{Change: chg.ID()}) }