func CreateV40()

in traffic_ops/traffic_ops_golang/invalidationjobs/invalidationjobs.go [533:696]


func CreateV40(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.InvalidationJobCreateV4{}
	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
	}

	// Check if request object is valid
	w.Header().Set(rfc.ContentType, rfc.ApplicationJSON)
	if err := validateJobCreateV4(job, inf.Tx.Tx); err != nil {
		response := tc.Alerts{
			Alerts: []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
	}

	// Check if authorized
	if ok, err := IsUserAuthorizedToModifyDSXMLID(inf, job.DeliveryService); err != nil {
		sysErr = fmt.Errorf("failed checking current user permissions for DS #%s: %v", job.DeliveryService, err)
		errCode = http.StatusInternalServerError
		api.HandleErr(w, r, inf.Tx.Tx, errCode, nil, sysErr)
		return
	} else if !ok {
		userErr = fmt.Errorf("failed to authorize based on tenancy")
		errCode = http.StatusNotFound
		api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, nil)
		return
	}

	// DS existence was already verified in the Validate() function
	dsid, exists, err := dbhelpers.GetDSIDFromXMLID(inf.Tx.Tx, job.DeliveryService)
	if err != nil {
		sysErr = fmt.Errorf("failed to match XML ID to int ID for Delivery Service %s: %v", job.DeliveryService, err)
		errCode = http.StatusInternalServerError
		api.HandleErr(w, r, inf.Tx.Tx, errCode, nil, sysErr)
		return
	}
	if !exists {
		userErr = fmt.Errorf("delivery service \"%v\" does not exist", job.DeliveryService)
		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(insertQueryV4,
		job.TTLHours,
		dsid, // Used in inner select for deliveryservice
		job.Regex,
		job.StartTime,
		time.Now(),
		inf.User.ID,
		dsid,
		job.InvalidationType) // Defaults for all api versions below 4.0

	result := tc.InvalidationJobV4{}
	err = row.Scan(
		&result.ID,
		&result.AssetURL,
		&result.CreatedBy,
		&result.DeliveryService,
		&result.TTLHours,
		&result.InvalidationType,
		&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(uint(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, uint(dsid), result.StartTime, result.AssetURL, result.TTLHours)
	response := apiResponseV4{
		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 (%s) request created for %v, start:%v end %v",
			result.InvalidationType,
			result.AssetURL,
			result.StartTime,
			result.StartTime.Add(time.Hour*time.Duration(job.TTLHours))),
		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/%d.%d/jobs?id=%d",
		inf.Config.URL.Scheme,
		r.Host,
		inf.Version.Major,
		inf.Version.Minor,
		result.ID))
	w.WriteHeader(http.StatusOK)
	api.WriteAndLogErr(w, r, append(resp, '\n'))

	duplicate := ""
	if len(conflicts) > 0 {
		duplicate = "(duplicate) "
	}
	changeLogMsg := fmt.Sprintf("%s content invalidation job %s- ID: %d DSXMLID: %s ASSET_URL: '%s' TTLHRs: %d INVALIDATION: %s",
		api.Created,
		duplicate,
		result.ID,
		result.DeliveryService,
		result.AssetURL,
		result.TTLHours,
		result.InvalidationType,
	)
	api.CreateChangeLogRawTx(api.ApiChange,
		changeLogMsg,
		inf.User,
		inf.Tx.Tx)
}