You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@trafficcontrol.apache.org by GitBox <gi...@apache.org> on 2018/06/27 14:48:42 UTC

[GitHub] dangogh closed pull request #2472: Fix TO Go profile param endpoints to have better user error messages

dangogh closed pull request #2472: Fix TO Go profile param endpoints to have better user error messages
URL: https://github.com/apache/trafficcontrol/pull/2472
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/lib/go-tc/parameters.go b/lib/go-tc/parameters.go
index c09928041..9bbf3b993 100644
--- a/lib/go-tc/parameters.go
+++ b/lib/go-tc/parameters.go
@@ -1,6 +1,18 @@
 package tc
 
-import "encoding/json"
+import (
+	"bytes"
+	"database/sql"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"strconv"
+	"strings"
+
+	"github.com/apache/trafficcontrol/lib/go-util"
+
+	"github.com/lib/pq"
+)
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -61,10 +73,66 @@ type ProfileParameterByName struct {
 }
 
 type ProfileParameterByNamePost struct {
-	ConfigFile string `json:"configFile"`
-	Name       string `json:"name"`
-	Secure     int    `json:"secure"`
-	Value      string `json:"value"`
+	ConfigFile *string `json:"configFile"`
+	Name       *string `json:"name"`
+	Secure     *int    `json:"secure"`
+	Value      *string `json:"value"`
+}
+
+func (p *ProfileParameterByNamePost) Validate(tx *sql.Tx) error {
+	errs := []string{}
+	if p.ConfigFile == nil || *p.ConfigFile == "" {
+		errs = append(errs, "configFile")
+	}
+	if p.Name == nil || *p.Name == "" {
+		errs = append(errs, "name")
+	}
+	if p.Secure == nil {
+		errs = append(errs, "secure")
+	}
+	if p.Value == nil {
+		errs = append(errs, "value")
+	}
+	if len(errs) > 0 {
+		return errors.New("required fields missing: " + strings.Join(errs, ", "))
+	}
+	return nil
+}
+
+// ProfileParametersByNamePost is the object posted to profile/name/parameter endpoints. This object may be posted as either a single JSON object, or an array of objects. Either will unmarshal into this object; a single object will unmarshal into an array of 1 element.
+type ProfileParametersByNamePost []ProfileParameterByNamePost
+
+func (pp *ProfileParametersByNamePost) UnmarshalJSON(bts []byte) error {
+	bts = bytes.TrimLeft(bts, " \n\t\r")
+	if len(bts) == 0 {
+		errors.New("no body")
+	}
+	if bts[0] == '[' {
+		ppArr := []ProfileParameterByNamePost{}
+		err := json.Unmarshal(bts, &ppArr)
+		*pp = ppArr
+		return err
+	}
+	p := ProfileParameterByNamePost{}
+	if err := json.Unmarshal(bts, &p); err != nil {
+		return err
+	}
+	*pp = append(*pp, p)
+	return nil
+}
+
+func (pp *ProfileParametersByNamePost) Validate(tx *sql.Tx) error {
+	errs := []string{}
+	ppArr := ([]ProfileParameterByNamePost)(*pp)
+	for i, profileParam := range ppArr {
+		if err := profileParam.Validate(tx); err != nil {
+			errs = append(errs, "object "+strconv.Itoa(i)+": "+err.Error())
+		}
+	}
+	if len(errs) > 0 {
+		return errors.New("validate errors: " + strings.Join(errs, "; "))
+	}
+	return nil
 }
 
 type ProfileParameterPostRespObj struct {
@@ -79,13 +147,112 @@ type ProfileParameterPostResp struct {
 }
 
 type PostProfileParam struct {
-	ProfileID int64   `json:"profileId"`
-	ParamIDs  []int64 `json:"paramIds"`
-	Replace   bool    `json:"replace"`
+	ProfileID *int64   `json:"profileId"`
+	ParamIDs  *[]int64 `json:"paramIds"`
+	Replace   *bool    `json:"replace"`
+}
+
+func (pp *PostProfileParam) Sanitize(tx *sql.Tx) {
+	if pp.Replace == nil {
+		pp.Replace = util.BoolPtr(false)
+	}
+}
+
+func (pp *PostProfileParam) Validate(tx *sql.Tx) error {
+	pp.Sanitize(tx)
+	errs := []string{}
+	if pp.ProfileID == nil {
+		errs = append(errs, "profileId missing")
+	} else if ok, err := ProfileExists(*pp.ProfileID, tx); err != nil {
+		errs = append(errs, "checking profile ID "+strconv.Itoa(int(*pp.ProfileID))+" existence: "+err.Error())
+	} else if !ok {
+		errs = append(errs, "no profile with ID "+strconv.Itoa(int(*pp.ProfileID))+" exists")
+	}
+	if pp.ParamIDs == nil {
+		errs = append(errs, "paramIds missing")
+	} else if ok, err := ParamsExist(*pp.ParamIDs, tx); err != nil {
+		errs = append(errs, fmt.Sprintf("checking parameter IDs %v existence: "+err.Error(), *pp.ParamIDs))
+	} else if !ok {
+		errs = append(errs, fmt.Sprintf("parameters with IDs %v don't all exist", *pp.ParamIDs))
+	}
+	if len(errs) > 0 {
+		return errors.New("validate errors: " + strings.Join(errs, ", "))
+	}
+	return nil
 }
 
 type PostParamProfile struct {
-	ParamID    int64   `json:"paramId"`
-	ProfileIDs []int64 `json:"profileIds"`
-	Replace    bool    `json:"replace"`
+	ParamID    *int64   `json:"paramId"`
+	ProfileIDs *[]int64 `json:"profileIds"`
+	Replace    *bool    `json:"replace"`
+}
+
+func (pp *PostParamProfile) Sanitize(tx *sql.Tx) {
+	if pp.Replace == nil {
+		pp.Replace = util.BoolPtr(false)
+	}
+}
+
+func (pp *PostParamProfile) Validate(tx *sql.Tx) error {
+	pp.Sanitize(tx)
+
+	errs := []string{}
+	if pp.ParamID == nil {
+		errs = append(errs, "paramId missing")
+	} else if ok, err := ParamExists(*pp.ParamID, tx); err != nil {
+		errs = append(errs, "checking param ID "+strconv.Itoa(int(*pp.ParamID))+" existence: "+err.Error())
+	} else if !ok {
+		errs = append(errs, "no parameter with ID "+strconv.Itoa(int(*pp.ParamID))+" exists")
+	}
+	if pp.ProfileIDs == nil {
+		errs = append(errs, "profileIds missing")
+	} else if ok, err := ProfilesExist(*pp.ProfileIDs, tx); err != nil {
+		errs = append(errs, fmt.Sprintf("checking profiles IDs %v existence: "+err.Error(), *pp.ProfileIDs))
+	} else if !ok {
+		errs = append(errs, fmt.Sprintf("profiles with IDs %v don't all exist", *pp.ProfileIDs))
+	}
+	if len(errs) > 0 {
+		return errors.New("validate errors: " + strings.Join(errs, ", "))
+	}
+	return nil
+}
+
+// ParamExists returns whether a parameter with the given id exists, and any error.
+// TODO move to helper package.
+func ParamExists(id int64, tx *sql.Tx) (bool, error) {
+	count := 0
+	if err := tx.QueryRow(`SELECT count(*) from parameter where id = $1`, id).Scan(&count); err != nil {
+		return false, errors.New("querying param existence from id: " + err.Error())
+	}
+	return count > 0, nil
+}
+
+// ProfilesExist returns whether profiles exist for all the given ids, and any error.
+// TODO move to helper package.
+func ProfilesExist(ids []int64, tx *sql.Tx) (bool, error) {
+	count := 0
+	if err := tx.QueryRow(`SELECT count(*) from profile where id = ANY($1)`, pq.Array(ids)).Scan(&count); err != nil {
+		return false, errors.New("querying profiles existence from id: " + err.Error())
+	}
+	return count == len(ids), nil
+}
+
+// ProfileExists returns whether a profile with the given id exists, and any error.
+// TODO move to helper package.
+func ProfileExists(id int64, tx *sql.Tx) (bool, error) {
+	count := 0
+	if err := tx.QueryRow(`SELECT count(*) from profile where id = $1`, id).Scan(&count); err != nil {
+		return false, errors.New("querying profile existence from id: " + err.Error())
+	}
+	return count > 0, nil
+}
+
+// ParamsExist returns whether parameters exist for all the given ids, and any error.
+// TODO move to helper package.
+func ParamsExist(ids []int64, tx *sql.Tx) (bool, error) {
+	count := 0
+	if err := tx.QueryRow(`SELECT count(*) from parameter where id = ANY($1)`, pq.Array(ids)).Scan(&count); err != nil {
+		return false, errors.New("querying parameters existence from id: " + err.Error())
+	}
+	return count == len(ids), nil
 }
diff --git a/traffic_ops/traffic_ops_golang/api/api.go b/traffic_ops/traffic_ops_golang/api/api.go
index 5310fa53e..5194ec09b 100644
--- a/traffic_ops/traffic_ops_golang/api/api.go
+++ b/traffic_ops/traffic_ops_golang/api/api.go
@@ -137,6 +137,25 @@ func WriteRespAlert(w http.ResponseWriter, r *http.Request, level tc.AlertLevel,
 	w.Write(respBts)
 }
 
+// WriteRespAlertObj Writes the given alert, and the given response object.
+// This is a helper for the common case; not using this in unusual cases is perfectly acceptable.
+func WriteRespAlertObj(w http.ResponseWriter, r *http.Request, level tc.AlertLevel, msg string, obj interface{}) {
+	resp := struct {
+		tc.Alerts
+		Response interface{} `json:"response"`
+	}{
+		Alerts:   tc.CreateAlerts(level, msg),
+		Response: obj,
+	}
+	respBts, err := json.Marshal(resp)
+	if err != nil {
+		HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("marshalling JSON: "+err.Error()))
+		return
+	}
+	w.Header().Set(tc.ContentType, tc.ApplicationJson)
+	w.Write(respBts)
+}
+
 // IntParams parses integer parameters, and returns map of the given params, or an error if any integer param is not an integer. The intParams may be nil if no integer parameters are required. Note this does not check existence; if an integer paramter is required, it should be included in the requiredParams given to NewInfo.
 // This is a helper for the common case; not using this in unusual cases is perfectly acceptable.
 func IntParams(params map[string]string, intParamNames []string) (map[string]int, error) {
diff --git a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
index 04dd8ce87..d5acc4196 100644
--- a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
+++ b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
@@ -156,3 +156,74 @@ func AddTenancyCheck(where string, queryValues map[string]interface{}, tenantCol
 
 	return where, queryValues
 }
+
+// GetGlobalParams returns the value of the global param, whether it existed, or any error
+func GetGlobalParam(tx *sql.Tx, name string) (string, bool, error) {
+	return GetParam(tx, name, "global")
+}
+
+// GetParam returns the value of the param, whether it existed, or any error.
+func GetParam(tx *sql.Tx, name string, configFile string) (string, bool, error) {
+	val := ""
+	if err := tx.QueryRow(`select value from parameter where name = $1 and config_file = $2`, name, configFile).Scan(&val); err != nil {
+		if err == sql.ErrNoRows {
+			return "", false, nil
+		}
+		return "", false, errors.New("Error querying global paramter '" + name + "': " + err.Error())
+	}
+	return val, true, nil
+}
+
+// GetDSNameFromID returns the delivery service name, whether it existed, and any error.
+func GetDSNameFromID(tx *sql.Tx, id int) (tc.DeliveryServiceName, bool, error) {
+	name := tc.DeliveryServiceName("")
+	if err := tx.QueryRow(`select xml_id from deliveryservice where id = $1`, id).Scan(&name); err != nil {
+		if err == sql.ErrNoRows {
+			return tc.DeliveryServiceName(""), false, nil
+		}
+		return tc.DeliveryServiceName(""), false, errors.New("querying delivery service name: " + err.Error())
+	}
+	return name, true, nil
+}
+
+// returns returns the delivery service name and cdn, whether it existed, and any error.
+func GetDSNameAndCDNFromID(tx *sql.Tx, id int) (tc.DeliveryServiceName, tc.CDNName, bool, error) {
+	name := tc.DeliveryServiceName("")
+	cdn := tc.CDNName("")
+	if err := tx.QueryRow(`
+SELECT ds.xml_id, cdn.name
+FROM deliveryservice as ds
+JOIN cdn on cdn.id = ds.cdn_id
+WHERE ds.id = $1
+`, id).Scan(&name, &cdn); err != nil {
+		if err == sql.ErrNoRows {
+			return tc.DeliveryServiceName(""), tc.CDNName(""), false, nil
+		}
+		return tc.DeliveryServiceName(""), tc.CDNName(""), false, errors.New("querying delivery service name: " + err.Error())
+	}
+	return name, cdn, true, nil
+}
+
+// GetProfileNameFromID returns the profile's name, whether a profile with ID exists, or any error.
+func GetProfileNameFromID(id int, tx *sql.Tx) (string, bool, error) {
+	name := ""
+	if err := tx.QueryRow(`SELECT name from profile where id = $1`, id).Scan(&name); err != nil {
+		if err == sql.ErrNoRows {
+			return "", false, nil
+		}
+		return "", false, errors.New("querying profile name from id: " + err.Error())
+	}
+	return name, true, nil
+}
+
+// GetProfileIDFromName returns the profile's ID, whether a profile with name exists, or any error.
+func GetProfileIDFromName(name string, tx *sql.Tx) (int, bool, error) {
+	id := 0
+	if err := tx.QueryRow(`SELECT id from profile where name = $1`, name).Scan(&id); err != nil {
+		if err == sql.ErrNoRows {
+			return 0, false, nil
+		}
+		return 0, false, errors.New("querying profile id from name: " + err.Error())
+	}
+	return id, true, nil
+}
diff --git a/traffic_ops/traffic_ops_golang/profileparameter/postparameterprofile.go b/traffic_ops/traffic_ops_golang/profileparameter/postparameterprofile.go
index 84362e756..a5ba2a44a 100644
--- a/traffic_ops/traffic_ops_golang/profileparameter/postparameterprofile.go
+++ b/traffic_ops/traffic_ops_golang/profileparameter/postparameterprofile.go
@@ -21,7 +21,6 @@ package profileparameter
 
 import (
 	"database/sql"
-	"encoding/json"
 	"errors"
 	"fmt"
 	"net/http"
@@ -32,79 +31,33 @@ import (
 	"github.com/lib/pq"
 )
 
-func PostParamProfile(db *sql.DB) http.HandlerFunc {
-	return func(w http.ResponseWriter, r *http.Request) {
-		defer r.Body.Close()
-
-		paramProfile := tc.PostParamProfile{}
-		if err := json.NewDecoder(r.Body).Decode(&paramProfile); err != nil {
-			api.HandleErr(w, r, http.StatusBadRequest, errors.New("malformed JSON"), nil)
-			return
-		}
-
-		if ok, err := paramExists(paramProfile.ParamID, db); err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, fmt.Errorf("checking param ID %d existence: "+err.Error(), paramProfile.ParamID))
-			return
-		} else if !ok {
-			api.HandleErr(w, r, http.StatusBadRequest, fmt.Errorf("no parameter with ID %d exists", paramProfile.ParamID), nil)
-			return
-		}
-		if ok, err := profilesExist(paramProfile.ProfileIDs, db); err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, fmt.Errorf("checking profiles IDs %v existence: "+err.Error(), paramProfile.ProfileIDs))
-			return
-		} else if !ok {
-			api.HandleErr(w, r, http.StatusBadRequest, fmt.Errorf("profiles with IDs %v don't all exist", paramProfile.ProfileIDs), nil)
-			return
-		}
-		if err := insertParameterProfile(paramProfile, db); err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("posting parameter profile: "+err.Error()))
-			return
-		}
-		// TODO create helper func
-		resp := struct {
-			Response tc.PostParamProfile `json:"response"`
-			tc.Alerts
-		}{paramProfile, tc.CreateAlerts(tc.SuccessLevel, fmt.Sprintf("%d profiles were assigned to the %d parameter", len(paramProfile.ProfileIDs), paramProfile.ParamID))}
-		respBts, err := json.Marshal(resp)
-		if err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("posting parameter profiles: "+err.Error()))
-			return
-		}
-		w.Header().Set(tc.ContentType, tc.ApplicationJson)
-		w.Write(respBts)
+func PostParamProfile(w http.ResponseWriter, r *http.Request) {
+	inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+	if userErr != nil || sysErr != nil {
+		api.HandleErr(w, r, errCode, userErr, sysErr)
+		return
 	}
-}
+	defer inf.Close()
 
-func paramExists(id int64, db *sql.DB) (bool, error) {
-	count := 0
-	if err := db.QueryRow(`SELECT count(*) from parameter where id = $1`, id).Scan(&count); err != nil {
-		return false, errors.New("querying param existence from id: " + err.Error())
+	paramProfile := tc.PostParamProfile{}
+	if err := api.Parse(r.Body, inf.Tx.Tx, &paramProfile); err != nil {
+		api.HandleErr(w, r, http.StatusBadRequest, errors.New("parse error: "+err.Error()), nil)
+		return
 	}
-	return count > 0, nil
-}
-
-func profilesExist(ids []int64, db *sql.DB) (bool, error) {
-	count := 0
-	if err := db.QueryRow(`SELECT count(*) from profile where id = ANY($1)`, pq.Array(ids)).Scan(&count); err != nil {
-		return false, errors.New("querying profiles existence from id: " + err.Error())
+	if err := insertParameterProfile(paramProfile, inf.Tx.Tx); err != nil {
+		api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("posting parameter profile: "+err.Error()))
+		return
 	}
-	return count == len(ids), nil
+	*inf.CommitTx = true
+	api.WriteRespAlertObj(w, r, tc.SuccessLevel, fmt.Sprintf("%d profiles were assigned to the %d parameter", len(*paramProfile.ProfileIDs), *paramProfile.ParamID), paramProfile)
 }
 
-func insertParameterProfile(post tc.PostParamProfile, db *sql.DB) error {
-	tx, err := db.Begin()
-	if err != nil {
-		return errors.New("beginning transaction: " + err.Error())
-	}
-	commitTx := false
-	defer FinishTx(tx, &commitTx)
-
-	if post.Replace {
+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 {
 			return errors.New("deleting old parameter profile: " + err.Error())
 		}
 	}
-
 	q := `
 INSERT INTO profile_parameter (profile, parameter)
 VALUES (unnest($1::int[]), $2)
@@ -113,6 +66,5 @@ ON CONFLICT DO NOTHING;
 	if _, err := tx.Exec(q, pq.Array(post.ProfileIDs), post.ParamID); err != nil {
 		return errors.New("inserting parameter profile: " + err.Error())
 	}
-	commitTx = true
 	return nil
 }
diff --git a/traffic_ops/traffic_ops_golang/profileparameter/postprofileparameter.go b/traffic_ops/traffic_ops_golang/profileparameter/postprofileparameter.go
index b405e595e..c1c2c7165 100644
--- a/traffic_ops/traffic_ops_golang/profileparameter/postprofileparameter.go
+++ b/traffic_ops/traffic_ops_golang/profileparameter/postprofileparameter.go
@@ -21,7 +21,6 @@ package profileparameter
 
 import (
 	"database/sql"
-	"encoding/json"
 	"errors"
 	"fmt"
 	"net/http"
@@ -32,87 +31,40 @@ import (
 	"github.com/lib/pq"
 )
 
-func PostProfileParam(db *sql.DB) http.HandlerFunc {
-	return func(w http.ResponseWriter, r *http.Request) {
-		defer r.Body.Close()
-
-		profileParam := tc.PostProfileParam{}
-		if err := json.NewDecoder(r.Body).Decode(&profileParam); err != nil {
-			api.HandleErr(w, r, http.StatusBadRequest, errors.New("malformed JSON"), nil)
-			return
-		}
-
-		if ok, err := profileExists(profileParam.ProfileID, db); err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, fmt.Errorf("checking profile ID %d existence: "+err.Error(), profileParam.ProfileID))
-			return
-		} else if !ok {
-			api.HandleErr(w, r, http.StatusBadRequest, fmt.Errorf("no profile with ID %d exists", profileParam.ProfileID), nil)
-			return
-		}
-		if ok, err := paramsExist(profileParam.ParamIDs, db); err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, fmt.Errorf("checking parameters IDs %v existence: "+err.Error(), profileParam.ParamIDs))
-			return
-		} else if !ok {
-			api.HandleErr(w, r, http.StatusBadRequest, fmt.Errorf("parameters with IDs %v don't all exist", profileParam.ParamIDs), nil)
-			return
-		}
-		if err := insertProfileParameter(profileParam, db); err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("posting profile parameter: "+err.Error()))
-			return
-		}
-		// TODO create helper func
-		resp := struct {
-			Response tc.PostProfileParam `json:"response"`
-			tc.Alerts
-		}{profileParam, tc.CreateAlerts(tc.SuccessLevel, fmt.Sprintf("%d parameters were assigned to the %d profile", len(profileParam.ParamIDs), profileParam.ProfileID))}
-		respBts, err := json.Marshal(resp)
-		if err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("posting profile parameters by name: "+err.Error()))
-			return
-		}
-		w.Header().Set(tc.ContentType, tc.ApplicationJson)
-		w.Write(respBts)
+func PostProfileParam(w http.ResponseWriter, r *http.Request) {
+	inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+	if userErr != nil || sysErr != nil {
+		api.HandleErr(w, r, errCode, userErr, sysErr)
+		return
 	}
-}
+	defer inf.Close()
 
-func profileExists(id int64, db *sql.DB) (bool, error) {
-	count := 0
-	if err := db.QueryRow(`SELECT count(*) from profile where id = $1`, id).Scan(&count); err != nil {
-		return false, errors.New("querying profile existence from id: " + err.Error())
+	profileParam := tc.PostProfileParam{}
+	if err := api.Parse(r.Body, inf.Tx.Tx, &profileParam); err != nil {
+		api.HandleErr(w, r, http.StatusBadRequest, errors.New("parse error: "+err.Error()), nil)
+		return
 	}
-	return count > 0, nil
-}
-
-func paramsExist(ids []int64, db *sql.DB) (bool, error) {
-	count := 0
-	if err := db.QueryRow(`SELECT count(*) from parameter where id = ANY($1)`, pq.Array(ids)).Scan(&count); err != nil {
-		return false, errors.New("querying parameters existence from id: " + err.Error())
+	if err := insertProfileParameter(profileParam, inf.Tx.Tx); err != nil {
+		api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("posting profile parameter: "+err.Error()))
+		return
 	}
-	return count == len(ids), nil
+	*inf.CommitTx = true
+	api.WriteRespAlertObj(w, r, tc.SuccessLevel, fmt.Sprintf("%d parameters were assigned to the %d profile", len(*profileParam.ParamIDs), *profileParam.ProfileID), profileParam)
 }
 
-func insertProfileParameter(post tc.PostProfileParam, db *sql.DB) error {
-	tx, err := db.Begin()
-	if err != nil {
-		return errors.New("beginning transaction: " + err.Error())
-	}
-	commitTx := false
-	defer FinishTx(tx, &commitTx)
-
-	if post.Replace {
-		if _, err := tx.Exec(`DELETE FROM profile_parameter WHERE profile = $1`, post.ProfileID); err != nil {
+func insertProfileParameter(post tc.PostProfileParam, tx *sql.Tx) error {
+	if *post.Replace {
+		if _, err := tx.Exec(`DELETE FROM profile_parameter WHERE profile = $1`, *post.ProfileID); err != nil {
 			return errors.New("deleting old profile parameter: " + err.Error())
 		}
 	}
-
 	q := `
 INSERT INTO profile_parameter (profile, parameter)
 VALUES ($1, unnest($2::int[]))
 ON CONFLICT DO NOTHING;
 `
-	if _, err := tx.Exec(q, post.ProfileID, pq.Array(post.ParamIDs)); err != nil {
+	if _, err := tx.Exec(q, *post.ProfileID, pq.Array(*post.ParamIDs)); err != nil {
 		return errors.New("inserting profile parameter: " + err.Error())
 	}
-	commitTx = true
 	return nil
 }
diff --git a/traffic_ops/traffic_ops_golang/profileparameter/postprofileparametersbyid.go b/traffic_ops/traffic_ops_golang/profileparameter/postprofileparametersbyid.go
index 355b88854..e2076560f 100644
--- a/traffic_ops/traffic_ops_golang/profileparameter/postprofileparametersbyid.go
+++ b/traffic_ops/traffic_ops_golang/profileparameter/postprofileparametersbyid.go
@@ -20,91 +20,47 @@ package profileparameter
  */
 
 import (
-	"bytes"
-	"database/sql"
-	"encoding/json"
 	"errors"
 	"fmt"
-	"io/ioutil"
 	"net/http"
 
 	"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"
 )
 
-func PostProfileParamsByID(db *sql.DB) http.HandlerFunc {
-	return func(w http.ResponseWriter, r *http.Request) {
-		defer r.Body.Close()
-		_, intParams, userErr, sysErr, errCode := api.AllParams(r, []string{"id"}, []string{"id"})
-		if userErr != nil || sysErr != nil {
-			api.HandleErr(w, r, errCode, userErr, sysErr)
-			return
-		}
-		bts, err := ioutil.ReadAll(r.Body)
-		if err != nil {
-			api.HandleErr(w, r, http.StatusBadRequest, errors.New("body read failed"), nil)
-			return
-		}
-		bts = bytes.TrimLeft(bts, " \n\t\r")
-		if len(bts) == 0 {
-			api.HandleErr(w, r, http.StatusBadRequest, errors.New("no body"), nil)
-			return
-		}
-		profParams := []tc.ProfileParameterByNamePost{}
-		if bts[0] == '[' {
-			if err := json.Unmarshal(bts, &profParams); err != nil {
-				api.HandleErr(w, r, http.StatusBadRequest, errors.New("malformed JSON"), nil)
-				return
-			}
-		} else {
-			param := tc.ProfileParameterByNamePost{}
-			if err := json.Unmarshal(bts, &param); err != nil {
-				api.HandleErr(w, r, http.StatusInternalServerError, errors.New("posting profile parameters by name: "+err.Error()), nil)
-				return
-			}
-			profParams = append(profParams, param)
-		}
-
-		profileID := intParams["id"]
-		profileName, profileExists, err := getProfileNameFromID(profileID, db)
-		if err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, fmt.Errorf("getting profile ID %d: "+err.Error(), profileID))
-			return
-		}
-		if !profileExists {
-			api.HandleErr(w, r, http.StatusBadRequest, fmt.Errorf("no profile with ID %d exists", profileID), nil)
-			return
-		}
+func PostProfileParamsByID(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, errCode, userErr, sysErr)
+		return
+	}
+	defer inf.Close()
 
-		insertedObjs, err := insertParametersForProfile(profileName, profParams, db)
-		if err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("posting profile parameters by name: "+err.Error()))
-			return
-		}
+	profParams := tc.ProfileParametersByNamePost{}
+	if err := api.Parse(r.Body, inf.Tx.Tx, &profParams); err != nil {
+		api.HandleErr(w, r, http.StatusBadRequest, errors.New("parse error: "+err.Error()), nil)
+		return
+	}
 
-		// TODO create helper func
-		resp := struct {
-			Response tc.ProfileParameterPostResp `json:"response"`
-			tc.Alerts
-		}{tc.ProfileParameterPostResp{Parameters: insertedObjs, ProfileName: profileName, ProfileID: profileID}, tc.CreateAlerts(tc.SuccessLevel, "Assign parameters successfully to profile "+profileName)}
-		respBts, err := json.Marshal(resp)
-		if err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("posting profile parameters by name: "+err.Error()))
-			return
-		}
-		w.Header().Set(tc.ContentType, tc.ApplicationJson)
-		w.Write(respBts)
+	profileID := inf.IntParams["id"]
+	profileName, profileExists, err := dbhelp.GetProfileNameFromID(profileID, inf.Tx.Tx)
+	if err != nil {
+		api.HandleErr(w, r, http.StatusInternalServerError, nil, fmt.Errorf("getting profile ID %d: "+err.Error(), profileID))
+		return
+	}
+	if !profileExists {
+		api.HandleErr(w, r, http.StatusBadRequest, fmt.Errorf("no profile with ID %d exists", profileID), nil)
+		return
 	}
-}
 
-// getProfileIDFromName returns the profile's name, whether a profile with ID exists, or any error.
-func getProfileNameFromID(id int, db *sql.DB) (string, bool, error) {
-	name := ""
-	if err := db.QueryRow(`SELECT name from profile where id = $1`, id).Scan(&name); err != nil {
-		if err == sql.ErrNoRows {
-			return "", false, nil
-		}
-		return "", false, errors.New("querying profile name from id: " + err.Error())
+	insertedObjs, err := insertParametersForProfile(profileName, profParams, inf.Tx.Tx)
+	if err != nil {
+		api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("posting profile parameters by name: "+err.Error()))
+		return
 	}
-	return name, true, nil
+
+	resp := tc.ProfileParameterPostResp{Parameters: insertedObjs, ProfileName: profileName, ProfileID: profileID}
+	*inf.CommitTx = true
+	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 9d6eb873e..18c904304 100644
--- a/traffic_ops/traffic_ops_golang/profileparameter/postprofileparametersbyname.go
+++ b/traffic_ops/traffic_ops_golang/profileparameter/postprofileparametersbyname.go
@@ -20,104 +20,51 @@ package profileparameter
  */
 
 import (
-	"bytes"
 	"database/sql"
-	"encoding/json"
 	"errors"
-	"io/ioutil"
 	"net/http"
 
 	"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/lib/pq"
 )
 
-func PostProfileParamsByName(db *sql.DB) http.HandlerFunc {
-	return func(w http.ResponseWriter, r *http.Request) {
-		defer r.Body.Close()
-		params, _, userErr, sysErr, errCode := api.AllParams(r, []string{"name"}, nil)
-		if userErr != nil || sysErr != nil {
-			api.HandleErr(w, r, errCode, userErr, sysErr)
-			return
-		}
-		bts, err := ioutil.ReadAll(r.Body)
-		if err != nil {
-			api.HandleErr(w, r, http.StatusBadRequest, errors.New("body read failed"), nil)
-			return
-		}
-		bts = bytes.TrimLeft(bts, " \n\t\r")
-		if len(bts) == 0 {
-			api.HandleErr(w, r, http.StatusBadRequest, errors.New("no body"), nil)
-			return
-		}
-		profParams := []tc.ProfileParameterByNamePost{}
-		if bts[0] == '[' {
-			if err := json.Unmarshal(bts, &profParams); err != nil {
-				api.HandleErr(w, r, http.StatusBadRequest, errors.New("malformed JSON"), nil)
-				return
-			}
-		} else {
-			param := tc.ProfileParameterByNamePost{}
-			if err := json.Unmarshal(bts, &param); err != nil {
-				api.HandleErr(w, r, http.StatusInternalServerError, errors.New("posting profile parameters by name: "+err.Error()), nil)
-				return
-			}
-			profParams = append(profParams, param)
-		}
-		profileName := params["name"]
-
-		profileID, profileExists, err := getProfileIDFromName(profileName, db)
-		if err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("getting profile '"+profileName+"' ID: "+err.Error()))
-			return
-		}
-		if !profileExists {
-			api.HandleErr(w, r, http.StatusBadRequest, errors.New("no profile with that name exists"), nil)
-			return
-		}
-
-		insertedObjs, err := insertParametersForProfile(profileName, profParams, db)
-		if err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("posting profile parameters by name: "+err.Error()))
-			return
-		}
-
-		// TODO create helper func
-		resp := struct {
-			Response tc.ProfileParameterPostResp `json:"response"`
-			tc.Alerts
-		}{tc.ProfileParameterPostResp{Parameters: insertedObjs, ProfileName: profileName, ProfileID: profileID}, tc.CreateAlerts(tc.SuccessLevel, "Assign parameters successfully to profile "+profileName)}
-		respBts, err := json.Marshal(resp)
-		if err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("posting profile parameters by name: "+err.Error()))
-			return
-		}
-		w.Header().Set(tc.ContentType, tc.ApplicationJson)
-		w.Write(respBts)
+func PostProfileParamsByName(w http.ResponseWriter, r *http.Request) {
+	inf, userErr, sysErr, errCode := api.NewInfo(r, []string{"name"}, nil)
+	if userErr != nil || sysErr != nil {
+		api.HandleErr(w, r, errCode, userErr, sysErr)
+		return
 	}
-}
-
-// getProfileIDFromName returns the profile's ID, whether a profile with name exists, or any error.
-func getProfileIDFromName(name string, db *sql.DB) (int, bool, error) {
-	id := 0
-	if err := db.QueryRow(`SELECT id from profile where name = $1`, name).Scan(&id); err != nil {
-		if err == sql.ErrNoRows {
-			return 0, false, nil
-		}
-		return 0, false, errors.New("querying profile id from name: " + err.Error())
+	defer inf.Close()
+	profParams := tc.ProfileParametersByNamePost{}
+	if err := api.Parse(r.Body, inf.Tx.Tx, &profParams); err != nil {
+		api.HandleErr(w, r, http.StatusBadRequest, errors.New("parse error: "+err.Error()), nil)
+		return
 	}
-	return id, true, nil
+	profileName := inf.Params["name"]
+	profileID, profileExists, err := dbhelp.GetProfileIDFromName(profileName, inf.Tx.Tx)
+	if err != nil {
+		api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("getting profile '"+profileName+"' ID: "+err.Error()))
+		return
+	}
+	if !profileExists {
+		api.HandleErr(w, r, http.StatusBadRequest, errors.New("no profile with that name exists"), nil)
+		return
+	}
+	insertedObjs, err := insertParametersForProfile(profileName, profParams, inf.Tx.Tx)
+	if err != nil {
+		api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("posting profile parameters by name: "+err.Error()))
+		return
+	}
+	resp := tc.ProfileParameterPostResp{Parameters: insertedObjs, ProfileName: profileName, ProfileID: profileID}
+	*inf.CommitTx = true
+	api.WriteRespAlertObj(w, r, tc.SuccessLevel, "Assign parameters successfully to profile "+profileName, resp)
 }
 
 // insertParametersForProfile returns the PostResp object, because the ID is needed, and the ID must be associated with the real key (name,value,config_file), so we might as well return the whole object.
-func insertParametersForProfile(profileName string, params []tc.ProfileParameterByNamePost, db *sql.DB) ([]tc.ProfileParameterPostRespObj, error) {
-	tx, err := db.Begin()
-	if err != nil {
-		return nil, errors.New("beginning transaction: " + err.Error())
-	}
-	commitTx := false
-	defer FinishTx(tx, &commitTx)
+func insertParametersForProfile(profileName string, params tc.ProfileParametersByNamePost, tx *sql.Tx) ([]tc.ProfileParameterPostRespObj, error) {
 	insertParamsQ := `
 INSERT INTO parameter (name, config_file, value, secure)
 VALUES (unnest($1::text[]), unnest($2::text[]), unnest($3::text[]), unnest($4::bool[]))
@@ -128,10 +75,10 @@ ON CONFLICT(name, config_file, value) DO UPDATE set name=EXCLUDED.name RETURNING
 	paramValues := make([]string, len(params))
 	paramSecures := make([]bool, len(params))
 	for i, param := range params {
-		paramNames[i] = param.Name
-		paramConfigFiles[i] = param.ConfigFile
-		paramValues[i] = param.Value
-		if param.Secure != 0 {
+		paramNames[i] = *param.Name
+		paramConfigFiles[i] = *param.ConfigFile
+		paramValues[i] = *param.Value
+		if *param.Secure != 0 {
 			paramSecures[i] = true
 		}
 	}
@@ -156,7 +103,7 @@ ON CONFLICT(name, config_file, value) DO UPDATE set name=EXCLUDED.name RETURNING
 			secureNum = 1
 		}
 		ids = append(ids, id)
-		insertedObjs = append(insertedObjs, tc.ProfileParameterPostRespObj{ID: id, ProfileParameterByNamePost: tc.ProfileParameterByNamePost{Name: name, ConfigFile: configFile, Value: value, Secure: secureNum}})
+		insertedObjs = append(insertedObjs, tc.ProfileParameterPostRespObj{ID: id, ProfileParameterByNamePost: tc.ProfileParameterByNamePost{Name: &name, ConfigFile: &configFile, Value: &value, Secure: &secureNum}})
 	}
 	insertProfileParamsQ := `
 INSERT INTO profile_parameter (profile, parameter)
@@ -167,18 +114,5 @@ ON CONFLICT DO NOTHING;
 		return nil, errors.New("inserting profile parameters: " + err.Error())
 	}
 
-	commitTx = true
 	return insertedObjs, nil
 }
-
-// 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 {
-		return
-	}
-	if !*commit {
-		tx.Rollback()
-		return
-	}
-	tx.Commit()
-}
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index 01cdb9222..bf8c8cf46 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -272,12 +272,12 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
 		{1.1, http.MethodGet, `profiles/{id}/unassigned_parameters/?(\.json)?$`, profileparameter.GetUnassigned(d.DB.DB), auth.PrivLevelReadOnly, Authenticated, nil},
 		{1.1, http.MethodGet, `profiles/name/{name}/parameters/?(\.json)?$`, profileparameter.GetProfileName(d.DB.DB), auth.PrivLevelReadOnly, Authenticated, nil},
 		{1.1, http.MethodGet, `parameters/profile/{name}/?(\.json)?$`, profileparameter.GetProfileName(d.DB.DB), auth.PrivLevelReadOnly, Authenticated, nil},
-		{1.1, http.MethodPost, `profiles/name/{name}/parameters/?$`, profileparameter.PostProfileParamsByName(d.DB.DB), auth.PrivLevelOperations, Authenticated, nil},
-		{1.1, http.MethodPost, `profiles/{id}/parameters/?$`, profileparameter.PostProfileParamsByID(d.DB.DB), auth.PrivLevelOperations, Authenticated, nil},
+		{1.1, http.MethodPost, `profiles/name/{name}/parameters/?$`, profileparameter.PostProfileParamsByName, auth.PrivLevelOperations, Authenticated, nil},
+		{1.1, http.MethodPost, `profiles/{id}/parameters/?$`, profileparameter.PostProfileParamsByID, auth.PrivLevelOperations, Authenticated, nil},
 		{1.1, http.MethodGet, `profileparameters/?(\.json)?$`, api.ReadHandler(profileparameter.GetRefType(), d.DB), auth.PrivLevelReadOnly, Authenticated, nil},
 		{1.1, http.MethodPost, `profileparameters/?$`, api.CreateHandler(profileparameter.GetRefType(), d.DB), auth.PrivLevelOperations, Authenticated, nil},
-		{1.1, http.MethodPost, `profileparameter/?$`, profileparameter.PostProfileParam(d.DB.DB), auth.PrivLevelOperations, Authenticated, nil},
-		{1.1, http.MethodPost, `parameterprofile/?$`, profileparameter.PostParamProfile(d.DB.DB), auth.PrivLevelOperations, Authenticated, nil},
+		{1.1, http.MethodPost, `profileparameter/?$`, profileparameter.PostProfileParam, auth.PrivLevelOperations, Authenticated, nil},
+		{1.1, http.MethodPost, `parameterprofile/?$`, profileparameter.PostParamProfile, auth.PrivLevelOperations, Authenticated, nil},
 		{1.1, http.MethodDelete, `profileparameters/{profileId}/{parameterId}$`, api.DeleteHandler(profileparameter.GetRefType(), d.DB), auth.PrivLevelOperations, Authenticated, nil},
 
 		//CRConfig
diff --git a/traffic_ops/vendor/github.com/lib/pq/CONTRIBUTING.md b/vendor/github.com/lib/pq/CONTRIBUTING.md
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/CONTRIBUTING.md
rename to vendor/github.com/lib/pq/CONTRIBUTING.md
diff --git a/traffic_ops/vendor/github.com/lib/pq/LICENSE.md b/vendor/github.com/lib/pq/LICENSE.md
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/LICENSE.md
rename to vendor/github.com/lib/pq/LICENSE.md
diff --git a/traffic_ops/vendor/github.com/lib/pq/README.md b/vendor/github.com/lib/pq/README.md
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/README.md
rename to vendor/github.com/lib/pq/README.md
diff --git a/traffic_ops/vendor/github.com/lib/pq/array.go b/vendor/github.com/lib/pq/array.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/array.go
rename to vendor/github.com/lib/pq/array.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/array_test.go b/vendor/github.com/lib/pq/array_test.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/array_test.go
rename to vendor/github.com/lib/pq/array_test.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/bench_test.go b/vendor/github.com/lib/pq/bench_test.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/bench_test.go
rename to vendor/github.com/lib/pq/bench_test.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/buf.go b/vendor/github.com/lib/pq/buf.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/buf.go
rename to vendor/github.com/lib/pq/buf.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/certs/README b/vendor/github.com/lib/pq/certs/README
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/certs/README
rename to vendor/github.com/lib/pq/certs/README
diff --git a/traffic_ops/vendor/github.com/lib/pq/certs/bogus_root.crt b/vendor/github.com/lib/pq/certs/bogus_root.crt
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/certs/bogus_root.crt
rename to vendor/github.com/lib/pq/certs/bogus_root.crt
diff --git a/traffic_ops/vendor/github.com/lib/pq/certs/postgresql.crt b/vendor/github.com/lib/pq/certs/postgresql.crt
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/certs/postgresql.crt
rename to vendor/github.com/lib/pq/certs/postgresql.crt
diff --git a/traffic_ops/vendor/github.com/lib/pq/certs/postgresql.key b/vendor/github.com/lib/pq/certs/postgresql.key
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/certs/postgresql.key
rename to vendor/github.com/lib/pq/certs/postgresql.key
diff --git a/traffic_ops/vendor/github.com/lib/pq/certs/root.crt b/vendor/github.com/lib/pq/certs/root.crt
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/certs/root.crt
rename to vendor/github.com/lib/pq/certs/root.crt
diff --git a/traffic_ops/vendor/github.com/lib/pq/certs/server.crt b/vendor/github.com/lib/pq/certs/server.crt
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/certs/server.crt
rename to vendor/github.com/lib/pq/certs/server.crt
diff --git a/traffic_ops/vendor/github.com/lib/pq/certs/server.key b/vendor/github.com/lib/pq/certs/server.key
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/certs/server.key
rename to vendor/github.com/lib/pq/certs/server.key
diff --git a/traffic_ops/vendor/github.com/lib/pq/conn.go b/vendor/github.com/lib/pq/conn.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/conn.go
rename to vendor/github.com/lib/pq/conn.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/conn_go18.go b/vendor/github.com/lib/pq/conn_go18.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/conn_go18.go
rename to vendor/github.com/lib/pq/conn_go18.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/conn_test.go b/vendor/github.com/lib/pq/conn_test.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/conn_test.go
rename to vendor/github.com/lib/pq/conn_test.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/copy.go b/vendor/github.com/lib/pq/copy.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/copy.go
rename to vendor/github.com/lib/pq/copy.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/copy_test.go b/vendor/github.com/lib/pq/copy_test.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/copy_test.go
rename to vendor/github.com/lib/pq/copy_test.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/doc.go b/vendor/github.com/lib/pq/doc.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/doc.go
rename to vendor/github.com/lib/pq/doc.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/encode.go b/vendor/github.com/lib/pq/encode.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/encode.go
rename to vendor/github.com/lib/pq/encode.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/encode_test.go b/vendor/github.com/lib/pq/encode_test.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/encode_test.go
rename to vendor/github.com/lib/pq/encode_test.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/error.go b/vendor/github.com/lib/pq/error.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/error.go
rename to vendor/github.com/lib/pq/error.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/go18_test.go b/vendor/github.com/lib/pq/go18_test.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/go18_test.go
rename to vendor/github.com/lib/pq/go18_test.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/hstore/hstore.go b/vendor/github.com/lib/pq/hstore/hstore.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/hstore/hstore.go
rename to vendor/github.com/lib/pq/hstore/hstore.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/hstore/hstore_test.go b/vendor/github.com/lib/pq/hstore/hstore_test.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/hstore/hstore_test.go
rename to vendor/github.com/lib/pq/hstore/hstore_test.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/issues_test.go b/vendor/github.com/lib/pq/issues_test.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/issues_test.go
rename to vendor/github.com/lib/pq/issues_test.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/listen_example/doc.go b/vendor/github.com/lib/pq/listen_example/doc.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/listen_example/doc.go
rename to vendor/github.com/lib/pq/listen_example/doc.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/notify.go b/vendor/github.com/lib/pq/notify.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/notify.go
rename to vendor/github.com/lib/pq/notify.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/notify_test.go b/vendor/github.com/lib/pq/notify_test.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/notify_test.go
rename to vendor/github.com/lib/pq/notify_test.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/oid/doc.go b/vendor/github.com/lib/pq/oid/doc.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/oid/doc.go
rename to vendor/github.com/lib/pq/oid/doc.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/oid/gen.go b/vendor/github.com/lib/pq/oid/gen.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/oid/gen.go
rename to vendor/github.com/lib/pq/oid/gen.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/oid/types.go b/vendor/github.com/lib/pq/oid/types.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/oid/types.go
rename to vendor/github.com/lib/pq/oid/types.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/ssl.go b/vendor/github.com/lib/pq/ssl.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/ssl.go
rename to vendor/github.com/lib/pq/ssl.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/ssl_go1.7.go b/vendor/github.com/lib/pq/ssl_go1.7.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/ssl_go1.7.go
rename to vendor/github.com/lib/pq/ssl_go1.7.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/ssl_permissions.go b/vendor/github.com/lib/pq/ssl_permissions.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/ssl_permissions.go
rename to vendor/github.com/lib/pq/ssl_permissions.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/ssl_renegotiation.go b/vendor/github.com/lib/pq/ssl_renegotiation.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/ssl_renegotiation.go
rename to vendor/github.com/lib/pq/ssl_renegotiation.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/ssl_test.go b/vendor/github.com/lib/pq/ssl_test.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/ssl_test.go
rename to vendor/github.com/lib/pq/ssl_test.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/ssl_windows.go b/vendor/github.com/lib/pq/ssl_windows.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/ssl_windows.go
rename to vendor/github.com/lib/pq/ssl_windows.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/url.go b/vendor/github.com/lib/pq/url.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/url.go
rename to vendor/github.com/lib/pq/url.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/url_test.go b/vendor/github.com/lib/pq/url_test.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/url_test.go
rename to vendor/github.com/lib/pq/url_test.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/user_posix.go b/vendor/github.com/lib/pq/user_posix.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/user_posix.go
rename to vendor/github.com/lib/pq/user_posix.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/user_windows.go b/vendor/github.com/lib/pq/user_windows.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/user_windows.go
rename to vendor/github.com/lib/pq/user_windows.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/uuid.go b/vendor/github.com/lib/pq/uuid.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/uuid.go
rename to vendor/github.com/lib/pq/uuid.go
diff --git a/traffic_ops/vendor/github.com/lib/pq/uuid_test.go b/vendor/github.com/lib/pq/uuid_test.go
similarity index 100%
rename from traffic_ops/vendor/github.com/lib/pq/uuid_test.go
rename to vendor/github.com/lib/pq/uuid_test.go


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services