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/11/02 15:06:06 UTC

[GitHub] rawlinp closed pull request #2928: TO Client: no ids required in input json

rawlinp closed pull request #2928: TO Client:  no ids required in input json
URL: https://github.com/apache/trafficcontrol/pull/2928
 
 
   

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/infrastructure/cdn-in-a-box/enroller/enroller.go b/infrastructure/cdn-in-a-box/enroller/enroller.go
index f3557a1f0..3c1c4ca76 100644
--- a/infrastructure/cdn-in-a-box/enroller/enroller.go
+++ b/infrastructure/cdn-in-a-box/enroller/enroller.go
@@ -52,96 +52,6 @@ func printJSON(label string, b interface{}) {
 	fmt.Println(label, buf.String())
 }
 
-// TODO: Some GetxxxByxxx() methods escape the string passed in; others don't
-//  Here we escape the name if not escaped in the Getxxx method being called
-func (s session) getTypeIDByName(n string) (int, error) {
-	types, _, err := s.GetTypeByName(url.QueryEscape(n))
-	if err != nil {
-		return -1, err
-	}
-	if len(types) == 0 {
-		return -1, errors.New("no type with name " + n)
-	}
-	return types[0].ID, err
-}
-
-func (s session) getCoordinateIDByName(n string) (int, error) {
-	coordinates, _, err := s.GetCoordinateByName(url.QueryEscape(n))
-	if err != nil {
-		return -1, err
-	}
-	if len(coordinates) == 0 {
-		return -1, errors.New("no coordinate with name " + n)
-	}
-	return coordinates[0].ID, err
-}
-
-func (s session) getCDNIDByName(n string) (int, error) {
-	cdns, _, err := s.GetCDNByName(url.QueryEscape(n))
-	if err != nil {
-		return -1, err
-	}
-	if len(cdns) == 0 {
-		return -1, errors.New("no CDN with name " + n)
-	}
-	return cdns[0].ID, err
-}
-
-func (s session) getRegionIDByName(n string) (int, error) {
-	divisions, _, err := s.GetRegionByName(url.QueryEscape(n))
-	if err != nil {
-		return -1, err
-	}
-	if len(divisions) == 0 {
-		return -1, errors.New("no division with name " + n)
-	}
-	return divisions[0].ID, err
-}
-
-func (s session) getDivisionIDByName(n string) (int, error) {
-	divisions, _, err := s.GetDivisionByName(url.QueryEscape(n))
-	if err != nil {
-		return -1, err
-	}
-	if len(divisions) == 0 {
-		return -1, errors.New("no division with name " + n)
-	}
-	return divisions[0].ID, err
-}
-
-func (s session) getPhysLocationIDByName(n string) (int, error) {
-	physLocs, _, err := s.GetPhysLocationByName(url.QueryEscape(n))
-	if err != nil {
-		return -1, err
-	}
-	if len(physLocs) == 0 {
-		return -1, errors.New("no physLocation with name " + n)
-	}
-	return physLocs[0].ID, err
-}
-
-func (s session) getCachegroupIDByName(n string) (int, error) {
-	cgs, _, err := s.GetCacheGroupByName(url.QueryEscape(n))
-	if err != nil {
-		return -1, err
-	}
-	if len(cgs) == 0 {
-		return -1, errors.New("no cachegroups with name" + n)
-	}
-	return cgs[0].ID, err
-}
-
-func (s session) getProfileIDByName(n string) (int, error) {
-	profiles, _, err := s.GetProfileByName(n)
-	if err != nil {
-		return -1, err
-	}
-	if len(profiles) == 0 {
-		return -1, errors.New("no profile with name " + n)
-	}
-	return profiles[0].ID, err
-}
-
 func (s session) getParameterIDMatching(m tc.Parameter) (int, error) {
 	// TODO: s.GetParameterByxxx() does not seem to work with values with spaces --
 	// doing this the hard way for now
@@ -157,39 +67,6 @@ func (s session) getParameterIDMatching(m tc.Parameter) (int, error) {
 	return -1, fmt.Errorf("no parameter matching name %s, configFile %s, value %s", m.Name, m.ConfigFile, m.Value)
 }
 
-func (s session) getStatusIDByName(n string) (int, error) {
-	statuses, _, err := s.GetStatusByName(url.QueryEscape(n))
-	if err != nil {
-		return -1, err
-	}
-	if len(statuses) == 0 {
-		return -1, errors.New("no status with name " + n)
-	}
-	return statuses[0].ID, err
-}
-
-func (s session) getRoleIDByName(n string) (int, error) {
-	roles, _, _, err := s.GetRoleByName(url.QueryEscape(n))
-	if err != nil {
-		return -1, err
-	}
-	if len(roles) == 0 || roles[0].ID == nil {
-		return -1, errors.New("no role with name " + n)
-	}
-	return *roles[0].ID, err
-}
-
-func (s session) getServerIDByHostName(n string) (int, error) {
-	servers, _, err := s.GetServerByHostName(url.QueryEscape(n))
-	if err != nil {
-		return -1, err
-	}
-	if len(servers) == 0 {
-		return -1, errors.New("no server with hostName " + n)
-	}
-	return servers[0].ID, err
-}
-
 func (s session) getDeliveryServiceIDByXMLID(n string) (int, error) {
 	dses, _, err := s.GetDeliveryServiceByXMLID(url.QueryEscape(n))
 	if err != nil {
@@ -201,17 +78,6 @@ func (s session) getDeliveryServiceIDByXMLID(n string) (int, error) {
 	return dses[0].ID, err
 }
 
-func (s session) getTenantIDByName(n string) (int, error) {
-	tenant, _, err := s.TenantByName(url.QueryEscape(n))
-	if err != nil {
-		return -1, err
-	}
-	if tenant == nil {
-		return -1, errors.New("no tenant with name " + n)
-	}
-	return tenant.ID, err
-}
-
 var to struct {
 	URL      string `envconfig:"TO_URL"`
 	User     string `envconfig:"TO_USER"`
@@ -340,30 +206,6 @@ func enrollCachegroup(toSession *session, fn string) error {
 		return err
 	}
 
-	if s.Type != nil {
-		id, err := toSession.getTypeIDByName(*s.Type)
-		if err != nil {
-			return err
-		}
-		s.TypeID = &id
-	}
-
-	if s.ParentName != nil {
-		id, err := toSession.getCachegroupIDByName(*s.ParentName)
-		if err != nil {
-			return err
-		}
-		s.ParentCachegroupID = &id
-	}
-
-	if s.SecondaryParentName != nil {
-		id, err := toSession.getCachegroupIDByName(*s.SecondaryParentName)
-		if err != nil {
-			return err
-		}
-		s.SecondaryParentCachegroupID = &id
-	}
-
 	alerts, _, err := toSession.CreateCacheGroupNullable(s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
@@ -398,38 +240,6 @@ func enrollDeliveryService(toSession *session, fn string) error {
 		return err
 	}
 
-	if s.Type != nil && *s.Type != "" {
-		id, err := toSession.getTypeIDByName(s.Type.String())
-		if err != nil {
-			return err
-		}
-		s.TypeID = &id
-	}
-
-	if s.CDNName != nil && *s.CDNName != "" {
-		id, err := toSession.getCDNIDByName(*s.CDNName)
-		if err != nil {
-			return err
-		}
-		s.CDNID = &id
-	}
-
-	if s.ProfileName != nil && *s.ProfileName != "" {
-		id, err := toSession.getProfileIDByName(*s.ProfileName)
-		if err != nil {
-			return err
-		}
-		s.ProfileID = &id
-	}
-
-	if s.Tenant != nil && *s.Tenant != "" {
-		id, err := toSession.getTenantIDByName(*s.Tenant)
-		if err != nil {
-			return err
-		}
-		s.TenantID = &id
-	}
-
 	alerts, err := toSession.CreateDeliveryServiceNullable(&s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
@@ -466,19 +276,25 @@ func enrollDeliveryServiceServer(toSession *session, fn string) error {
 		return err
 	}
 
-	dsID, err := toSession.getDeliveryServiceIDByXMLID(dss.XmlId)
+	dses, _, err := toSession.GetDeliveryServiceByXMLID(dss.XmlId)
 	if err != nil {
 		return err
 	}
+	if len(dses) == 0 {
+		return errors.New("no deliveryservice with name " + dss.XmlId)
+	}
+	dsID := dses[0].ID
 
 	var serverIDs []int
 	for _, sn := range dss.ServerNames {
-		id, err := toSession.getServerIDByHostName(sn)
+		servers, _, err := toSession.GetServerByHostName(sn)
 		if err != nil {
-			log.Println("error finding " + sn + ": " + err.Error())
-			continue
+			return err
+		}
+		if len(servers) == 0 {
+			return errors.New("no server with hostName " + sn)
 		}
-		serverIDs = append(serverIDs, id)
+		serverIDs = append(serverIDs, servers[0].ID)
 	}
 	_, err = toSession.CreateDeliveryServiceServers(dsID, serverIDs, true)
 	if err != nil {
@@ -539,46 +355,6 @@ func enrollOrigin(toSession *session, fn string) error {
 		return err
 	}
 
-	if s.Cachegroup != nil && *s.Cachegroup != "" {
-		id, err := toSession.getCachegroupIDByName(*s.Cachegroup)
-		if err != nil {
-			return err
-		}
-		s.CachegroupID = &id
-	}
-
-	if s.DeliveryService != nil && *s.DeliveryService != "" {
-		id, err := toSession.getDeliveryServiceIDByXMLID(*s.DeliveryService)
-		if err != nil {
-			return err
-		}
-		s.DeliveryServiceID = &id
-	}
-
-	if s.Profile != nil && *s.Profile != "" {
-		id, err := toSession.getProfileIDByName(*s.Profile)
-		if err != nil {
-			return err
-		}
-		s.ProfileID = &id
-	}
-
-	if s.Coordinate != nil && *s.Coordinate != "" {
-		id, err := toSession.getCoordinateIDByName(*s.Coordinate)
-		if err != nil {
-			return err
-		}
-		s.CoordinateID = &id
-	}
-
-	if s.Tenant != nil && *s.Tenant != "" {
-		id, err := toSession.getTenantIDByName(*s.Tenant)
-		if err != nil {
-			return err
-		}
-		s.TenantID = &id
-	}
-
 	alerts, _, err := toSession.CreateOrigin(s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
@@ -621,6 +397,7 @@ func enrollParameter(toSession *session, fn string) error {
 			alerts, _, err = toSession.UpdateParameterByID(paramID, p)
 			if err != nil {
 				log.Printf("error updating parameter %d: %s with %+v ", paramID, err.Error(), p)
+				break
 			}
 		} else {
 			alerts, _, err = toSession.CreateParameter(p)
@@ -647,19 +424,20 @@ func enrollParameter(toSession *session, fn string) error {
 			}
 
 			for _, n := range profiles {
-				pid, err := toSession.getProfileIDByName(n)
+				profiles, _, err := toSession.GetProfileByName(n)
 				if err != nil {
-					log.Printf("%v", err)
-					continue
+					return err
+				}
+				if len(profiles) == 0 {
+					return errors.New("no profile with name " + n)
 				}
-				pp := tc.ProfileParameter{ParameterID: paramID, ProfileID: pid}
+
+				pp := tc.ProfileParameter{ParameterID: paramID, ProfileID: profiles[0].ID}
 				_, _, err = toSession.CreateProfileParameter(pp)
 				if err != nil {
 					if strings.Contains(err.Error(), "already exists") {
 						continue
 					}
-					log.Printf("%v", err)
-					continue
 				}
 			}
 		}
@@ -687,13 +465,6 @@ func enrollPhysLocation(toSession *session, fn string) error {
 		return err
 	}
 
-	if s.RegionName != "" {
-		id, err := toSession.getRegionIDByName(s.RegionName)
-		if err != nil {
-			return err
-		}
-		s.RegionID = id
-	}
 	alerts, _, err := toSession.CreatePhysLocation(s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
@@ -728,14 +499,6 @@ func enrollRegion(toSession *session, fn string) error {
 		return err
 	}
 
-	if s.DivisionName != "" {
-		id, err := toSession.getDivisionIDByName(s.DivisionName)
-		if err != nil {
-			return err
-		}
-		s.Division = id
-	}
-
 	alerts, _, err := toSession.CreateRegion(s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
@@ -804,14 +567,6 @@ func enrollTenant(toSession *session, fn string) error {
 		return err
 	}
 
-	if s.ParentName != "" {
-		id, err := toSession.getTenantIDByName(s.ParentName)
-		if err != nil {
-			return err
-		}
-		s.ParentID = id
-	}
-
 	alerts, err := toSession.CreateTenant(&s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
@@ -847,22 +602,6 @@ func enrollUser(toSession *session, fn string) error {
 		return err
 	}
 
-	if s.Tenant != nil && *s.Tenant != "" {
-		id, err := toSession.getTenantIDByName(*s.Tenant)
-		if err != nil {
-			return err
-		}
-		s.TenantID = &id
-	}
-
-	if s.RoleName != nil && *s.RoleName != "" {
-		id, err := toSession.getRoleIDByName(*s.RoleName)
-		if err != nil {
-			return err
-		}
-		s.Role = &id
-	}
-
 	alerts, _, err := toSession.CreateUser(&s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
@@ -925,15 +664,6 @@ func enrollProfile(toSession *session, fn string) error {
 		profile.ID = profiles[0].ID
 	}
 
-	// these need to be done whether creating or updating
-	if profile.CDNName != "" {
-		id, err := toSession.getCDNIDByName(profile.CDNName)
-		if err != nil {
-			return err
-		}
-		profile.CDNID = id
-	}
-
 	var alerts tc.Alerts
 	var action string
 	if createProfile {
@@ -945,10 +675,11 @@ func enrollProfile(toSession *session, fn string) error {
 				log.Printf("error creating profile from %+v: %s\n", profile, err.Error())
 			}
 		}
-		profile.ID, err = toSession.getProfileIDByName(profile.Name)
-		if err != nil {
+		profiles, _, err = toSession.GetProfileByName(profile.Name)
+		if err != nil || len(profiles) == 0 {
 			log.Printf("error getting profile ID from %+v: %s\n", profile, err.Error())
 		}
+		profile.ID = profiles[0].ID
 		action = "creating"
 	} else {
 		alerts, _, err = toSession.UpdateProfileByID(profile.ID, profile)
@@ -1036,51 +767,6 @@ func enrollServer(toSession *session, fn string) error {
 		return err
 	}
 
-	if s.Type != "" {
-		id, err := toSession.getTypeIDByName(s.Type)
-		if err != nil {
-			return err
-		}
-		s.TypeID = id
-	}
-
-	if s.Profile != "" {
-		id, err := toSession.getProfileIDByName(s.Profile)
-		if err != nil {
-			return err
-		}
-		s.ProfileID = id
-	}
-
-	if s.Status != "" {
-		id, err := toSession.getStatusIDByName(s.Status)
-		if err != nil {
-			return err
-		}
-		s.StatusID = id
-	}
-	if s.CDNName != "" {
-		id, err := toSession.getCDNIDByName(s.CDNName)
-		if err != nil {
-			return err
-		}
-		s.CDNID = id
-	}
-	if s.Cachegroup != "" {
-		id, err := toSession.getCachegroupIDByName(s.Cachegroup)
-		if err != nil {
-			return err
-		}
-		s.CachegroupID = id
-	}
-	if s.PhysLocation != "" {
-		id, err := toSession.getPhysLocationIDByName(s.PhysLocation)
-		if err != nil {
-			return err
-		}
-		s.PhysLocationID = id
-	}
-
 	alerts, _, err := toSession.CreateServer(s)
 	if err != nil {
 		log.Printf("error creating from %s: %s\n", fn, err)
diff --git a/traffic_ops/client/cachegroup.go b/traffic_ops/client/cachegroup.go
index bc3792688..e0dd5adf5 100644
--- a/traffic_ops/client/cachegroup.go
+++ b/traffic_ops/client/cachegroup.go
@@ -17,6 +17,7 @@ package client
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net"
 	"net/http"
@@ -30,14 +31,45 @@ const (
 
 // Create a CacheGroup
 func (to *Session) CreateCacheGroupNullable(cachegroup tc.CacheGroupNullable) (*tc.CacheGroupDetailResponse, ReqInf, error) {
+	if cachegroup.TypeID == nil && cachegroup.Type != nil {
+		ty, _, err := to.GetTypeByName(*cachegroup.Type)
+		if err != nil {
+			return nil, ReqInf{}, err
+		}
+		if len(ty) == 0 {
+			return nil, ReqInf{}, errors.New("no type named " + *cachegroup.Type)
+		}
+		cachegroup.TypeID = &ty[0].ID
+	}
+
+	if cachegroup.ParentCachegroupID == nil && cachegroup.ParentName != nil {
+		p, _, err := to.GetCacheGroupByName(*cachegroup.ParentName)
+		if err != nil {
+			return nil, ReqInf{}, err
+		}
+		if len(p) == 0 {
+			return nil, ReqInf{}, errors.New("no cachegroup named " + *cachegroup.ParentName)
+		}
+		cachegroup.ParentCachegroupID = &p[0].ID
+	}
+
+	if cachegroup.SecondaryParentCachegroupID == nil && cachegroup.SecondaryParentName != nil {
+		p, _, err := to.GetCacheGroupByName(*cachegroup.SecondaryParentName)
+		if err != nil {
+			return nil, ReqInf{}, err
+		}
+		if len(p) == 0 {
+			return nil, ReqInf{}, errors.New("no cachegroup named " + *cachegroup.ParentName)
+		}
+		cachegroup.SecondaryParentCachegroupID = &p[0].ID
+	}
 
-	var remoteAddr net.Addr
 	reqBody, err := json.Marshal(cachegroup)
-	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
 	if err != nil {
-		return nil, reqInf, err
+		return nil, ReqInf{}, err
 	}
 	resp, remoteAddr, err := to.request(http.MethodPost, API_v13_CacheGroups, reqBody)
+	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
 	if err != nil {
 		return nil, reqInf, err
 	}
@@ -52,14 +84,45 @@ func (to *Session) CreateCacheGroupNullable(cachegroup tc.CacheGroupNullable) (*
 // Create a CacheGroup
 // Deprecated: Use CreateCacheGroupNullable
 func (to *Session) CreateCacheGroup(cachegroup tc.CacheGroup) (tc.Alerts, ReqInf, error) {
+	if cachegroup.TypeID == 0 && cachegroup.Type != "" {
+		ty, _, err := to.GetTypeByName(cachegroup.Type)
+		if err != nil {
+			return tc.Alerts{}, ReqInf{}, err
+		}
+		if len(ty) == 0 {
+			return tc.Alerts{}, ReqInf{}, errors.New("no type named " + cachegroup.Type)
+		}
+		cachegroup.TypeID = ty[0].ID
+	}
+
+	if cachegroup.ParentCachegroupID == 0 && cachegroup.ParentName != "" {
+		p, _, err := to.GetCacheGroupByName(cachegroup.ParentName)
+		if err != nil {
+			return tc.Alerts{}, ReqInf{}, err
+		}
+		if len(p) == 0 {
+			return tc.Alerts{}, ReqInf{}, errors.New("no cachegroup named " + cachegroup.ParentName)
+		}
+		cachegroup.ParentCachegroupID = p[0].ID
+	}
+
+	if cachegroup.SecondaryParentCachegroupID == 0 && cachegroup.SecondaryParentName != "" {
+		p, _, err := to.GetCacheGroupByName(cachegroup.SecondaryParentName)
+		if err != nil {
+			return tc.Alerts{}, ReqInf{}, err
+		}
+		if len(p) == 0 {
+			return tc.Alerts{}, ReqInf{}, errors.New("no cachegroup named " + cachegroup.ParentName)
+		}
+		cachegroup.SecondaryParentCachegroupID = p[0].ID
+	}
 
-	var remoteAddr net.Addr
 	reqBody, err := json.Marshal(cachegroup)
-	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
 	if err != nil {
-		return tc.Alerts{}, reqInf, err
+		return tc.Alerts{}, ReqInf{}, err
 	}
 	resp, remoteAddr, err := to.request(http.MethodPost, API_v13_CacheGroups, reqBody)
+	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
 	if err != nil {
 		return tc.Alerts{}, reqInf, err
 	}
diff --git a/traffic_ops/client/deliveryservice.go b/traffic_ops/client/deliveryservice.go
index 231384f1b..0b63bafdc 100644
--- a/traffic_ops/client/deliveryservice.go
+++ b/traffic_ops/client/deliveryservice.go
@@ -17,6 +17,7 @@ package client
 
 import (
 	"encoding/json"
+	"errors"
 	"strconv"
 
 	"github.com/apache/trafficcontrol/lib/go-tc"
@@ -48,6 +49,7 @@ func (to *Session) DeliveryServicesByServer(id int) ([]tc.DeliveryService, error
 
 func (to *Session) GetDeliveryServicesByServer(id int) ([]tc.DeliveryService, ReqInf, error) {
 	var data tc.DeliveryServicesResponse
+
 	reqInf, err := get(to, deliveryServicesByServerEp(strconv.Itoa(id)), &data)
 	if err != nil {
 		return nil, reqInf, err
@@ -112,6 +114,47 @@ func (to *Session) GetDeliveryServiceNullable(id string) (*tc.DeliveryServiceNul
 
 // CreateDeliveryService creates the DeliveryService it's passed
 func (to *Session) CreateDeliveryService(ds *tc.DeliveryService) (*tc.CreateDeliveryServiceResponse, error) {
+	if ds.TypeID == 0 && ds.Type.String() != "" {
+		ty, _, err := to.GetTypeByName(ds.Type.String())
+		if err != nil {
+			return nil, err
+		}
+		if len(ty) == 0 {
+			return nil, errors.New("no type named " + ds.Type.String())
+		}
+		ds.TypeID = ty[0].ID
+	}
+
+	if ds.CDNID == 0 && ds.CDNName != "" {
+		cdns, _, err := to.GetCDNByName(ds.CDNName)
+		if err != nil {
+			return nil, err
+		}
+		if len(cdns) == 0 {
+			return nil, errors.New("no CDN named " + ds.CDNName)
+		}
+		ds.CDNID = cdns[0].ID
+	}
+
+	if ds.ProfileID == 0 && ds.ProfileName != "" {
+		profiles, _, err := to.GetProfileByName(ds.ProfileName)
+		if err != nil {
+			return nil, err
+		}
+		if len(profiles) == 0 {
+			return nil, errors.New("no Profile named " + ds.ProfileName)
+		}
+		ds.ProfileID = profiles[0].ID
+	}
+
+	if ds.TenantID == 0 && ds.Tenant != "" {
+		ten, _, err := to.TenantByName(ds.Tenant)
+		if err != nil {
+			return nil, err
+		}
+		ds.TenantID = ten.ID
+	}
+
 	var data tc.CreateDeliveryServiceResponse
 	jsonReq, err := json.Marshal(ds)
 	if err != nil {
@@ -125,8 +168,49 @@ func (to *Session) CreateDeliveryService(ds *tc.DeliveryService) (*tc.CreateDeli
 	return &data, nil
 }
 
-// CreateDeliveryService creates the DeliveryService it's passed
+// CreateDeliveryServiceNullable creates the DeliveryService it's passed
 func (to *Session) CreateDeliveryServiceNullable(ds *tc.DeliveryServiceNullable) (*tc.CreateDeliveryServiceNullableResponse, error) {
+	if ds.TypeID == nil && ds.Type != nil {
+		ty, _, err := to.GetTypeByName(ds.Type.String())
+		if err != nil {
+			return nil, err
+		}
+		if len(ty) == 0 {
+			return nil, errors.New("no type named " + ds.Type.String())
+		}
+		ds.TypeID = &ty[0].ID
+	}
+
+	if ds.CDNID == nil && ds.CDNName != nil {
+		cdns, _, err := to.GetCDNByName(*ds.CDNName)
+		if err != nil {
+			return nil, err
+		}
+		if len(cdns) == 0 {
+			return nil, errors.New("no CDN named " + *ds.CDNName)
+		}
+		ds.CDNID = &cdns[0].ID
+	}
+
+	if ds.ProfileID == nil && ds.ProfileName != nil {
+		profiles, _, err := to.GetProfileByName(*ds.ProfileName)
+		if err != nil {
+			return nil, err
+		}
+		if len(profiles) == 0 {
+			return nil, errors.New("no Profile named " + *ds.ProfileName)
+		}
+		ds.ProfileID = &profiles[0].ID
+	}
+
+	if ds.TenantID == nil && ds.Tenant != nil {
+		ten, _, err := to.TenantByName(*ds.Tenant)
+		if err != nil {
+			return nil, err
+		}
+		ds.TenantID = &ten.ID
+	}
+
 	var data tc.CreateDeliveryServiceNullableResponse
 	jsonReq, err := json.Marshal(ds)
 	if err != nil {
diff --git a/traffic_ops/client/deliveryservice_endpoints.go b/traffic_ops/client/deliveryservice_endpoints.go
index 32eb1d729..a9313f47e 100644
--- a/traffic_ops/client/deliveryservice_endpoints.go
+++ b/traffic_ops/client/deliveryservice_endpoints.go
@@ -22,7 +22,7 @@ func deliveryServicesEp() string {
 }
 
 func deliveryServicesByServerEp(id string) string {
-	return apiBase + "/servers/" + id + dsPath + ".json"
+	return apiBase + "/servers/" + id + dsPath
 }
 
 func deliveryServiceBaseEp(id string) string {
diff --git a/traffic_ops/client/deliveryservice_requests.go b/traffic_ops/client/deliveryservice_requests.go
index e8d543b41..e01182da9 100644
--- a/traffic_ops/client/deliveryservice_requests.go
+++ b/traffic_ops/client/deliveryservice_requests.go
@@ -17,6 +17,7 @@ package client
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"io/ioutil"
 	"net"
@@ -31,9 +32,62 @@ const (
 
 // Create a Delivery Service Request
 func (to *Session) CreateDeliveryServiceRequest(dsr tc.DeliveryServiceRequest) (tc.Alerts, ReqInf, error) {
-
 	var alerts tc.Alerts
 	var remoteAddr net.Addr
+	if dsr.AssigneeID == 0 && dsr.Assignee != "" {
+		res, reqInf, err := to.GetUserByUsername(dsr.Assignee)
+		if err != nil {
+			return alerts, reqInf, err
+		}
+		if len(res) == 0 {
+			return alerts, reqInf, errors.New("no user with name " + dsr.Assignee)
+		}
+		dsr.AssigneeID = *res[0].ID
+	}
+
+	if dsr.AuthorID == 0 && dsr.Author != "" {
+		res, reqInf, err := to.GetUserByUsername(dsr.Author)
+		if err != nil {
+			return alerts, reqInf, err
+		}
+		if len(res) == 0 {
+			return alerts, reqInf, errors.New("no user with name " + dsr.Author)
+		}
+		dsr.AuthorID = tc.IDNoMod(*res[0].ID)
+	}
+
+	if dsr.DeliveryService.TypeID == 0 && dsr.DeliveryService.Type.String() != "" {
+		ty, reqInf, err := to.GetTypeByName(dsr.DeliveryService.Type.String())
+		if err != nil || len(ty) == 0 {
+			return alerts, reqInf, errors.New("no type named " + dsr.DeliveryService.Type.String())
+		}
+		dsr.DeliveryService.TypeID = ty[0].ID
+	}
+
+	if dsr.DeliveryService.CDNID == 0 && dsr.DeliveryService.CDNName != "" {
+		cdns, reqInf, err := to.GetCDNByName(dsr.DeliveryService.CDNName)
+		if err != nil || len(cdns) == 0 {
+			return alerts, reqInf, errors.New("no CDN named " + dsr.DeliveryService.CDNName)
+		}
+		dsr.DeliveryService.CDNID = cdns[0].ID
+	}
+
+	if dsr.DeliveryService.ProfileID == 0 && dsr.DeliveryService.ProfileName != "" {
+		profiles, reqInf, err := to.GetProfileByName(dsr.DeliveryService.ProfileName)
+		if err != nil || len(profiles) == 0 {
+			return alerts, reqInf, errors.New("no Profile named " + dsr.DeliveryService.ProfileName)
+		}
+		dsr.DeliveryService.ProfileID = profiles[0].ID
+	}
+
+	if dsr.DeliveryService.TenantID == 0 && dsr.DeliveryService.Tenant != "" {
+		ten, reqInf, err := to.TenantByName(dsr.DeliveryService.Tenant)
+		if err != nil || ten == nil {
+			return alerts, reqInf, errors.New("no Tenant named " + dsr.DeliveryService.Tenant)
+		}
+		dsr.DeliveryService.TenantID = ten.ID
+	}
+
 	reqBody, err := json.Marshal(dsr)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
 	if err != nil {
diff --git a/traffic_ops/client/origin.go b/traffic_ops/client/origin.go
index d76ab5cc3..9e89d66de 100644
--- a/traffic_ops/client/origin.go
+++ b/traffic_ops/client/origin.go
@@ -17,6 +17,7 @@ package client
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net"
 	"net/http"
@@ -28,12 +29,73 @@ const (
 	API_v13_Origins = "/api/1.3/origins"
 )
 
+func originIDs(to *Session, origin *tc.Origin) error {
+	if origin.CachegroupID == nil && origin.Cachegroup != nil {
+		p, _, err := to.GetCacheGroupByName(*origin.Cachegroup)
+		if err != nil {
+			return err
+		}
+		if len(p) == 0 {
+			return errors.New("no cachegroup named " + *origin.Cachegroup)
+		}
+		origin.CachegroupID = &p[0].ID
+	}
+
+	if origin.DeliveryServiceID == nil && origin.DeliveryService != nil {
+		dses, _, err := to.GetDeliveryServiceByXMLID(*origin.DeliveryService)
+		if err != nil {
+			return err
+		}
+		if len(dses) == 0 {
+			return errors.New("no deliveryservice with name " + *origin.DeliveryService)
+		}
+		origin.DeliveryServiceID = &dses[0].ID
+	}
+
+	if origin.ProfileID == nil && origin.Profile != nil {
+		profiles, _, err := to.GetProfileByName(*origin.Profile)
+		if err != nil {
+			return err
+		}
+		if len(profiles) == 0 {
+			return errors.New("no profile with name " + *origin.Profile)
+		}
+		origin.ProfileID = &profiles[0].ID
+	}
+
+	if origin.CoordinateID == nil && origin.Coordinate != nil {
+		coordinates, _, err := to.GetCoordinateByName(*origin.Coordinate)
+		if err != nil {
+			return err
+		}
+		if len(coordinates) == 0 {
+			return errors.New("no coordinate with name " + *origin.Coordinate)
+		}
+		origin.CoordinateID = &coordinates[0].ID
+	}
+
+	if origin.TenantID == nil && origin.Tenant != nil {
+		tenant, _, err := to.TenantByName(*origin.Tenant)
+		if err != nil {
+			return err
+		}
+		origin.TenantID = &tenant.ID
+	}
+
+	return nil
+}
+
 // Create an Origin
 func (to *Session) CreateOrigin(origin tc.Origin) (*tc.OriginDetailResponse, ReqInf, error) {
-
 	var remoteAddr net.Addr
-	reqBody, err := json.Marshal(origin)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
+
+	err := originIDs(to, &origin)
+	if err != nil {
+		return nil, reqInf, err
+	}
+
+	reqBody, err := json.Marshal(origin)
 	if err != nil {
 		return nil, reqInf, err
 	}
@@ -51,10 +113,15 @@ func (to *Session) CreateOrigin(origin tc.Origin) (*tc.OriginDetailResponse, Req
 
 // Update an Origin by ID
 func (to *Session) UpdateOriginByID(id int, origin tc.Origin) (*tc.OriginDetailResponse, ReqInf, error) {
-
 	var remoteAddr net.Addr
-	reqBody, err := json.Marshal(origin)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
+
+	err := originIDs(to, &origin)
+	if err != nil {
+		return nil, reqInf, err
+	}
+
+	reqBody, err := json.Marshal(origin)
 	if err != nil {
 		return nil, reqInf, err
 	}
diff --git a/traffic_ops/client/parameter.go b/traffic_ops/client/parameter.go
index f5706cd55..e8a5eca3f 100644
--- a/traffic_ops/client/parameter.go
+++ b/traffic_ops/client/parameter.go
@@ -178,6 +178,22 @@ func (to *Session) GetParameterByNameAndConfigFile(name string, configFile strin
 	return data.Response, reqInf, nil
 }
 
+// GET a Parameter by the Parameter Name and ConfigFile and Value
+// TODO: API should support all 3,  but does not support filter by value
+// currently.  Until then, loop thru hits until you find one with that value
+func (to *Session) GetParameterByNameAndConfigFileAndValue(name, configFile, value string) ([]tc.Parameter, ReqInf, error) {
+	params, reqInf, err := to.GetParameterByNameAndConfigFile(name, configFile)
+	if err != nil {
+		return params, reqInf, err
+	}
+	for _, p := range params {
+		if p.Value == value {
+			return []tc.Parameter{p}, reqInf, err
+		}
+	}
+	return nil, reqInf, err
+}
+
 // DELETE a Parameter by ID
 func (to *Session) DeleteParameterByID(id int) (tc.Alerts, ReqInf, error) {
 	URI := fmt.Sprintf("%s/%d", API_v13_Parameters, id)
diff --git a/traffic_ops/client/phys_location.go b/traffic_ops/client/phys_location.go
index b1f3f11b8..baa326f76 100644
--- a/traffic_ops/client/phys_location.go
+++ b/traffic_ops/client/phys_location.go
@@ -17,6 +17,7 @@ package client
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net"
 	"net/http"
@@ -30,7 +31,16 @@ const (
 
 // Create a PhysLocation
 func (to *Session) CreatePhysLocation(pl tc.PhysLocation) (tc.Alerts, ReqInf, error) {
-
+	if pl.RegionID == 0 && pl.RegionName != "" {
+		regions, _, err := to.GetRegionByName(pl.RegionName)
+		if err != nil {
+			return tc.Alerts{}, ReqInf{}, err
+		}
+		if len(regions) == 0 {
+			return tc.Alerts{}, ReqInf{}, errors.New("no region with name " + pl.RegionName)
+		}
+		pl.RegionID = regions[0].ID
+	}
 	var remoteAddr net.Addr
 	reqBody, err := json.Marshal(pl)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
diff --git a/traffic_ops/client/profile.go b/traffic_ops/client/profile.go
index 5d8379818..258581ce6 100644
--- a/traffic_ops/client/profile.go
+++ b/traffic_ops/client/profile.go
@@ -17,6 +17,7 @@ package client
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net"
 	"net/http"
@@ -32,7 +33,16 @@ const (
 
 // Create a Profile
 func (to *Session) CreateProfile(pl tc.Profile) (tc.Alerts, ReqInf, error) {
-
+	if pl.CDNID == 0 && pl.CDNName != "" {
+		cdns, _, err := to.GetCDNByName(pl.CDNName)
+		if err != nil {
+			return tc.Alerts{}, ReqInf{}, err
+		}
+		if len(cdns) == 0 {
+			return tc.Alerts{[]tc.Alert{tc.Alert{"no CDN with name " + pl.CDNName, "error"}}}, ReqInf{}, errors.New("no CDN with name " + pl.CDNName)
+		}
+		pl.CDNID = cdns[0].ID
+	}
 	var remoteAddr net.Addr
 	reqBody, err := json.Marshal(pl)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
diff --git a/traffic_ops/client/profile_parameter.go b/traffic_ops/client/profile_parameter.go
index 69cda7834..667cfd3b2 100644
--- a/traffic_ops/client/profile_parameter.go
+++ b/traffic_ops/client/profile_parameter.go
@@ -83,7 +83,7 @@ func (to *Session) GetProfileParameterByQueryParams(queryParams string) ([]tc.Pr
 
 // DELETE a Parameter by Parameter
 func (to *Session) DeleteParameterByProfileParameter(profile int, parameter int) (tc.Alerts, ReqInf, error) {
-	URI := fmt.Sprintf("%s/profile/%d/parameter/%d", API_v13_Profile_Parameters, profile, parameter)
+	URI := fmt.Sprintf("%s/%d/%d", API_v13_Profile_Parameters, profile, parameter)
 	resp, remoteAddr, err := to.request(http.MethodDelete, URI, nil)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
 	if err != nil {
diff --git a/traffic_ops/client/region.go b/traffic_ops/client/region.go
index 74d04a36c..5eb4df8b8 100644
--- a/traffic_ops/client/region.go
+++ b/traffic_ops/client/region.go
@@ -17,6 +17,7 @@ package client
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net"
 	"net/http"
@@ -30,6 +31,16 @@ const (
 
 // Create a Region
 func (to *Session) CreateRegion(region tc.Region) (tc.Alerts, ReqInf, error) {
+	if region.Division == 0 && region.DivisionName != "" {
+		divisions, _, err := to.GetDivisionByName(region.DivisionName)
+		if err != nil {
+			return tc.Alerts{}, ReqInf{}, err
+		}
+		if len(divisions) == 0 {
+			return tc.Alerts{}, ReqInf{}, errors.New("no division with name " + region.DivisionName)
+		}
+		region.Division = divisions[0].ID
+	}
 
 	var remoteAddr net.Addr
 	reqBody, err := json.Marshal(region)
diff --git a/traffic_ops/client/server.go b/traffic_ops/client/server.go
index 0e6f9b505..c3ddcd50c 100644
--- a/traffic_ops/client/server.go
+++ b/traffic_ops/client/server.go
@@ -35,11 +35,73 @@ const (
 func (to *Session) CreateServer(server tc.Server) (tc.Alerts, ReqInf, error) {
 
 	var remoteAddr net.Addr
-	reqBody, err := json.Marshal(server)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
+
+	if server.CachegroupID == 0 && server.Cachegroup != "" {
+		cg, _, err := to.GetCacheGroupByName(server.Cachegroup)
+		if err != nil {
+			return tc.Alerts{}, ReqInf{}, errors.New("no cachegroup named " + server.Cachegroup + ":" + err.Error())
+		}
+		if len(cg) == 0 {
+			return tc.Alerts{}, ReqInf{}, errors.New("no cachegroup named " + server.Cachegroup)
+		}
+		server.CachegroupID = cg[0].ID
+	}
+	if server.CDNID == 0 && server.CDNName != "" {
+		c, _, err := to.GetCDNByName(server.CDNName)
+		if err != nil {
+			return tc.Alerts{}, ReqInf{}, errors.New("no CDN named " + server.CDNName + ":" + err.Error())
+		}
+		if len(c) == 0 {
+			return tc.Alerts{}, ReqInf{}, errors.New("no CDN named " + server.CDNName)
+		}
+		server.CDNID = c[0].ID
+	}
+	if server.PhysLocationID == 0 && server.PhysLocation != "" {
+		ph, _, err := to.GetPhysLocationByName(server.PhysLocation)
+		if err != nil {
+			return tc.Alerts{}, ReqInf{}, errors.New("no physlocation named " + server.PhysLocation + ":" + err.Error())
+		}
+		if len(ph) == 0 {
+			return tc.Alerts{}, ReqInf{}, errors.New("no physlocation named " + server.PhysLocation)
+		}
+		server.PhysLocationID = ph[0].ID
+	}
+	if server.ProfileID == 0 && server.Profile != "" {
+		pr, _, err := to.GetProfileByName(server.Profile)
+		if err != nil {
+			return tc.Alerts{}, ReqInf{}, errors.New("no profile named " + server.Profile + ":" + err.Error())
+		}
+		if len(pr) == 0 {
+			return tc.Alerts{}, ReqInf{}, errors.New("no profile named " + server.Profile)
+		}
+		server.ProfileID = pr[0].ID
+	}
+	if server.StatusID == 0 && server.Status != "" {
+		st, _, err := to.GetStatusByName(server.Status)
+		if err != nil {
+			return tc.Alerts{}, ReqInf{}, errors.New("no status named " + server.Status + ":" + err.Error())
+		}
+		if len(st) == 0 {
+			return tc.Alerts{}, ReqInf{}, errors.New("no status named " + server.Status)
+		}
+		server.StatusID = st[0].ID
+	}
+	if server.TypeID == 0 && server.Type != "" {
+		ty, _, err := to.GetTypeByName(server.Type)
+		if err != nil {
+			return tc.Alerts{}, ReqInf{}, errors.New("no type named " + server.Type + ":" + err.Error())
+		}
+		if len(ty) == 0 {
+			return tc.Alerts{}, ReqInf{}, errors.New("no type named " + server.Type)
+		}
+		server.TypeID = ty[0].ID
+	}
+	reqBody, err := json.Marshal(server)
 	if err != nil {
 		return tc.Alerts{}, reqInf, err
 	}
+
 	resp, remoteAddr, err := to.request(http.MethodPost, API_v13_Servers, reqBody)
 	if err != nil {
 		return tc.Alerts{}, reqInf, err
diff --git a/traffic_ops/client/staticdnsentry.go b/traffic_ops/client/staticdnsentry.go
index 0479160f7..3d6e2738c 100644
--- a/traffic_ops/client/staticdnsentry.go
+++ b/traffic_ops/client/staticdnsentry.go
@@ -17,6 +17,7 @@ package client
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net"
 	"net/http"
@@ -28,11 +29,49 @@ const (
 	API_v13_StaticDNSEntries = "/api/1.3/staticdnsentries"
 )
 
-// Create a StaticDNSEntry
-func (to *Session) CreateStaticDNSEntry(cdn tc.StaticDNSEntry) (tc.Alerts, ReqInf, error) {
+func staticDNSEntryIDs(to *Session, sdns *tc.StaticDNSEntry) error {
+	if sdns.CacheGroupID == 0 && sdns.CacheGroupName != "" {
+		p, _, err := to.GetCacheGroupByName(sdns.CacheGroupName)
+		if err != nil {
+			return err
+		}
+		if len(p) == 0 {
+			return errors.New("no CacheGroup named " + sdns.CacheGroupName)
+		}
+		sdns.CacheGroupID = p[0].ID
+	}
+
+	if sdns.DeliveryServiceID == 0 && sdns.DeliveryService != "" {
+		dses, _, err := to.GetDeliveryServiceByXMLID(sdns.DeliveryService)
+		if err != nil {
+			return err
+		}
+		if len(dses) == 0 {
+			return errors.New("no deliveryservice with name " + sdns.DeliveryService)
+		}
+		sdns.DeliveryServiceID = dses[0].ID
+	}
 
+	if sdns.TypeID == 0 && sdns.Type != "" {
+		types, _, err := to.GetTypeByName(sdns.Type)
+		if err != nil {
+			return err
+		}
+		if len(types) == 0 {
+			return errors.New("no type with name " + sdns.Type)
+		}
+		sdns.TypeID = types[0].ID
+	}
+
+	return nil
+}
+
+// Create a StaticDNSEntry
+func (to *Session) CreateStaticDNSEntry(sdns tc.StaticDNSEntry) (tc.Alerts, ReqInf, error) {
+	// fill in missing IDs from names
+	staticDNSEntryIDs(to, &sdns)
 	var remoteAddr net.Addr
-	reqBody, err := json.Marshal(cdn)
+	reqBody, err := json.Marshal(sdns)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
 	if err != nil {
 		return tc.Alerts{}, reqInf, err
@@ -48,10 +87,11 @@ func (to *Session) CreateStaticDNSEntry(cdn tc.StaticDNSEntry) (tc.Alerts, ReqIn
 }
 
 // Update a StaticDNSEntry by ID
-func (to *Session) UpdateStaticDNSEntryByID(id int, cdn tc.StaticDNSEntry) (tc.Alerts, ReqInf, int, error) {
-
+func (to *Session) UpdateStaticDNSEntryByID(id int, sdns tc.StaticDNSEntry) (tc.Alerts, ReqInf, int, error) {
+	// fill in missing IDs from names
+	staticDNSEntryIDs(to, &sdns)
 	var remoteAddr net.Addr
-	reqBody, err := json.Marshal(cdn)
+	reqBody, err := json.Marshal(sdns)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
 	if err != nil {
 		return tc.Alerts{}, reqInf, 0, err
diff --git a/traffic_ops/client/tenant.go b/traffic_ops/client/tenant.go
index 23552ce93..29230b6b7 100644
--- a/traffic_ops/client/tenant.go
+++ b/traffic_ops/client/tenant.go
@@ -65,6 +65,17 @@ func (to *Session) TenantByName(name string) (*tc.Tenant, ReqInf, error) {
 
 // CreateTenant creates the Tenant it's passed
 func (to *Session) CreateTenant(t *tc.Tenant) (*tc.TenantResponse, error) {
+	if t.ParentID == 0 && t.ParentName != "" {
+		tenant, _, err := to.TenantByName(t.ParentName)
+		if err != nil {
+			return nil, err
+		}
+		if tenant == nil {
+			return nil, errors.New("no tenant with name " + t.ParentName)
+		}
+		t.ParentID = tenant.ID
+	}
+
 	var data tc.TenantResponse
 	jsonReq, err := json.Marshal(t)
 	if err != nil {
diff --git a/traffic_ops/client/user.go b/traffic_ops/client/user.go
index f248a3caf..93f4de327 100644
--- a/traffic_ops/client/user.go
+++ b/traffic_ops/client/user.go
@@ -17,6 +17,7 @@ package client
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net"
 	"net/http"
@@ -77,6 +78,34 @@ func (to *Session) GetUserCurrent() (*tc.UserCurrent, ReqInf, error) {
 
 // CreateUser creates a user
 func (to *Session) CreateUser(user *tc.User) (*tc.CreateUserResponse, ReqInf, error) {
+	if user.TenantID == nil && user.Tenant != nil {
+		tenant, _, err := to.TenantByName(*user.Tenant)
+		if err != nil {
+			return nil, ReqInf{}, err
+		}
+		if tenant == nil {
+			return nil, ReqInf{}, errors.New("no tenant with name " + *user.Tenant)
+		}
+		if err != nil {
+			return nil, ReqInf{}, err
+		}
+		user.TenantID = &tenant.ID
+	}
+
+	if user.RoleName != nil && *user.RoleName != "" {
+		roles, _, _, err := to.GetRoleByName(*user.RoleName)
+		if err != nil {
+			return nil, ReqInf{}, err
+		}
+		if len(roles) == 0 || roles[0].ID == nil {
+			return nil, ReqInf{}, errors.New("no role with name " + *user.RoleName)
+		}
+		if err != nil {
+			return nil, ReqInf{}, err
+		}
+		user.Role = roles[0].ID
+	}
+
 	var remoteAddr net.Addr
 	reqBody, err := json.Marshal(user)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
diff --git a/traffic_ops/testing/api/config/config.go b/traffic_ops/testing/api/config/config.go
index 5154edd31..e5281625e 100644
--- a/traffic_ops/testing/api/config/config.go
+++ b/traffic_ops/testing/api/config/config.go
@@ -42,7 +42,7 @@ type TrafficOps struct {
 	// UserPassword - The Traffic Ops test user password hitting the API
 	UserPassword string `json:"password" envconfig:"TO_USER_PASSWORD"`
 
-	// UserPassword - The Traffic Ops Users
+	// User - The Traffic Ops Users
 	Users Users `json:"users"`
 
 	// Insecure - ignores insecure ssls certs that were self-generated
diff --git a/traffic_ops/testing/api/v14/cachegroups_test.go b/traffic_ops/testing/api/v14/cachegroups_test.go
index eb7a664db..61b27c39c 100644
--- a/traffic_ops/testing/api/v14/cachegroups_test.go
+++ b/traffic_ops/testing/api/v14/cachegroups_test.go
@@ -39,37 +39,7 @@ func CreateTestCacheGroups(t *testing.T) {
 	failed := false
 
 	for _, cg := range testData.CacheGroups {
-		// get the typeID
-		typeResp, _, err := TOSession.GetTypeByName(*cg.Type)
-		if err != nil {
-			t.Error("could not lookup a typeID for this cachegroup")
-			failed = true
-		}
-		cg.TypeID = &typeResp[0].ID
-
-		if cg.ParentName != nil && *cg.ParentName != "" {
-			// get parent cachegroup ID (must already be created)
-			resp, _, err := TOSession.GetCacheGroupNullableByName(*cg.ParentName)
-			if err != nil {
-				t.Errorf("cannot GET CacheGroup by name: %v - %v\n", err, resp)
-				failed = true
-			}
-			cg.ParentCachegroupID = resp[0].ID
-			cg.ParentName = nil // to guarantee that parent IDs aren't looked up by name
-		}
-
-		if cg.SecondaryParentName != nil && *cg.SecondaryParentName != "" {
-			// get secondary parent cachegroup ID (must already be created)
-			resp, _, err := TOSession.GetCacheGroupNullableByName(*cg.SecondaryParentName)
-			if err != nil {
-				t.Errorf("cannot GET CacheGroup by name: %v - %v\n", err, resp)
-				failed = true
-			}
-			cg.SecondaryParentCachegroupID = resp[0].ID
-			cg.SecondaryParentName = nil // to guarantee that parent IDs aren't looked up by name
-		}
-
-		_, _, err = TOSession.CreateCacheGroupNullable(cg)
+		_, _, err := TOSession.CreateCacheGroupNullable(cg)
 		if err != nil {
 			t.Errorf("could not CREATE cachegroups: %v, request: %v\n", err, cg)
 			failed = true
@@ -288,7 +258,7 @@ func CheckCacheGroupsAuthentication(t *testing.T) {
 	errors = append(errors, utils.ErrorAndMessage{err, fmt.Sprintf(errFormat, "DeleteCacheGroupByID")})
 
 	for _, err := range errors {
-		if err.Error == nil {
+		if err.Error != nil {
 			t.Error(err.Message)
 			failed = true
 		}
diff --git a/traffic_ops/testing/api/v14/cachegroupsdeliveryservices_test.go b/traffic_ops/testing/api/v14/cachegroupsdeliveryservices_test.go
index a3bdf617c..4fdc570c9 100644
--- a/traffic_ops/testing/api/v14/cachegroupsdeliveryservices_test.go
+++ b/traffic_ops/testing/api/v14/cachegroupsdeliveryservices_test.go
@@ -23,6 +23,7 @@ import (
 func TestDeliveryServicesCachegroups(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestProfiles(t)
 	CreateTestStatuses(t)
 	CreateTestDivisions(t)
@@ -43,6 +44,7 @@ func TestDeliveryServicesCachegroups(t *testing.T) {
 	DeleteTestDivisions(t)
 	DeleteTestStatuses(t)
 	DeleteTestProfiles(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 }
@@ -54,23 +56,23 @@ func CreateTestCachegroupsDeliveryServices(t *testing.T) {
 
 	dss, _, err := TOSession.GetDeliveryServiceServers()
 	if err != nil {
-		t.Fatalf("cannot GET DeliveryServiceServers: %v\n", err)
+		t.Errorf("cannot GET DeliveryServiceServers: %v\n", err)
 	}
 	if len(dss.Response) > 0 {
-		t.Fatalf("cannot test cachegroups delivery services: expected no initial delivery service servers, actual %v\n", len(dss.Response))
+		t.Errorf("cannot test cachegroups delivery services: expected no initial delivery service servers, actual %v\n", len(dss.Response))
 	}
 
 	dses, _, err := TOSession.GetDeliveryServices()
 	if err != nil {
-		t.Fatalf("cannot GET DeliveryServices: %v - %v\n", err, dses)
+		t.Errorf("cannot GET DeliveryServices: %v - %v\n", err, dses)
 	}
 
 	clientCGs, _, err := TOSession.GetCacheGroupByName(TestEdgeServerCacheGroupName)
 	if err != nil {
-		t.Fatalf("getting cachegroup: " + err.Error() + "\n")
+		t.Errorf("getting cachegroup: " + err.Error() + "\n")
 	}
 	if len(clientCGs) != 1 {
-		t.Fatalf("getting cachegroup expected 1, got %v\n", len(clientCGs))
+		t.Errorf("getting cachegroup expected 1, got %v\n", len(clientCGs))
 	}
 	clientCG := clientCGs[0]
 
@@ -83,19 +85,19 @@ func CreateTestCachegroupsDeliveryServices(t *testing.T) {
 
 	resp, _, err := TOSession.SetCachegroupDeliveryServices(cgID, dsIDs)
 	if err != nil {
-		t.Fatalf("setting cachegroup delivery services returned error: %v\n", err)
+		t.Errorf("setting cachegroup delivery services returned error: %v\n", err)
 	}
 	if len(resp.Response.ServerNames) == 0 {
-		t.Fatalf("setting cachegroup delivery services returned success, but no servers set\n")
+		t.Errorf("setting cachegroup delivery services returned success, but no servers set\n")
 	}
 
 	for _, serverName := range resp.Response.ServerNames {
 		servers, _, err := TOSession.GetServerByHostName(string(serverName))
 		if err != nil {
-			t.Fatalf("getting server: " + err.Error())
+			t.Errorf("getting server: " + err.Error())
 		}
 		if len(servers) != 1 {
-			t.Fatalf("getting servers: expected 1 got %v\n", len(servers))
+			t.Errorf("getting servers: expected 1 got %v\n", len(servers))
 		}
 		server := servers[0]
 		serverID := server.ID
@@ -111,7 +113,7 @@ func CreateTestCachegroupsDeliveryServices(t *testing.T) {
 				}
 			}
 			if !found {
-				t.Fatalf("post succeeded, but didn't assign delivery service %v to server\n", dsID)
+				t.Errorf("post succeeded, but didn't assign delivery service %v to server\n", dsID)
 			}
 		}
 	}
@@ -122,20 +124,20 @@ func DeleteTestCachegroupsDeliveryServices(t *testing.T) {
 
 	dss, _, err := TOSession.GetDeliveryServiceServers()
 	if err != nil {
-		t.Fatalf("cannot GET DeliveryServiceServers: %v\n", err)
+		t.Errorf("cannot GET DeliveryServiceServers: %v\n", err)
 	}
 	for _, ds := range dss.Response {
 		_, _, err := TOSession.DeleteDeliveryServiceServer(*ds.DeliveryService, *ds.Server)
 		if err != nil {
-			t.Fatalf("deleting delivery service servers: " + err.Error() + "\n")
+			t.Errorf("deleting delivery service servers: " + err.Error() + "\n")
 		}
 	}
 
 	dss, _, err = TOSession.GetDeliveryServiceServers()
 	if err != nil {
-		t.Fatalf("cannot GET DeliveryServiceServers: %v\n", err)
+		t.Errorf("cannot GET DeliveryServiceServers: %v\n", err)
 	}
 	if len(dss.Response) > 0 {
-		t.Fatalf("deleting delivery service servers: delete succeeded, expected empty subsequent get, actual %v\n", len(dss.Response))
+		t.Errorf("deleting delivery service servers: delete succeeded, expected empty subsequent get, actual %v\n", len(dss.Response))
 	}
 }
diff --git a/traffic_ops/testing/api/v14/cdnfederations_test.go b/traffic_ops/testing/api/v14/cdnfederations_test.go
index 970f4e4ca..a326fad8d 100644
--- a/traffic_ops/testing/api/v14/cdnfederations_test.go
+++ b/traffic_ops/testing/api/v14/cdnfederations_test.go
@@ -27,12 +27,14 @@ var fedIDs []int
 func TestCDNFederations(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestDeliveryServices(t)
 	CreateTestCDNFederations(t)
 	UpdateTestCDNFederations(t)
 	GetTestCDNFederations(t)
 	DeleteTestCDNFederations(t)
 	DeleteTestDeliveryServices(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 }
diff --git a/traffic_ops/testing/api/v14/crconfig_test.go b/traffic_ops/testing/api/v14/crconfig_test.go
index 708cfade2..6d9ed1e4a 100644
--- a/traffic_ops/testing/api/v14/crconfig_test.go
+++ b/traffic_ops/testing/api/v14/crconfig_test.go
@@ -26,6 +26,7 @@ import (
 func TestCRConfig(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestProfiles(t)
 	CreateTestStatuses(t)
 	CreateTestDivisions(t)
@@ -45,6 +46,7 @@ func TestCRConfig(t *testing.T) {
 	DeleteTestDivisions(t)
 	DeleteTestStatuses(t)
 	DeleteTestProfiles(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 }
@@ -53,24 +55,24 @@ func UpdateTestCRConfigSnapshot(t *testing.T) {
 	log.Debugln("UpdateTestCRConfigSnapshot")
 
 	if len(testData.CDNs) < 1 {
-		t.Fatalf("no cdn test data")
+		t.Errorf("no cdn test data")
 	}
 	cdn := testData.CDNs[0].Name
 	_, err := TOSession.SnapshotCRConfig(cdn)
 	if err != nil {
-		t.Fatalf("SnapshotCRConfig err expected nil, actual %+v", err)
+		t.Errorf("SnapshotCRConfig err expected nil, actual %+v", err)
 	}
 	crcBts, _, err := TOSession.GetCRConfig(cdn)
 	if err != nil {
-		t.Fatalf("GetCRConfig err expected nil, actual %+v", err)
+		t.Errorf("GetCRConfig err expected nil, actual %+v", err)
 	}
 	crc := tc.CRConfig{}
 	if err := json.Unmarshal(crcBts, &crc); err != nil {
-		t.Fatalf("GetCRConfig bytes expected: valid tc.CRConfig, actual JSON unmarshal err: %+v", err)
+		t.Errorf("GetCRConfig bytes expected: valid tc.CRConfig, actual JSON unmarshal err: %+v", err)
 	}
 
 	if len(crc.DeliveryServices) == 0 {
-		t.Fatalf("GetCRConfig len(crc.DeliveryServices) expected: >0, actual: 0")
+		t.Errorf("GetCRConfig len(crc.DeliveryServices) expected: >0, actual: 0")
 	}
 
 	log.Debugln("UpdateTestCRConfigSnapshot() PASSED: ")
diff --git a/traffic_ops/testing/api/v14/deliveryservice_request_comments_test.go b/traffic_ops/testing/api/v14/deliveryservice_request_comments_test.go
index 0ef2b23eb..1397d24dc 100644
--- a/traffic_ops/testing/api/v14/deliveryservice_request_comments_test.go
+++ b/traffic_ops/testing/api/v14/deliveryservice_request_comments_test.go
@@ -25,12 +25,14 @@ func TestDeliveryServiceRequestComments(t *testing.T) {
 
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestDeliveryServiceRequests(t)
 	CreateTestDeliveryServiceRequestComments(t)
 	UpdateTestDeliveryServiceRequestComments(t)
 	GetTestDeliveryServiceRequestComments(t)
 	DeleteTestDeliveryServiceRequestComments(t)
 	DeleteTestDeliveryServiceRequests(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 
@@ -45,6 +47,10 @@ func CreateTestDeliveryServiceRequestComments(t *testing.T) {
 	if err != nil {
 		t.Errorf("cannot GET delivery service request by xml id: %v - %v\n", dsr.XMLID, err)
 	}
+	if len(resp) != 1 {
+		t.Errorf("found %d delivery service request by xml id, expected %d: %s\n", len(resp), 1, dsr.XMLID)
+	}
+
 	respDSR := resp[0]
 
 	for _, comment := range testData.DeliveryServiceRequestComments {
diff --git a/traffic_ops/testing/api/v14/deliveryservice_requests_test.go b/traffic_ops/testing/api/v14/deliveryservice_requests_test.go
index 38dd67ad9..0f845dae5 100644
--- a/traffic_ops/testing/api/v14/deliveryservice_requests_test.go
+++ b/traffic_ops/testing/api/v14/deliveryservice_requests_test.go
@@ -35,11 +35,12 @@ func TestDeliveryServiceRequests(t *testing.T) {
 
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestDeliveryServiceRequests(t)
 	GetTestDeliveryServiceRequests(t)
 	UpdateTestDeliveryServiceRequests(t)
 	DeleteTestDeliveryServiceRequests(t)
-
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 
@@ -48,25 +49,7 @@ func TestDeliveryServiceRequests(t *testing.T) {
 func CreateTestDeliveryServiceRequests(t *testing.T) {
 	log.Debugln("CreateTestDeliveryServiceRequests")
 
-	// Attach CDNs
-	cdn := testData.CDNs[0]
-	resp, _, err := TOSession.GetCDNByName(cdn.Name)
-	if err != nil {
-		t.Errorf("cannot GET CDN by name: %v - %v\n", cdn.Name, err)
-	}
-	respCDN := resp[0]
-
-	// Attach Type
-	typ := testData.DeliveryServiceRequests[dsrGood].DeliveryService.Type.String()
-	respTypes, _, err := TOSession.GetTypeByName(typ)
-	if err != nil {
-		t.Errorf("cannot GET Type by name: %v - %v\n", typ, err)
-	}
-	respTyp := respTypes[0]
-
 	dsr := testData.DeliveryServiceRequests[dsrGood]
-	dsr.DeliveryService.CDNID = respCDN.ID
-	dsr.DeliveryService.TypeID = respTyp.ID
 	respDSR, _, err := TOSession.CreateDeliveryServiceRequest(dsr)
 	log.Debugln("Response: ", respDSR)
 	if err != nil {
@@ -78,6 +61,7 @@ func CreateTestDeliveryServiceRequests(t *testing.T) {
 func TestDeliveryServiceRequestRequired(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	dsr := testData.DeliveryServiceRequests[dsrRequired]
 	alerts, _, err := TOSession.CreateDeliveryServiceRequest(dsr)
 	if err != nil {
@@ -87,6 +71,7 @@ func TestDeliveryServiceRequestRequired(t *testing.T) {
 	if len(alerts.Alerts) == 0 {
 		t.Errorf("Expected: validation error alerts, actual: %+v", alerts)
 	}
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 }
@@ -95,6 +80,7 @@ func TestDeliveryServiceRequestRules(t *testing.T) {
 
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	routingName := strings.Repeat("X", 1) + "." + strings.Repeat("X", 48)
 	// Test the xmlId length and form
 	XMLID := "X " + strings.Repeat("X", 46)
@@ -105,24 +91,6 @@ func TestDeliveryServiceRequestRules(t *testing.T) {
 	dsr.DeliveryService.RoutingName = routingName
 	dsr.DeliveryService.XMLID = XMLID
 
-	// Attach Types
-	typ := testData.Types[3]
-	rt, _, err := TOSession.GetTypeByName(typ.Name)
-	if err != nil {
-		t.Errorf("cannot GET Type by name: %v - %v\n", typ.Name, err)
-	}
-	respType := rt[0]
-
-	// Attach CDNs
-	cdn := testData.CDNs[3]
-	resp, _, err := TOSession.GetCDNByName(cdn.Name)
-	if err != nil {
-		t.Errorf("cannot GET CDN by name: %v - %v\n", cdn.Name, err)
-	}
-	respCDN := resp[0]
-	dsr.DeliveryService.TypeID = respType.ID
-	dsr.DeliveryService.CDNID = respCDN.ID
-
 	alerts, _, err := TOSession.CreateDeliveryServiceRequest(dsr)
 	if err != nil {
 		t.Errorf("Error occurred %v", err)
@@ -130,6 +98,7 @@ func TestDeliveryServiceRequestRules(t *testing.T) {
 	if len(alerts.Alerts) == 0 {
 		t.Errorf("Expected: validation error alerts, actual: %+v", alerts)
 	}
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 
@@ -138,28 +107,11 @@ func TestDeliveryServiceRequestRules(t *testing.T) {
 func TestDeliveryServiceRequestTypeFields(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestParameters(t)
 
 	dsr := testData.DeliveryServiceRequests[dsrBadTenant]
 
-	// Attach Types
-	typ := testData.Types[3]
-	rt, _, err := TOSession.GetTypeByName(typ.Name)
-	if err != nil {
-		t.Errorf("cannot GET Type by name: %v - %v\n", typ.Name, err)
-	}
-	respType := rt[0]
-
-	// Attach CDNs
-	cdn := testData.CDNs[3]
-	resp, _, err := TOSession.GetCDNByName(cdn.Name)
-	if err != nil {
-		t.Errorf("cannot GET CDN by name: %v - %v\n", cdn.Name, err)
-	}
-	respCDN := resp[0]
-	dsr.DeliveryService.TypeID = respType.ID
-	dsr.DeliveryService.CDNID = respCDN.ID
-
 	alerts, _, err := TOSession.CreateDeliveryServiceRequest(dsr)
 	if err != nil {
 		t.Errorf("Error occurred %v", err)
@@ -182,6 +134,7 @@ func TestDeliveryServiceRequestTypeFields(t *testing.T) {
 	}
 
 	DeleteTestParameters(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 
@@ -190,6 +143,7 @@ func TestDeliveryServiceRequestTypeFields(t *testing.T) {
 func TestDeliveryServiceRequestBad(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	// try to create non-draft/submitted
 	src := testData.DeliveryServiceRequests[dsrDraft]
 	s, err := tc.RequestStatusFromString("pending")
@@ -198,24 +152,6 @@ func TestDeliveryServiceRequestBad(t *testing.T) {
 	}
 	src.Status = s
 
-	// Attach Types
-	typ := testData.Types[3]
-	rt, _, err := TOSession.GetTypeByName(typ.Name)
-	if err != nil {
-		t.Errorf("cannot GET Type by name: %v - %v\n", typ.Name, err)
-	}
-	respType := rt[0]
-
-	// Attach CDNs
-	cdn := testData.CDNs[3]
-	resp, _, err := TOSession.GetCDNByName(cdn.Name)
-	if err != nil {
-		t.Errorf("cannot GET CDN by name: %v - %v\n", cdn.Name, err)
-	}
-	respCDN := resp[0]
-	src.DeliveryService.TypeID = respType.ID
-	src.DeliveryService.CDNID = respCDN.ID
-
 	alerts, _, err := TOSession.CreateDeliveryServiceRequest(src)
 	if err != nil {
 		t.Errorf("Error creating DeliveryServiceRequest %v", err)
@@ -224,6 +160,7 @@ func TestDeliveryServiceRequestBad(t *testing.T) {
 		`'status' invalid transition from draft to pending`,
 	}
 	utils.Compare(t, expected, alerts.ToStrings())
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 }
@@ -233,6 +170,7 @@ func TestDeliveryServiceRequestWorkflow(t *testing.T) {
 
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	// test empty request table
 	dsrs, _, err := TOSession.GetDeliveryServiceRequests()
 	if err != nil {
@@ -248,24 +186,6 @@ func TestDeliveryServiceRequestWorkflow(t *testing.T) {
 	// Create a draft request
 	src := testData.DeliveryServiceRequests[dsrDraft]
 
-	// Attach Types
-	typ := testData.Types[3]
-	rt, _, err := TOSession.GetTypeByName(typ.Name)
-	if err != nil {
-		t.Errorf("cannot GET Type by name: %v - %v\n", typ.Name, err)
-	}
-	respType := rt[0]
-
-	// Attach CDNs
-	cdn := testData.CDNs[3]
-	resp, _, err := TOSession.GetCDNByName(cdn.Name)
-	if err != nil {
-		t.Errorf("cannot GET CDN by name: %v - %v\n", cdn.Name, err)
-	}
-	respCDN := resp[0]
-	src.DeliveryService.TypeID = respType.ID
-	src.DeliveryService.CDNID = respCDN.ID
-
 	alerts, _, err := TOSession.CreateDeliveryServiceRequest(src)
 	if err != nil {
 		t.Errorf("Error creating DeliveryServiceRequest %v", err)
@@ -301,6 +221,7 @@ func TestDeliveryServiceRequestWorkflow(t *testing.T) {
 	if dsr.Status != tc.RequestStatus("submitted") {
 		t.Errorf("expected status=submitted,  got %s", string(dsr.Status))
 	}
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 
@@ -342,7 +263,7 @@ func UpdateTestDeliveryServiceRequests(t *testing.T) {
 	dsr := testData.DeliveryServiceRequests[dsrGood]
 	resp, _, err := TOSession.GetDeliveryServiceRequestByXMLID(dsr.DeliveryService.XMLID)
 	if err != nil {
-		t.Fatalf("cannot GET DeliveryServiceRequest by name: %v - %v\n", dsr.DeliveryService.XMLID, err)
+		t.Errorf("cannot GET DeliveryServiceRequest by name: %v - %v\n", dsr.DeliveryService.XMLID, err)
 	}
 	if len(resp) == 0 {
 		t.Fatal("Length of GET DeliveryServiceRequest is 0")
diff --git a/traffic_ops/testing/api/v14/deliveryservicematches_test.go b/traffic_ops/testing/api/v14/deliveryservicematches_test.go
index e530da890..892f064e5 100644
--- a/traffic_ops/testing/api/v14/deliveryservicematches_test.go
+++ b/traffic_ops/testing/api/v14/deliveryservicematches_test.go
@@ -24,6 +24,7 @@ import (
 func TestDeliveryServiceMatches(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestProfiles(t)
 	CreateTestStatuses(t)
 	CreateTestDivisions(t)
@@ -43,6 +44,7 @@ func TestDeliveryServiceMatches(t *testing.T) {
 	DeleteTestDivisions(t)
 	DeleteTestStatuses(t)
 	DeleteTestProfiles(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 }
@@ -51,7 +53,7 @@ func GetTestDeliveryServiceMatches(t *testing.T) {
 	log.Debugln("GetTestDeliveryServiceMatches")
 	dsMatches, _, err := TOSession.GetDeliveryServiceMatches()
 	if err != nil {
-		t.Fatalf("cannot GET DeliveryService matches: %v\n", err)
+		t.Errorf("cannot GET DeliveryService matches: %v\n", err)
 	}
 
 	dsMatchMap := map[tc.DeliveryServiceName][]string{}
@@ -61,7 +63,7 @@ func GetTestDeliveryServiceMatches(t *testing.T) {
 
 	for _, ds := range testData.DeliveryServices {
 		if _, ok := dsMatchMap[tc.DeliveryServiceName(ds.XMLID)]; !ok {
-			t.Fatalf("GET DeliveryService matches missing: %v\n", ds.XMLID)
+			t.Errorf("GET DeliveryService matches missing: %v\n", ds.XMLID)
 		}
 	}
 }
diff --git a/traffic_ops/testing/api/v14/deliveryservices_test.go b/traffic_ops/testing/api/v14/deliveryservices_test.go
index 94f5ef489..885216725 100644
--- a/traffic_ops/testing/api/v14/deliveryservices_test.go
+++ b/traffic_ops/testing/api/v14/deliveryservices_test.go
@@ -26,6 +26,7 @@ import (
 func TestDeliveryServices(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestProfiles(t)
 	CreateTestStatuses(t)
 	CreateTestDivisions(t)
@@ -45,6 +46,7 @@ func TestDeliveryServices(t *testing.T) {
 	DeleteTestDivisions(t)
 	DeleteTestStatuses(t)
 	DeleteTestProfiles(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 }
@@ -59,50 +61,12 @@ func CreateTestDeliveryServices(t *testing.T) {
 	}
 	_, _, err := TOSession.CreateParameter(pl)
 	if err != nil {
-		t.Fatalf("cannot create parameter: %v\n", err)
+		t.Errorf("cannot create parameter: %v\n", err)
 	}
 	for _, ds := range testData.DeliveryServices {
-		respCDNs, _, err := TOSession.GetCDNByName(ds.CDNName)
-		if err != nil {
-			t.Fatalf("cannot GET CDN - %v\n", err)
-		}
-		if len(respCDNs) < 1 {
-			t.Fatalf("cannot GET CDN - no CDNs\n")
-		}
-		ds.CDNID = respCDNs[0].ID
-
-		respTypes, _, err := TOSession.GetTypeByName(string(ds.Type))
-		if err != nil {
-			t.Fatalf("cannot GET Type by name: %v\n", err)
-		}
-		if len(respTypes) < 1 {
-			t.Fatalf("cannot GET Type - no Types\n")
-		}
-		ds.TypeID = respTypes[0].ID
-
-		if ds.ProfileName != "" {
-			respProfiles, _, err := TOSession.GetProfileByName(ds.ProfileName)
-			if err != nil {
-				t.Fatalf("cannot GET Profile by name: %v\n", err)
-			}
-			if len(respProfiles) < 1 {
-				t.Fatalf("cannot GET Profile - no Profiles\n")
-			}
-			ds.ProfileID = respProfiles[0].ID
-		}
-
-		respTenants, _, err := TOSession.Tenants()
-		if err != nil {
-			t.Fatalf("cannot GET tenants: %v\n", err)
-		}
-		if len(respTenants) < 1 {
-			t.Fatalf("cannot GET tenants: no tenants returned from Traffic Ops\n")
-		}
-		ds.TenantID = respTenants[0].ID
-
 		_, err = TOSession.CreateDeliveryService(&ds)
 		if err != nil {
-			t.Fatalf("could not CREATE delivery service '%s': %v\n", ds.XMLID, err)
+			t.Errorf("could not CREATE delivery service '%s': %v\n", ds.XMLID, err)
 		}
 	}
 }
@@ -111,7 +75,7 @@ func GetTestDeliveryServices(t *testing.T) {
 	failed := false
 	actualDSes, _, err := TOSession.GetDeliveryServices()
 	if err != nil {
-		t.Fatalf("cannot GET DeliveryServices: %v - %v\n", err, actualDSes)
+		t.Errorf("cannot GET DeliveryServices: %v - %v\n", err, actualDSes)
 		failed = true
 	}
 	actualDSMap := map[string]tc.DeliveryService{}
@@ -136,7 +100,7 @@ func UpdateTestDeliveryServices(t *testing.T) {
 	dses, _, err := TOSession.GetDeliveryServices()
 	if err != nil {
 		failed = true
-		t.Fatalf("cannot GET Delivery Services: %v\n", err)
+		t.Errorf("cannot GET Delivery Services: %v\n", err)
 	}
 
 	remoteDS := tc.DeliveryService{}
@@ -150,7 +114,7 @@ func UpdateTestDeliveryServices(t *testing.T) {
 	}
 	if !found {
 		failed = true
-		t.Fatalf("GET Delivery Services missing: %v\n", firstDS.XMLID)
+		t.Errorf("GET Delivery Services missing: %v\n", firstDS.XMLID)
 	}
 
 	updatedLongDesc := "something different"
@@ -166,11 +130,11 @@ func UpdateTestDeliveryServices(t *testing.T) {
 	resp, _, err := TOSession.GetDeliveryService(strconv.Itoa(remoteDS.ID))
 	if err != nil {
 		failed = true
-		t.Fatalf("cannot GET Delivery Service by ID: %v - %v\n", remoteDS.XMLID, err)
+		t.Errorf("cannot GET Delivery Service by ID: %v - %v\n", remoteDS.XMLID, err)
 	}
 	if resp == nil {
 		failed = true
-		t.Fatalf("cannot GET Delivery Service by ID: %v - nil\n", remoteDS.XMLID)
+		t.Errorf("cannot GET Delivery Service by ID: %v - nil\n", remoteDS.XMLID)
 	}
 
 	if resp.LongDesc != updatedLongDesc || resp.MaxDNSAnswers != updatedMaxDNSAnswers {
@@ -251,7 +215,7 @@ func DeleteTestDeliveryServices(t *testing.T) {
 	failed := false
 	if err != nil {
 		failed = true
-		t.Fatalf("cannot GET Servers: %v\n", err)
+		t.Errorf("cannot GET Servers: %v\n", err)
 	}
 	for _, testDS := range testData.DeliveryServices {
 		ds := tc.DeliveryService{}
@@ -265,7 +229,7 @@ func DeleteTestDeliveryServices(t *testing.T) {
 		}
 		if !found {
 			failed = true
-			t.Fatalf("DeliveryService not found in Traffic Ops: %v\n", ds.XMLID)
+			t.Errorf("DeliveryService not found in Traffic Ops: %v\n", ds.XMLID)
 		}
 
 		delResp, err := TOSession.DeleteDeliveryService(strconv.Itoa(ds.ID))
diff --git a/traffic_ops/testing/api/v14/deliveryserviceservers_test.go b/traffic_ops/testing/api/v14/deliveryserviceservers_test.go
index 893bcad52..1fa3e4dde 100644
--- a/traffic_ops/testing/api/v14/deliveryserviceservers_test.go
+++ b/traffic_ops/testing/api/v14/deliveryserviceservers_test.go
@@ -24,6 +24,7 @@ import (
 func TestDeliveryServiceServers(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestProfiles(t)
 	CreateTestStatuses(t)
 	CreateTestDivisions(t)
@@ -43,6 +44,7 @@ func TestDeliveryServiceServers(t *testing.T) {
 	DeleteTestDivisions(t)
 	DeleteTestStatuses(t)
 	DeleteTestProfiles(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 }
@@ -52,30 +54,30 @@ func DeleteTestDeliveryServiceServers(t *testing.T) {
 
 	dses, _, err := TOSession.GetDeliveryServices()
 	if err != nil {
-		t.Fatalf("cannot GET DeliveryServices: %v\n", err)
+		t.Errorf("cannot GET DeliveryServices: %v\n", err)
 	}
 	if len(dses) < 1 {
-		t.Fatalf("GET DeliveryServices returned no dses, must have at least 1 to test ds-servers")
+		t.Errorf("GET DeliveryServices returned no dses, must have at least 1 to test ds-servers")
 	}
 	ds := dses[0]
 
 	servers, _, err := TOSession.GetServers()
 	if err != nil {
-		t.Fatalf("cannot GET Servers: %v\n", err)
+		t.Errorf("cannot GET Servers: %v\n", err)
 	}
 	if len(servers) < 1 {
-		t.Fatalf("GET Servers returned no dses, must have at least 1 to test ds-servers")
+		t.Errorf("GET Servers returned no dses, must have at least 1 to test ds-servers")
 	}
 	server := servers[0]
 
 	_, err = TOSession.CreateDeliveryServiceServers(ds.ID, []int{server.ID}, true)
 	if err != nil {
-		t.Fatalf("POST delivery service servers: %v\n", err)
+		t.Errorf("POST delivery service servers: %v\n", err)
 	}
 
 	dsServers, _, err := TOSession.GetDeliveryServiceServers()
 	if err != nil {
-		t.Fatalf("GET delivery service servers: %v\n", err)
+		t.Errorf("GET delivery service servers: %v\n", err)
 	}
 
 	found := false
@@ -86,16 +88,16 @@ func DeleteTestDeliveryServiceServers(t *testing.T) {
 		}
 	}
 	if !found {
-		t.Fatalf("POST delivery service servers returned success, but ds-server not in GET")
+		t.Errorf("POST delivery service servers returned success, but ds-server not in GET")
 	}
 
 	if _, _, err := TOSession.DeleteDeliveryServiceServer(ds.ID, server.ID); err != nil {
-		t.Fatalf("DELETE delivery service server: %v\n", err)
+		t.Errorf("DELETE delivery service server: %v\n", err)
 	}
 
 	dsServers, _, err = TOSession.GetDeliveryServiceServers()
 	if err != nil {
-		t.Fatalf("GET delivery service servers: %v\n", err)
+		t.Errorf("GET delivery service servers: %v\n", err)
 	}
 
 	found = false
@@ -106,6 +108,6 @@ func DeleteTestDeliveryServiceServers(t *testing.T) {
 		}
 	}
 	if found {
-		t.Fatalf("DELETE delivery service servers returned success, but still in GET")
+		t.Errorf("DELETE delivery service servers returned success, but still in GET")
 	}
 }
diff --git a/traffic_ops/testing/api/v14/deliveryservicesideligible_test.go b/traffic_ops/testing/api/v14/deliveryservicesideligible_test.go
index ad4a69168..ad2943fc2 100644
--- a/traffic_ops/testing/api/v14/deliveryservicesideligible_test.go
+++ b/traffic_ops/testing/api/v14/deliveryservicesideligible_test.go
@@ -22,6 +22,7 @@ import (
 func TestDeliveryServicesEligible(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestProfiles(t)
 	CreateTestStatuses(t)
 	CreateTestDivisions(t)
@@ -41,6 +42,7 @@ func TestDeliveryServicesEligible(t *testing.T) {
 	DeleteTestDivisions(t)
 	DeleteTestStatuses(t)
 	DeleteTestProfiles(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 }
@@ -48,17 +50,17 @@ func TestDeliveryServicesEligible(t *testing.T) {
 func GetTestDeliveryServicesEligible(t *testing.T) {
 	dses, _, err := TOSession.GetDeliveryServices()
 	if err != nil {
-		t.Fatalf("cannot GET DeliveryServices: %v\n", err)
+		t.Errorf("cannot GET DeliveryServices: %v\n", err)
 	}
 	if len(dses) == 0 {
-		t.Fatalf("GET DeliveryServices returned no delivery services, need at least 1 to test")
+		t.Errorf("GET DeliveryServices returned no delivery services, need at least 1 to test")
 	}
 	dsID := dses[0].ID
 	servers, _, err := TOSession.GetDeliveryServicesEligible(dsID)
 	if err != nil {
-		t.Fatalf("getting delivery services eligible: %v\n", err)
+		t.Errorf("getting delivery services eligible: %v\n", err)
 	}
 	if len(servers) == 0 {
-		t.Fatalf("getting delivery services eligible returned no servers\n")
+		t.Errorf("getting delivery services eligible returned no servers\n")
 	}
 }
diff --git a/traffic_ops/testing/api/v14/federations_test.go b/traffic_ops/testing/api/v14/federations_test.go
index 02cd4ee69..6404f74b3 100644
--- a/traffic_ops/testing/api/v14/federations_test.go
+++ b/traffic_ops/testing/api/v14/federations_test.go
@@ -24,6 +24,7 @@ import (
 func TestFederations(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestProfiles(t)
 	CreateTestStatuses(t)
 	CreateTestDivisions(t)
@@ -46,6 +47,7 @@ func TestFederations(t *testing.T) {
 	DeleteTestDivisions(t)
 	DeleteTestStatuses(t)
 	DeleteTestProfiles(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 }
@@ -54,38 +56,38 @@ func GetTestFederations(t *testing.T) {
 	log.Debugln("GetTestFederations")
 
 	if len(testData.Federations) == 0 {
-		t.Fatalf("no federations test data")
+		t.Errorf("no federations test data")
 	}
 
 	feds, _, err := TOSession.AllFederations()
 	if err != nil {
-		t.Fatalf("getting federations: " + err.Error())
+		t.Errorf("getting federations: " + err.Error())
 	}
 
 	if len(feds) != 1 {
-		t.Fatalf("federations expected 1, actual: %+v", len(feds))
+		t.Errorf("federations expected 1, actual: %+v", len(feds))
 	}
 	fed := feds[0]
 
 	if len(fed.Mappings) < 1 {
-		t.Fatalf("federation mappings expected <0, actual: 0")
+		t.Errorf("federation mappings expected <0, actual: 0")
 	}
 
 	mapping := fed.Mappings[0]
 	if mapping.CName == nil {
-		t.Fatalf("federation mapping expected cname, actual: nil")
+		t.Errorf("federation mapping expected cname, actual: nil")
 	}
 	if mapping.TTL == nil {
-		t.Fatalf("federation mapping expected ttl, actual: nil")
+		t.Errorf("federation mapping expected ttl, actual: nil")
 	}
 
 	matched := false
 	for _, testFed := range testData.Federations {
 		if testFed.CName == nil {
-			t.Fatalf("test federation missing cname!")
+			t.Errorf("test federation missing cname!")
 		}
 		if testFed.TTL == nil {
-			t.Fatalf("test federation missing ttl!")
+			t.Errorf("test federation missing ttl!")
 		}
 
 		if *mapping.CName != *testFed.CName {
@@ -94,11 +96,11 @@ func GetTestFederations(t *testing.T) {
 		matched = true
 
 		if *mapping.TTL != *testFed.TTL {
-			t.Fatalf("federation mapping ttl expected: %v, actual: %v", *testFed.TTL, *mapping.TTL)
+			t.Errorf("federation mapping ttl expected: %v, actual: %v", *testFed.TTL, *mapping.TTL)
 		}
 	}
 	if !matched {
-		t.Fatalf("federation mapping expected to match test data, actual: cname %v not in test data", *mapping.CName)
+		t.Errorf("federation mapping expected to match test data, actual: cname %v not in test data", *mapping.CName)
 	}
 
 	log.Debugln("GetTestFederations PASSED")
@@ -108,19 +110,19 @@ func PostTestFederationsDeliveryServices(t *testing.T) {
 	log.Debugln("PostTestFederationsDeliveryServices")
 	dses, _, err := TOSession.GetDeliveryServices()
 	if err != nil {
-		t.Fatalf("cannot GET DeliveryServices: %v - %v\n", err, dses)
+		t.Errorf("cannot GET DeliveryServices: %v - %v\n", err, dses)
 	}
 	if len(dses) == 0 {
-		t.Fatalf("no delivery services, must have at least 1 ds to test federations deliveryservices\n")
+		t.Errorf("no delivery services, must have at least 1 ds to test federations deliveryservices\n")
 	}
 	ds := dses[0]
 	if len(fedIDs) == 0 {
-		t.Fatalf("no federations, must have at least 1 federation to test federations deliveryservices\n")
+		t.Errorf("no federations, must have at least 1 federation to test federations deliveryservices\n")
 	}
 	fedID := fedIDs[0]
 
 	if _, err = TOSession.CreateFederationDeliveryServices(fedID, []int{ds.ID}, true); err != nil {
-		t.Fatalf("creating federations delivery services: %v\n", err)
+		t.Errorf("creating federations delivery services: %v\n", err)
 	}
 	log.Debugln("PostTestFederationsDeliveryServices PASSED")
 }
diff --git a/traffic_ops/testing/api/v14/origins_test.go b/traffic_ops/testing/api/v14/origins_test.go
index 682e17ea3..82fb881c2 100644
--- a/traffic_ops/testing/api/v14/origins_test.go
+++ b/traffic_ops/testing/api/v14/origins_test.go
@@ -26,6 +26,8 @@ func TestOrigins(t *testing.T) {
 	defer DeleteTestCDNs(t)
 	CreateTestTypes(t)
 	defer DeleteTestTypes(t)
+	CreateTestTenants(t)
+	defer DeleteTestTenants(t)
 	CreateTestProfiles(t)
 	defer DeleteTestProfiles(t)
 	CreateTestStatuses(t)
@@ -44,7 +46,6 @@ func TestOrigins(t *testing.T) {
 	defer DeleteTestDeliveryServices(t)
 	CreateTestCoordinates(t)
 	defer DeleteTestCoordinates(t)
-	// TODO: add tenants once their API integration tests are implemented
 
 	CreateTestOrigins(t)
 	defer DeleteTestOrigins(t)
@@ -55,49 +56,9 @@ func TestOrigins(t *testing.T) {
 func CreateTestOrigins(t *testing.T) {
 	failed := false
 
-	// GET ORIGIN1 profile
-	respProfiles, _, err := TOSession.GetProfileByName("ORIGIN1")
-	if err != nil {
-		t.Errorf("cannot GET Profiles - %v\n", err)
-		failed = true
-	}
-	respProfile := respProfiles[0]
-
-	// GET originCachegroup cachegroup
-	respCacheGroups, _, err := TOSession.GetCacheGroupNullableByName("originCachegroup")
-	if err != nil {
-		t.Errorf("cannot GET CacheGroup by name: originCachegroup - %v\n", err)
-		failed = true
-	}
-	respCacheGroup := respCacheGroups[0]
-
-	// GET deliveryservices
-	respDeliveryServices, _, err := TOSession.GetDeliveryServices()
-	if err != nil {
-		t.Errorf("cannot GET Delivery Services - %v\n", err)
-		failed = true
-	}
-	if len(respDeliveryServices) == 0 {
-		t.Errorf("no delivery services found")
-		failed = true
-	}
-
-	// GET coordinate1 coordinate
-	respCoordinates, _, err := TOSession.GetCoordinateByName("coordinate1")
-	if err != nil {
-		t.Errorf("cannot GET Coordinate by name: coordinate1 - %v\n", err)
-		failed = true
-	}
-	respCoordinate := respCoordinates[0]
-
 	// loop through origins, assign FKs and create
 	for _, origin := range testData.Origins {
-		origin.CachegroupID = respCacheGroup.ID
-		origin.CoordinateID = &respCoordinate.ID
-		origin.ProfileID = &respProfile.ID
-		origin.DeliveryServiceID = &respDeliveryServices[0].ID
-
-		_, _, err = TOSession.CreateOrigin(origin)
+		_, _, err := TOSession.CreateOrigin(origin)
 		if err != nil {
 			t.Errorf("could not CREATE origins: %v\n", err)
 			failed = true
diff --git a/traffic_ops/testing/api/v14/phys_locations_test.go b/traffic_ops/testing/api/v14/phys_locations_test.go
index 1b4b316ef..0cc6605eb 100644
--- a/traffic_ops/testing/api/v14/phys_locations_test.go
+++ b/traffic_ops/testing/api/v14/phys_locations_test.go
@@ -38,22 +38,11 @@ func TestPhysLocations(t *testing.T) {
 }
 
 func CreateTestPhysLocations(t *testing.T) {
-
-	// Attach CDNs
-	region := testData.Regions[0]
-	resp, _, err := TOSession.GetRegionByName(region.Name)
-	if err != nil {
-		t.Errorf("cannot GET region by name: %v - %v\n", region.Name, err)
-	}
-	respRegion := resp[0]
-
 	for _, pl := range testData.PhysLocations {
-
-		pl.RegionID = respRegion.ID
 		resp, _, err := TOSession.CreatePhysLocation(pl)
 		log.Debugln("Response: ", resp)
 		if err != nil {
-			t.Errorf("could not CREATE cdns: %v\n", err)
+			t.Errorf("could not CREATE physlocations: %v\n", err)
 		}
 	}
 
diff --git a/traffic_ops/testing/api/v14/profiles_test.go b/traffic_ops/testing/api/v14/profiles_test.go
index 6afa97c08..82ab0e2ee 100644
--- a/traffic_ops/testing/api/v14/profiles_test.go
+++ b/traffic_ops/testing/api/v14/profiles_test.go
@@ -16,6 +16,7 @@
 package v14
 
 import (
+	"strings"
 	"testing"
 
 	"github.com/apache/trafficcontrol/lib/go-log"
@@ -31,11 +32,9 @@ func TestProfiles(t *testing.T) {
 	CreateBadProfiles(t)
 	CreateTestProfiles(t)
 	CreateTestParameters(t)
-	CreateTestProfileParameters(t)
 	UpdateTestProfiles(t)
 	GetTestProfiles(t)
 	GetTestProfilesWithParameters(t)
-	DeleteTestProfileParameters(t)
 	DeleteTestParameters(t)
 	DeleteTestProfiles(t)
 	DeleteTestTypes(t)
@@ -68,16 +67,47 @@ func CreateBadProfiles(t *testing.T) {
 func CreateTestProfiles(t *testing.T) {
 
 	for _, pr := range testData.Profiles {
-		cdns, _, err := TOSession.GetCDNByName(pr.CDNName)
-		respCDN := cdns[0]
-		pr.CDNID = respCDN.ID
-
 		resp, _, err := TOSession.CreateProfile(pr)
 
 		log.Debugln("Response: ", resp)
 		if err != nil {
 			t.Errorf("could not CREATE profiles with name: %s %v\n", pr.Name, err)
 		}
+		profiles, _, err := TOSession.GetProfileByName(pr.Name)
+		if err != nil {
+			t.Errorf("could not GET profile with name: %s %v\n", pr.Name, err)
+		}
+		if len(profiles) == 0 {
+			t.Errorf("could not GET profile %++v: not found\n", pr)
+		}
+		profileID := profiles[0].ID
+
+		for _, param := range pr.Parameters {
+			if param.Name == nil || param.Value == nil || param.ConfigFile == nil {
+				t.Errorf("invalid parameter specification: %++v", param)
+				continue
+			}
+			_, _, err := TOSession.CreateParameter(tc.Parameter{Name: *param.Name, Value: *param.Value, ConfigFile: *param.ConfigFile})
+			if err != nil {
+				// ok if already exists
+				if !strings.Contains(err.Error(), "already exists") {
+					t.Errorf("could not CREATE parameter %++v: %s\n", param, err.Error())
+					continue
+				}
+			}
+			p, _, err := TOSession.GetParameterByNameAndConfigFileAndValue(*param.Name, *param.ConfigFile, *param.Value)
+			if err != nil {
+				t.Errorf("could not GET parameter %++v: %s\n", param, err.Error())
+			}
+			if len(p) == 0 {
+				t.Errorf("could not GET parameter %++v: not found\n", param)
+			}
+			_, _, err = TOSession.CreateProfileParameter(tc.ProfileParameter{ProfileID: profileID, ParameterID: p[0].ID})
+			if err != nil {
+				t.Errorf("could not CREATE profile_parameter %++v: %s\n", param, err.Error())
+			}
+		}
+
 	}
 }
 
@@ -129,26 +159,31 @@ func GetTestProfiles(t *testing.T) {
 		}
 	}
 }
+
 func GetTestProfilesWithParameters(t *testing.T) {
 	firstProfile := testData.Profiles[0]
 	resp, _, err := TOSession.GetProfileByName(firstProfile.Name)
-	if len(resp) > 0 {
-		respProfile := resp[0]
-		resp, _, err := TOSession.GetProfileByID(respProfile.ID)
-		if err != nil {
-			t.Errorf("cannot GET Profile by name: %v - %v\n", err, resp)
-		}
-		if len(resp) > 0 {
-			respProfile = resp[0]
-			respParameters := respProfile.Parameters
-			if len(respParameters) == 0 {
-				t.Errorf("expected a profile with parameters to be retrieved: %v - %v\n", err, respParameters)
-			}
-		}
+	if err != nil {
+		t.Errorf("cannot GET Profile by name: %v - %v\n", err, resp)
+		return
+	}
+	if len(resp) == 0 {
+		t.Errorf("cannot GET Profile by name: not found - %v\n", resp)
+		return
 	}
+	respProfile := resp[0]
+	// query by name does not retrieve associated parameters.  But query by id does.
+	resp, _, err = TOSession.GetProfileByID(respProfile.ID)
 	if err != nil {
 		t.Errorf("cannot GET Profile by name: %v - %v\n", err, resp)
 	}
+	if len(resp) > 0 {
+		respProfile = resp[0]
+		respParameters := respProfile.Parameters
+		if len(respParameters) == 0 {
+			t.Errorf("expected a profile with parameters to be retrieved: %v - %v\n", err, respParameters)
+		}
+	}
 }
 
 func DeleteTestProfiles(t *testing.T) {
@@ -157,25 +192,40 @@ func DeleteTestProfiles(t *testing.T) {
 		// Retrieve the Profile by name so we can get the id for the Update
 		resp, _, err := TOSession.GetProfileByName(pr.Name)
 		if err != nil {
-			t.Errorf("cannot GET Profile by name: %v - %v\n", pr.Name, err)
+			t.Errorf("cannot GET Profile by name: %s - %v\n", pr.Name, err)
+			continue
+		}
+		if len(resp) == 0 {
+			t.Errorf("cannot GET Profile by name: not found - %s\n", pr.Name)
+			continue
 		}
-		if len(resp) > 0 {
-			respProfile := resp[0]
 
-			delResp, _, err := TOSession.DeleteProfileByID(respProfile.ID)
+		profileID := resp[0].ID
+		// query by name does not retrieve associated parameters.  But query by id does.
+		resp, _, err = TOSession.GetProfileByID(profileID)
+		if err != nil {
+			t.Errorf("cannot GET Profile by id: %v - %v\n", err, resp)
+		}
+		// delete any profile_parameter associations first
+		for _, param := range resp[0].Parameters {
+			_, _, err := TOSession.DeleteParameterByProfileParameter(profileID, *param.ID)
 			if err != nil {
-				t.Errorf("cannot DELETE Profile by name: %v - %v\n", err, delResp)
+				t.Errorf("cannot DELETE profile_parameter with profileID %d, parameterID %d: %s\n", profileID, *param.ID, err.Error())
 			}
-			//time.Sleep(1 * time.Second)
+		}
+		delResp, _, err := TOSession.DeleteProfileByID(profileID)
+		if err != nil {
+			t.Errorf("cannot DELETE Profile by name: %v - %v\n", err, delResp)
+		}
+		//time.Sleep(1 * time.Second)
 
-			// Retrieve the Profile to see if it got deleted
-			prs, _, err := TOSession.GetProfileByName(pr.Name)
-			if err != nil {
-				t.Errorf("error deleting Profile name: %s\n", err.Error())
-			}
-			if len(prs) > 0 {
-				t.Errorf("expected Profile Name: %s to be deleted\n", pr.Name)
-			}
+		// Retrieve the Profile to see if it got deleted
+		prs, _, err := TOSession.GetProfileByName(pr.Name)
+		if err != nil {
+			t.Errorf("error deleting Profile name: %s\n", err.Error())
+		}
+		if len(prs) > 0 {
+			t.Errorf("expected Profile Name: %s to be deleted\n", pr.Name)
 		}
 	}
 }
diff --git a/traffic_ops/testing/api/v14/regions_test.go b/traffic_ops/testing/api/v14/regions_test.go
index 936833a28..c4d0a168f 100644
--- a/traffic_ops/testing/api/v14/regions_test.go
+++ b/traffic_ops/testing/api/v14/regions_test.go
@@ -36,16 +36,7 @@ func TestRegions(t *testing.T) {
 
 func CreateTestRegions(t *testing.T) {
 
-	// Retrieve the Division by name so we can get the ID
-	division := testData.Divisions[0]
-	resp, _, err := TOSession.GetDivisionByName(division.Name)
-	if err != nil {
-		t.Errorf("cannot GET Division by name: %v - %v\n", division.Name, err)
-	}
-	respDivision := resp[0]
-
 	for _, region := range testData.Regions {
-		region.Division = respDivision.ID
 		resp, _, err := TOSession.CreateRegion(region)
 		log.Debugln("Response: ", resp)
 		if err != nil {
@@ -104,7 +95,7 @@ func GetTestRegionsByNamePath(t *testing.T) {
 	for _, region := range testData.Regions {
 		_, _, err := TOSession.GetRegionByNamePath(region.Name)
 		if err != nil {
-			t.Fatalf("cannot GET Region by name: %v - %v\n", region.Name, err)
+			t.Errorf("cannot GET Region by name: %v - %v\n", region.Name, err)
 		}
 	}
 }
diff --git a/traffic_ops/testing/api/v14/servers_test.go b/traffic_ops/testing/api/v14/servers_test.go
index 0d448f5d9..c482052ed 100644
--- a/traffic_ops/testing/api/v14/servers_test.go
+++ b/traffic_ops/testing/api/v14/servers_test.go
@@ -49,50 +49,8 @@ func TestServers(t *testing.T) {
 
 func CreateTestServers(t *testing.T) {
 
-	// GET EDGE1 profile
-	respProfiles, _, err := TOSession.GetProfileByName("EDGE1")
-	if err != nil {
-		t.Errorf("cannot GET Profiles - %v\n", err)
-	}
-	respProfile := respProfiles[0]
-
-	// GET ONLINE status
-	respStatuses, _, err := TOSession.GetStatusByName("ONLINE")
-	if err != nil {
-		t.Errorf("cannot GET Status by name: ONLINE - %v\n", err)
-	}
-	respStatus := respStatuses[0]
-
-	// GET Denver physlocation
-	respPhysLocations, _, err := TOSession.GetPhysLocationByName("Denver")
-	if err != nil {
-		t.Errorf("cannot GET PhysLocation by name: Denver - %v\n", err)
-	}
-	respPhysLocation := respPhysLocations[0]
-
-	// GET cachegroup1 cachegroup
-	respCacheGroups, _, err := TOSession.GetCacheGroupNullableByName("cachegroup1")
-	if err != nil {
-		t.Errorf("cannot GET CacheGroup by name: cachegroup1 - %v\n", err)
-	}
-	respCacheGroup := respCacheGroups[0]
-
 	// loop through servers, assign FKs and create
 	for _, server := range testData.Servers {
-		// GET EDGE type
-		respTypes, _, err := TOSession.GetTypeByName(server.Type)
-		if err != nil {
-			t.Errorf("cannot GET Division by name: EDGE - %v\n", err)
-		}
-		respType := respTypes[0]
-
-		server.CDNID = respProfile.CDNID
-		server.ProfileID = respProfile.ID
-		server.TypeID = respType.ID
-		server.StatusID = respStatus.ID
-		server.PhysLocationID = respPhysLocation.ID
-		server.CachegroupID = *respCacheGroup.ID
-
 		resp, _, err := TOSession.CreateServer(server)
 		log.Debugln("Response: ", server.HostName, " ", resp)
 		if err != nil {
diff --git a/traffic_ops/testing/api/v14/staticdnsentries_test.go b/traffic_ops/testing/api/v14/staticdnsentries_test.go
index 3dca5768c..4d4427c5c 100644
--- a/traffic_ops/testing/api/v14/staticdnsentries_test.go
+++ b/traffic_ops/testing/api/v14/staticdnsentries_test.go
@@ -27,6 +27,7 @@ func TestStaticDNSEntries(t *testing.T) {
 
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestProfiles(t)
 	CreateTestStatuses(t)
 	CreateTestDivisions(t)
@@ -48,39 +49,14 @@ func TestStaticDNSEntries(t *testing.T) {
 	DeleteTestDivisions(t)
 	DeleteTestStatuses(t)
 	DeleteTestProfiles(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 
 }
 
 func CreateTestStaticDNSEntries(t *testing.T) {
-
 	for _, staticDNSEntry := range testData.StaticDNSEntries {
-
-		// GET StaticDNSEntry type
-		respTypes, _, err := TOSession.GetTypeByName(staticDNSEntry.Type)
-		if err != nil {
-			t.Errorf("cannot GET Type by name: %v\n", err)
-		}
-		respType := respTypes[0]
-		staticDNSEntry.TypeID = respType.ID
-
-		// GET DeliveryService to associate
-		respDSes, _, err := TOSession.GetDeliveryServiceByXMLID(staticDNSEntry.DeliveryService)
-		if err != nil {
-			t.Errorf("cannot GET DeliveryService by XMLID: %v\n", err)
-		}
-		respDS := respDSes[0]
-		staticDNSEntry.DeliveryServiceID = respDS.ID
-
-		// GET Cachegroup to associate
-		respGroups, _, err := TOSession.GetCacheGroupNullableByName(staticDNSEntry.CacheGroupName)
-		if err != nil {
-			t.Errorf("cannot GET CacheGroup by Name: %v\n", err)
-		}
-		respGroup := respGroups[0]
-		staticDNSEntry.CacheGroupID = *respGroup.ID
-
 		resp, _, err := TOSession.CreateStaticDNSEntry(staticDNSEntry)
 		log.Debugln("Response: ", resp)
 		if err != nil {
@@ -123,7 +99,7 @@ func UpdateTestStaticDNSEntries(t *testing.T) {
 
 func UpdateTestStaticDNSEntriesInvalidAddress(t *testing.T) {
 
-	expectedAlerts := []tc.Alerts{tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid IPv4 address","error"}}}, tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid DNS name","error"}}}, tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid IPv6 address","error"}}}}
+	expectedAlerts := []tc.Alerts{tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid IPv4 address", "error"}}}, tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid DNS name", "error"}}}, tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid IPv6 address", "error"}}}}
 
 	// A_RECORD
 	firstStaticDNSEntry := testData.StaticDNSEntries[0]
diff --git a/traffic_ops/testing/api/v14/steering_test.go b/traffic_ops/testing/api/v14/steering_test.go
index c04e68cb6..6ecfe2255 100644
--- a/traffic_ops/testing/api/v14/steering_test.go
+++ b/traffic_ops/testing/api/v14/steering_test.go
@@ -24,6 +24,7 @@ import (
 func TestSteering(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestProfiles(t)
 	CreateTestStatuses(t)
 	CreateTestDivisions(t)
@@ -45,6 +46,7 @@ func TestSteering(t *testing.T) {
 	DeleteTestDivisions(t)
 	DeleteTestStatuses(t)
 	DeleteTestProfiles(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 }
@@ -53,42 +55,42 @@ func GetTestSteering(t *testing.T) {
 	log.Debugln("GetTestSteering")
 
 	if len(testData.SteeringTargets) < 1 {
-		t.Fatalf("get steering: no steering target test data\n")
+		t.Errorf("get steering: no steering target test data\n")
 	}
 	st := testData.SteeringTargets[0]
 	if st.DeliveryService == nil {
-		t.Fatalf("get steering: test data missing ds\n")
+		t.Errorf("get steering: test data missing ds\n")
 	}
 
 	steerings, _, err := TOSession.Steering()
 	if err != nil {
-		t.Fatalf("steering get: getting steering: %v\n", err)
+		t.Errorf("steering get: getting steering: %v\n", err)
 	}
 
 	if len(steerings) != len(testData.SteeringTargets) {
-		t.Fatalf("steering get: expected %v actual %v\n", len(testData.SteeringTargets), len(steerings))
+		t.Errorf("steering get: expected %v actual %v\n", len(testData.SteeringTargets), len(steerings))
 	}
 
 	if steerings[0].ClientSteering {
-		t.Fatalf("steering get: ClientSteering expected %v actual %v\n", false, true)
+		t.Errorf("steering get: ClientSteering expected %v actual %v\n", false, true)
 	}
 	if len(steerings[0].Targets) != 1 {
-		t.Fatalf("steering get: Targets expected %v actual %v\n", 1, len(steerings[0].Targets))
+		t.Errorf("steering get: Targets expected %v actual %v\n", 1, len(steerings[0].Targets))
 	}
 	if steerings[0].Targets[0].Order != 0 {
-		t.Fatalf("steering get: Targets Order expected %v actual %v\n", 0, steerings[0].Targets[0].Order)
+		t.Errorf("steering get: Targets Order expected %v actual %v\n", 0, steerings[0].Targets[0].Order)
 	}
 	if testData.SteeringTargets[0].Value != nil && steerings[0].Targets[0].Weight != int32(*testData.SteeringTargets[0].Value) {
-		t.Fatalf("steering get: Targets Order expected %v actual %v\n", testData.SteeringTargets[0].Value, steerings[0].Targets[0].Weight)
+		t.Errorf("steering get: Targets Order expected %v actual %v\n", testData.SteeringTargets[0].Value, steerings[0].Targets[0].Weight)
 	}
 	if steerings[0].Targets[0].GeoOrder != nil {
-		t.Fatalf("steering get: Targets Order expected %v actual %+v\n", nil, *steerings[0].Targets[0].GeoOrder)
+		t.Errorf("steering get: Targets Order expected %v actual %+v\n", nil, *steerings[0].Targets[0].GeoOrder)
 	}
 	if steerings[0].Targets[0].Longitude != nil {
-		t.Fatalf("steering get: Targets Order expected %v actual %+v\n", nil, *steerings[0].Targets[0].Longitude)
+		t.Errorf("steering get: Targets Order expected %v actual %+v\n", nil, *steerings[0].Targets[0].Longitude)
 	}
 	if steerings[0].Targets[0].Latitude != nil {
-		t.Fatalf("steering get: Targets Order expected %v actual %+v\n", nil, *steerings[0].Targets[0].Latitude)
+		t.Errorf("steering get: Targets Order expected %v actual %+v\n", nil, *steerings[0].Targets[0].Latitude)
 	}
 	log.Debugln("GetTestSteering() PASSED")
 }
diff --git a/traffic_ops/testing/api/v14/steeringtargets_test.go b/traffic_ops/testing/api/v14/steeringtargets_test.go
index b709ba883..385f2532f 100644
--- a/traffic_ops/testing/api/v14/steeringtargets_test.go
+++ b/traffic_ops/testing/api/v14/steeringtargets_test.go
@@ -25,6 +25,7 @@ import (
 func TestSteeringTargets(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestProfiles(t)
 	CreateTestStatuses(t)
 	CreateTestDivisions(t)
@@ -47,6 +48,7 @@ func TestSteeringTargets(t *testing.T) {
 	DeleteTestDivisions(t)
 	DeleteTestStatuses(t)
 	DeleteTestProfiles(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 }
@@ -55,30 +57,30 @@ func CreateTestSteeringTargets(t *testing.T) {
 	log.Debugln("CreateTestSteeringTargets")
 	for _, st := range testData.SteeringTargets {
 		if st.Type == nil {
-			t.Fatalf("creating steering target: test data missing type\n")
+			t.Errorf("creating steering target: test data missing type\n")
 		}
 		if st.DeliveryService == nil {
-			t.Fatalf("creating steering target: test data missing ds\n")
+			t.Errorf("creating steering target: test data missing ds\n")
 		}
 		if st.Target == nil {
-			t.Fatalf("creating steering target: test data missing target\n")
+			t.Errorf("creating steering target: test data missing target\n")
 		}
 
 		{
 			respTypes, _, err := TOSession.GetTypeByName(*st.Type)
 			if err != nil {
-				t.Fatalf("creating steering target: getting type: %v\n", err)
+				t.Errorf("creating steering target: getting type: %v\n", err)
 			} else if len(respTypes) < 1 {
-				t.Fatalf("creating steering target: getting type: not found\n")
+				t.Errorf("creating steering target: getting type: not found\n")
 			}
 			st.TypeID = util.IntPtr(respTypes[0].ID)
 		}
 		{
 			respDS, _, err := TOSession.GetDeliveryServiceByXMLID(string(*st.DeliveryService))
 			if err != nil {
-				t.Fatalf("creating steering target: getting ds: %v\n", err)
+				t.Errorf("creating steering target: getting ds: %v\n", err)
 			} else if len(respDS) < 1 {
-				t.Fatalf("creating steering target: getting ds: not found\n")
+				t.Errorf("creating steering target: getting ds: not found\n")
 			}
 			dsID := uint64(respDS[0].ID)
 			st.DeliveryServiceID = &dsID
@@ -86,9 +88,9 @@ func CreateTestSteeringTargets(t *testing.T) {
 		{
 			respTarget, _, err := TOSession.GetDeliveryServiceByXMLID(string(*st.Target))
 			if err != nil {
-				t.Fatalf("creating steering target: getting target ds: %v\n", err)
+				t.Errorf("creating steering target: getting target ds: %v\n", err)
 			} else if len(respTarget) < 1 {
-				t.Fatalf("creating steering target: getting target ds: not found\n")
+				t.Errorf("creating steering target: getting target ds: not found\n")
 			}
 			targetID := uint64(respTarget[0].ID)
 			st.TargetID = &targetID
@@ -97,7 +99,7 @@ func CreateTestSteeringTargets(t *testing.T) {
 		resp, _, err := TOSession.CreateSteeringTarget(st)
 		log.Debugln("Response: ", resp)
 		if err != nil {
-			t.Fatalf("creating steering target: %v\n", err)
+			t.Errorf("creating steering target: %v\n", err)
 		}
 	}
 	log.Debugln("CreateTestSteeringTargets() PASSED")
@@ -107,31 +109,31 @@ func UpdateTestSteeringTargets(t *testing.T) {
 	log.Debugln("UpdateTestSteeringTargets")
 
 	if len(testData.SteeringTargets) < 1 {
-		t.Fatalf("updating steering target: no steering target test data\n")
+		t.Errorf("updating steering target: no steering target test data\n")
 	}
 	st := testData.SteeringTargets[0]
 	if st.DeliveryService == nil {
-		t.Fatalf("updating steering target: test data missing ds\n")
+		t.Errorf("updating steering target: test data missing ds\n")
 	}
 	if st.Target == nil {
-		t.Fatalf("updating steering target: test data missing target\n")
+		t.Errorf("updating steering target: test data missing target\n")
 	}
 
 	respDS, _, err := TOSession.GetDeliveryServiceByXMLID(string(*st.DeliveryService))
 	if err != nil {
-		t.Fatalf("updating steering target: getting ds: %v\n", err)
+		t.Errorf("updating steering target: getting ds: %v\n", err)
 	}
 	if len(respDS) < 1 {
-		t.Fatalf("updating steering target: getting ds: not found\n")
+		t.Errorf("updating steering target: getting ds: not found\n")
 	}
 	dsID := respDS[0].ID
 
 	sts, _, err := TOSession.GetSteeringTargets(dsID)
 	if err != nil {
-		t.Fatalf("updating steering targets: getting steering target: %v\n", err)
+		t.Errorf("updating steering targets: getting steering target: %v\n", err)
 	}
 	if len(sts) < 1 {
-		t.Fatalf("updating steering targets: getting steering target: got 0\n")
+		t.Errorf("updating steering targets: getting steering target: got 0\n")
 	}
 	st = sts[0]
 
@@ -143,52 +145,52 @@ func UpdateTestSteeringTargets(t *testing.T) {
 
 	_, _, err = TOSession.UpdateSteeringTarget(st)
 	if err != nil {
-		t.Fatalf("updating steering targets: updating: %+v\n", err)
+		t.Errorf("updating steering targets: updating: %+v\n", err)
 	}
 
 	sts, _, err = TOSession.GetSteeringTargets(dsID)
 	if err != nil {
-		t.Fatalf("updating steering targets: getting updated steering target: %v\n", err)
+		t.Errorf("updating steering targets: getting updated steering target: %v\n", err)
 	}
 	if len(sts) < 1 {
-		t.Fatalf("updating steering targets: getting updated steering target: got 0\n")
+		t.Errorf("updating steering targets: getting updated steering target: got 0\n")
 	}
 	actual := sts[0]
 
 	if actual.DeliveryServiceID == nil {
-		t.Fatalf("steering target update: ds id expected %v actual %v\n", dsID, nil)
+		t.Errorf("steering target update: ds id expected %v actual %v\n", dsID, nil)
 	} else if *actual.DeliveryServiceID != uint64(dsID) {
-		t.Fatalf("steering target update: ds id expected %v actual %v\n", dsID, *actual.DeliveryServiceID)
+		t.Errorf("steering target update: ds id expected %v actual %v\n", dsID, *actual.DeliveryServiceID)
 	}
 	if actual.TargetID == nil {
-		t.Fatalf("steering target update: ds id expected %v actual %v\n", dsID, nil)
+		t.Errorf("steering target update: ds id expected %v actual %v\n", dsID, nil)
 	} else if *actual.TargetID != *st.TargetID {
-		t.Fatalf("steering target update: ds id expected %v actual %v\n", *st.TargetID, *actual.TargetID)
+		t.Errorf("steering target update: ds id expected %v actual %v\n", *st.TargetID, *actual.TargetID)
 	}
 	if actual.TypeID == nil {
-		t.Fatalf("steering target update: ds id expected %v actual %v\n", *st.TypeID, nil)
+		t.Errorf("steering target update: ds id expected %v actual %v\n", *st.TypeID, nil)
 	} else if *actual.TypeID != *st.TypeID {
-		t.Fatalf("steering target update: ds id expected %v actual %v\n", *st.TypeID, *actual.TypeID)
+		t.Errorf("steering target update: ds id expected %v actual %v\n", *st.TypeID, *actual.TypeID)
 	}
 	if actual.DeliveryService == nil {
-		t.Fatalf("steering target update: ds expected %v actual %v\n", *st.DeliveryService, nil)
+		t.Errorf("steering target update: ds expected %v actual %v\n", *st.DeliveryService, nil)
 	} else if *st.DeliveryService != *actual.DeliveryService {
-		t.Fatalf("steering target update: ds name expected %v actual %v\n", *st.DeliveryService, *actual.DeliveryService)
+		t.Errorf("steering target update: ds name expected %v actual %v\n", *st.DeliveryService, *actual.DeliveryService)
 	}
 	if actual.Target == nil {
-		t.Fatalf("steering target update: target expected %v actual %v\n", *st.Target, nil)
+		t.Errorf("steering target update: target expected %v actual %v\n", *st.Target, nil)
 	} else if *st.Target != *actual.Target {
-		t.Fatalf("steering target update: target expected %v actual %v\n", *st.Target, *actual.Target)
+		t.Errorf("steering target update: target expected %v actual %v\n", *st.Target, *actual.Target)
 	}
 	if actual.Type == nil {
-		t.Fatalf("steering target update: type expected %v actual %v\n", *st.Type, nil)
+		t.Errorf("steering target update: type expected %v actual %v\n", *st.Type, nil)
 	} else if *st.Type != *actual.Type {
-		t.Fatalf("steering target update: type expected %v actual %v\n", *st.Type, *actual.Type)
+		t.Errorf("steering target update: type expected %v actual %v\n", *st.Type, *actual.Type)
 	}
 	if actual.Value == nil {
-		t.Fatalf("steering target update: ds expected %v actual %v\n", *st.Value, nil)
+		t.Errorf("steering target update: ds expected %v actual %v\n", *st.Value, nil)
 	} else if *st.Value != *actual.Value {
-		t.Fatalf("steering target update: value expected %v actual %v\n", *st.Value, actual.Value)
+		t.Errorf("steering target update: value expected %v actual %v\n", *st.Value, actual.Value)
 	}
 	log.Debugln("UpdateTestSteeringTargets() PASSED")
 }
@@ -197,57 +199,57 @@ func GetTestSteeringTargets(t *testing.T) {
 	log.Debugln("GetTestSteeringTargets")
 
 	if len(testData.SteeringTargets) < 1 {
-		t.Fatalf("updating steering target: no steering target test data\n")
+		t.Errorf("updating steering target: no steering target test data\n")
 	}
 	st := testData.SteeringTargets[0]
 	if st.DeliveryService == nil {
-		t.Fatalf("updating steering target: test data missing ds\n")
+		t.Errorf("updating steering target: test data missing ds\n")
 	}
 
 	respDS, _, err := TOSession.GetDeliveryServiceByXMLID(string(*st.DeliveryService))
 	if err != nil {
-		t.Fatalf("creating steering target: getting ds: %v\n", err)
+		t.Errorf("creating steering target: getting ds: %v\n", err)
 	} else if len(respDS) < 1 {
-		t.Fatalf("steering target get: getting ds: not found\n")
+		t.Errorf("steering target get: getting ds: not found\n")
 	}
 	dsID := respDS[0].ID
 
 	sts, _, err := TOSession.GetSteeringTargets(dsID)
 	if err != nil {
-		t.Fatalf("steering target get: getting steering target: %v\n", err)
+		t.Errorf("steering target get: getting steering target: %v\n", err)
 	}
 
 	if len(sts) != len(testData.SteeringTargets) {
-		t.Fatalf("steering target get: expected %v actual %v\n", len(testData.SteeringTargets), len(sts))
+		t.Errorf("steering target get: expected %v actual %v\n", len(testData.SteeringTargets), len(sts))
 	}
 
 	expected := testData.SteeringTargets[0]
 	actual := sts[0]
 
 	if actual.DeliveryServiceID == nil {
-		t.Fatalf("steering target get: ds id expected %v actual %v\n", dsID, nil)
+		t.Errorf("steering target get: ds id expected %v actual %v\n", dsID, nil)
 	} else if *actual.DeliveryServiceID != uint64(dsID) {
-		t.Fatalf("steering target get: ds id expected %v actual %v\n", dsID, *actual.DeliveryServiceID)
+		t.Errorf("steering target get: ds id expected %v actual %v\n", dsID, *actual.DeliveryServiceID)
 	}
 	if actual.DeliveryService == nil {
-		t.Fatalf("steering target get: ds expected %v actual %v\n", expected.DeliveryService, nil)
+		t.Errorf("steering target get: ds expected %v actual %v\n", expected.DeliveryService, nil)
 	} else if *expected.DeliveryService != *actual.DeliveryService {
-		t.Fatalf("steering target get: ds name expected %v actual %v\n", expected.DeliveryService, actual.DeliveryService)
+		t.Errorf("steering target get: ds name expected %v actual %v\n", expected.DeliveryService, actual.DeliveryService)
 	}
 	if actual.Target == nil {
-		t.Fatalf("steering target get: target expected %v actual %v\n", expected.Target, nil)
+		t.Errorf("steering target get: target expected %v actual %v\n", expected.Target, nil)
 	} else if *expected.Target != *actual.Target {
-		t.Fatalf("steering target get: target expected %v actual %v\n", expected.Target, actual.Target)
+		t.Errorf("steering target get: target expected %v actual %v\n", expected.Target, actual.Target)
 	}
 	if actual.Type == nil {
-		t.Fatalf("steering target get: type expected %v actual %v\n", expected.Type, nil)
+		t.Errorf("steering target get: type expected %v actual %v\n", expected.Type, nil)
 	} else if *expected.Type != *actual.Type {
-		t.Fatalf("steering target get: type expected %v actual %v\n", expected.Type, actual.Type)
+		t.Errorf("steering target get: type expected %v actual %v\n", expected.Type, actual.Type)
 	}
 	if actual.Value == nil {
-		t.Fatalf("steering target get: ds expected %v actual %v\n", expected.Value, nil)
+		t.Errorf("steering target get: ds expected %v actual %v\n", expected.Value, nil)
 	} else if *expected.Value != *actual.Value {
-		t.Fatalf("steering target get: value expected %v actual %v\n", *expected.Value, *actual.Value)
+		t.Errorf("steering target get: value expected %v actual %v\n", *expected.Value, *actual.Value)
 	}
 	log.Debugln("GetTestSteeringTargets() PASSED")
 }
@@ -257,17 +259,17 @@ func DeleteTestSteeringTargets(t *testing.T) {
 	dsIDs := []uint64{}
 	for _, st := range testData.SteeringTargets {
 		if st.DeliveryService == nil {
-			t.Fatalf("deleting steering target: test data missing ds\n")
+			t.Errorf("deleting steering target: test data missing ds\n")
 		}
 		if st.Target == nil {
-			t.Fatalf("deleting steering target: test data missing target\n")
+			t.Errorf("deleting steering target: test data missing target\n")
 		}
 
 		respDS, _, err := TOSession.GetDeliveryServiceByXMLID(string(*st.DeliveryService))
 		if err != nil {
-			t.Fatalf("deleting steering target: getting ds: %v\n", err)
+			t.Errorf("deleting steering target: getting ds: %v\n", err)
 		} else if len(respDS) < 1 {
-			t.Fatalf("deleting steering target: getting ds: not found\n")
+			t.Errorf("deleting steering target: getting ds: not found\n")
 		}
 		dsID := uint64(respDS[0].ID)
 		st.DeliveryServiceID = &dsID
@@ -276,26 +278,26 @@ func DeleteTestSteeringTargets(t *testing.T) {
 
 		respTarget, _, err := TOSession.GetDeliveryServiceByXMLID(string(*st.Target))
 		if err != nil {
-			t.Fatalf("deleting steering target: getting target ds: %v\n", err)
+			t.Errorf("deleting steering target: getting target ds: %v\n", err)
 		} else if len(respTarget) < 1 {
-			t.Fatalf("deleting steering target: getting target ds: not found\n")
+			t.Errorf("deleting steering target: getting target ds: not found\n")
 		}
 		targetID := uint64(respTarget[0].ID)
 		st.TargetID = &targetID
 
 		_, _, err = TOSession.DeleteSteeringTarget(int(*st.DeliveryServiceID), int(*st.TargetID))
 		if err != nil {
-			t.Fatalf("deleting steering target: deleting: %+v\n", err)
+			t.Errorf("deleting steering target: deleting: %+v\n", err)
 		}
 	}
 
 	for _, dsID := range dsIDs {
 		sts, _, err := TOSession.GetSteeringTargets(int(dsID))
 		if err != nil {
-			t.Fatalf("deleting steering targets: getting steering target: %v\n", err)
+			t.Errorf("deleting steering targets: getting steering target: %v\n", err)
 		}
 		if len(sts) != 0 {
-			t.Fatalf("deleting steering targets: after delete, getting steering target: expected 0 actual %+v\n", len(sts))
+			t.Errorf("deleting steering targets: after delete, getting steering target: expected 0 actual %+v\n", len(sts))
 		}
 	}
 	log.Debugln("DeleteTestSteeringTargets() PASSED")
diff --git a/traffic_ops/testing/api/v14/tc-fixtures.json b/traffic_ops/testing/api/v14/tc-fixtures.json
index eb786c7d6..211b65114 100644
--- a/traffic_ops/testing/api/v14/tc-fixtures.json
+++ b/traffic_ops/testing/api/v14/tc-fixtures.json
@@ -96,6 +96,7 @@
             "changeType": "create",
             "deliveryService": {
                 "active": true,
+                "cdnName": "cdn1",
                 "ccrDnsTtl": 30,
                 "deepCachingType": "NEVER",
                 "displayName": "Good Kabletown CDN",
@@ -107,7 +108,7 @@
                 "longDesc": "long desc",
                 "regionalGeoBlocking": true,
                 "routingName": "goodroute",
-                "tenantId": 2,
+                "tenant": "tenant1",
                 "type": "HTTP",
                 "xmlId": "test-ds1"
             },
@@ -117,6 +118,7 @@
             "changeType": "create",
             "deliveryService": {
                 "active": true,
+                "cdnName": "cdn1",
                 "ccrDnsTtl": 30,
                 "deepCachingType": "NEVER",
                 "displayName": "Bad Tenant",
@@ -127,9 +129,9 @@
                 "logsEnabled": false,
                 "longDesc": "long desc",
                 "regionalGeoBlocking": false,
-                "tenantId": 1,
+                "tenant": "root",
                 "type": "HTTP",
-                "xmlId": "test-ds1"
+                "xmlId": "test-ds2"
             },
             "status": "draft"
         },
@@ -149,9 +151,9 @@
                 "orgServerFqdn": "xxx",
                 "regionalGeoBlocking": true,
                 "routingName": "x routing",
-                "tenantId": 2,
+                "tenant": "tenant1",
                 "type": "HTTP",
-                "xmlId": "test ds1"
+                "xmlId": "test-ds3"
             },
             "status": "draft"
         },
@@ -159,6 +161,7 @@
             "changeType": "update",
             "deliveryService": {
                 "active": false,
+                "cdnName": "cdn1",
                 "ccrDnsTtl": 30,
                 "deepCachingType": "NEVER",
                 "displayName": "Testing transitions",
@@ -170,7 +173,7 @@
                 "longDesc": "long desc",
                 "regionalGeoBlocking": true,
                 "routingName": "goodroute",
-                "tenantId": 2,
+                "tenant": "tenant1",
                 "type": "HTTP",
                 "xmlId": "test-transitions"
             },
@@ -180,6 +183,7 @@
     "deliveryServices": [
         {
             "active": true,
+            "cdnName": "cdn1",
             "cacheurl": "cacheUrl1",
             "ccrDnsTtl": 3600,
             "cdnName": "cdn1",
@@ -227,7 +231,6 @@
             "orgServerFqdn": "http://origin.example.net",
             "originShield": null,
             "profileDescription": null,
-            "profileId": null,
             "profileName": null,
             "protocol": 2,
             "qstringIgnore": 1,
@@ -247,6 +250,7 @@
         },
         {
             "active": true,
+            "cdnName": "cdn1",
             "cacheurl": "cacheUrl2",
             "ccrDnsTtl": 3600,
             "cdnName": "cdn1",
@@ -347,21 +351,25 @@
     "origins": [
         {
             "name": "origin1",
+            "cachegroup": "originCachegroup",
+            "deliveryService": "ds1",
             "fqdn": "origin1.example.com",
             "ipAddress": "1.2.3.4",
             "ip6Address": "dead:beef:cafe::42",
             "port": 1234,
             "protocol": "http",
-            "tenantId": 2
+            "tenant": "tenant1"
         },
         {
             "name": "origin2",
+            "cachegroup": "originCachegroup",
+            "deliveryService": "ds2",
             "fqdn": "origin2.example.com",
             "ipAddress": "5.6.7.8",
             "ip6Address": "cafe::42",
             "port": 5678,
             "protocol": "https",
-            "tenantId": 2
+            "tenant": "tenant1"
         }
     ],
     "parameters": [
@@ -386,20 +394,6 @@
             "secure": false,
             "value": "30"
         },
-        {
-            "configFile": "url_sig.config",
-            "lastUpdated": "2018-01-19T19:01:21.431062+00:00",
-            "name": "error_url",
-            "secure": true,
-            "value": "403"
-        },
-        {
-            "configFile": "records.config",
-            "lastUpdated": "2018-01-19T19:01:21.432692+00:00",
-            "name": "CONFIG proxy.config.allocator.debug_filter",
-            "secure": false,
-            "value": "INT 0"
-        },
         {
             "configFile": "records.config",
             "lastUpdated": "2018-01-19T19:01:21.434425+00:00",
@@ -523,7 +517,7 @@
             "name": "Denver",
             "phone": "303-111-1111",
             "poc": null,
-            "regionId": 100,
+            "region": "region1",
             "shortName": "denver",
             "state": "CO",
             "zip": "80202"
@@ -537,7 +531,7 @@
             "name": "Boulder",
             "phone": "303-222-2222",
             "poc": null,
-            "regionId": 100,
+            "region": "region1",
             "shortName": "boulder",
             "state": "CO",
             "zip": "80301"
@@ -551,7 +545,7 @@
             "name": "HotAtlanta",
             "phone": "404-222-2222",
             "poc": null,
-            "regionId": 100,
+            "region": "region1",
             "shortName": "atlanta",
             "state": "GA",
             "zip": "30301"
@@ -564,7 +558,19 @@
             "lastUpdated": "2018-03-02T17:27:11.796899+00:00",
             "name": "EDGE1",
             "routing_disabled": true,
-            "type": "ATS_PROFILE"
+            "type": "ATS_PROFILE",
+            "params": [
+                {
+                    "name": "param1",
+                    "configFile": "param1.txt",
+                    "value": "value1"
+                },
+                {
+                    "name": "param2",
+                    "configFile": "param2.txt",
+                    "value": "value2"
+                }
+            ]
         },
         {
             "cdnName": "cdn4",
@@ -615,14 +621,6 @@
             "type": "TM_PROFILE"
         }
     ],
-    "profileParameters": [
-        {
-            "parameterId": 100
-        },
-        {
-            "parameterId": 200
-        }
-    ],
     "regions": [
         {
             "divisionName": "division1",
@@ -657,6 +655,8 @@
     ],
     "servers": [
         {
+            "cachegroup": "cachegroup1",
+            "cdnName": "cdn1",
             "domainName": "ga.atlanta.kabletown.net",
             "guid": null,
             "hostName": "atlanta-edge-01",
@@ -678,10 +678,13 @@
             "mgmtIpGateway": "",
             "mgmtIpNetmask": "",
             "offlineReason": null,
+            "physLocation": "Denver",
+            "profile": "EDGE1",
             "rack": "RR 119.02",
             "revalPending": false,
             "routerHostName": "",
             "routerPortName": "",
+            "status": "REPORTED",
             "tcpPort": 80,
             "type": "EDGE",
             "updPending": true,
@@ -689,6 +692,8 @@
             "xmppPasswd": "X"
         },
         {
+            "cachegroup": "cachegroup1",
+            "cdnName": "cdn1",
             "domainName": "kabletown.net",
             "guid": null,
             "hostName": "influxdb02",
@@ -710,10 +715,13 @@
             "mgmtIpGateway": "",
             "mgmtIpNetmask": "",
             "offlineReason": null,
+            "physLocation": "Denver",
+            "profile": "EDGE1",
             "rack": "RR 119.02",
             "revalPending": false,
             "routerHostName": "",
             "routerPortName": "",
+            "status": "REPORTED",
             "tcpPort": 8086,
             "type": "EDGE",
             "updPending": true,
@@ -721,6 +729,8 @@
             "xmppPasswd": ""
         },
         {
+            "cachegroup": "cachegroup1",
+            "cdnName": "cdn1",
             "domainName": "ga.atlanta.kabletown.net",
             "guid": null,
             "hostName": "atlanta-router-01",
@@ -742,10 +752,13 @@
             "mgmtIpGateway": "",
             "mgmtIpNetmask": "",
             "offlineReason": null,
+            "physLocation": "Denver",
+            "profile": "EDGE1",
             "rack": "RR 119.02",
             "revalPending": false,
             "routerHostName": "",
             "routerPortName": "",
+            "status": "REPORTED",
             "tcpPort": 80,
             "type": "EDGE",
             "updPending": true,
@@ -753,6 +766,8 @@
             "xmppPasswd": "X"
         },
         {
+            "cachegroup": "cachegroup1",
+            "cdnName": "cdn1",
             "domainName": "ga.atlanta.kabletown.net",
             "guid": null,
             "hostName": "atlanta-edge-03",
@@ -774,10 +789,13 @@
             "mgmtIpGateway": "",
             "mgmtIpNetmask": "",
             "offlineReason": null,
+            "physLocation": "Denver",
+            "profile": "EDGE1",
             "rack": "RR 119.02",
             "revalPending": false,
             "routerHostName": "",
             "routerPortName": "",
+            "status": "REPORTED",
             "tcpPort": 80,
             "type": "EDGE",
             "updPending": true,
@@ -785,6 +803,8 @@
             "xmppPasswd": "X"
         },
         {
+            "cachegroup": "cachegroup1",
+            "cdnName": "cdn1",
             "domainName": "ga.atlanta.kabletown.net",
             "guid": null,
             "hostName": "atlanta-edge-14",
@@ -806,10 +826,13 @@
             "mgmtIpGateway": "",
             "mgmtIpNetmask": "",
             "offlineReason": null,
+            "physLocation": "Denver",
+            "profile": "EDGE1",
             "rack": "RR 119.02",
             "revalPending": false,
             "routerHostName": "",
             "routerPortName": "",
+            "status": "REPORTED",
             "tcpPort": 80,
             "type": "EDGE",
             "updPending": true,
@@ -817,6 +840,8 @@
             "xmppPasswd": "X"
         },
         {
+            "cachegroup": "cachegroup1",
+            "cdnName": "cdn1",
             "domainName": "ga.atlanta.kabletown.net",
             "guid": null,
             "hostName": "atlanta-edge-15",
@@ -838,10 +863,13 @@
             "mgmtIpGateway": "",
             "mgmtIpNetmask": "",
             "offlineReason": null,
+            "physLocation": "Denver",
+            "profile": "EDGE1",
             "rack": "RR 119.02",
             "revalPending": false,
             "routerHostName": "",
             "routerPortName": "",
+            "status": "REPORTED",
             "tcpPort": 80,
             "type": "EDGE",
             "updPending": true,
@@ -849,6 +877,8 @@
             "xmppPasswd": "X"
         },
         {
+            "cachegroup": "cachegroup1",
+            "cdnName": "cdn1",
             "domainName": "ga.atlanta.kabletown.net",
             "guid": null,
             "hostName": "atlanta-mid-16",
@@ -870,10 +900,13 @@
             "mgmtIpGateway": "",
             "mgmtIpNetmask": "",
             "offlineReason": null,
+            "physLocation": "Denver",
+            "profile": "EDGE1",
             "rack": "RR 119.02",
             "revalPending": false,
             "routerHostName": "",
             "routerPortName": "",
+            "status": "REPORTED",
             "tcpPort": 80,
             "type": "MID",
             "updPending": true,
@@ -881,6 +914,8 @@
             "xmppPasswd": "X"
         },
         {
+            "cachegroup": "cachegroup1",
+            "cdnName": "cdn1",
             "domainName": "ga.atlanta.kabletown.net",
             "guid": null,
             "hostName": "atlanta-org-1",
@@ -902,10 +937,13 @@
             "mgmtIpGateway": "",
             "mgmtIpNetmask": "",
             "offlineReason": null,
+            "physLocation": "Denver",
+            "profile": "EDGE1",
             "rack": "RR 119.02",
             "revalPending": false,
             "routerHostName": "",
             "routerPortName": "",
+            "status": "REPORTED",
             "tcpPort": 80,
             "type": "EDGE",
             "updPending": true,
@@ -913,6 +951,8 @@
             "xmppPasswd": "X"
         },
         {
+            "cachegroup": "cachegroup1",
+            "cdnName": "cdn1",
             "domainName": "ga.atlanta.kabletown.net",
             "guid": null,
             "hostName": "atlanta-org-2",
@@ -934,10 +974,13 @@
             "mgmtIpGateway": "",
             "mgmtIpNetmask": "",
             "offlineReason": null,
+            "physLocation": "Denver",
+            "profile": "EDGE1",
             "rack": "RR 119.02",
             "revalPending": false,
             "routerHostName": "",
             "routerPortName": "",
+            "status": "REPORTED",
             "tcpPort": 80,
             "type": "EDGE",
             "updPending": true,
@@ -945,6 +988,8 @@
             "xmppPasswd": "X"
         },
         {
+            "cachegroup": "cachegroup1",
+            "cdnName": "cdn1",
             "domainName": "ga.atlanta.kabletown.net",
             "guid": null,
             "hostName": "atlanta-mid-01",
@@ -966,10 +1011,13 @@
             "mgmtIpGateway": "",
             "mgmtIpNetmask": "",
             "offlineReason": null,
+            "physLocation": "Denver",
+            "profile": "EDGE1",
             "rack": "RR 119.02",
             "revalPending": false,
             "routerHostName": "",
             "routerPortName": "",
+            "status": "REPORTED",
             "tcpPort": 80,
             "type": "MID",
             "updPending": true,
@@ -977,6 +1025,8 @@
             "xmppPasswd": "X"
         },
         {
+            "cachegroup": "cachegroup1",
+            "cdnName": "cdn1",
             "domainName": "kabletown.net",
             "guid": null,
             "hostName": "rascal01",
@@ -998,10 +1048,13 @@
             "mgmtIpGateway": "",
             "mgmtIpNetmask": "",
             "offlineReason": null,
+            "physLocation": "Denver",
+            "profile": "EDGE1",
             "rack": "RR 119.02",
             "revalPending": false,
             "routerHostName": "",
             "routerPortName": "",
+            "status": "REPORTED",
             "tcpPort": 81,
             "type": "TRAFFIC_MONITOR",
             "updPending": true,
@@ -1009,6 +1062,8 @@
             "xmppPasswd": "X"
         },
         {
+            "cachegroup": "cachegroup1",
+            "cdnName": "cdn1",
             "domainName": "local",
             "guid": null,
             "hostName": "riak",
@@ -1030,10 +1085,13 @@
             "mgmtIpGateway": "",
             "mgmtIpNetmask": "",
             "offlineReason": null,
+            "physLocation": "Denver",
+            "profile": "EDGE1",
             "rack": "RR 119.02",
             "revalPending": false,
             "routerHostName": "",
             "routerPortName": "",
+            "status": "REPORTED",
             "tcpPort": 8088,
             "type": "RIAK",
             "updPending": true,
@@ -1102,7 +1160,7 @@
         {
             "active": false,
             "name": "tenant2",
-            "parentName": "root"
+            "parentName": "tenant1"
         }
     ],
     "types": [
@@ -1317,7 +1375,7 @@
             "publicSshKey": "",
             "role": 4,
             "stateOrProvince": "LA",
-            "tenantId": 1,
+            "tenant": "root",
             "uid": 0,
             "username": "adminuser"
         },
@@ -1339,7 +1397,7 @@
             "registrationSent": "",
             "role": 1,
             "stateOrProvince": "",
-            "tenantId": 2,
+            "tenant": "tenant1",
             "uid": 0,
             "username": "disalloweduser"
         }
diff --git a/traffic_ops/testing/api/v14/tenants_test.go b/traffic_ops/testing/api/v14/tenants_test.go
index 431e7af92..fcf295b9c 100644
--- a/traffic_ops/testing/api/v14/tenants_test.go
+++ b/traffic_ops/testing/api/v14/tenants_test.go
@@ -19,6 +19,8 @@ import (
 	"strconv"
 	"strings"
 	"testing"
+
+	tc "github.com/apache/trafficcontrol/lib/go-tc"
 )
 
 func TestTenants(t *testing.T) {
@@ -30,21 +32,14 @@ func TestTenants(t *testing.T) {
 
 func CreateTestTenants(t *testing.T) {
 	for _, ten := range testData.Tenants {
-		// testData does not define ParentID -- look up by name and fill in
-		if ten.ParentID == 0 {
-			parent, _, err := TOSession.TenantByName(ten.ParentName)
-			if err != nil || parent == nil {
-				t.Errorf("parent tenant %s: %++v", ten.ParentName, err)
-				continue
-			}
-			ten.ParentID = parent.ID
-		}
 		resp, err := TOSession.CreateTenant(&ten)
-		t.Logf("response: %++v", resp)
 
 		if err != nil {
 			t.Errorf("could not CREATE tenant %s: %v\n", ten.Name, err)
 		}
+		if resp.Response.Name != ten.Name {
+			t.Errorf("expected tenant %+v; got %+v", ten, resp.Response)
+		}
 	}
 }
 
@@ -54,22 +49,23 @@ func GetTestTenants(t *testing.T) {
 		t.Errorf("cannot GET all tenants: %v - %v\n", err, resp)
 		return
 	}
+	foundTenants := make(map[string]tc.Tenant, len(resp))
+	for _, ten := range resp {
+		foundTenants[ten.Name] = ten
+	}
 
-	t.Logf("resp: %++v\n", resp)
 	// expect root and badTenant (defined in todb.go) + all defined in testData.Tenants
 	if len(resp) != 2+len(testData.Tenants) {
 		t.Errorf("expected %d tenants,  got %d", 2+len(testData.Tenants), len(resp))
 	}
 
 	for _, ten := range testData.Tenants {
-		resp, _, err := TOSession.TenantByName(ten.Name)
-		if err != nil {
-			t.Errorf("cannot GET Tenant by name: %v - %v\n", err, resp)
-			continue
-		}
-		if resp.Name != ten.Name {
-			t.Errorf("expected tenant %s,  got %s", ten.Name, resp.Name)
-			continue
+		if ft, ok := foundTenants[ten.Name]; ok {
+			if ft.ParentName != ten.ParentName {
+				t.Errorf("tenant %s: expected parent %s,  got %s", ten.Name, ten.ParentName, ft.ParentName)
+			}
+		} else {
+			t.Errorf("expected tenant %s: not found", ten.Name)
 		}
 	}
 }
@@ -84,26 +80,22 @@ func UpdateTestTenants(t *testing.T) {
 		t.Errorf("cannot GET Tenant by name: %s - %v\n", name, err)
 	}
 
-	t.Logf("modTenant is %++v", modTenant)
 	newParent, _, err := TOSession.TenantByName(parentName)
 	if err != nil {
 		t.Errorf("cannot GET Tenant by name: %s - %v\n", parentName, err)
 	}
-	t.Logf("newParent is %++v", newParent)
 	modTenant.ParentID = newParent.ID
 
-	resp, err := TOSession.UpdateTenant(strconv.Itoa(modTenant.ID), modTenant)
+	_, err = TOSession.UpdateTenant(strconv.Itoa(modTenant.ID), modTenant)
 	if err != nil {
 		t.Errorf("cannot UPDATE Tenant by id: %v\n", err)
 	}
 
-	t.Logf("AFTER UPDATE modTenant is %++v", modTenant)
 	// Retrieve the Tenant to check Tenant parent name got updated
 	respTenant, _, err := TOSession.Tenant(strconv.Itoa(modTenant.ID))
 	if err != nil {
 		t.Errorf("cannot GET Tenant by name: %v - %v\n", name, err)
 	}
-	t.Logf("modified: %++v", resp)
 	if respTenant.ParentName != parentName {
 		t.Errorf("results do not match actual: %s, expected: %s\n", respTenant.ParentName, parentName)
 	}
@@ -123,7 +115,7 @@ func DeleteTestTenants(t *testing.T) {
 	if err == nil {
 		t.Errorf("%s has child tenants -- should not be able to delete", t1)
 	}
-	expected := `Tenant '`+ strconv.Itoa(tenant1.ID) + `' has child tenants. Please update these child tenants and retry.`
+	expected := `Tenant '` + strconv.Itoa(tenant1.ID) + `' has child tenants. Please update these child tenants and retry.`
 	if !strings.Contains(err.Error(), expected) {
 		t.Errorf("expected error: %s;  got %s", expected, err.Error())
 	}
@@ -141,5 +133,4 @@ func DeleteTestTenants(t *testing.T) {
 	if err != nil {
 		t.Errorf("error deleting tenant %s: %v", t1, err)
 	}
-
 }
diff --git a/traffic_ops/testing/api/v14/user_test.go b/traffic_ops/testing/api/v14/user_test.go
index ba24c94a0..323956439 100644
--- a/traffic_ops/testing/api/v14/user_test.go
+++ b/traffic_ops/testing/api/v14/user_test.go
@@ -15,14 +15,17 @@ package v14
 */
 
 import (
+	"strings"
+	"testing"
+
 	"github.com/apache/trafficcontrol/lib/go-log"
 	"github.com/apache/trafficcontrol/lib/go-tc"
-	"testing"
 )
 
 func TestUsers(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestProfiles(t)
 	CreateTestStatuses(t)
 	CreateTestDivisions(t)
@@ -37,6 +40,7 @@ func TestUsers(t *testing.T) {
 	GetTestUserCurrent(t)
 	//Delete will be new functionality to 1.4, ignore for now
 	//DeleteTestUsers(t)
+	ForceDeleteTestUsers(t)
 
 	DeleteTestDeliveryServices(t)
 	DeleteTestCacheGroups(t)
@@ -45,6 +49,7 @@ func TestUsers(t *testing.T) {
 	DeleteTestDivisions(t)
 	DeleteTestStatuses(t)
 	DeleteTestProfiles(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 
@@ -95,20 +100,46 @@ func UpdateTestUsers(t *testing.T) {
 func GetTestUsers(t *testing.T) {
 	_, _, err := TOSession.GetUsers()
 	if err != nil {
-		t.Fatalf("cannot GET users: %v\n", err)
+		t.Errorf("cannot GET users: %v\n", err)
 	}
 }
 
 func GetTestUserCurrent(t *testing.T) {
 	user, _, err := TOSession.GetUserCurrent()
 	if err != nil {
-		t.Fatalf("cannot GET current user: %v\n", err)
+		t.Errorf("cannot GET current user: %v\n", err)
 	}
 	if user.UserName == nil {
-		t.Fatalf("current user expected: %v actual: %v\n", SessionUserName, nil)
+		t.Errorf("current user expected: %v actual: %v\n", SessionUserName, nil)
 	}
 	if *user.UserName != SessionUserName {
-		t.Fatalf("current user expected: %v actual: %v\n", SessionUserName, *user.UserName)
+		t.Errorf("current user expected: %v actual: %v\n", SessionUserName, *user.UserName)
+	}
+}
+
+// ForceDeleteTestUsers forcibly deletes the users from the db.
+func ForceDeleteTestUsers(t *testing.T) {
+
+	// NOTE: Special circumstances!  This should *NOT* be done without a really good reason!
+	//  Connects directly to the DB to remove users rather than going thru the client.
+	//  This is required here because the DeleteUser action does not really delete users,  but disables them.
+	db, err := OpenConnection()
+	if err != nil {
+		t.Errorf("cannot open db")
+	}
+	defer db.Close()
+
+	var usernames []string
+	for _, user := range testData.Users {
+		usernames = append(usernames, `'`+*user.Username+`'`)
+	}
+
+	q := `DELETE FROM tm_user WHERE username IN (` + strings.Join(usernames, ",") + `)`
+
+	err = execSQL(db, q, "tm_user")
+
+	if err != nil {
+		t.Errorf("cannot execute SQL: %s; SQL is %s", err.Error(), q)
 	}
 }
 
diff --git a/traffic_ops/testing/api/v14/userdeliveryservices_test.go b/traffic_ops/testing/api/v14/userdeliveryservices_test.go
index cec199cb4..b7b4af112 100644
--- a/traffic_ops/testing/api/v14/userdeliveryservices_test.go
+++ b/traffic_ops/testing/api/v14/userdeliveryservices_test.go
@@ -20,9 +20,10 @@ import (
 	"testing"
 )
 
-func TestUsersDeliveryServices(t *testing.T) {
+func TestUserDeliveryServices(t *testing.T) {
 	CreateTestCDNs(t)
 	CreateTestTypes(t)
+	CreateTestTenants(t)
 	CreateTestProfiles(t)
 	CreateTestStatuses(t)
 	CreateTestDivisions(t)
@@ -42,6 +43,7 @@ func TestUsersDeliveryServices(t *testing.T) {
 	DeleteTestDivisions(t)
 	DeleteTestStatuses(t)
 	DeleteTestProfiles(t)
+	DeleteTestTenants(t)
 	DeleteTestTypes(t)
 	DeleteTestCDNs(t)
 }
@@ -53,17 +55,17 @@ func CreateTestUsersDeliveryServices(t *testing.T) {
 
 	dses, _, err := TOSession.GetDeliveryServices()
 	if err != nil {
-		t.Fatalf("cannot GET DeliveryServices: %v - %v\n", err, dses)
+		t.Errorf("cannot GET DeliveryServices: %v - %v\n", err, dses)
 	}
 	if len(dses) == 0 {
-		t.Fatalf("no delivery services, must have at least 1 ds to test users_deliveryservices\n")
+		t.Errorf("no delivery services, must have at least 1 ds to test users_deliveryservices\n")
 	}
 	users, _, err := TOSession.GetUsers()
 	if err != nil {
-		t.Fatalf("cannot GET users: %v\n", err)
+		t.Errorf("cannot GET users: %v\n", err)
 	}
 	if len(users) == 0 {
-		t.Fatalf("no users, must have at least 1 user to test users_deliveryservices\n")
+		t.Errorf("no users, must have at least 1 user to test users_deliveryservices\n")
 	}
 
 	dsIDs := []int{}
@@ -81,33 +83,33 @@ func CreateTestUsersDeliveryServices(t *testing.T) {
 		}
 	}
 	if !foundUser {
-		t.Fatalf("get users expected: %v actual: missing\n", TestUsersDeliveryServicesUser)
+		t.Errorf("get users expected: %v actual: missing\n", TestUsersDeliveryServicesUser)
 	}
 
 	_, err = TOSession.SetDeliveryServiceUser(userID, dsIDs, true)
 	if err != nil {
-		t.Fatalf("failed to set delivery service users: " + err.Error())
+		t.Errorf("failed to set delivery service users: " + err.Error())
 	}
 
 	userDSes, _, err := TOSession.GetUserDeliveryServices(userID)
 	if err != nil {
-		t.Fatalf("get user delivery services returned error: " + err.Error())
+		t.Errorf("get user delivery services returned error: " + err.Error())
 	}
 
 	if len(userDSes.Response) != len(dsIDs) {
-		t.Fatalf("get user delivery services expected %v actual %v\n", len(dsIDs), len(userDSes.Response))
+		t.Errorf("get user delivery services expected %v actual %v\n", len(dsIDs), len(userDSes.Response))
 	}
 
 	actualDSIDMap := map[int]struct{}{}
 	for _, userDS := range userDSes.Response {
 		if userDS.ID == nil {
-			t.Fatalf("get user delivery services returned a DS with a nil ID\n")
+			t.Errorf("get user delivery services returned a DS with a nil ID\n")
 		}
 		actualDSIDMap[*userDS.ID] = struct{}{}
 	}
 	for _, dsID := range dsIDs {
 		if _, ok := actualDSIDMap[dsID]; !ok {
-			t.Fatalf("get user delivery services expected %v actual %v\n", dsID, "missing")
+			t.Errorf("get user delivery services expected %v actual %v\n", dsID, "missing")
 		}
 	}
 }
@@ -117,17 +119,17 @@ func GetTestUsersDeliveryServices(t *testing.T) {
 
 	dses, _, err := TOSession.GetDeliveryServices()
 	if err != nil {
-		t.Fatalf("cannot GET DeliveryServices: %v - %v\n", err, dses)
+		t.Errorf("cannot GET DeliveryServices: %v - %v\n", err, dses)
 	}
 	if len(dses) == 0 {
-		t.Fatalf("no delivery services, must have at least 1 ds to test users_deliveryservices\n")
+		t.Errorf("no delivery services, must have at least 1 ds to test users_deliveryservices\n")
 	}
 	users, _, err := TOSession.GetUsers()
 	if err != nil {
-		t.Fatalf("cannot GET users: %v\n", err)
+		t.Errorf("cannot GET users: %v\n", err)
 	}
 	if len(users) == 0 {
-		t.Fatalf("no users, must have at least 1 user to test users_deliveryservices\n")
+		t.Errorf("no users, must have at least 1 user to test users_deliveryservices\n")
 	}
 
 	dsIDs := []int64{}
@@ -145,28 +147,28 @@ func GetTestUsersDeliveryServices(t *testing.T) {
 		}
 	}
 	if !foundUser {
-		t.Fatalf("get users expected: %v actual: missing\n", TestUsersDeliveryServicesUser)
+		t.Errorf("get users expected: %v actual: missing\n", TestUsersDeliveryServicesUser)
 	}
 
 	userDSes, _, err := TOSession.GetUserDeliveryServices(userID)
 	if err != nil {
-		t.Fatalf("get user delivery services returned error: " + err.Error() + "\n")
+		t.Errorf("get user delivery services returned error: " + err.Error() + "\n")
 	}
 
 	if len(userDSes.Response) != len(dsIDs) {
-		t.Fatalf("get user delivery services expected %v actual %v\n", len(dsIDs), len(userDSes.Response))
+		t.Errorf("get user delivery services expected %v actual %v\n", len(dsIDs), len(userDSes.Response))
 	}
 
 	actualDSIDMap := map[int]struct{}{}
 	for _, userDS := range userDSes.Response {
 		if userDS.ID == nil {
-			t.Fatalf("get user delivery services returned a DS with a nil ID\n")
+			t.Errorf("get user delivery services returned a DS with a nil ID\n")
 		}
 		actualDSIDMap[*userDS.ID] = struct{}{}
 	}
 	for _, dsID := range dsIDs {
 		if _, ok := actualDSIDMap[int(dsID)]; !ok {
-			t.Fatalf("get user delivery services expected %v actual %v\n", dsID, "missing")
+			t.Errorf("get user delivery services expected %v actual %v\n", dsID, "missing")
 		}
 	}
 }
@@ -176,10 +178,10 @@ func DeleteTestUsersDeliveryServices(t *testing.T) {
 
 	users, _, err := TOSession.GetUsers()
 	if err != nil {
-		t.Fatalf("cannot GET users: %v\n", err)
+		t.Errorf("cannot GET users: %v\n", err)
 	}
 	if len(users) == 0 {
-		t.Fatalf("no users, must have at least 1 user to test users_deliveryservices\n")
+		t.Errorf("no users, must have at least 1 user to test users_deliveryservices\n")
 	}
 	userID := 0
 	foundUser := false
@@ -191,32 +193,32 @@ func DeleteTestUsersDeliveryServices(t *testing.T) {
 		}
 	}
 	if !foundUser {
-		t.Fatalf("get users expected: %v actual: missing\n", TestUsersDeliveryServicesUser)
+		t.Errorf("get users expected: %v actual: missing\n", TestUsersDeliveryServicesUser)
 	}
 
 	dses, _, err := TOSession.GetUserDeliveryServices(userID)
 	if err != nil {
-		t.Fatalf("get user delivery services returned error: " + err.Error())
+		t.Errorf("get user delivery services returned error: " + err.Error())
 	}
 	if len(dses.Response) == 0 {
-		t.Fatalf("get user delivery services expected %v actual %v\n", ">0", "0")
+		t.Errorf("get user delivery services expected %v actual %v\n", ">0", "0")
 	}
 
 	for _, ds := range dses.Response {
 		if ds.ID == nil {
-			t.Fatalf("get user delivery services returned ds with nil ID\n")
+			t.Errorf("get user delivery services returned ds with nil ID\n")
 		}
 		_, err := TOSession.DeleteDeliveryServiceUser(userID, *ds.ID)
 		if err != nil {
-			t.Fatalf("delete user delivery service returned error: " + err.Error())
+			t.Errorf("delete user delivery service returned error: " + err.Error())
 		}
 	}
 
 	dses, _, err = TOSession.GetUserDeliveryServices(userID)
 	if err != nil {
-		t.Fatalf("get user delivery services returned error: " + err.Error())
+		t.Errorf("get user delivery services returned error: " + err.Error())
 	}
 	if len(dses.Response) != 0 {
-		t.Fatalf("get user delivery services after deleting expected %v actual %v\n", "0", len(dses.Response))
+		t.Errorf("get user delivery services after deleting expected %v actual %v\n", "0", len(dses.Response))
 	}
 }


 

----------------------------------------------------------------
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