in traffic_ops/traffic_ops_golang/invalidationjobs/invalidationjobs.go [850:1036]
func UpdateV40(w http.ResponseWriter, r *http.Request) {
inf, userErr, sysErr, errCode := api.NewInfo(r, []string{"id"}, []string{"id"})
if userErr != nil || sysErr != nil {
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
return
}
defer inf.Close()
var oFQDN string
var dsid uint
var uid uint
job := tc.InvalidationJobV4{}
row := inf.Tx.Tx.QueryRow(putInfoQueryV4, inf.Params["id"])
err := row.Scan(&job.ID,
&job.CreatedBy,
&uid,
&dsid,
&job.DeliveryService,
&job.AssetURL,
&job.TTLHours,
&job.StartTime,
&job.InvalidationType,
&oFQDN)
if err != nil {
if err == sql.ErrNoRows {
userErr = fmt.Errorf("No job by id '%s'!", inf.Params["id"])
errCode = http.StatusNotFound
} else {
sysErr = fmt.Errorf("fetching job update info: %v", err)
errCode = http.StatusInternalServerError
}
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
return
}
if ok, err := IsUserAuthorizedToModifyDSID(inf, dsid); err != nil {
sysErr = fmt.Errorf("Checking user permissions on DS #%d: %v", dsid, err)
errCode = http.StatusInternalServerError
api.HandleErr(w, r, inf.Tx.Tx, errCode, nil, sysErr)
return
} else if !ok {
userErr = errors.New("No such Delivery Service!")
errCode = http.StatusNotFound
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, nil)
return
}
if ok, err := IsUserAuthorizedToModifyJobsMadeByUsername(inf, job.CreatedBy); err != nil {
sysErr = fmt.Errorf("Checking user permissions against user %s: %v", job.CreatedBy, err)
errCode = http.StatusInternalServerError
api.HandleErr(w, r, inf.Tx.Tx, errCode, nil, sysErr)
return
} else if !ok {
userErr = fmt.Errorf("No job by id '%s'!", inf.Params["id"])
errCode = http.StatusNotFound
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, nil)
return
}
input := tc.InvalidationJobV4{}
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
userErr = fmt.Errorf("Unable to parse input: %v", err)
sysErr = fmt.Errorf("parsing input to PUT jobs?id=%s: %v", inf.Params["id"], err)
errCode = http.StatusBadRequest
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
return
}
if err := validateInvalidationJobV4(input); err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, err, nil)
return
}
if !strings.HasPrefix(input.AssetURL, oFQDN) {
userErr = fmt.Errorf("Cannot set asset URL that does not start with Delivery Service origin URL: %s", oFQDN)
errCode = http.StatusBadRequest
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, nil)
return
}
if job.StartTime.Before(time.Now()) {
userErr = errors.New("Cannot modify a job that has already started!")
errCode = http.StatusMethodNotAllowed
w.Header().Set(http.CanonicalHeaderKey("allow"), "GET,HEAD,DELETE")
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, nil)
return
}
if job.DeliveryService != input.DeliveryService {
userErr = errors.New("Cannot change 'deliveryService' of existing invalidation job!")
errCode = http.StatusConflict
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, nil)
return
}
if job.CreatedBy != input.CreatedBy {
userErr = errors.New("Cannot change 'createdBy' of existing invalidation jobs!")
errCode = http.StatusConflict
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, nil)
return
}
if job.ID != input.ID {
userErr = errors.New("Cannot change an invalidation job 'id'!")
errCode = http.StatusConflict
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, nil)
return
}
if job.InvalidationType != input.InvalidationType {
if input.InvalidationType == tc.REFETCH && !refetchAllowed(inf.Tx.Tx) {
userErr = errors.New("Invalidation Type REFETCH is disallowed")
errCode = http.StatusBadRequest
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, nil)
return
}
}
row = inf.Tx.Tx.QueryRow(updateQueryV4,
input.AssetURL,
input.TTLHours,
input.StartTime,
input.InvalidationType,
job.ID)
err = row.Scan(&job.AssetURL,
&job.CreatedBy,
&job.DeliveryService,
&job.ID,
&job.TTLHours,
&job.StartTime,
&job.InvalidationType)
if err != nil {
sysErr = fmt.Errorf("Updating a job: %v", err)
errCode = http.StatusInternalServerError
api.HandleErr(w, r, inf.Tx.Tx, errCode, nil, sysErr)
return
}
if err = setRevalFlags(job.DeliveryService, inf.Tx.Tx); err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("Setting reval flags: %v", err))
return
}
conflicts := tc.ValidateJobUniqueness(inf.Tx.Tx, dsid, input.StartTime, input.AssetURL, input.TTLHours)
response := apiResponseV4{
make([]tc.Alert, len(conflicts)+1),
job,
}
for i, conflict := range conflicts {
response.Alerts[i] = tc.Alert{
Text: conflict,
Level: tc.WarnLevel.String(),
}
}
response.Alerts[len(conflicts)] = tc.Alert{
Text: fmt.Sprintf("Invalidation request created for %s, start: %v end: %v invalidation type: %v",
job.AssetURL,
job.StartTime,
job.StartTime.Add(time.Hour*time.Duration(job.TTLHours)),
job.InvalidationType),
Level: tc.SuccessLevel.String(),
}
resp, err := json.Marshal(response)
if err != nil {
sysErr = fmt.Errorf("encoding response: %v", err)
errCode = http.StatusInternalServerError
api.HandleErr(w, r, inf.Tx.Tx, errCode, nil, sysErr)
return
}
w.Header().Set(http.CanonicalHeaderKey("content-type"), rfc.ApplicationJSON)
api.WriteAndLogErr(w, r, append(resp, '\n'))
changeLogMsg := fmt.Sprintf("%s content invalidation job - ID: %d DSXMLID: %s ASSET_URL: '%s' TTLHRs: %d INVALIDATION: %s",
api.Updated,
input.ID,
input.DeliveryService,
input.AssetURL,
input.TTLHours,
input.InvalidationType,
)
api.CreateChangeLogRawTx(api.ApiChange,
changeLogMsg,
inf.User,
inf.Tx.Tx)
}