This is an automated email from the ASF dual-hosted git repository. rob pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git
commit 821f1f60759e3f9eab2c99cf768b68de55d450c4 Author: moltzaum <matt...@moltzau.net> AuthorDate: Thu Sep 20 14:06:00 2018 -0600 Refactored a little bit --- traffic_ops/traffic_ops_golang/api/api.go | 54 +++++++++++++++++++--- traffic_ops/traffic_ops_golang/api/api_test.go | 14 ++++++ traffic_ops/traffic_ops_golang/api/crud.go | 4 +- .../traffic_ops_golang/cachegroup/cachegroups.go | 4 +- .../traffic_ops_golang/dbhelpers/db_helpers.go | 44 ------------------ .../dbhelpers/db_helpers_test.go | 11 ----- .../deliveryservice/deliveryservicesv13.go | 4 +- .../deliveryservice/request/comment/comments.go | 2 +- .../deliveryservice/request/requests.go | 4 +- .../deliveryservice/servers/servers.go | 26 ++--------- traffic_ops/traffic_ops_golang/origin/origins.go | 4 +- .../profileparameter/profile_parameters.go | 2 +- .../steeringtargets/steeringtargets.go | 4 +- 13 files changed, 79 insertions(+), 98 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/api/api.go b/traffic_ops/traffic_ops_golang/api/api.go index 10b5b80..6d3d5d0 100644 --- a/traffic_ops/traffic_ops_golang/api/api.go +++ b/traffic_ops/traffic_ops_golang/api/api.go @@ -27,6 +27,7 @@ import ( "fmt" "io" "net/http" + "regexp" "strconv" "strings" "time" @@ -36,7 +37,6 @@ import ( "github.com/apache/trafficcontrol/lib/go-util" "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth" "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config" - "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers" "github.com/jmoiron/sqlx" "github.com/lib/pq" @@ -416,24 +416,64 @@ func TypeErrToAPIErr(err error, errType tc.ApiErrorType) (error, error, int) { } } -// ParseDBErr parses pq errors for uniqueness constraint violations, and returns the (userErr, sysErr, httpCode) format expected by the API helpers. -// The dataType is the name of the API object, e.g. 'coordinate' or 'delivery service', used to construct the error string. -func ParseDBErr(ierr error, dataType string) (error, error, int) { +// small helper function to help with parsing below +func toCamelCase(str string) string { + mutable := []byte(str) + for i := 0; i < len(str); i++ { + if mutable[i] == '_' && i+1 < len(str) { + mutable[i+1] = strings.ToUpper(string(str[i+1]))[0] + } + } + return strings.Replace(string(mutable[:]), "_", "", -1) +} + +// parses pq errors for not null constraint +func parseNotNullConstraintError(err *pq.Error) (error, error, int) { + pattern := regexp.MustCompile(`null value in column "(.+)" violates not-null constraint`) + match := pattern.FindStringSubmatch(err.Message) + if match == nil { + return nil, nil, http.StatusOK + } + return fmt.Errorf("%s is a required field", toCamelCase(match[1])), nil, http.StatusBadRequest +} + +// parses pq errors for violated foreign key constraints +func parseNotPresentFKConstraintError(err *pq.Error) (error, error, int) { + pattern := regexp.MustCompile(`Key \(.+\)=\(.+\) is not present in table "(.+)"`) + match := pattern.FindStringSubmatch(err.Detail) + if match == nil { + return nil, nil, http.StatusOK + } + return fmt.Errorf("%s not found", match[1]), nil, http.StatusNotFound +} + +// parses pq errors for uniqueness constraint violations +func parseUniqueConstraintError(err *pq.Error) (error, error, int) { + pattern := regexp.MustCompile(`Key \((.+)\)=\((.+)\) already exists`) + match := pattern.FindStringSubmatch(err.Detail) + if match == nil { + return nil, nil, http.StatusOK + } + return fmt.Errorf("%s %s already exists.", match[1], match[2]), nil, http.StatusBadRequest +} + +// ParseDBError parses pq errors for uniqueness constraint violations, and returns the (userErr, sysErr, httpCode) format expected by the API helpers. +func ParseDBError(ierr error) (error, error, int) { err, ok := ierr.(*pq.Error) if !ok { return nil, errors.New("database returned non pq error: " + err.Error()), http.StatusInternalServerError } - if usrErr, sysErr, errCode := dbhelpers.ParsePQNotNullConstraintError(err); errCode != http.StatusOK { + if usrErr, sysErr, errCode := parseNotNullConstraintError(err); errCode != http.StatusOK { return usrErr, sysErr, errCode } - if usrErr, sysErr, errCode := dbhelpers.ParsePQPresentFKConstraintError(err); errCode != http.StatusOK { + if usrErr, sysErr, errCode := parseNotPresentFKConstraintError(err); errCode != http.StatusOK { return usrErr, sysErr, errCode } - if usrErr, sysErr, errCode := dbhelpers.ParsePQUniqueConstraintError(err); errCode != http.StatusOK { + if usrErr, sysErr, errCode := parseUniqueConstraintError(err); errCode != http.StatusOK { return usrErr, sysErr, errCode } diff --git a/traffic_ops/traffic_ops_golang/api/api_test.go b/traffic_ops/traffic_ops_golang/api/api_test.go new file mode 100644 index 0000000..700d9c8 --- /dev/null +++ b/traffic_ops/traffic_ops_golang/api/api_test.go @@ -0,0 +1,14 @@ +package api + +import "testing" + +func TestCamelCase(t *testing.T) { + + testStrings := []string{"hello_world", "trailing_underscore_", "w_h_a_t____"} + expected := []string{"helloWorld", "trailingUnderscore", "wHAT"} + for i, str := range testStrings { + if toCamelCase(str) != expected[i] { + t.Errorf("expected: %v error, actual: %v", expected[i], toCamelCase(str)) + } + } +} diff --git a/traffic_ops/traffic_ops_golang/api/crud.go b/traffic_ops/traffic_ops_golang/api/crud.go index bb44c30..5c0dd35 100644 --- a/traffic_ops/traffic_ops_golang/api/crud.go +++ b/traffic_ops/traffic_ops_golang/api/crud.go @@ -62,7 +62,7 @@ type GenericDeleter interface { func GenericCreate(val GenericCreator) (error, error, int) { resultRows, err := val.APIInfo().Tx.NamedQuery(val.InsertQuery(), val) if err != nil { - return ParseDBErr(err, val.GetType()) + return ParseDBError(err) } defer resultRows.Close() @@ -113,7 +113,7 @@ func GenericRead(val GenericReader) ([]interface{}, error, error, int) { func GenericUpdate(val GenericUpdater) (error, error, int) { rows, err := val.APIInfo().Tx.NamedQuery(val.UpdateQuery(), val) if err != nil { - return ParseDBErr(err, val.GetType()) + return ParseDBError(err) } defer rows.Close() diff --git a/traffic_ops/traffic_ops_golang/cachegroup/cachegroups.go b/traffic_ops/traffic_ops_golang/cachegroup/cachegroups.go index 5c838b6..9a833a0 100644 --- a/traffic_ops/traffic_ops_golang/cachegroup/cachegroups.go +++ b/traffic_ops/traffic_ops_golang/cachegroup/cachegroups.go @@ -202,7 +202,7 @@ func (cg *TOCacheGroup) Create() (error, error, int) { cg.SecondaryParentCachegroupID, ) if err != nil { - return api.ParseDBErr(err, cg.GetType()) + return api.ParseDBError(err) } defer resultRows.Close() @@ -375,7 +375,7 @@ func (cg *TOCacheGroup) Update() (error, error, int) { cg.ID, ) if err != nil { - return api.ParseDBErr(err, cg.GetType()) + return api.ParseDBError(err) } defer resultRows.Close() diff --git a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go index 059576b..866342c 100644 --- a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go +++ b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go @@ -22,9 +22,6 @@ package dbhelpers import ( "database/sql" "errors" - "fmt" - "net/http" - "regexp" "strings" "github.com/apache/trafficcontrol/lib/go-log" @@ -104,47 +101,6 @@ func parseCriteriaAndQueryValues(queryParamsToSQLCols map[string]WhereColumnInfo return criteria, queryValues, errs } -// small helper function to help with parsing below -func toCamelCase(str string) string { - mutable := []byte(str) - for i := 0; i < len(str); i++ { - if mutable[i] == '_' && i+1 < len(str) { - mutable[i+1] = strings.ToUpper(string(str[i+1]))[0] - } - } - return strings.Replace(string(mutable[:]), "_", "", -1) -} - -// parses pq errors for not null constraint -func ParsePQNotNullConstraintError(err *pq.Error) (error, error, int) { - pattern := regexp.MustCompile(`null value in column "(.+)" violates not-null constraint`) - match := pattern.FindStringSubmatch(err.Message) - if match == nil { - return nil, nil, http.StatusOK - } - return fmt.Errorf("%s is a required field", toCamelCase(match[1])), nil, http.StatusBadRequest -} - -// parses pq errors for violated foreign key constraints -func ParsePQPresentFKConstraintError(err *pq.Error) (error, error, int) { - pattern := regexp.MustCompile(`Key \(.+\)=\(.+\) is not present in table "(.+)"`) - match := pattern.FindStringSubmatch(err.Detail) - if match == nil { - return nil, nil, http.StatusOK - } - return fmt.Errorf("%s not found", match[1]), nil, http.StatusNotFound -} - -// parses pq errors for uniqueness constraint violations -func ParsePQUniqueConstraintError(err *pq.Error) (error, error, int) { - pattern := regexp.MustCompile(`Key \((.+)\)=\((.+)\) already exists`) - match := pattern.FindStringSubmatch(err.Detail) - if match == nil { - return nil, nil, http.StatusOK - } - return fmt.Errorf("%s %s already exists.", match[1], match[2]), nil, http.StatusBadRequest -} - // FinishTx commits the transaction if commit is true when it's called, otherwise it rolls back the transaction. This is designed to be called in a defer. func FinishTx(tx *sql.Tx, commit *bool) { if tx == nil { diff --git a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers_test.go b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers_test.go index 74f4f07..5607dfc 100644 --- a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers_test.go +++ b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers_test.go @@ -71,14 +71,3 @@ FROM table t } } - -func TestCamelCase(t *testing.T) { - - testStrings := []string{"hello_world", "trailing_underscore_", "w_h_a_t____"} - expected := []string{"helloWorld", "trailingUnderscore", "wHAT"} - for i, str := range testStrings { - if toCamelCase(str) != expected[i] { - t.Errorf("expected: %v error, actual: %v", expected[i], toCamelCase(str)) - } - } -} diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv13.go b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv13.go index 865ebe1..649afb1 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv13.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv13.go @@ -147,7 +147,7 @@ func create(tx *sql.Tx, cfg config.Config, user *auth.CurrentUser, ds tc.Deliver resultRows, err := tx.Query(insertQuery(), &ds.Active, &ds.AnonymousBlockingEnabled, &ds.CacheURL, &ds.CCRDNSTTL, &ds.CDNID, &ds.CheckPath, &deepCachingType, &ds.DisplayName, &ds.DNSBypassCNAME, &ds.DNSBypassIP, &ds.DNSBypassIP6, &ds.DNSBypassTTL, &ds.DSCP, &ds.EdgeHeaderRewrite, &ds.GeoLimitRedirectURL, &ds.GeoLimit, &ds.GeoLimitCountries, &ds.GeoProvider, &ds.GlobalMaxMBPS, &ds.GlobalMaxTPS, &ds.FQPacingRate, &ds.HTTPBypassFQDN, &ds.InfoURL, &ds.InitialDispersion, &ds.IPV6RoutingEnabl [...] if err != nil { - usrErr, sysErr, code := api.ParseDBErr(err, "delivery service") + usrErr, sysErr, code := api.ParseDBError(err) return tc.DeliveryServiceNullable{}, code, usrErr, sysErr } defer resultRows.Close() @@ -453,7 +453,7 @@ func update(tx *sql.Tx, cfg config.Config, user *auth.CurrentUser, ds *tc.Delive resultRows, err := tx.Query(updateDSQuery(), &ds.Active, &ds.CacheURL, &ds.CCRDNSTTL, &ds.CDNID, &ds.CheckPath, &deepCachingType, &ds.DisplayName, &ds.DNSBypassCNAME, &ds.DNSBypassIP, &ds.DNSBypassIP6, &ds.DNSBypassTTL, &ds.DSCP, &ds.EdgeHeaderRewrite, &ds.GeoLimitRedirectURL, &ds.GeoLimit, &ds.GeoLimitCountries, &ds.GeoProvider, &ds.GlobalMaxMBPS, &ds.GlobalMaxTPS, &ds.FQPacingRate, &ds.HTTPBypassFQDN, &ds.InfoURL, &ds.InitialDispersion, &ds.IPV6RoutingEnabled, &ds.LogsEnabled, &ds.Lon [...] if err != nil { - usrErr, sysErr, code := api.ParseDBErr(err, "delivery service") + usrErr, sysErr, code := api.ParseDBError(err) return tc.DeliveryServiceNullable{}, code, usrErr, sysErr } defer resultRows.Close() diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/request/comment/comments.go b/traffic_ops/traffic_ops_golang/deliveryservice/request/comment/comments.go index 5b41695..db1ded1 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/request/comment/comments.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/request/comment/comments.go @@ -114,7 +114,7 @@ func (comment *TODeliveryServiceRequestComment) Update() (error, error, int) { current := TODeliveryServiceRequestComment{} err := comment.ReqInfo.Tx.QueryRowx(selectQuery() + `WHERE dsrc.id=` + strconv.Itoa(*comment.ID)).StructScan(¤t) if err != nil { - return api.ParseDBErr(err, comment.GetType()) + return api.ParseDBError(err) } userID := tc.IDNoMod(comment.ReqInfo.User.ID) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/request/requests.go b/traffic_ops/traffic_ops_golang/deliveryservice/request/requests.go index 7751b04..613ef70 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/request/requests.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/request/requests.go @@ -389,7 +389,7 @@ func (req *deliveryServiceRequestAssignment) Update() (error, error, int) { } if _, err = req.APIInfo().Tx.Tx.Exec(`UPDATE deliveryservice_request SET assignee_id = $1 WHERE id = $2`, v, *req.ID); err != nil { - return api.ParseDBErr(err, req.GetType()) + return api.ParseDBError(err) } if err = req.APIInfo().Tx.QueryRowx(selectDeliveryServiceRequestsQuery()+` WHERE r.id = $1`, *req.ID).StructScan(req); err != nil { @@ -455,7 +455,7 @@ func (req *deliveryServiceRequestStatus) Update() (error, error, int) { // LastEditedBy field should not change with status update if _, err = req.APIInfo().Tx.Tx.Exec(`UPDATE deliveryservice_request SET status = $1 WHERE id = $2`, *req.Status, *req.ID); err != nil { - return api.ParseDBErr(err, req.GetType()) + return api.ParseDBError(err) } if err = req.APIInfo().Tx.QueryRowx(selectDeliveryServiceRequestsQuery()+` WHERE r.id = $1`, *req.ID).StructScan(req); err != nil { diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go index 0e26c0f..e6a00ce 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go @@ -32,7 +32,6 @@ import ( "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/deliveryservice" "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant" @@ -267,17 +266,8 @@ func GetReplaceHandler(w http.ResponseWriter, r *http.Request) { for _, server := range servers { dtos := map[string]interface{}{"id": dsId, "server": server} if _, err := inf.Tx.NamedExec(insertIdsQuery(), dtos); err != nil { - if pqErr, ok := err.(*pq.Error); ok { - err, _, code := dbhelpers.ParsePQUniqueConstraintError(pqErr) - log.Errorln("could not begin transaction: %v", err) - if code == http.StatusBadRequest { - api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("inserting for delivery service servers replace: "+err.Error())) - return - } - api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("inserting for delivery service servers replace: "+err.Error())) - return - } - api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("inserting for delivery service servers replace: "+err.Error())) + usrErr, sysErr, code := api.ParseDBError(err) + api.HandleErr(w, r, inf.Tx.Tx, code, usrErr, sysErr) return } respServers = append(respServers, server) @@ -328,16 +318,8 @@ func GetCreateHandler(w http.ResponseWriter, r *http.Request) { res, err := inf.Tx.Tx.Exec(`INSERT INTO deliveryservice_server (deliveryservice, server) SELECT $1, id FROM server WHERE host_name = ANY($2::text[])`, dsID, pq.Array(serverNames)) if err != nil { - if pqErr, ok := err.(*pq.Error); ok { - err, _, code := dbhelpers.ParsePQUniqueConstraintError(pqErr) - if code == http.StatusBadRequest { - api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("a deliveryservice-server association with "+err.Error()), nil) - return - } - api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("ds servers inserting for create delivery service servers: "+err.Error())) - return - } - api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("ds servers inserting for create delivery service servers received non pq error: "+err.Error())) + usrErr, sysErr, code := api.ParseDBError(err) + api.HandleErr(w, r, inf.Tx.Tx, code, usrErr, sysErr) return } diff --git a/traffic_ops/traffic_ops_golang/origin/origins.go b/traffic_ops/traffic_ops_golang/origin/origins.go index 0df598f..15d117b 100644 --- a/traffic_ops/traffic_ops_golang/origin/origins.go +++ b/traffic_ops/traffic_ops_golang/origin/origins.go @@ -341,7 +341,7 @@ func (origin *TOOrigin) Update() (error, error, int) { log.Debugf("about to run exec query: %s with origin: %++v", updateQuery(), origin) resultRows, err := origin.ReqInfo.Tx.NamedQuery(updateQuery(), origin) if err != nil { - return api.ParseDBErr(err, origin.GetType()) + return api.ParseDBError(err) } defer resultRows.Close() @@ -397,7 +397,7 @@ func (origin *TOOrigin) Create() (error, error, int) { resultRows, err := origin.ReqInfo.Tx.NamedQuery(insertQuery(), origin) if err != nil { - return api.ParseDBErr(err, origin.GetType()) + return api.ParseDBError(err) } defer resultRows.Close() diff --git a/traffic_ops/traffic_ops_golang/profileparameter/profile_parameters.go b/traffic_ops/traffic_ops_golang/profileparameter/profile_parameters.go index 287b8db..872cf65 100644 --- a/traffic_ops/traffic_ops_golang/profileparameter/profile_parameters.go +++ b/traffic_ops/traffic_ops_golang/profileparameter/profile_parameters.go @@ -124,7 +124,7 @@ func (pp *TOProfileParameter) Validate() error { func (pp *TOProfileParameter) Create() (error, error, int) { resultRows, err := pp.APIInfo().Tx.NamedQuery(insertQuery(), pp) if err != nil { - return api.ParseDBErr(err, pp.GetType()) + return api.ParseDBError(err) } defer resultRows.Close() diff --git a/traffic_ops/traffic_ops_golang/steeringtargets/steeringtargets.go b/traffic_ops/traffic_ops_golang/steeringtargets/steeringtargets.go index 9642983..c205b08 100644 --- a/traffic_ops/traffic_ops_golang/steeringtargets/steeringtargets.go +++ b/traffic_ops/traffic_ops_golang/steeringtargets/steeringtargets.go @@ -182,7 +182,7 @@ func (st *TOSteeringTargetV11) Create() (error, error, int) { rows, err := st.ReqInfo.Tx.NamedQuery(insertQuery(), st) if err != nil { - return api.ParseDBErr(err, st.GetType()) + return api.ParseDBError(err) } defer rows.Close() @@ -223,7 +223,7 @@ func (st *TOSteeringTargetV11) Update() (error, error, int) { rows, err := st.ReqInfo.Tx.NamedQuery(updateQuery(), st) if err != nil { - return api.ParseDBErr(err, st.GetType()) + return api.ParseDBError(err) } defer rows.Close()