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()}) }
func change2changeInfo(chg *state.Change) *changeInfo { status := chg.Status() chgInfo := &changeInfo{ ID: chg.ID(), Kind: chg.Kind(), Summary: chg.Summary(), Status: status.String(), Ready: status.Ready(), SpawnTime: chg.SpawnTime(), } readyTime := chg.ReadyTime() if !readyTime.IsZero() { chgInfo.ReadyTime = &readyTime } if err := chg.Err(); err != nil { chgInfo.Err = err.Error() } tasks := chg.Tasks() taskInfos := make([]*taskInfo, len(tasks)) for j, t := range tasks { label, done, total := t.Progress() taskInfo := &taskInfo{ ID: t.ID(), Kind: t.Kind(), Summary: t.Summary(), Status: t.Status().String(), Log: t.Log(), Progress: taskInfoProgress{ Label: label, Done: done, Total: total, }, SpawnTime: t.SpawnTime(), } readyTime := t.ReadyTime() if !readyTime.IsZero() { taskInfo.ReadyTime = &readyTime } taskInfos[j] = taskInfo } chgInfo.Tasks = taskInfos var data map[string]*json.RawMessage if chg.Get("api-data", &data) == nil { chgInfo.Data = data } return chgInfo }