in traffic_ops/traffic_ops_golang/cdni/shared.go [318:457]
func PutConfigurationResponse(w http.ResponseWriter, r *http.Request) {
inf, userErr, sysErr, errCode := api.NewInfo(r, []string{"approved", "id"}, []string{"id"})
if userErr != nil || sysErr != nil {
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
return
}
defer inf.Close()
reqId := inf.IntParams["id"]
approvedString := inf.Params["approved"]
approved, err := strconv.ParseBool(approvedString)
if err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("approved parameter must be a boolean"), nil)
return
}
db, err := api.GetDB(r.Context())
if err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("getting async db: %w", err))
return
}
logTx, err := db.Begin()
if err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("getting log tx: %w", err))
return
}
defer logTx.Commit()
rows, err := inf.Tx.Tx.Query(SelectCapabilityUpdateQuery, reqId)
if err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("querying for capability update request: %w", err))
return
}
defer log.Close(rows, "closing capabilities update query")
var ucdn string
var data json.RawMessage
var host string
var asyncId int
var requestType string
count := 0
for rows.Next() {
if err := rows.Scan(&ucdn, &data, &asyncId, &requestType, &host); err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("scanning db rows: %w", err))
return
}
count++
}
if count == 0 {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, fmt.Errorf("no configuration request for that id"), nil)
return
}
if !approved {
if asyncErr := api.UpdateAsyncStatus(db, api.AsyncFailed, "Requested configuration update has been denied.", asyncId, true); asyncErr != nil {
log.Errorf("updating async status for id %d: %s", asyncId, asyncErr.Error())
}
status, err := deleteCapabilityRequest(reqId, inf.Tx.Tx)
if err != nil {
api.HandleErr(w, r, inf.Tx.Tx, status, nil, fmt.Errorf("deleting configuration request from queue: %w", err))
return
}
msg := "Successfully denied configuration update request."
api.CreateChangeLogRawTx(api.ApiChange, msg, inf.User, inf.Tx.Tx)
api.WriteResp(w, r, msg)
return
}
var updatedDataList []GenericMetadata
if err = json.Unmarshal(data, &updatedDataList); err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("unmarshalling data for configuration update: %w", err))
return
}
var unsupportedTypes []string
for _, updatedData := range updatedDataList {
if !updatedData.Type.isValid() {
unsupportedTypes = append(unsupportedTypes, string(updatedData.Type))
}
}
if len(unsupportedTypes) != 0 {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, fmt.Errorf("unsupported generic metadata types found: %v", strings.Join(unsupportedTypes, ", ")), nil)
return
}
for _, updatedData := range updatedDataList {
switch updatedData.Type {
case MiRequestedCapacityLimits:
var capacityRequestedLimits CapacityRequestedLimits
if err = json.Unmarshal(updatedData.Value, &capacityRequestedLimits); err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("unmarshalling data for configuration update: %w", err))
return
}
for _, capLim := range capacityRequestedLimits.RequestedLimits {
capId, err := getCapabilityIdFromFootprints(capLim, ucdn, inf)
if err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("finding capability for given information: %w", err))
return
}
query := UpdateLimitsByCapabilityAndLimitTypeQuery
queryParams := []interface{}{capLim.LimitValue, capId, capLim.LimitType}
if host != "" {
query = query + " AND $4 = ANY(scope_value)"
queryParams = []interface{}{capLim.LimitValue, capId, capLim.LimitType, host}
}
result, err := inf.Tx.Tx.Exec(query, queryParams...)
if err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("updating capacity: %w", err))
return
}
if rowsAffected, err := result.RowsAffected(); err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("updating capacity: getting rows affected: %w", err))
return
} else if rowsAffected < 1 {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, fmt.Errorf("no capacity found for update: host: %s, type: %s, limit: %v", host, updatedData.Type, capLim), nil)
return
} else if rowsAffected > 1 {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("capacity update affected too many rows: %d", rowsAffected))
return
}
}
}
}
if asyncErr := api.UpdateAsyncStatus(db, api.AsyncSucceeded, "Capacity requested update has been completed.", asyncId, true); asyncErr != nil {
log.Errorf("updating async status for id %v: %v", asyncId, asyncErr)
}
status, err := deleteCapabilityRequest(reqId, inf.Tx.Tx)
if err != nil {
api.HandleErr(w, r, inf.Tx.Tx, status, nil, fmt.Errorf("deleting capacity request from queue: %w", err))
return
}
msg := "Successfully updated configuration."
api.CreateChangeLogRawTx(api.ApiChange, msg, inf.User, logTx)
api.WriteResp(w, r, msg)
}