in traffic_ops/traffic_ops_golang/deliveryservice/request/status.go [104:242]
func PutStatus(w http.ResponseWriter, r *http.Request) {
inf, userErr, sysErr, errCode := api.NewInfo(r, []string{"id"}, []string{"id"})
tx := inf.Tx.Tx
if userErr != nil || sysErr != nil {
api.HandleErr(w, r, tx, errCode, userErr, sysErr)
return
}
defer inf.Close()
// Middleware should've already handled this, so idk why this is a pointer at all tbh
if inf.Version == nil {
middleware.NotImplementedHandler().ServeHTTP(w, r)
return
}
if inf.User == nil {
sysErr = errors.New("got api info with no user")
api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, sysErr)
return
}
var req tc.StatusChangeRequest
if err := api.Parse(r.Body, tx, &req); err != nil {
api.HandleErr(w, r, tx, http.StatusBadRequest, err, nil)
return
}
dsrID := inf.IntParams["id"]
var dsr tc.DeliveryServiceRequestV5
if err := inf.Tx.QueryRowx(selectQuery+"WHERE r.id=$1", dsrID).StructScan(&dsr); err != nil {
if errors.Is(err, sql.ErrNoRows) {
errCode = http.StatusNotFound
userErr = fmt.Errorf("no such Delivery Service Request: %d", dsrID)
sysErr = nil
} else {
errCode = http.StatusInternalServerError
userErr = nil
sysErr = fmt.Errorf("looking for DSR: %w", err)
}
api.HandleErr(w, r, tx, errCode, userErr, sysErr)
return
}
dsr.SetXMLID()
if err := dsr.Status.ValidTransition(req.Status); err != nil {
api.HandleErr(w, r, tx, http.StatusBadRequest, err, nil)
return
}
authorized, err := isTenantAuthorized(dsr, inf)
if err != nil {
api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, err)
return
}
if !authorized {
api.HandleErr(w, r, tx, http.StatusForbidden, errors.New("not authorized on this tenant"), nil)
return
}
dsr.LastEditedBy = inf.User.UserName
dsr.LastEditedByID = new(int)
*dsr.LastEditedByID = inf.User.ID
// store the current original DS if the DSR is being closed
// (and isn't a "create" request)
if dsr.IsOpen() && req.Status != tc.RequestStatusDraft && req.Status != tc.RequestStatusSubmitted && dsr.ChangeType != tc.DSRChangeTypeCreate {
if dsr.ChangeType == tc.DSRChangeTypeUpdate && dsr.Requested != nil && dsr.Requested.ID != nil {
errCode, userErr, sysErr = getOriginals([]int{*dsr.Requested.ID}, inf.Tx, map[int][]*tc.DeliveryServiceRequestV5{*dsr.Requested.ID: {&dsr}})
if userErr != nil || sysErr != nil {
api.HandleErr(w, r, tx, errCode, userErr, sysErr)
return
}
if dsr.Original == nil {
sysErr = fmt.Errorf("failed to build original from dsr #%d that was to be closed; requested ID: %d", dsrID, *dsr.Requested.ID)
}
} else if dsr.ChangeType == tc.DSRChangeTypeDelete && dsr.Original != nil && dsr.Original.ID != nil {
errCode, userErr, sysErr = getOriginals([]int{*dsr.Original.ID}, inf.Tx, map[int][]*tc.DeliveryServiceRequestV5{*dsr.Original.ID: {&dsr}})
if userErr != nil || sysErr != nil {
api.HandleErr(w, r, tx, errCode, userErr, sysErr)
return
}
if dsr.Original == nil {
sysErr = fmt.Errorf("failed to build original from dsr #%d that was to be closed; original ID: %d", dsrID, *dsr.Original.ID)
}
}
if sysErr != nil {
api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, sysErr)
return
}
err := tx.QueryRow(updateStatusAndOriginalQuery, dsr.Original, req.Status, dsr.LastEditedByID, dsrID).Scan(&dsr.LastUpdated)
if err != nil {
sysErr = fmt.Errorf("updating original for dsr #%d: %w", dsrID, err)
api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, sysErr)
return
}
} else if err := tx.QueryRow(updateStatusQuery, req.Status, dsr.LastEditedByID, *dsr.ID).Scan(&dsr.LastUpdated); err == nil {
if dsr.IsOpen() && dsr.ChangeType != tc.DSRChangeTypeCreate {
query := deliveryservice.SelectDeliveryServicesQuery + " WHERE ds.xml_id = :xmlid"
original, userErr, sysErr, errCode := deliveryservice.GetDeliveryServices(query, map[string]interface{}{"xmlid": dsr.XMLID}, inf.Tx)
if userErr != nil || sysErr != nil {
api.HandleErr(w, r, tx, errCode, userErr, sysErr)
return
}
if len(original) != 1 {
api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, fmt.Errorf("expected exactly one DS with XMLID '%s', found: %d", dsr.XMLID, len(original)))
return
}
dsr.Original = new(tc.DeliveryServiceV5)
*dsr.Original = original[0].DS
}
} else {
userErr, sysErr, errCode = api.ParseDBError(err)
api.HandleErr(w, r, tx, errCode, userErr, sysErr)
return
}
message := fmt.Sprintf("Changed status of '%s' Delivery Service Request from '%s' to '%s'", dsr.XMLID, dsr.Status, req.Status)
dsr.Status = req.Status
var resp interface{}
if inf.Version.Major >= 5 {
resp = dsr
} else if inf.Version.Major >= 4 {
if inf.Version.Minor >= 1 {
resp = dsr.Downgrade()
} else {
resp = dsr.Downgrade().Downgrade()
}
} else {
resp = dsr.Downgrade().Downgrade().Downgrade()
}
api.WriteRespAlertObj(w, r, tc.SuccessLevel, message, resp)
message = fmt.Sprintf("Delivery Service Request: %d, ID: %d, ACTION: %s deliveryservice_request, keys: {id:%d }", *dsr.ID, *dsr.ID, message, *dsr.ID)
inf.CreateChangeLog(message)
}