This is an automated email from the ASF dual-hosted git repository.

mitchell852 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new 108bce1  Add consistent audit log messages to TO Go (#3771)
108bce1 is described below

commit 108bce189a264a0ed92d88efa9dba66b6607da34
Author: Alex Luckerman <[email protected]>
AuthorDate: Wed Aug 14 12:03:53 2019 -0600

    Add consistent audit log messages to TO Go (#3771)
    
    * Add audit log message to TO cdn.DeleteName
    
    * Add and update logging for non-DS endpoints
    
    * Move helper functions to db_helpers/other clean up
    
    * Remove fmt.Sprintf from non-DS endpoints
    
    * Fix merge conflicts for cleaning dbhelpers
    
    * Fix compile issues
    
    * Add audit logging to DS related endpoints
    
    * Fix int-to-string conversions
    
    * Update CHANGELOG.md
    
    * Return proper user errors, fix other small issues
    
    * Updated log messages according to PR feedback
    
    * More PR changes
    
    * Add context to DS regex deletion
    
    * Fix remaining int to string conversion bugs
---
 CHANGELOG.md                                       |  1 +
 traffic_ops/traffic_ops_golang/api/change_log.go   |  7 +++-
 .../traffic_ops_golang/api/change_log_test.go      |  3 +-
 .../traffic_ops_golang/cachegroup/dspost.go        | 10 ++++-
 .../traffic_ops_golang/cachegroup/queueupdate.go   |  8 ++--
 traffic_ops/traffic_ops_golang/cdn/dnssec.go       | 32 +++++++++++++-
 traffic_ops/traffic_ops_golang/cdn/genksk.go       |  9 ++++
 traffic_ops/traffic_ops_golang/cdn/namedelete.go   | 18 +++-----
 traffic_ops/traffic_ops_golang/cdn/queue.go        | 13 +++++-
 traffic_ops/traffic_ops_golang/crconfig/handler.go |  3 +-
 .../deliveryservice/deliveryservices.go            | 14 +++----
 .../traffic_ops_golang/deliveryservice/keys.go     | 32 ++++++++++++++
 .../deliveryservice/servers/delete.go              | 18 ++++++++
 .../deliveryservice/servers/servers.go             |  7 ++--
 .../traffic_ops_golang/deliveryservice/sslkeys.go  | 10 +++++
 .../traffic_ops_golang/deliveryservice/urlkey.go   | 20 +++++++++
 .../deliveryservicesregexes.go                     | 49 +++++++++++++++++++++-
 traffic_ops/traffic_ops_golang/federations/ds.go   | 21 +++++++++-
 .../profileparameter/postparameterprofile.go       | 20 +++++++++
 .../profileparameter/postprofileparameter.go       |  9 ++++
 .../profileparameter/postprofileparametersbyid.go  | 11 ++---
 .../postprofileparametersbyname.go                 | 11 ++---
 .../server/servers_assignment.go                   | 14 ++++---
 .../traffic_ops_golang/urisigning/urisigning.go    | 30 ++++++++++++-
 24 files changed, 318 insertions(+), 52 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3b51a6f..0ca6329 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,6 +39,7 @@ The format is based on [Keep a 
Changelog](http://keepachangelog.com/en/1.0.0/).
 - In Traffic Portal, server table columns can now be rearranged and their 
visibility toggled on/off as desired by the user. Hidden table columns are 
excluded from the table search. These settings are persisted in the browser.
 - Added pagination support to some Traffic Ops endpoints via three new query 
parameters, limit and offset/page
 - Traffic Ops now supports a "sortOrder" query parameter on some endpoints to 
return API responses in descending order
+- Traffic Ops now uses a consistent format for audit logs across all Go 
endpoints
 
 ### Changed
 - Traffic Router, added TLS certificate validation on certificates imported 
from Traffic Ops
diff --git a/traffic_ops/traffic_ops_golang/api/change_log.go 
b/traffic_ops/traffic_ops_golang/api/change_log.go
index 9cd1762..adb008c 100644
--- a/traffic_ops/traffic_ops_golang/api/change_log.go
+++ b/traffic_ops/traffic_ops_golang/api/change_log.go
@@ -23,6 +23,7 @@ import (
        "database/sql"
        "errors"
        "fmt"
+       "strings"
 
        "github.com/apache/trafficcontrol/lib/go-log"
        "github.com/apache/trafficcontrol/lib/go-tc"
@@ -70,7 +71,11 @@ func CreateChangeLogBuildMsg(level string, action string, 
user *auth.CurrentUser
                keyStr += key + ":" + fmt.Sprintf("%v", value) + " "
        }
        keyStr += "}"
-       msg := action + " " + objType + ": " + auditName + " keys: " + keyStr
+       id, ok := keys["id"]
+       if !ok {
+               id = "N/A"
+       }
+       msg := fmt.Sprintf("%v: %v, ID: %v, ACTION: %v %v, keys: %v", 
strings.ToTitle(objType), auditName, id, strings.Title(action), objType, keyStr)
        return CreateChangeLogRawErr(level, msg, user, tx)
 }
 
diff --git a/traffic_ops/traffic_ops_golang/api/change_log_test.go 
b/traffic_ops/traffic_ops_golang/api/change_log_test.go
index 4d74f08..5776f52 100644
--- a/traffic_ops/traffic_ops_golang/api/change_log_test.go
+++ b/traffic_ops/traffic_ops_golang/api/change_log_test.go
@@ -21,6 +21,7 @@ package api
 
 import (
        "strconv"
+       "strings"
        "testing"
 
        "github.com/jmoiron/sqlx"
@@ -66,7 +67,7 @@ func TestCreateChangeLog(t *testing.T) {
        i := testIdentifier{}
 
        keys, _ := i.GetKeys()
-       expectedMessage := Created + " " + i.GetType() + ": " + 
i.GetAuditName() + " keys: { id:" + strconv.Itoa(keys["id"].(int)) + " }"
+       expectedMessage := strings.ToUpper(i.GetType()) + ": " + 
i.GetAuditName() + ", ID: " + strconv.Itoa(keys["id"].(int)) + ", ACTION: " + 
Created + " " + i.GetType() + ", keys: { id:" + strconv.Itoa(keys["id"].(int)) 
+ " }"
 
        mock.ExpectBegin()
        mock.ExpectExec("INSERT").WithArgs(ApiChange, expectedMessage, 
1).WillReturnResult(sqlmock.NewResult(1, 1))
diff --git a/traffic_ops/traffic_ops_golang/cachegroup/dspost.go 
b/traffic_ops/traffic_ops_golang/cachegroup/dspost.go
index 6d3afc9..812b62e 100644
--- a/traffic_ops/traffic_ops_golang/cachegroup/dspost.go
+++ b/traffic_ops/traffic_ops_golang/cachegroup/dspost.go
@@ -23,7 +23,6 @@ import (
        "database/sql"
        "encoding/json"
        "errors"
-       "fmt"
        "net/http"
        "strconv"
 
@@ -85,6 +84,13 @@ func postDSes(tx *sql.Tx, user *auth.CurrentUser, cgID 
int64, dsIDs []int64) (tc
                }
        }
 
+       cgName, ok, err := getCGNameFromID(tx, cgID)
+       if err != nil {
+               return tc.CacheGroupPostDSResp{}, nil, errors.New("getting 
cachegroup name from ID '" + string(cgID) + "': " + err.Error()), 
http.StatusInternalServerError
+       } else if !ok {
+               return tc.CacheGroupPostDSResp{}, errors.New("cachegroup " + 
string(cgID) + " does not exist"), nil, http.StatusNotFound
+       }
+
        if err := verifyDSesCDN(tx, dsIDs, cdnName); err != nil {
                return tc.CacheGroupPostDSResp{}, nil, errors.New("verifying 
delivery service CDNs match cachegroup server CDNs: " + err.Error()), 
http.StatusInternalServerError
        }
@@ -99,7 +105,7 @@ func postDSes(tx *sql.Tx, user *auth.CurrentUser, cgID 
int64, dsIDs []int64) (tc
        if err := updateParams(tx, dsIDs); err != nil {
                return tc.CacheGroupPostDSResp{}, nil, errors.New("updating 
delivery service parameters: " + err.Error()), http.StatusInternalServerError
        }
-       api.CreateChangeLogRawTx(api.ApiChange, fmt.Sprintf("assign servers in 
cache group %v to deliveryservices %v", cgID, dsIDs), user, tx)
+       api.CreateChangeLogRawTx(api.ApiChange, "CACHEGROUP: 
"+string(cgName)+", ID: "+strconv.FormatInt(cgID, 10)+", ACTION: Assign DSes to 
CacheGroup servers", user, tx)
        return tc.CacheGroupPostDSResp{ID: util.JSONIntStr(cgID), ServerNames: 
cgServers, DeliveryServices: dsIDs}, nil, nil, http.StatusOK
 }
 
diff --git a/traffic_ops/traffic_ops_golang/cachegroup/queueupdate.go 
b/traffic_ops/traffic_ops_golang/cachegroup/queueupdate.go
index 6a4a478..455d669 100644
--- a/traffic_ops/traffic_ops_golang/cachegroup/queueupdate.go
+++ b/traffic_ops/traffic_ops_golang/cachegroup/queueupdate.go
@@ -25,6 +25,7 @@ import (
        "errors"
        "net/http"
        "strconv"
+       "strings"
 
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
@@ -69,9 +70,8 @@ func QueueUpdates(w http.ResponseWriter, r *http.Request) {
        if err != nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting cachegroup name from ID '"+inf.Params["id"]+"': 
"+err.Error()))
                return
-       }
-       if !ok {
-               api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, 
errors.New("cachegroup "+inf.Params["id"]+" does not exist"), nil)
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, nil, nil)
                return
        }
        queue := reqObj.Action == "queue"
@@ -88,7 +88,7 @@ func QueueUpdates(w http.ResponseWriter, r *http.Request) {
                CDN:            *reqObj.CDN,
                CacheGroupID:   cgID,
        })
-       api.CreateChangeLogRawTx(api.ApiChange, "Server updates 
"+reqObj.Action+"d for "+string(cgName), inf.User, inf.Tx.Tx)
+       api.CreateChangeLogRawTx(api.ApiChange, "CACHEGROUP: 
"+string(cgName)+", ID: "+strconv.FormatInt(cgID, 10)+", ACTION: 
"+strings.Title(reqObj.Action)+"d CacheGroup server updates to the 
"+string(*reqObj.CDN)+" CDN", inf.User, inf.Tx.Tx)
 }
 
 type QueueUpdatesResp struct {
diff --git a/traffic_ops/traffic_ops_golang/cdn/dnssec.go 
b/traffic_ops/traffic_ops_golang/cdn/dnssec.go
index 2f405f8..df7de24 100644
--- a/traffic_ops/traffic_ops_golang/cdn/dnssec.go
+++ b/traffic_ops/traffic_ops_golang/cdn/dnssec.go
@@ -23,6 +23,7 @@ import (
        "database/sql"
        "errors"
        "net/http"
+       "strconv"
        "strings"
        "time"
 
@@ -57,6 +58,14 @@ func CreateDNSSECKeys(w http.ResponseWriter, r 
*http.Request) {
        }
        cdnName := *req.Key
 
+       cdnID, ok, err := getCDNIDFromName(inf.Tx.Tx, tc.CDNName(cdnName))
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting cdn ID from name '"+cdnName+"': "+err.Error()))
+               return
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, nil, nil)
+       }
+
        cdnDomain, cdnExists, err := dbhelpers.GetCDNDomainFromName(inf.Tx.Tx, 
tc.CDNName(cdnName))
        if err != nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("create DNSSEC keys: getting CDN domain: "+err.Error()))
@@ -70,6 +79,7 @@ func CreateDNSSECKeys(w http.ResponseWriter, r *http.Request) 
{
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("generating and storing DNSSEC CDN keys: "+err.Error()))
                return
        }
+       api.CreateChangeLogRawTx(api.ApiChange, "CDN: "+string(cdnName)+", ID: 
"+strconv.Itoa(cdnID)+", ACTION: Generated DNSSEC keys", inf.User, inf.Tx.Tx)
        api.WriteResp(w, r, "Successfully created dnssec keys for "+cdnName)
 }
 
@@ -302,11 +312,31 @@ func DeleteDNSSECKeys(w http.ResponseWriter, r 
*http.Request) {
        }
 
        key := inf.Params["name"]
+       cdnID, ok, err := getCDNIDFromName(inf.Tx.Tx, tc.CDNName(key))
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting cdn id: "+err.Error()))
+               return
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, nil, nil)
+               return
+       }
 
        if err := riaksvc.DeleteObject(key, CDNDNSSECKeyType, cluster); err != 
nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("deleting cdn dnssec keys: "+err.Error()))
                return
        }
-       api.CreateChangeLogRawTx(api.ApiChange, "Deleted DNSSEC keys for CDN 
"+key, inf.User, inf.Tx.Tx)
+       api.CreateChangeLogRawTx(api.ApiChange, "CDN: "+key+", ID: 
"+strconv.Itoa(cdnID)+", ACTION: Deleted DNSSEC keys", inf.User, inf.Tx.Tx)
        api.WriteResp(w, r, "Successfully deleted "+CDNDNSSECKeyType+" for 
"+key)
 }
+
+// getCDNIDFromName returns the CDN's ID if a CDN with the given name exists
+func getCDNIDFromName(tx *sql.Tx, name tc.CDNName) (int, bool, error) {
+       id := 0
+       if err := tx.QueryRow(`SELECT id FROM cdn WHERE name = $1`, 
name).Scan(&id); err != nil {
+               if err == sql.ErrNoRows {
+                       return id, false, nil
+               }
+               return id, false, errors.New("querying CDN ID: " + err.Error())
+       }
+       return id, true, nil
+}
diff --git a/traffic_ops/traffic_ops_golang/cdn/genksk.go 
b/traffic_ops/traffic_ops_golang/cdn/genksk.go
index 5a8400f..73b4553 100644
--- a/traffic_ops/traffic_ops_golang/cdn/genksk.go
+++ b/traffic_ops/traffic_ops_golang/cdn/genksk.go
@@ -64,6 +64,14 @@ func GenerateKSK(w http.ResponseWriter, r *http.Request) {
                return
        }
 
+       cdnID, ok, err := getCDNIDFromName(inf.Tx.Tx, cdnName)
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting cdn ID from name '"+string(cdnName)+"': "+err.Error()))
+               return
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, nil, nil)
+       }
+
        ttl, multiplier, err := getKSKParams(inf.Tx.Tx, cdnName)
        if err != nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting CDN KSK parameters: "+err.Error()))
@@ -100,6 +108,7 @@ func GenerateKSK(w http.ResponseWriter, r *http.Request) {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("putting CDN DNSSEC keys: "+err.Error()))
                return
        }
+       api.CreateChangeLogRawTx(api.ApiChange, "CDN: "+string(cdnName)+", ID: 
"+strconv.Itoa(cdnID)+", ACTION: Generated KSK DNSSEC keys", inf.User, 
inf.Tx.Tx)
        api.WriteResp(w, r, "Successfully generated ksk dnssec keys for 
"+string(cdnName))
 }
 
diff --git a/traffic_ops/traffic_ops_golang/cdn/namedelete.go 
b/traffic_ops/traffic_ops_golang/cdn/namedelete.go
index 1c4c852..c942335 100644
--- a/traffic_ops/traffic_ops_golang/cdn/namedelete.go
+++ b/traffic_ops/traffic_ops_golang/cdn/namedelete.go
@@ -23,6 +23,7 @@ import (
        "database/sql"
        "errors"
        "net/http"
+       "strconv"
 
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
@@ -37,7 +38,8 @@ func DeleteName(w http.ResponseWriter, r *http.Request) {
        defer inf.Close()
 
        cdnName := tc.CDNName(inf.Params["name"])
-       if ok, err := cdnExists(inf.Tx.Tx, cdnName); err != nil {
+       cdnID, ok, err := getCDNIDFromName(inf.Tx.Tx, cdnName)
+       if err != nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("checking CDN existence: "+err.Error()))
                return
        } else if !ok {
@@ -51,11 +53,12 @@ func DeleteName(w http.ResponseWriter, r *http.Request) {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, 
errors.New("Failed to delete cdn name = "+string(cdnName)+" has delivery 
services or servers"), nil)
                return
        }
-       if err := deleteCDNByName(inf.Tx.Tx, tc.CDNName(cdnName)); err != nil {
+       if err := deleteCDNByName(inf.Tx.Tx, cdnName); err != nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("deleting CDN: "+err.Error()))
                return
        }
        api.WriteRespAlert(w, r, tc.SuccessLevel, "cdn was deleted.")
+       api.CreateChangeLogRawTx(api.ApiChange, "CDN: "+string(cdnName)+", ID: 
"+strconv.Itoa(cdnID)+", ACTION: Deleted CDN", inf.User, inf.Tx.Tx)
 }
 
 func deleteCDNByName(tx *sql.Tx, name tc.CDNName) error {
@@ -65,17 +68,6 @@ func deleteCDNByName(tx *sql.Tx, name tc.CDNName) error {
        return nil
 }
 
-func cdnExists(tx *sql.Tx, name tc.CDNName) (bool, error) {
-       id := 0
-       if err := tx.QueryRow(`SELECT id FROM cdn WHERE name = $1`, 
name).Scan(&id); err != nil {
-               if err == sql.ErrNoRows {
-                       return false, nil
-               }
-               return false, errors.New("querying cdn existence: " + 
err.Error())
-       }
-       return true, nil
-}
-
 func cdnUnused(tx *sql.Tx, name tc.CDNName) (bool, error) {
        useCount := 0
        if err := tx.QueryRow(`
diff --git a/traffic_ops/traffic_ops_golang/cdn/queue.go 
b/traffic_ops/traffic_ops_golang/cdn/queue.go
index 690ee24..b9bce05 100644
--- a/traffic_ops/traffic_ops_golang/cdn/queue.go
+++ b/traffic_ops/traffic_ops_golang/cdn/queue.go
@@ -24,8 +24,10 @@ import (
        "encoding/json"
        "errors"
        "net/http"
+       "strconv"
 
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+       
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
 )
 
 type QueueReq struct {
@@ -57,7 +59,16 @@ func Queue(w http.ResponseWriter, r *http.Request) {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("CDN queueing updates: "+err.Error()))
                return
        }
-       api.CreateChangeLogRawTx(api.ApiChange, "Server updates 
"+reqObj.Action+"d for cdn "+inf.Params["id"], inf.User, inf.Tx.Tx)
+
+       cdnName, ok, err := dbhelpers.GetCDNNameFromID(inf.Tx.Tx, 
int64(inf.IntParams["id"]))
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting cdn name from ID '"+inf.Params["id"]+"': 
"+err.Error()))
+               return
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, nil, nil)
+               return
+       }
+       api.CreateChangeLogRawTx(api.ApiChange, "CDN: "+string(cdnName)+", ID: 
"+strconv.Itoa(inf.IntParams["id"])+", ACTION: Queue CDN updates", inf.User, 
inf.Tx.Tx)
        api.WriteResp(w, r, QueueResp{Action: reqObj.Action, CDNID: 
int64(inf.IntParams["id"])})
 }
 
diff --git a/traffic_ops/traffic_ops_golang/crconfig/handler.go 
b/traffic_ops/traffic_ops_golang/crconfig/handler.go
index 6797128..f31439a 100644
--- a/traffic_ops/traffic_ops_golang/crconfig/handler.go
+++ b/traffic_ops/traffic_ops_golang/crconfig/handler.go
@@ -24,6 +24,7 @@ import (
        "errors"
        "net/http"
        "net/url"
+       "strconv"
        "time"
 
        "github.com/apache/trafficcontrol/lib/go-log"
@@ -175,7 +176,7 @@ func SnapshotHandler(w http.ResponseWriter, r 
*http.Request) {
                return
        }
 
-       api.CreateChangeLogRawTx(api.ApiChange, "Snapshot of CRConfig and 
Monitor performed for "+cdn, inf.User, inf.Tx.Tx)
+       api.CreateChangeLogRawTx(api.ApiChange, "CDN: "+cdn+", ID: 
"+strconv.Itoa(inf.IntParams["id"])+", ACTION: Snapshot of CRConfig and 
Monitor", inf.User, inf.Tx.Tx)
        api.WriteResp(w, r, "SUCCESS")
 }
 
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go 
b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
index 2a5af5b..2fac680 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
@@ -299,7 +299,7 @@ func createV14(w http.ResponseWriter, r *http.Request, inf 
*api.APIInfo, reqDS t
                usrErr, sysErr, code := api.ParseDBError(err)
                return nil, code, usrErr, sysErr
        } else {
-               api.CreateChangeLogRawTx(api.ApiChange, fmt.Sprintf("Created %d 
consistent hash query params for delivery service: %s", c, *ds.XMLID), user, tx)
+               api.CreateChangeLogRawTx(api.ApiChange, "DS: "+*ds.XMLID+", ID: 
"+strconv.Itoa(*ds.ID)+", ACTION: Created "+strconv.Itoa(c)+" consistent hash 
query params", user, tx)
        }
 
        matchlists, err := GetDeliveryServicesMatchLists([]string{*ds.XMLID}, 
tx)
@@ -334,7 +334,7 @@ func createV14(w http.ResponseWriter, r *http.Request, inf 
*api.APIInfo, reqDS t
        }
 
        ds.LastUpdated = &lastUpdated
-       if err := api.CreateChangeLogRawErr(api.ApiChange, "Created ds: 
"+*ds.XMLID+" id: "+strconv.Itoa(*ds.ID), user, tx); err != nil {
+       if err := api.CreateChangeLogRawErr(api.ApiChange, "DS: "+*ds.XMLID+", 
ID: "+strconv.Itoa(*ds.ID)+", ACTION: Created delivery service", user, tx); err 
!= nil {
                return nil, http.StatusInternalServerError, nil, 
errors.New("error writing to audit log: " + err.Error())
        }
 
@@ -734,14 +734,14 @@ func updateV14(w http.ResponseWriter, r *http.Request, 
inf *api.APIInfo, reqDS *
        if res, err := tx.Exec(q, *ds.ID); err != nil {
                return nil, http.StatusInternalServerError, nil, 
fmt.Errorf("deleting consistent hash query params for ds %s: %s", *ds.XMLID, 
err.Error())
        } else if c, _ := res.RowsAffected(); c > 0 {
-               api.CreateChangeLogRawTx(api.ApiChange, fmt.Sprintf("Deleted %d 
consistent hash query params for delivery service: %s", c, *ds.XMLID), user, tx)
+               api.CreateChangeLogRawTx(api.ApiChange, "DS: "+*ds.XMLID+", ID: 
"+strconv.Itoa(*ds.ID)+", ACTION: Deleted "+strconv.FormatInt(c, 10)+" 
consistent hash query params", user, tx)
        }
 
        if c, err := createConsistentHashQueryParams(tx, *ds.ID, 
ds.ConsistentHashQueryParams); err != nil {
                usrErr, sysErr, code := api.ParseDBError(err)
                return nil, code, usrErr, sysErr
        } else {
-               api.CreateChangeLogRawTx(api.ApiChange, fmt.Sprintf("Created %d 
consistent hash query params for delivery service: %s", c, *ds.XMLID), user, tx)
+               api.CreateChangeLogRawTx(api.ApiChange, "DS: "+*ds.XMLID+", ID: 
"+strconv.Itoa(*ds.ID)+", ACTION: Created "+strconv.Itoa(c)+" consistent hash 
query params", user, tx)
        }
 
        if err := api.CreateChangeLogRawErr(api.ApiChange, "Updated ds: 
"+*ds.XMLID+" id: "+strconv.Itoa(*ds.ID), user, tx); err != nil {
@@ -899,7 +899,7 @@ func updatePrimaryOrigin(tx *sql.Tx, user 
*auth.CurrentUser, ds tc.DeliveryServi
                        if _, err := tx.Exec(q, *ds.ID); err != nil {
                                return fmt.Errorf("deleting primary origin for 
ds %s: %s", *ds.XMLID, err.Error())
                        }
-                       api.CreateChangeLogRawTx(api.ApiChange, "Deleted 
primary origin for delivery service: "+*ds.XMLID, user, tx)
+                       api.CreateChangeLogRawTx(api.ApiChange, "DS: 
"+*ds.XMLID+", ID: "+strconv.Itoa(*ds.ID)+", ACTION: Deleted primary origin", 
user, tx)
                }
                return nil
        }
@@ -920,7 +920,7 @@ func updatePrimaryOrigin(tx *sql.Tx, user 
*auth.CurrentUser, ds tc.DeliveryServi
                return fmt.Errorf("update primary origin for ds %s from '%s': 
%s", *ds.XMLID, *ds.OrgServerFQDN, err.Error())
        }
 
-       api.CreateChangeLogRawTx(api.ApiChange, "Updated primary origin: 
"+name+" for delivery service: "+*ds.XMLID, user, tx)
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+*ds.XMLID+", ID: 
"+strconv.Itoa(*ds.ID)+", ACTION: Updated primary origin: "+name, user, tx)
 
        return nil
 }
@@ -941,7 +941,7 @@ func createPrimaryOrigin(tx *sql.Tx, user 
*auth.CurrentUser, ds tc.DeliveryServi
                return fmt.Errorf("insert origin from '%s': %s", 
*ds.OrgServerFQDN, err.Error())
        }
 
-       api.CreateChangeLogRawTx(api.ApiChange, "Created primary origin id: 
"+strconv.Itoa(originID)+" for delivery service: "+*ds.XMLID, user, tx)
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+*ds.XMLID+", ID: 
"+strconv.Itoa(*ds.ID)+", ACTION: Created primary origin id: 
"+strconv.Itoa(originID), user, tx)
 
        return nil
 }
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go 
b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go
index 2923b41..0e36322 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go
@@ -30,6 +30,7 @@ import (
        "errors"
        "fmt"
        "net/http"
+       "strconv"
        "strings"
 
        "github.com/apache/trafficcontrol/lib/go-tc"
@@ -65,6 +66,15 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) {
                return
        }
 
+       dsID, ok, err := getDSIDFromName(inf.Tx.Tx, *req.DeliveryService)
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("deliveryservice.AddSSLKeys: getting DS ID from name 
"+err.Error()))
+               return
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, 
errors.New("no DS with name "+*req.DeliveryService), nil)
+               return
+       }
+
        // ECDSA keys support is only permitted for DNS delivery services
        // Traffic Router (HTTP* delivery service types) do not support ECDSA 
keys
        dsType, dsFound, err := getDSType(inf.Tx.Tx, *req.Key)
@@ -106,6 +116,7 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) {
                api.WriteRespAlert(w, r, tc.WarnLevel, "WARNING: SSL keys were 
successfully added for '"+*req.DeliveryService+"', but the input certificate 
may be invalid (certificate verification produced a different chain)")
                return
        }
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+*req.DeliveryService+", 
ID: "+strconv.Itoa(dsID)+", ACTION: Added SSL keys", inf.User, inf.Tx.Tx)
        api.WriteResp(w, r, "Successfully added ssl keys for 
"+*req.DeliveryService)
 }
 
@@ -239,6 +250,14 @@ func DeleteSSLKeys(w http.ResponseWriter, r *http.Request) 
{
                return
        }
        xmlID := inf.Params["xmlid"]
+       dsID, ok, err := getDSIDFromName(inf.Tx.Tx, xmlID)
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("deliveryservice.DeleteSSLKeys: getting DS ID from name 
"+err.Error()))
+               return
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, 
errors.New("no DS with name "+xmlID), nil)
+               return
+       }
        if userErr, sysErr, errCode := tenant.Check(inf.User, xmlID, 
inf.Tx.Tx); userErr != nil || sysErr != nil {
                api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
                return
@@ -247,6 +266,7 @@ func DeleteSSLKeys(w http.ResponseWriter, r *http.Request) {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
userErr, errors.New("deliveryservice.DeleteSSLKeys: deleting SSL keys: 
"+err.Error()))
                return
        }
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+xmlID+", ID: 
"+strconv.Itoa(dsID)+", ACTION: Deleted SSL keys", inf.User, inf.Tx.Tx)
        api.WriteResp(w, r, "Successfully deleted ssl keys for "+xmlID)
 }
 
@@ -270,6 +290,18 @@ func getCDNIDByDomainname(domainName string, tx *sql.Tx) 
(int64, bool, error) {
        return cdnID, true, nil
 }
 
+// getDSIDFromName loads the DeliveryService's ID from the database, from the 
xml_id. Returns whether the delivery service was found, and any error.
+func getDSIDFromName(tx *sql.Tx, xmlID string) (int, bool, error) {
+       id := 0
+       if err := tx.QueryRow(`SELECT id FROM deliveryservice WHERE xml_id = 
$1`, xmlID).Scan(&id); err != nil {
+               if err == sql.ErrNoRows {
+                       return id, false, nil
+               }
+               return id, false, fmt.Errorf("querying ID for delivery service 
ID '%v': %v", xmlID, err)
+       }
+       return id, true, nil
+}
+
 // returns a delivery service xmlId for a cdn by host regex.
 func getXMLID(cdnID int64, hostRegex string, tx *sql.Tx) (string, bool, error) 
{
        q := `
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/delete.go 
b/traffic_ops/traffic_ops_golang/deliveryservice/servers/delete.go
index e80630e..6581eaa 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/delete.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/delete.go
@@ -23,9 +23,11 @@ import (
        "database/sql"
        "errors"
        "net/http"
+       "strconv"
 
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+       
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
 )
 
@@ -46,6 +48,21 @@ func Delete(w http.ResponseWriter, r *http.Request) {
                return
        }
 
+       dsName, _, err := dbhelpers.GetDSNameFromID(inf.Tx.Tx, dsID)
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting delivery service name from id: "+err.Error()))
+               return
+       }
+
+       serverName, exists, err := dbhelpers.GetServerNameFromID(inf.Tx.Tx, 
int64(serverID))
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting server name from id: "+err.Error()))
+               return
+       } else if !exists {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, 
errors.New("server not found"), nil)
+               return
+       }
+
        ok, err := deleteDSServer(inf.Tx.Tx, dsID, serverID)
        if err != nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("deleting delivery service server: "+err.Error()))
@@ -55,6 +72,7 @@ func Delete(w http.ResponseWriter, r *http.Request) {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, nil, nil)
                return
        }
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+string(dsName)+", ID: 
"+strconv.Itoa(dsID)+", ACTION: Remove server "+string(serverName)+" from 
delivery service", inf.User, inf.Tx.Tx)
        api.WriteRespAlert(w, r, tc.SuccessLevel, "Server unlinked from 
delivery service.")
 }
 
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go 
b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
index 60a853c..2a5136f 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
@@ -26,6 +26,7 @@ import (
        "fmt"
        "net/http"
        "strconv"
+       "strings"
 
        "github.com/apache/trafficcontrol/lib/go-log"
        "github.com/apache/trafficcontrol/lib/go-tc"
@@ -37,7 +38,7 @@ import (
        
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
 
-       "github.com/go-ozzo/ozzo-validation"
+       validation "github.com/go-ozzo/ozzo-validation"
        "github.com/jmoiron/sqlx"
        "github.com/lib/pq"
 )
@@ -291,7 +292,7 @@ func GetReplaceHandler(w http.ResponseWriter, r 
*http.Request) {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("deliveryservice_server replace ensuring ds parameters: 
"+err.Error()))
                return
        }
-
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+ds.Name+", ID: 
"+strconv.Itoa(*dsId)+", ACTION: Replace existing servers assigned to delivery 
service", inf.User, inf.Tx.Tx)
        api.WriteRespAlertObj(w, r, tc.SuccessLevel, "server assignements 
complete", tc.DSSMapResponse{*dsId, *payload.Replace, respServers})
 }
 
@@ -357,7 +358,7 @@ func GetCreateHandler(w http.ResponseWriter, r 
*http.Request) {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("deliveryservice_server replace ensuring ds parameters: 
"+err.Error()))
                return
        }
-
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+dsName+", ID: 
"+strconv.Itoa(ds.ID)+", ACTION: Assigned servers "+strings.Join(serverNames, 
", ")+" to delivery service", inf.User, inf.Tx.Tx)
        api.WriteResp(w, r, tc.DeliveryServiceServers{payload.ServerNames, 
payload.XmlId})
 }
 
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/sslkeys.go 
b/traffic_ops/traffic_ops_golang/deliveryservice/sslkeys.go
index 680575f..479a51b 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/sslkeys.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/sslkeys.go
@@ -23,6 +23,7 @@ import (
        "database/sql"
        "errors"
        "net/http"
+       "strconv"
 
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
@@ -48,6 +49,14 @@ func GenerateSSLKeys(w http.ResponseWriter, r *http.Request) 
{
                api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
                return
        }
+       dsID, ok, err := getDSIDFromName(inf.Tx.Tx, *req.DeliveryService)
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("deliveryservice.GenerateSSLKeys: getting DS ID from name 
"+err.Error()))
+               return
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, 
errors.New("no DS with name "+*req.DeliveryService), nil)
+               return
+       }
        if err := generatePutRiakKeys(req, inf.Tx.Tx, inf.Config); err != nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("generating and putting SSL keys: "+err.Error()))
                return
@@ -56,6 +65,7 @@ func GenerateSSLKeys(w http.ResponseWriter, r *http.Request) {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("generating SSL keys for delivery service 
'"+*req.DeliveryService+"': "+err.Error()))
                return
        }
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+*req.DeliveryService+", 
ID: "+strconv.Itoa(dsID)+", ACTION: Added SSL keys", inf.User, inf.Tx.Tx)
        api.WriteResp(w, r, "Successfully created ssl keys for 
"+*req.DeliveryService)
 }
 
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/urlkey.go 
b/traffic_ops/traffic_ops_golang/deliveryservice/urlkey.go
index fcdd1c8..7a9e7f6 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/urlkey.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/urlkey.go
@@ -182,6 +182,15 @@ func CopyURLKeys(w http.ResponseWriter, r *http.Request) {
                }
        }
 
+       dsID, ok, err := getDSIDFromName(inf.Tx.Tx, string(copyDS))
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("deliveryservice.CopyURLKeys: getting DS ID from name 
"+err.Error()))
+               return
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, 
errors.New("no DS with name "+string(copyDS)), nil)
+               return
+       }
+
        keys, ok, err := riaksvc.GetURLSigKeys(inf.Tx.Tx, 
inf.Config.RiakAuthOptions, inf.Config.RiakPort, copyDS)
        if err != nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting URL Sig keys from riak: "+err.Error()))
@@ -196,6 +205,7 @@ func CopyURLKeys(w http.ResponseWriter, r *http.Request) {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("setting URL Sig keys for '"+string(ds)+" copied from 
"+string(copyDS)+": "+err.Error()))
                return
        }
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+string(ds)+", ID: 
"+strconv.Itoa(dsID)+", ACTION: Copied URL sig keys from "+string(copyDS), 
inf.User, inf.Tx.Tx)
        api.WriteRespAlert(w, r, tc.SuccessLevel, "Successfully copied and 
stored keys")
 }
 
@@ -231,6 +241,15 @@ func GenerateURLKeys(w http.ResponseWriter, r 
*http.Request) {
                return
        }
 
+       dsID, ok, err := getDSIDFromName(inf.Tx.Tx, string(ds))
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("deliveryservice.GenerateURLKeys: getting DS ID from name 
"+err.Error()))
+               return
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, 
errors.New("no DS with name "+string(ds)), nil)
+               return
+       }
+
        keys, err := GenerateURLSigKeys()
        if err != nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("generating URL sig keys: "+err.Error()))
@@ -240,6 +259,7 @@ func GenerateURLKeys(w http.ResponseWriter, r 
*http.Request) {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("setting URL Sig keys for '"+string(ds)+": "+err.Error()))
                return
        }
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+string(ds)+", ID: 
"+strconv.Itoa(dsID)+", ACTION: Generated URL sig keys", inf.User, inf.Tx.Tx)
        api.WriteRespAlert(w, r, tc.SuccessLevel, "Successfully generated and 
stored keys")
 }
 
diff --git 
a/traffic_ops/traffic_ops_golang/deliveryservicesregexes/deliveryservicesregexes.go
 
b/traffic_ops/traffic_ops_golang/deliveryservicesregexes/deliveryservicesregexes.go
index dba6c1d..3339a88 100644
--- 
a/traffic_ops/traffic_ops_golang/deliveryservicesregexes/deliveryservicesregexes.go
+++ 
b/traffic_ops/traffic_ops_golang/deliveryservicesregexes/deliveryservicesregexes.go
@@ -25,11 +25,13 @@ import (
        "errors"
        "fmt"
        "net/http"
+       "strconv"
 
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/lib/go-util"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth"
+       
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
 )
 
@@ -227,6 +229,13 @@ func Post(w http.ResponseWriter, r *http.Request) {
                return
        }
 
+       dsID := inf.IntParams["dsid"]
+       dsName, _, err := dbhelpers.GetDSNameFromID(inf.Tx.Tx, dsID)
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting delivery service name from id: "+err.Error()))
+               return
+       }
+
        respObj := tc.DeliveryServiceIDRegex{
                ID:        regexID,
                Pattern:   dsr.Pattern,
@@ -234,6 +243,7 @@ func Post(w http.ResponseWriter, r *http.Request) {
                TypeName:  typeName,
                SetNumber: dsr.SetNumber,
        }
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+string(dsName)+", ID: 
"+strconv.Itoa(dsID)+", ACTION: Created a regular expression ("+dsr.Pattern+") 
in position "+strconv.Itoa(dsr.SetNumber), inf.User, inf.Tx.Tx)
        api.WriteRespAlertObj(w, r, tc.SuccessLevel, "Delivery service regex 
creation was successful.", respObj)
 }
 
@@ -247,6 +257,14 @@ func Put(w http.ResponseWriter, r *http.Request) {
        tx := inf.Tx.Tx
 
        dsID := inf.IntParams["dsid"]
+       dsName, ok, err := dbhelpers.GetDSNameFromID(inf.Tx.Tx, dsID)
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting delivery service name from id: "+err.Error()))
+               return
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, nil, nil)
+               return
+       }
        regexID := inf.IntParams["regexid"]
        dsTenantID := 0
        if err := tx.QueryRow(`SELECT tenant_id from deliveryservice where id = 
$1`, dsID).Scan(&dsTenantID); err != nil {
@@ -291,6 +309,7 @@ func Put(w http.ResponseWriter, r *http.Request) {
                TypeName:  typeName,
                SetNumber: dsr.SetNumber,
        }
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+string(dsName)+", ID: 
"+strconv.Itoa(dsID)+", ACTION: Updated a regular expression ("+dsr.Pattern+") 
in position "+strconv.Itoa(dsr.SetNumber), inf.User, inf.Tx.Tx)
        api.WriteRespAlertObj(w, r, tc.SuccessLevel, "Delivery service regex 
creation was successful.", respObj)
 }
 
@@ -308,6 +327,14 @@ func Delete(w http.ResponseWriter, r *http.Request) {
        defer inf.Close()
 
        dsID := inf.IntParams["dsid"]
+       dsName, ok, err := dbhelpers.GetDSNameFromID(inf.Tx.Tx, dsID)
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting delivery service name from id: "+err.Error()))
+               return
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, nil, nil)
+               return
+       }
        regexID := inf.IntParams["regexid"]
 
        count := 0
@@ -337,6 +364,26 @@ func Delete(w http.ResponseWriter, r *http.Request) {
                return
        }
 
+       dsrSetNumber := 0
+       if err := inf.Tx.Tx.QueryRow(`SELECT set_number FROM 
deliveryservice_regex WHERE regex = $1`, regexID).Scan(&dsrSetNumber); err != 
nil {
+               if err == sql.ErrNoRows {
+                       api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, 
errors.New("regex not found for this delivery service"), nil)
+                       return
+               }
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("deliveryservicesregexes.Delete finding set number: 
"+err.Error()))
+               return
+       }
+
+       dsrType, dsrPattern := 0, ""
+       if err := inf.Tx.Tx.QueryRow(`SELECT type, pattern FROM regex WHERE id 
= $1`, regexID).Scan(&dsrType, &dsrPattern); err != nil {
+               if err == sql.ErrNoRows {
+                       api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, 
errors.New("regex not found"), nil)
+                       return
+               }
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("deliveryservicesregexes.Delete finding type and pattern: 
"+err.Error()))
+               return
+       }
+
        result, err := inf.Tx.Tx.Exec(`DELETE FROM deliveryservice_regex WHERE 
deliveryservice = $1 and regex = $2`, dsID, regexID)
        if err != nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("deliveryservicesregexes.Delete deleting delivery service 
regexes: "+err.Error()))
@@ -355,7 +402,7 @@ func Delete(w http.ResponseWriter, r *http.Request) {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, fmt.Errorf("this create affected too many rows: %d", rowsAffected))
                return
        }
-       api.CreateChangeLogRawTx(api.ApiChange, fmt.Sprintf(`deleted 
deliveryservice_regex {"ds": %d, "regex": %d}`, dsID, regexID), inf.User, 
inf.Tx.Tx)
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+string(dsName)+", ID: 
"+strconv.Itoa(dsID)+", ACTION: Deleted a regular expression ("+dsrPattern+") 
in position "+strconv.Itoa(dsrSetNumber), inf.User, inf.Tx.Tx)
        api.WriteRespAlert(w, r, tc.SuccessLevel, "deliveryservice_regex was 
deleted.")
 }
 
diff --git a/traffic_ops/traffic_ops_golang/federations/ds.go 
b/traffic_ops/traffic_ops_golang/federations/ds.go
index ba4742f..9baa00b 100644
--- a/traffic_ops/traffic_ops_golang/federations/ds.go
+++ b/traffic_ops/traffic_ops_golang/federations/ds.go
@@ -22,6 +22,7 @@ package federations
 import (
        "database/sql"
        "errors"
+       "fmt"
        "net/http"
        "strconv"
 
@@ -40,6 +41,12 @@ func PostDSes(w http.ResponseWriter, r *http.Request) {
        defer inf.Close()
 
        fedID := inf.IntParams["id"]
+       fedName, ok, err := getFedNameByID(inf.Tx.Tx, fedID)
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting federation cname from ID '"+string(fedID)+"': 
"+err.Error()))
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, 
errors.New("federation not found: "+err.Error()), nil)
+       }
 
        post := tc.FederationDSPost{}
        if err := api.Parse(r.Body, inf.Tx.Tx, &post); err != nil {
@@ -67,7 +74,7 @@ func PostDSes(w http.ResponseWriter, r *http.Request) {
                        return
                }
        }
-
+       api.CreateChangeLogRawTx(api.ApiChange, fmt.Sprintf("FEDERATION: %v, 
ID: %v, ACTION: Assign DSes to federation", fedName, fedID), inf.User, 
inf.Tx.Tx)
        api.WriteRespAlertObj(w, r, tc.SuccessLevel, 
strconv.Itoa(len(post.DSIDs))+" delivery service(s) were assigned to the 
federation "+strconv.Itoa(fedID), post)
 }
 
@@ -85,3 +92,15 @@ VALUES ($1, unnest($2::integer[]))
        _, err := tx.Exec(qry, fedID, pq.Array(dsIDs))
        return err
 }
+
+// getFedNameFromID returns the federations name and whether or not one with 
the given ID exists, or an error
+func getFedNameByID(tx *sql.Tx, id int) (string, bool, error) {
+       name := ""
+       if err := tx.QueryRow(`select cname from federation where id = $1`, 
id).Scan(&name); err != nil {
+               if err == sql.ErrNoRows {
+                       return "", false, nil
+               }
+               return "", false, errors.New("Error querying federation cname: 
" + err.Error())
+       }
+       return name, true, nil
+}
diff --git 
a/traffic_ops/traffic_ops_golang/profileparameter/postparameterprofile.go 
b/traffic_ops/traffic_ops_golang/profileparameter/postparameterprofile.go
index c6f3463..164a774 100644
--- a/traffic_ops/traffic_ops_golang/profileparameter/postparameterprofile.go
+++ b/traffic_ops/traffic_ops_golang/profileparameter/postparameterprofile.go
@@ -24,6 +24,7 @@ import (
        "errors"
        "fmt"
        "net/http"
+       "strconv"
 
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
@@ -48,9 +49,28 @@ func PostParamProfile(w http.ResponseWriter, r 
*http.Request) {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("posting parameter profile: "+err.Error()))
                return
        }
+       paramName, ok, err := getParamNameFromID(*paramProfile.ParamID, 
inf.Tx.Tx)
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting parameter name from id: "+err.Error()))
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, 
errors.New("parameter not found"), nil)
+       }
+       api.CreateChangeLogRawTx(api.ApiChange, "PARAM: "+paramName+", ID: 
"+strconv.FormatInt(*paramProfile.ParamID, 10)+", ACTION: Assigned 
"+strconv.Itoa(len(*paramProfile.ProfileIDs))+" profiles to parameter", 
inf.User, inf.Tx.Tx)
        api.WriteRespAlertObj(w, r, tc.SuccessLevel, fmt.Sprintf("%d profiles 
were assigned to the %d parameter", len(*paramProfile.ProfileIDs), 
*paramProfile.ParamID), paramProfile)
 }
 
+// getParamNameFromID returns the parameter's name, whether a parameter with 
ID exists, or any error.
+func getParamNameFromID(id int64, tx *sql.Tx) (string, bool, error) {
+       name := ""
+       if err := tx.QueryRow(`SELECT name from parameter where id = $1`, 
id).Scan(&name); err != nil {
+               if err == sql.ErrNoRows {
+                       return "", false, nil
+               }
+               return "", false, errors.New("querying param name from id: " + 
err.Error())
+       }
+       return name, true, nil
+}
+
 func insertParameterProfile(post tc.PostParamProfile, tx *sql.Tx) error {
        if *post.Replace {
                if _, err := tx.Exec(`DELETE FROM profile_parameter WHERE 
parameter = $1`, post.ParamID); err != nil {
diff --git 
a/traffic_ops/traffic_ops_golang/profileparameter/postprofileparameter.go 
b/traffic_ops/traffic_ops_golang/profileparameter/postprofileparameter.go
index 0eaeabf..10dc18b 100644
--- a/traffic_ops/traffic_ops_golang/profileparameter/postprofileparameter.go
+++ b/traffic_ops/traffic_ops_golang/profileparameter/postprofileparameter.go
@@ -24,9 +24,11 @@ import (
        "errors"
        "fmt"
        "net/http"
+       "strconv"
 
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+       
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
 
        "github.com/lib/pq"
 )
@@ -48,6 +50,13 @@ func PostProfileParam(w http.ResponseWriter, r 
*http.Request) {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("posting profile parameter: "+err.Error()))
                return
        }
+       profileName, ok, err := 
dbhelpers.GetProfileNameFromID(int(*profileParam.ProfileID), inf.Tx.Tx)
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting profile name from id: "+err.Error()))
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, 
errors.New("profile not found"), nil)
+       }
+       api.CreateChangeLogRawTx(api.ApiChange, "PROFILE: "+profileName+", ID: 
"+strconv.FormatInt(*profileParam.ProfileID, 10)+", ACTION: Assigned 
"+strconv.Itoa(len(*profileParam.ParamIDs))+" parameters to profile", inf.User, 
inf.Tx.Tx)
        api.WriteRespAlertObj(w, r, tc.SuccessLevel, fmt.Sprintf("%d parameters 
were assigned to the %d profile", len(*profileParam.ParamIDs), 
*profileParam.ProfileID), profileParam)
 }
 
diff --git 
a/traffic_ops/traffic_ops_golang/profileparameter/postprofileparametersbyid.go 
b/traffic_ops/traffic_ops_golang/profileparameter/postprofileparametersbyid.go
index 6fb2cb3..a7dc661 100644
--- 
a/traffic_ops/traffic_ops_golang/profileparameter/postprofileparametersbyid.go
+++ 
b/traffic_ops/traffic_ops_golang/profileparameter/postprofileparametersbyid.go
@@ -23,10 +23,11 @@ import (
        "errors"
        "fmt"
        "net/http"
+       "strconv"
 
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
-       dbhelp 
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
+       
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
 )
 
 func PostProfileParamsByID(w http.ResponseWriter, r *http.Request) {
@@ -44,13 +45,12 @@ func PostProfileParamsByID(w http.ResponseWriter, r 
*http.Request) {
        }
 
        profileID := inf.IntParams["id"]
-       profileName, profileExists, err := 
dbhelp.GetProfileNameFromID(profileID, inf.Tx.Tx)
+       profileName, ok, err := dbhelpers.GetProfileNameFromID(profileID, 
inf.Tx.Tx)
        if err != nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, fmt.Errorf("getting profile ID %d: "+err.Error(), profileID))
                return
-       }
-       if !profileExists {
-               api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, 
fmt.Errorf("no profile with ID %d exists", profileID), nil)
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, 
fmt.Errorf("no profile with ID %d exists", profileID), nil)
                return
        }
 
@@ -61,5 +61,6 @@ func PostProfileParamsByID(w http.ResponseWriter, r 
*http.Request) {
        }
 
        resp := tc.ProfileParameterPostResp{Parameters: insertedObjs, 
ProfileName: profileName, ProfileID: profileID}
+       api.CreateChangeLogRawTx(api.ApiChange, "PROFILE: "+profileName+", ID: 
"+strconv.Itoa(profileID)+", ACTION: Assigned parameters to profile", inf.User, 
inf.Tx.Tx)
        api.WriteRespAlertObj(w, r, tc.SuccessLevel, "Assign parameters 
successfully to profile "+profileName, resp)
 }
diff --git 
a/traffic_ops/traffic_ops_golang/profileparameter/postprofileparametersbyname.go
 
b/traffic_ops/traffic_ops_golang/profileparameter/postprofileparametersbyname.go
index 840c477..331da56 100644
--- 
a/traffic_ops/traffic_ops_golang/profileparameter/postprofileparametersbyname.go
+++ 
b/traffic_ops/traffic_ops_golang/profileparameter/postprofileparametersbyname.go
@@ -23,10 +23,11 @@ import (
        "database/sql"
        "errors"
        "net/http"
+       "strconv"
 
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
-       dbhelp 
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
+       
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
 
        "github.com/lib/pq"
 )
@@ -44,13 +45,12 @@ func PostProfileParamsByName(w http.ResponseWriter, r 
*http.Request) {
                return
        }
        profileName := inf.Params["name"]
-       profileID, profileExists, err := 
dbhelp.GetProfileIDFromName(profileName, inf.Tx.Tx)
+       profileID, ok, err := dbhelpers.GetProfileIDFromName(profileName, 
inf.Tx.Tx)
        if err != nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting profile '"+profileName+"' ID: "+err.Error()))
                return
-       }
-       if !profileExists {
-               api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, 
errors.New("no profile with that name exists"), nil)
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, 
errors.New("no profile with that name exists"), nil)
                return
        }
        insertedObjs, err := insertParametersForProfile(profileName, 
profParams, inf.Tx.Tx)
@@ -59,6 +59,7 @@ func PostProfileParamsByName(w http.ResponseWriter, r 
*http.Request) {
                return
        }
        resp := tc.ProfileParameterPostResp{Parameters: insertedObjs, 
ProfileName: profileName, ProfileID: profileID}
+       api.CreateChangeLogRawTx(api.ApiChange, "PROFILE: "+profileName+", ID: 
"+strconv.Itoa(profileID)+", ACTION: Assigned parameters to profile", inf.User, 
inf.Tx.Tx)
        api.WriteRespAlertObj(w, r, tc.SuccessLevel, "Assign parameters 
successfully to profile "+profileName, resp)
 }
 
diff --git a/traffic_ops/traffic_ops_golang/server/servers_assignment.go 
b/traffic_ops/traffic_ops_golang/server/servers_assignment.go
index 5be31f4..9bbe8f8 100644
--- a/traffic_ops/traffic_ops_golang/server/servers_assignment.go
+++ b/traffic_ops/traffic_ops_golang/server/servers_assignment.go
@@ -31,6 +31,7 @@ import (
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/ats"
+       
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
        "github.com/lib/pq"
 )
 
@@ -61,18 +62,21 @@ func AssignDeliveryServicesToServerHandler(w 
http.ResponseWriter, r *http.Reques
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, err, nil)
                return
        }
-
-       assignedDSes, err := assignDeliveryServicesToServer(server, dsList, 
replace, inf.Tx.Tx)
+       serverName, ok, err := dbhelpers.GetServerNameFromID(inf.Tx.Tx, 
int64(server))
        if err != nil {
-               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, err)
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("getting server name from ID: "+err.Error()))
                return
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, 
errors.New("no server with that ID found"), nil)
        }
 
-       if err := api.CreateChangeLogRawErr(api.ApiChange, "Assigned 
"+strconv.Itoa(len(assignedDSes))+" delivery services to server id: 
"+strconv.Itoa(server) , inf.User, inf.Tx.Tx); err != nil {
-               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("error writing to change log: " + err.Error()))
+       assignedDSes, err := assignDeliveryServicesToServer(server, dsList, 
replace, inf.Tx.Tx)
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, err)
                return
        }
 
+       api.CreateChangeLogRawTx(api.ApiChange, "SERVER: "+serverName+", ID: 
"+strconv.Itoa(server)+", ACTION: Assigned "+strconv.Itoa(len(assignedDSes))+" 
DSes to server", inf.User, inf.Tx.Tx)
        api.WriteRespAlertObj(w, r, tc.SuccessLevel, "successfully assigned 
dses to server", tc.AssignedDsResponse{server, assignedDSes, replace})
 }
 
diff --git a/traffic_ops/traffic_ops_golang/urisigning/urisigning.go 
b/traffic_ops/traffic_ops_golang/urisigning/urisigning.go
index cbe8781..5a83ad9 100644
--- a/traffic_ops/traffic_ops_golang/urisigning/urisigning.go
+++ b/traffic_ops/traffic_ops_golang/urisigning/urisigning.go
@@ -20,10 +20,13 @@ package urisigning
  */
 
 import (
+       "database/sql"
        "encoding/json"
        "errors"
+       "fmt"
        "io/ioutil"
        "net/http"
+       "strconv"
        "strings"
 
        "github.com/apache/trafficcontrol/lib/go-tc"
@@ -103,6 +106,12 @@ func RemoveDeliveryServiceURIKeysHandler(w 
http.ResponseWriter, r *http.Request)
                api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
                return
        }
+       dsID, ok, err := getDSIDFromName(inf.Tx.Tx, xmlID)
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
errors.New("error finding delivery service with xmlID: "+xmlID), 
errors.New("getting DS id from name failed: "+err.Error()))
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, nil, nil)
+       }
 
        cluster, err := riaksvc.GetPooledCluster(inf.Tx.Tx, 
inf.Config.RiakAuthOptions, inf.Config.RiakPort)
        if err != nil {
@@ -124,6 +133,7 @@ func RemoveDeliveryServiceURIKeysHandler(w 
http.ResponseWriter, r *http.Request)
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("deleting riak object: "+err.Error()))
                return
        }
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+xmlID+", ID: 
"+strconv.Itoa(dsID)+", ACTION: Removed URI signing keys", inf.User, inf.Tx.Tx)
        api.WriteRespAlert(w, r, tc.SuccessLevel, "object deleted")
        return
 }
@@ -143,11 +153,16 @@ func SaveDeliveryServiceURIKeysHandler(w 
http.ResponseWriter, r *http.Request) {
        }
 
        xmlID := inf.Params["xmlID"]
-
        if userErr, sysErr, errCode := tenant.Check(inf.User, xmlID, 
inf.Tx.Tx); userErr != nil || sysErr != nil {
                api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
                return
        }
+       dsID, ok, err := getDSIDFromName(inf.Tx.Tx, xmlID)
+       if err != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
errors.New("error finding delivery service with xmlID: "+xmlID), 
errors.New("getting DS id from name failed: "+err.Error()))
+       } else if !ok {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, nil, nil)
+       }
 
        data, err := ioutil.ReadAll(r.Body)
        if err != nil {
@@ -181,10 +196,23 @@ func SaveDeliveryServiceURIKeysHandler(w 
http.ResponseWriter, r *http.Request) {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, errors.New("saving riak object: "+err.Error()))
                return
        }
+       api.CreateChangeLogRawTx(api.ApiChange, "DS: "+xmlID+", ID: 
"+strconv.Itoa(dsID)+", ACTION: Stored URI signing keys to a delivery service", 
inf.User, inf.Tx.Tx)
        w.Header().Set("Content-Type", tc.ApplicationJson)
        w.Write(data)
 }
 
+// getDSIDFromName loads the DeliveryService's ID from the database, from the 
xml_id. Returns whether the delivery service was found, and any error.
+func getDSIDFromName(tx *sql.Tx, xmlID string) (int, bool, error) {
+       id := 0
+       if err := tx.QueryRow(`SELECT id FROM deliveryservice WHERE xml_id = 
$1`, xmlID).Scan(&id); err != nil {
+               if err == sql.ErrNoRows {
+                       return id, false, nil
+               }
+               return id, false, fmt.Errorf("querying ID for delivery service 
ID '%v': %v", xmlID, err)
+       }
+       return id, true, nil
+}
+
 // validateURIKeyset validates URISigingKeyset json.
 func validateURIKeyset(msg map[string]URISignerKeyset) error {
        var renewalKidFound int

Reply via email to