in traffic_ops/traffic_ops_golang/invalidationjobs/invalidationjobs.go [702:846]
func Create(w http.ResponseWriter, r *http.Request) {
inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
if userErr != nil || sysErr != nil {
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
return
}
defer inf.Close()
job := tc.InvalidationJobInput{}
if err := json.NewDecoder(r.Body).Decode(&job); err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("Unable to parse Invalidation Job"), fmt.Errorf("parsing jobs/ POST: %v", err))
return
}
w.Header().Set(rfc.ContentType, rfc.ApplicationJSON)
if err := job.Validate(inf.Tx.Tx); err != nil {
response := tc.Alerts{
Alerts: []tc.Alert{
tc.Alert{
Text: err.Error(),
Level: tc.ErrorLevel.String(),
},
},
}
resp, err := json.Marshal(response)
if err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("Encoding bad request response: %v", err))
return
}
w.WriteHeader(http.StatusBadRequest)
api.WriteAndLogErr(w, r, append(resp, '\n'))
return
}
// Validate() would have already checked for deliveryservice existence and
// parsed the ttl, so if either of these throws an error now, something
// weird has happened
dsid, err := job.DSID(nil)
if err != nil {
sysErr = fmt.Errorf("retrieving parsed DSID: %v", err)
errCode = http.StatusInternalServerError
api.HandleErr(w, r, inf.Tx.Tx, errCode, nil, sysErr)
return
}
var ttl uint
if ttl, err = job.TTLHours(); err != nil {
sysErr = fmt.Errorf("retrieving parsed TTL: %v", err)
errCode = http.StatusInternalServerError
api.HandleErr(w, r, inf.Tx.Tx, errCode, nil, sysErr)
return
}
if ok, err := IsUserAuthorizedToModifyDSID(inf, dsid); err != nil {
sysErr = fmt.Errorf("Checking current user permissions for DS #%d: %v", dsid, err)
errCode = http.StatusInternalServerError
api.HandleErr(w, r, inf.Tx.Tx, errCode, nil, sysErr)
return
} else if !ok {
userErr = fmt.Errorf("No such Delivery Service!")
errCode = http.StatusNotFound
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, nil)
return
}
_, cdnName, _, err := dbhelpers.GetDSNameAndCDNFromID(inf.Tx.Tx, int(dsid))
if err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting delivery service and CDN name from ID: "+err.Error()))
return
}
userErr, sysErr, statusCode := dbhelpers.CheckIfCurrentUserCanModifyCDN(inf.Tx.Tx, string(cdnName), inf.User.UserName)
if userErr != nil || sysErr != nil {
api.HandleErr(w, r, inf.Tx.Tx, statusCode, userErr, sysErr)
return
}
row := inf.Tx.Tx.QueryRow(insertQuery,
ttl,
dsid, // Used in inner select for deliveryservice
*job.Regex,
(*job.StartTime).Time,
time.Now(),
inf.User.ID,
dsid,
tc.REFRESH) // Defaults for all api versions below 4.0
result := tc.InvalidationJob{}
err = row.Scan(&result.AssetURL,
&result.DeliveryService,
&result.ID,
&result.CreatedBy,
&result.Keyword,
&result.Parameters,
&result.StartTime)
if err != nil {
userErr, sysErr, errCode = api.ParseDBError(err)
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
return
}
if err := setRevalFlags(dsid, 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, job.StartTime.Time, *result.AssetURL, ttl)
response := apiResponse{
make([]tc.Alert, len(conflicts)+1),
result,
}
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 %v, start:%v end %v", *result.AssetURL, job.StartTime.Time,
job.StartTime.Add(time.Hour*time.Duration(ttl))),
Level: tc.SuccessLevel.String(),
}
resp, err := json.Marshal(response)
if err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("Marshaling JSON: %v", err))
return
}
if inf.Version == nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("nil API version"))
return
}
w.Header().Set(http.CanonicalHeaderKey("location"), fmt.Sprintf("%s://%s/api/%s/jobs?id=%d", inf.Config.URL.Scheme, r.Host, inf.Version, *result.ID))
w.WriteHeader(http.StatusOK)
api.WriteAndLogErr(w, r, append(resp, '\n'))
duplicate := ""
if len(conflicts) > 0 {
duplicate = "(duplicate) "
}
api.CreateChangeLogRawTx(api.ApiChange, api.Created+" content invalidation job "+duplicate+"- ID: "+
strconv.FormatUint(*result.ID, 10)+" DS: "+*result.DeliveryService+" URL: '"+*result.AssetURL+
"' Params: '"+*result.Parameters+"'", inf.User, inf.Tx.Tx)
}