You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by da...@apache.org on 2018/09/20 16:39:44 UTC

[trafficcontrol] branch master updated: User client and tests

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 3683505  User client and tests
3683505 is described below

commit 3683505479e712d42688440125cb579a702f8897
Author: moltzaum <ma...@moltzau.net>
AuthorDate: Thu Sep 20 09:13:01 2018 -0600

    User client and tests
---
 lib/go-tc/users.go                                 | 161 ++++++++++-----------
 traffic_ops/client/user.go                         |  80 +++++++++-
 traffic_ops/testing/api/v13/tc-fixtures.json       | 101 +------------
 traffic_ops/testing/api/v13/traffic_control.go     |   3 +-
 traffic_ops/testing/api/v13/user_test.go           |  83 +++++++++--
 .../testing/api/v13/userdeliveryservices_test.go   |  12 +-
 6 files changed, 239 insertions(+), 201 deletions(-)

diff --git a/lib/go-tc/users.go b/lib/go-tc/users.go
index 5bb740f..1a5391d 100644
--- a/lib/go-tc/users.go
+++ b/lib/go-tc/users.go
@@ -19,114 +19,111 @@ package tc
  * under the License.
  */
 
-import (
-	"time"
-)
-
-// UsersResponse ...
-type UsersResponse struct {
-	Response []User `json:"response"`
+// UserCredentials contains Traffic Ops login credentials
+type UserCredentials struct {
+	Username string `json:"u"`
+	Password string `json:"p"`
 }
 
-// User contains information about a given user in Traffic Ops.
-type User struct {
-	Username         string    `json:"username,omitempty"`
-	PublicSSHKey     string    `json:"publicSshKey,omitempty"`
-	Role             int       `json:"role,omitempty"`
-	RoleName         string    `json:"rolename,omitempty"`
-	ID               int       `json:"id,omitempty"`
-	UID              int       `json:"uid,omitempty"`
-	GID              int       `json:"gid,omitempty"`
-	Company          string    `json:"company,omitempty"`
-	Email            string    `json:"email,omitempty"`
-	FullName         string    `json:"fullName,omitempty"`
-	NewUser          bool      `json:"newUser,omitempty"`
-	LastUpdated      string    `json:"lastUpdated,omitempty"`
+// UserV13 contains non-nullable TO user information
+type UserV13 struct {
+	Username         string    `json:"username"`
+	PublicSSHKey     string    `json:"publicSshKey"`
+	Role             int       `json:"role"`
+	RoleName         string    `json:"rolename"`
+	ID               int       `json:"id"`
+	UID              int       `json:"uid"`
+	GID              int       `json:"gid"`
+	Company          string    `json:"company"`
+	Email            string    `json:"email"`
+	FullName         string    `json:"fullName"`
+	NewUser          bool      `json:"newUser"`
+	LastUpdated      string    `json:"lastUpdated"`
 	AddressLine1     string    `json:"addressLine1"`
 	AddressLine2     string    `json:"addressLine2"`
 	City             string    `json:"city"`
 	Country          string    `json:"country"`
 	PhoneNumber      string    `json:"phoneNumber"`
 	PostalCode       string    `json:"postalCode"`
-	RegistrationSent time.Time `json:"registrationSent"`
+	RegistrationSent TimeNoMod `json:"registrationSent"`
 	StateOrProvince  string    `json:"stateOrProvince"`
 	Tenant           string    `json:"tenant"`
 	TenantID         int       `json:"tenantId"`
 }
 
-// Credentials contains Traffic Ops login credentials
-type UserCredentials struct {
-	Username string `json:"u"`
-	Password string `json:"p"`
+// commonUserFields is unexported, but its contents are still visible when it is embedded
+// LastUpdated is a new field for some structs
+type commonUserFields struct {
+	AddressLine1    *string `json:"addressLine1" db:"address_line1"`
+	AddressLine2    *string `json:"addressLine2" db:"address_line2"`
+	City            *string `json:"city" db:"city"`
+	Company         *string `json:"company" db:"company"`
+	Country         *string `json:"country" db:"country"`
+	Email           *string `json:"email" db:"email"`
+	FullName        *string `json:"fullName" db:"full_name"`
+	GID             *int    `json:"gid"`
+	ID              *int    `json:"id" db:"id"`
+	NewUser         *bool   `json:"newUser" db:"new_user"`
+	PhoneNumber     *string `json:"phoneNumber" db:"phone_number"`
+	PostalCode      *string `json:"postalCode" db:"postal_code"`
+	PublicSSHKey    *string `json:"publicSshKey" db:"public_ssh_key"`
+	Role            *int    `json:"role" db:"role"`
+	RoleName        *string `json:"rolename"`
+	StateOrProvince *string `json:"stateOrProvince" db:"state_or_province"`
+	Tenant          *string `json:"tenant"`
+	TenantID        *int    `json:"tenantId" db:"tenant_id"`
+	UID             *int    `json:"uid"`
+	//Username        *string    `json:"username" db:"username"`  //not including major change due to naming incompatibility
+	LastUpdated *TimeNoMod `json:"lastUpdated" db:"last_updated"` //including minor change to add field
 }
 
-// TODO reconcile APIUser and User
+// User fields in v14 have been updated to be nullable. omitempty is used to protect password data
+type User struct {
+	Username             *string    `json:"username" db:"username"`
+	RegistrationSent     *TimeNoMod `json:"registrationSent" db:"registration_sent"`
+	ConfirmLocalPassword *string    `json:"confirmLocalPasswd,omitempty" db:"confirm_local_passwd"`
+	LocalPassword        *string    `json:"localPasswd,omitempty" db:"local_passwd"`
+	commonUserFields
+}
 
-type APIUser struct {
-	AddressLine1     *string    `json:"addressLine1", db:"address_line1"`
-	AddressLine2     *string    `json:"addressLine2" db:"address_line2"`
-	City             *string    `json:"city" db:"city"`
-	Company          *string    `json:"company,omitempty" db:"company"`
-	Country          *string    `json:"country" db:"country"`
-	Email            *string    `json:"email" db:"email"`
-	FullName         *string    `json:"fullName" db:"full_name"`
-	GID              *int       `json:"gid" db:"gid"`
-	ID               *int       `json:"id" db:"id"`
-	LastUpdated      *time.Time `json:"lastUpdated" db:"last_updated"`
-	NewUser          *bool      `json:"newUser" db:"new_user"`
-	PhoneNumber      *string    `json:"phoneNumber" db:"phone_number"`
-	PostalCode       *string    `json:"postalCode" db:"postal_code"`
-	PublicSSHKey     *string    `json:"publicSshKey" db:"public_ssh_key"`
-	RegistrationSent *time.Time `json:"registrationSent" db:"registration_sent"`
-	Role             *int       `json:"role" db:"role"`
-	RoleName         *string    `json:"rolename"`
-	StateOrProvince  *string    `json:"stateOrProvince" db:"state_or_province"`
-	Tenant           *string    `json:"tenant"`
-	TenantID         *int       `json:"tenantId" db:"tenant_id"`
-	UID              *int       `json:"uid" db:"uid"`
-	UserName         *string    `json:"username" db:"username"`
+// UserCurrent represents the profile for the authenticated user
+type UserCurrent struct {
+	UserName  *string `json:"username"`
+	LocalUser *bool   `json:"localUser"`
+	commonUserFields
 }
 
-type APIUserPost struct {
-	APIUser
-	ConfirmLocalPassword *string `json:"confirmLocalPassword" db:"confirm_local_passwd"`
-	LocalPassword        *string `json:"localPassword" db:"local_passwd"`
+// ------------------- Response structs -------------------- //
+//  Response structs should only be used in the client       //
+//  The client's use of these will eventually be deprecated  //
+// --------------------------------------------------------- //
+
+type UsersResponseV13 struct {
+	Response []UserV13 `json:"response"`
 }
 
-type APIUsersResponse struct {
-	Response []APIUser `json:"response"`
+type UsersResponse struct {
+	Response []User `json:"response"`
 }
 
-type UserDeliveryServiceDeleteResponse struct {
-	Alerts []Alert `json:"alerts"`
+type CreateUserResponse struct {
+	Response User `json:"response"`
+	Alerts
 }
 
-// UserCurrent contains all the user info about the current user, as returned by /api/1.x/user/current
-type UserCurrent struct {
-	AddressLine1    *string `json:"addressLine1"`
-	AddressLine2    *string `json:"addressLine2"`
-	City            *string `json:"city"`
-	Company         *string `json:"company,omitempty"`
-	Country         *string `json:"country"`
-	Email           *string `json:"email,omitempty"`
-	FullName        *string `json:"fullName,omitempty"`
-	GID             *int    `json:"gid,omitempty"`
-	ID              *int    `json:"id,omitempty"`
-	LastUpdated     *string `json:"lastUpdated,omitempty"`
-	LocalUser       *bool   `json:"localUser"`
-	NewUser         *bool   `json:"newUser,omitempty"`
-	PhoneNumber     *string `json:"phoneNumber"`
-	PostalCode      *string `json:"postalCode"`
-	PublicSSHKey    *string `json:"publicSshKey,omitempty"`
-	Role            *int    `json:"role,omitempty"`
-	RoleName        *string `json:"roleName,omitempty"`
-	StateOrProvince *string `json:"stateOrProvince"`
-	Tenant          *string `json:"tenant"`
-	TenantID        *uint64 `json:"tenantId"`
-	UID             *int    `json:"uid,omitempty"`
-	UserName        *string `json:"username,omitempty"`
+type UpdateUserResponse struct {
+	Response User `json:"response"`
+	Alerts
+}
+
+type DeleteUserResponse struct {
+	Alerts
 }
 
 type UserCurrentResponse struct {
 	Response UserCurrent `json:"response"`
 }
+
+type UserDeliveryServiceDeleteResponse struct {
+	Alerts
+}
diff --git a/traffic_ops/client/user.go b/traffic_ops/client/user.go
index b7ca1b1..f248a3c 100644
--- a/traffic_ops/client/user.go
+++ b/traffic_ops/client/user.go
@@ -17,6 +17,10 @@ package client
 
 import (
 	"encoding/json"
+	"fmt"
+	"net"
+	"net/http"
+	"strconv"
 
 	"github.com/apache/trafficcontrol/lib/go-tc"
 )
@@ -28,9 +32,10 @@ func (to *Session) Users() ([]tc.User, error) {
 	return us, err
 }
 
+// GetUsers returns all users accessible from current user
 func (to *Session) GetUsers() ([]tc.User, ReqInf, error) {
-	url := apiBase + "/users.json"
-	resp, remoteAddr, err := to.request("GET", url, nil)
+	route := apiBase + "/users.json"
+	resp, remoteAddr, err := to.request("GET", route, nil)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
 	if err != nil {
 		return nil, reqInf, err
@@ -45,13 +50,80 @@ func (to *Session) GetUsers() ([]tc.User, ReqInf, error) {
 	return data.Response, reqInf, nil
 }
 
+func (to *Session) GetUserByID(id int) ([]tc.User, ReqInf, error) {
+	data := tc.UsersResponse{}
+	route := fmt.Sprintf("%s/users/%d", apiBase, id)
+	inf, err := get(to, route, &data)
+	return data.Response, inf, err
+}
+
+func (to *Session) GetUserByUsername(username string) ([]tc.User, ReqInf, error) {
+	data := tc.UsersResponse{}
+	route := fmt.Sprintf("%s/users?username=%s", apiBase, username)
+	inf, err := get(to, route, &data)
+	return data.Response, inf, err
+}
+
 // GetUserCurrent gets information about the current user
 func (to *Session) GetUserCurrent() (*tc.UserCurrent, ReqInf, error) {
-	url := apiBase + `/user/current`
+	route := apiBase + `/user/current`
 	resp := tc.UserCurrentResponse{}
-	reqInf, err := get(to, url, &resp)
+	reqInf, err := get(to, route, &resp)
 	if err != nil {
 		return nil, reqInf, err
 	}
 	return &resp.Response, reqInf, nil
 }
+
+// CreateUser creates a user
+func (to *Session) CreateUser(user *tc.User) (*tc.CreateUserResponse, ReqInf, error) {
+	var remoteAddr net.Addr
+	reqBody, err := json.Marshal(user)
+	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
+	if err != nil {
+		return nil, reqInf, err
+	}
+	route := apiBase + "/users.json"
+	resp, remoteAddr, err := to.request(http.MethodPost, route, reqBody)
+	if err != nil {
+		return nil, reqInf, err
+	}
+	defer resp.Body.Close()
+	var clientResp tc.CreateUserResponse
+	err = json.NewDecoder(resp.Body).Decode(&clientResp)
+	return &clientResp, reqInf, nil
+}
+
+// UpdateUserByID updates user with the given id
+func (to *Session) UpdateUserByID(id int, u *tc.User) (*tc.UpdateUserResponse, ReqInf, error) {
+
+	var remoteAddr net.Addr
+	reqBody, err := json.Marshal(u)
+	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
+	if err != nil {
+		return nil, reqInf, err
+	}
+	route := apiBase + "/users/" + strconv.Itoa(id)
+	resp, remoteAddr, err := to.request(http.MethodPut, route, reqBody)
+	if err != nil {
+		return nil, reqInf, err
+	}
+	defer resp.Body.Close()
+	var clientResp tc.UpdateUserResponse
+	err = json.NewDecoder(resp.Body).Decode(&clientResp)
+	return &clientResp, reqInf, nil
+}
+
+// DeleteUserByID updates user with the given id
+func (to *Session) DeleteUserByID(id int) (tc.Alerts, ReqInf, error) {
+	route := apiBase + "/users/" + strconv.Itoa(id)
+	resp, remoteAddr, err := to.request(http.MethodDelete, route, nil)
+	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
+	if err != nil {
+		return tc.Alerts{}, reqInf, err
+	}
+	defer resp.Body.Close()
+	var alerts tc.Alerts
+	err = json.NewDecoder(resp.Body).Decode(&alerts)
+	return alerts, reqInf, nil
+}
diff --git a/traffic_ops/testing/api/v13/tc-fixtures.json b/traffic_ops/testing/api/v13/tc-fixtures.json
index 1a6a58b..eb786c7 100644
--- a/traffic_ops/testing/api/v13/tc-fixtures.json
+++ b/traffic_ops/testing/api/v13/tc-fixtures.json
@@ -1310,14 +1310,14 @@
             "fullName": "Fred the admin",
             "gid": 0,
             "localPasswd": "pa$$word",
+            "confirmLocalPasswd": "pa$$word",
             "newUser": false,
             "phoneNumber": "810-555-9876",
             "postalCode": "55443",
             "publicSshKey": "",
             "role": 4,
-            "rolename": "admin",
             "stateOrProvince": "LA",
-            "tenant": "root",
+            "tenantId": 1,
             "uid": 0,
             "username": "adminuser"
         },
@@ -1331,110 +1331,17 @@
             "fullName": "Me me",
             "gid": 0,
             "localPasswd": "pa$$word",
+            "confirmLocalPasswd": "pa$$word",
             "newUser": false,
             "phoneNumber": "",
             "postalCode": "",
             "publicSshKey": "",
             "registrationSent": "",
             "role": 1,
-            "roleName": "disallowed",
             "stateOrProvince": "",
-            "tenant": "root",
-            "tenant": 3,
+            "tenantId": 2,
             "uid": 0,
             "username": "disalloweduser"
-        },
-        {
-            "addressLine1": "address of read-only",
-            "addressLine2": "",
-            "city": "",
-            "company": "",
-            "country": "",
-            "email": "readonly@example.com",
-            "fullName": "",
-            "gid": 0,
-            "localPasswd": "pa$$word",
-            "newUser": false,
-            "phoneNumber": "",
-            "postalCode": "",
-            "publicSshKey": "",
-            "registrationSent": "",
-            "role": 2,
-            "roleName": "read-only user",
-            "stateOrProvince": "",
-            "tenant": "root",
-            "tenant": 3,
-            "uid": 0,
-            "username": "readuser"
-        },
-        {
-            "addressLine1": "address of operations",
-            "addressLine2": "",
-            "city": "",
-            "company": "",
-            "country": "",
-            "email": "operations@example.com",
-            "fullName": "",
-            "gid": 0,
-            "localPasswd": "pa$$word",
-            "newUser": false,
-            "phoneNumber": "",
-            "postalCode": "",
-            "publicSshKey": "",
-            "registrationSent": "",
-            "role": 3,
-            "roleName": "operations",
-            "stateOrProvince": "",
-            "tenant": "root",
-            "tenant": 4,
-            "uid": 0,
-            "username": "operationsuser"
-        },
-        {
-            "addressLine1": "",
-            "addressLine2": "",
-            "city": "",
-            "company": "",
-            "country": "",
-            "email": "portal@example.com",
-            "fullName": "",
-            "gid": 0,
-            "localPasswd": "pa$$word",
-            "newUser": false,
-            "phoneNumber": "",
-            "postalCode": "",
-            "publicSshKey": "",
-            "registrationSent": "",
-            "role": 5,
-            "roleName": "portal",
-            "stateOrProvince": "",
-            "tenant": "root",
-            "tenant": 2,
-            "uid": 0,
-            "username": "portaluser"
-        },
-        {
-            "addressLine1": "",
-            "addressLine2": "",
-            "city": "",
-            "company": "",
-            "country": "",
-            "email": "federation@example.com",
-            "fullName": "",
-            "gid": 0,
-            "localPasswd": "pa$$word",
-            "newUser": false,
-            "phoneNumber": "",
-            "postalCode": "",
-            "publicSshKey": "",
-            "registrationSent": "",
-            "role": 7,
-            "roleName": "federation",
-            "stateOrProvince": "",
-            "tenant": "root",
-            "tenant": 4,
-            "uid": 0,
-            "username": "federationuser"
         }
     ],
     "steeringTargets": [
diff --git a/traffic_ops/testing/api/v13/traffic_control.go b/traffic_ops/testing/api/v13/traffic_control.go
index 625855c..7c8d492 100644
--- a/traffic_ops/testing/api/v13/traffic_control.go
+++ b/traffic_ops/testing/api/v13/traffic_control.go
@@ -24,12 +24,12 @@ type TrafficControl struct {
 	ASNs                           []tc.ASN                           `json:"asns"`
 	CDNs                           []tc.CDN                           `json:"cdns"`
 	CacheGroups                    []tc.CacheGroupNullable            `json:"cachegroups"`
+	Coordinates                    []tc.Coordinate                    `json:"coordinates"`
 	DeliveryServiceRequests        []tc.DeliveryServiceRequest        `json:"deliveryServiceRequests"`
 	DeliveryServiceRequestComments []tc.DeliveryServiceRequestComment `json:"deliveryServiceRequestComments"`
 	DeliveryServices               []tc.DeliveryService               `json:"deliveryservices"`
 	Divisions                      []tc.Division                      `json:"divisions"`
 	Federations                    []tc.CDNFederation                 `json:"federations"`
-	Coordinates                    []tc.Coordinate                    `json:"coordinates"`
 	Origins                        []tc.Origin                        `json:"origins"`
 	Profiles                       []tc.Profile                       `json:"profiles"`
 	Parameters                     []tc.Parameter                     `json:"parameters"`
@@ -43,4 +43,5 @@ type TrafficControl struct {
 	Tenants                        []tc.Tenant                        `json:"tenants"`
 	Types                          []tc.Type                          `json:"types"`
 	SteeringTargets                []tc.SteeringTargetNullable        `json:"steeringTargets"`
+	Users                          []tc.User                          `json:"users"`
 }
diff --git a/traffic_ops/testing/api/v13/user_test.go b/traffic_ops/testing/api/v13/user_test.go
index 7485b41..483e0dd 100644
--- a/traffic_ops/testing/api/v13/user_test.go
+++ b/traffic_ops/testing/api/v13/user_test.go
@@ -15,8 +15,8 @@ package v13
 */
 
 import (
-	"encoding/json"
 	"github.com/apache/trafficcontrol/lib/go-log"
+	"github.com/apache/trafficcontrol/lib/go-tc"
 	"testing"
 )
 
@@ -31,8 +31,12 @@ func TestUsers(t *testing.T) {
 	CreateTestCacheGroups(t)
 	CreateTestDeliveryServices(t)
 
+	CreateTestUsers(t)
+	UpdateTestUsers(t)
 	GetTestUsers(t)
 	GetTestUserCurrent(t)
+	//Delete will be new functionality to 1.4, ignore for now
+	//DeleteTestUsers(t)
 
 	DeleteTestDeliveryServices(t)
 	DeleteTestCacheGroups(t)
@@ -48,25 +52,54 @@ func TestUsers(t *testing.T) {
 
 const SessionUserName = "admin" // TODO make dynamic?
 
-func GetTestUsers(t *testing.T) {
+func CreateTestUsers(t *testing.T) {
+	for _, user := range testData.Users {
+
+		resp, _, err := TOSession.CreateUser(&user)
+		log.Debugln("Response: ", resp.Alerts)
+
+		if err != nil {
+			t.Errorf("could not CREATE user: %v\n", err)
+		}
+	}
+}
 
-	resp, _, err := TOSession.GetUsers()
+func UpdateTestUsers(t *testing.T) {
+	firstUsername := *testData.Users[0].Username
+	resp, _, err := TOSession.GetUserByUsername(firstUsername)
 	if err != nil {
-		t.Fatalf("cannot GET users: %v\n", err)
+		t.Errorf("cannot GET user by name: '%s', %v\n", firstUsername, err)
+	}
+	user := resp[0]
+	newCity := "kidz kable kown"
+	*user.City = newCity
+
+	var updateResp *tc.UpdateUserResponse
+	updateResp, _, err = TOSession.UpdateUserByID(*user.ID, &user)
+	if err != nil {
+		t.Errorf("cannot UPDATE user by id: %v - %v\n", err, updateResp.Alerts)
+	}
+
+	// Make sure it got updated
+	resp2, _, err := TOSession.GetUserByID(*user.ID)
+	updatedUser := resp2[0]
+
+	if err != nil {
+		t.Errorf("cannot GET user by id: '%d', %v\n", *user.ID, err)
 	}
-	if len(resp) == 0 {
-		t.Fatalf("no users, must have at least 1 user to test\n")
+	if *updatedUser.City != newCity {
+		t.Errorf("results do not match actual: %s, expected: %s\n", *updatedUser.City, newCity)
 	}
+}
 
-	log.Debugf("Response: %s\n")
-	for _, user := range resp {
-		bytes, _ := json.Marshal(user)
-		log.Debugf("%s\n", bytes)
+func GetTestUsers(t *testing.T) {
+	_, _, err := TOSession.GetUsers()
+	if err != nil {
+		t.Fatalf("cannot GET users: %v\n", err)
 	}
 }
 
 func GetTestUserCurrent(t *testing.T) {
-	log.Debugln("GetTestUserCurrent")
 	user, _, err := TOSession.GetUserCurrent()
 	if err != nil {
 		t.Fatalf("cannot GET current user: %v\n", err)
@@ -78,3 +111,31 @@ func GetTestUserCurrent(t *testing.T) {
 		t.Fatalf("current user expected: %v actual: %v\n", SessionUserName, *user.UserName)
 	}
 }
+
+func DeleteTestUsers(t *testing.T) {
+	for _, user := range testData.Users {
+
+		resp, _, err := TOSession.GetUserByUsername(*user.Username)
+		if err != nil {
+			t.Errorf("cannot GET user by name: %v - %v\n", *user.Username, err)
+		}
+
+		if resp != nil {
+			respUser := resp[0]
+
+			_, _, err := TOSession.DeleteUserByID(*respUser.ID)
+			if err != nil {
+				t.Errorf("cannot DELETE user by name: '%s' %v\n", *respUser.Username, err)
+			}
+
+			// Make sure it got deleted
+			resp, _, err := TOSession.GetUserByUsername(*user.Username)
+			if err != nil {
+				t.Errorf("error deleting user by name: %s\n", err.Error())
+			}
+			if len(resp) > 0 {
+				t.Errorf("expected user: %s to be deleted\n", *user.Username)
+			}
+		}
+	}
+}
diff --git a/traffic_ops/testing/api/v13/userdeliveryservices_test.go b/traffic_ops/testing/api/v13/userdeliveryservices_test.go
index 2b07f87..474f8aa 100644
--- a/traffic_ops/testing/api/v13/userdeliveryservices_test.go
+++ b/traffic_ops/testing/api/v13/userdeliveryservices_test.go
@@ -74,8 +74,8 @@ func CreateTestUsersDeliveryServices(t *testing.T) {
 	userID := 0
 	foundUser := false
 	for _, user := range users {
-		if user.Username == TestUsersDeliveryServicesUser {
-			userID = user.ID
+		if *user.Username == TestUsersDeliveryServicesUser {
+			userID = *user.ID
 			foundUser = true
 			break
 		}
@@ -138,8 +138,8 @@ func GetTestUsersDeliveryServices(t *testing.T) {
 	userID := 0
 	foundUser := false
 	for _, user := range users {
-		if user.Username == TestUsersDeliveryServicesUser {
-			userID = user.ID
+		if *user.Username == TestUsersDeliveryServicesUser {
+			userID = *user.ID
 			foundUser = true
 			break
 		}
@@ -184,8 +184,8 @@ func DeleteTestUsersDeliveryServices(t *testing.T) {
 	userID := 0
 	foundUser := false
 	for _, user := range users {
-		if user.Username == TestUsersDeliveryServicesUser {
-			userID = user.ID
+		if *user.Username == TestUsersDeliveryServicesUser {
+			userID = *user.ID
 			foundUser = true
 			break
 		}