You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by ne...@apache.org on 2020/03/24 14:35:09 UTC

[trafficcontrol] branch master updated: Fix server compatibility with v1 (#4530)

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

neuman 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 843555b  Fix server compatibility with v1 (#4530)
843555b is described below

commit 843555bcffcab4a250e664606e0103a82ea7be93
Author: Michael Hoppal <54...@users.noreply.github.com>
AuthorDate: Tue Mar 24 08:35:00 2020 -0600

    Fix server compatibility with v1 (#4530)
    
    * Fix server compatibility with v1
    
    * Update enroller
---
 .../cdn-in-a-box/enroller/server_template.json     |  1 +
 .../traffic_ops_data/servers/010-dns_server.json   |  1 +
 .../traffic_ops_data/servers/020-db_server.json    |  1 +
 .../servers/030-enroller_server.json               |  1 +
 lib/go-tc/servers.go                               | 65 +++++++++++++++++++++-
 traffic_ops/testing/api/v1/atsconfig_meta_test.go  |  2 +-
 .../testing/api/v1/deliveryserviceservers_test.go  |  2 +-
 .../testing/api/v1/ip_allow_dot_config_test.go     |  2 +-
 traffic_ops/testing/api/v1/profileconfig_test.go   |  2 +-
 .../servers_to_deliveryservice_assignment_test.go  |  2 +-
 .../testing/api/v1/serverupdatestatus_test.go      | 14 ++---
 traffic_ops/testing/api/v1/traffic_control_test.go |  2 +-
 traffic_ops/testing/api/v2/tc-fixtures.json        | 17 ++++++
 traffic_ops/traffic_ops_golang/server/servers.go   |  7 ++-
 .../traffic_ops_golang/server/servers_test.go      |  4 ++
 traffic_ops/v1-client/server.go                    | 20 +++----
 16 files changed, 116 insertions(+), 27 deletions(-)

diff --git a/infrastructure/cdn-in-a-box/enroller/server_template.json b/infrastructure/cdn-in-a-box/enroller/server_template.json
index 2013968..f4ac961 100644
--- a/infrastructure/cdn-in-a-box/enroller/server_template.json
+++ b/infrastructure/cdn-in-a-box/enroller/server_template.json
@@ -7,6 +7,7 @@
   "ipNetmask": "$MY_NETMASK",
   "ipGateway": "$MY_GATEWAY",
   "ip6Address": "$MY_IP6_ADDRESS",
+  "ipIsService": true,
   "ip6Gateway": "$MY_IP6_GATEWAY",
   "interfaceMtu": 1500,
   "type": "$MY_TYPE",
diff --git a/infrastructure/cdn-in-a-box/traffic_ops_data/servers/010-dns_server.json b/infrastructure/cdn-in-a-box/traffic_ops_data/servers/010-dns_server.json
index ff24cce..4cfb2cb 100644
--- a/infrastructure/cdn-in-a-box/traffic_ops_data/servers/010-dns_server.json
+++ b/infrastructure/cdn-in-a-box/traffic_ops_data/servers/010-dns_server.json
@@ -4,6 +4,7 @@
   "cachegroup": "CDN_in_a_Box_Edge",
   "interfaceName": "eth0",
   "interfaceMtu": 1500,
+  "ipIsService": true,
   "type": "BIND",
   "physLocation": "Apachecon North America 2018",
   "profile": "BIND_ALL",
diff --git a/infrastructure/cdn-in-a-box/traffic_ops_data/servers/020-db_server.json b/infrastructure/cdn-in-a-box/traffic_ops_data/servers/020-db_server.json
index 39fa73d..28f2a86 100644
--- a/infrastructure/cdn-in-a-box/traffic_ops_data/servers/020-db_server.json
+++ b/infrastructure/cdn-in-a-box/traffic_ops_data/servers/020-db_server.json
@@ -4,6 +4,7 @@
   "cachegroup": "CDN_in_a_Box_Edge",
   "interfaceName": "eth0",
   "interfaceMtu": 1500,
+  "ipIsService": true,
   "type": "TRAFFIC_OPS_DB",
   "physLocation": "Apachecon North America 2018",
   "profile": "TRAFFIC_OPS_DB",
diff --git a/infrastructure/cdn-in-a-box/traffic_ops_data/servers/030-enroller_server.json b/infrastructure/cdn-in-a-box/traffic_ops_data/servers/030-enroller_server.json
index 4070e90..b41f6c9 100644
--- a/infrastructure/cdn-in-a-box/traffic_ops_data/servers/030-enroller_server.json
+++ b/infrastructure/cdn-in-a-box/traffic_ops_data/servers/030-enroller_server.json
@@ -4,6 +4,7 @@
   "cachegroup": "CDN_in_a_Box_Edge",
   "interfaceName": "eth0",
   "interfaceMtu": 1500,
+  "ipIsService": true,
   "type": "ENROLLER",
   "physLocation": "Apachecon North America 2018",
   "profile": "ENROLLER_ALL",
diff --git a/lib/go-tc/servers.go b/lib/go-tc/servers.go
index 5c33e4c..ab7150b 100644
--- a/lib/go-tc/servers.go
+++ b/lib/go-tc/servers.go
@@ -37,6 +37,18 @@ type ServersDetailResponse struct {
 	Alerts
 }
 
+// ServersV1Response is a list of Servers for v1 as a response.
+type ServersV1Response struct {
+	Response []ServerV1 `json:"response"`
+	Alerts
+}
+
+// ServersV1DetailResponse is the JSON object returned for a single server for v1.
+type ServersV1DetailResponse struct {
+	Response ServerV1 `json:"response"`
+	Alerts
+}
+
 type Server struct {
 	Cachegroup       string              `json:"cachegroup" db:"cachegroup"`
 	CachegroupID     int                 `json:"cachegroupId" db:"cachegroup_id"`
@@ -58,6 +70,57 @@ type Server struct {
 	InterfaceMtu     int                 `json:"interfaceMtu" db:"interface_mtu"`
 	InterfaceName    string              `json:"interfaceName" db:"interface_name"`
 	IP6Address       string              `json:"ip6Address" db:"ip6_address"`
+	IP6IsService     bool                `json:"ip6IsService" db:"ip6_address_is_service"`
+	IP6Gateway       string              `json:"ip6Gateway" db:"ip6_gateway"`
+	IPAddress        string              `json:"ipAddress" db:"ip_address"`
+	IPIsService      bool                `json:"ipIsService" db:"ip_address_is_service"`
+	IPGateway        string              `json:"ipGateway" db:"ip_gateway"`
+	IPNetmask        string              `json:"ipNetmask" db:"ip_netmask"`
+	LastUpdated      TimeNoMod           `json:"lastUpdated" db:"last_updated"`
+	MgmtIPAddress    string              `json:"mgmtIpAddress" db:"mgmt_ip_address"`
+	MgmtIPGateway    string              `json:"mgmtIpGateway" db:"mgmt_ip_gateway"`
+	MgmtIPNetmask    string              `json:"mgmtIpNetmask" db:"mgmt_ip_netmask"`
+	OfflineReason    string              `json:"offlineReason" db:"offline_reason"`
+	PhysLocation     string              `json:"physLocation" db:"phys_location"`
+	PhysLocationID   int                 `json:"physLocationId" db:"phys_location_id"`
+	Profile          string              `json:"profile" db:"profile"`
+	ProfileDesc      string              `json:"profileDesc" db:"profile_desc"`
+	ProfileID        int                 `json:"profileId" db:"profile_id"`
+	Rack             string              `json:"rack" db:"rack"`
+	RevalPending     bool                `json:"revalPending" db:"reval_pending"`
+	RouterHostName   string              `json:"routerHostName" db:"router_host_name"`
+	RouterPortName   string              `json:"routerPortName" db:"router_port_name"`
+	Status           string              `json:"status" db:"status"`
+	StatusID         int                 `json:"statusId" db:"status_id"`
+	TCPPort          int                 `json:"tcpPort" db:"tcp_port"`
+	Type             string              `json:"type" db:"server_type"`
+	TypeID           int                 `json:"typeId" db:"server_type_id"`
+	UpdPending       bool                `json:"updPending" db:"upd_pending"`
+	XMPPID           string              `json:"xmppId" db:"xmpp_id"`
+	XMPPPasswd       string              `json:"xmppPasswd" db:"xmpp_passwd"`
+}
+
+type ServerV1 struct {
+	Cachegroup       string              `json:"cachegroup" db:"cachegroup"`
+	CachegroupID     int                 `json:"cachegroupId" db:"cachegroup_id"`
+	CDNID            int                 `json:"cdnId" db:"cdn_id"`
+	CDNName          string              `json:"cdnName" db:"cdn_name"`
+	DeliveryServices map[string][]string `json:"deliveryServices,omitempty"`
+	DomainName       string              `json:"domainName" db:"domain_name"`
+	FQDN             *string             `json:"fqdn,omitempty"`
+	FqdnTime         time.Time           `json:"-"`
+	GUID             string              `json:"guid" db:"guid"`
+	HostName         string              `json:"hostName" db:"host_name"`
+	HTTPSPort        int                 `json:"httpsPort" db:"https_port"`
+	ID               int                 `json:"id" db:"id"`
+	ILOIPAddress     string              `json:"iloIpAddress" db:"ilo_ip_address"`
+	ILOIPGateway     string              `json:"iloIpGateway" db:"ilo_ip_gateway"`
+	ILOIPNetmask     string              `json:"iloIpNetmask" db:"ilo_ip_netmask"`
+	ILOPassword      string              `json:"iloPassword" db:"ilo_password"`
+	ILOUsername      string              `json:"iloUsername" db:"ilo_username"`
+	InterfaceMtu     int                 `json:"interfaceMtu" db:"interface_mtu"`
+	InterfaceName    string              `json:"interfaceName" db:"interface_name"`
+	IP6Address       string              `json:"ip6Address" db:"ip6_address"`
 	IP6Gateway       string              `json:"ip6Gateway" db:"ip6_gateway"`
 	IPAddress        string              `json:"ipAddress" db:"ip_address"`
 	IPGateway        string              `json:"ipGateway" db:"ip_gateway"`
@@ -135,8 +198,6 @@ type ServerNullableV11 struct {
 	XMPPPasswd       *string              `json:"xmppPasswd" db:"xmpp_passwd"`
 }
 
-type ServerNullableV20 ServerNullable
-
 type ServerNullable struct {
 	ServerNullableV11
 	IPIsService  *bool `json:"ipIsService" db:"ip_address_is_service"`
diff --git a/traffic_ops/testing/api/v1/atsconfig_meta_test.go b/traffic_ops/testing/api/v1/atsconfig_meta_test.go
index 251a5db..c267b9e 100644
--- a/traffic_ops/testing/api/v1/atsconfig_meta_test.go
+++ b/traffic_ops/testing/api/v1/atsconfig_meta_test.go
@@ -85,7 +85,7 @@ func GetTestATSConfigMeta(t *testing.T) {
 }
 
 func GetTestATSConfigMetaMidHdrRw(t *testing.T) {
-	testServer := tc.Server{}
+	testServer := tc.ServerV1{}
 	for _, sv := range testData.Servers {
 		if tc.CacheTypeFromString(sv.Type) == tc.CacheTypeMid {
 
diff --git a/traffic_ops/testing/api/v1/deliveryserviceservers_test.go b/traffic_ops/testing/api/v1/deliveryserviceservers_test.go
index 4c1f4ea..b1ba53c 100644
--- a/traffic_ops/testing/api/v1/deliveryserviceservers_test.go
+++ b/traffic_ops/testing/api/v1/deliveryserviceservers_test.go
@@ -223,7 +223,7 @@ func DeleteTestDeliveryServiceServers(t *testing.T) {
 	}
 }
 
-func getServersAndDSes(t *testing.T) ([]tc.DeliveryService, []tc.Server) {
+func getServersAndDSes(t *testing.T) ([]tc.DeliveryService, []tc.ServerV1) {
 	dses, _, err := TOSession.GetDeliveryServices()
 	if err != nil {
 		t.Fatalf("cannot GET DeliveryServices: %v", err)
diff --git a/traffic_ops/testing/api/v1/ip_allow_dot_config_test.go b/traffic_ops/testing/api/v1/ip_allow_dot_config_test.go
index 51e9606..61961a3 100644
--- a/traffic_ops/testing/api/v1/ip_allow_dot_config_test.go
+++ b/traffic_ops/testing/api/v1/ip_allow_dot_config_test.go
@@ -97,7 +97,7 @@ func GetTestIPAllowMidDotConfig(t *testing.T) {
 	}
 }
 
-func getServer(t *testing.T, serverType string) tc.Server {
+func getServer(t *testing.T, serverType string) tc.ServerV1 {
 	v := url.Values{}
 	v.Add("type", serverType)
 	servers, _, err := TOSession.GetServersByType(v)
diff --git a/traffic_ops/testing/api/v1/profileconfig_test.go b/traffic_ops/testing/api/v1/profileconfig_test.go
index ea78eb6..bc17a5b 100644
--- a/traffic_ops/testing/api/v1/profileconfig_test.go
+++ b/traffic_ops/testing/api/v1/profileconfig_test.go
@@ -63,7 +63,7 @@ func GetTestProfileDotConfig(t *testing.T) {
 		t.Errorf("cannot GET Servers: %v", err)
 	}
 
-	server := tc.Server{ID: -1}
+	server := tc.ServerV1{ID: -1}
 	for _, potentialServer := range servers {
 		if potentialServer.Type != string(tc.CacheTypeEdge) {
 			continue
diff --git a/traffic_ops/testing/api/v1/servers_to_deliveryservice_assignment_test.go b/traffic_ops/testing/api/v1/servers_to_deliveryservice_assignment_test.go
index 45d842f..cbfea09 100644
--- a/traffic_ops/testing/api/v1/servers_to_deliveryservice_assignment_test.go
+++ b/traffic_ops/testing/api/v1/servers_to_deliveryservice_assignment_test.go
@@ -73,7 +73,7 @@ func AssignTestDeliveryService(t *testing.T) {
 }
 
 func AssignIncorrectTestDeliveryService(t *testing.T) {
-	var server *tc.Server
+	var server *tc.ServerV1
 	for _, s := range testData.Servers {
 		if s.CDNName == "cdn2" {
 			server = &s
diff --git a/traffic_ops/testing/api/v1/serverupdatestatus_test.go b/traffic_ops/testing/api/v1/serverupdatestatus_test.go
index 3d1a834..3a2bced 100644
--- a/traffic_ops/testing/api/v1/serverupdatestatus_test.go
+++ b/traffic_ops/testing/api/v1/serverupdatestatus_test.go
@@ -27,15 +27,15 @@ import (
 
 func TestServerUpdateStatus(t *testing.T) {
 	WithObjs(t, []TCObj{CDNs, Types, Parameters, Profiles, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers}, func() {
-		edge1cdn1 := tc.Server{}
-		edge2cdn1 := tc.Server{}
-		mid1cdn1 := tc.Server{}
-		edge1cdn2 := tc.Server{}
+		edge1cdn1 := tc.ServerV1{}
+		edge2cdn1 := tc.ServerV1{}
+		mid1cdn1 := tc.ServerV1{}
+		edge1cdn2 := tc.ServerV1{}
 
 		getServers := func() {
 			for _, s := range []struct {
 				name   string
-				server *tc.Server
+				server *tc.ServerV1
 			}{
 				{
 					"atlanta-edge-01",
@@ -64,7 +64,7 @@ func TestServerUpdateStatus(t *testing.T) {
 		getServers()
 
 		// assert that servers don't have updates pending
-		for _, s := range []tc.Server{
+		for _, s := range []tc.ServerV1{
 			edge1cdn1,
 			edge2cdn1,
 			mid1cdn1,
@@ -174,7 +174,7 @@ func TestServerQueueUpdate(t *testing.T) {
 			true:  "queue",
 		}
 
-		var s tc.Server
+		var s tc.ServerV1
 		resp, _, err := TOSession.GetServerByHostName(serverName)
 		if err != nil {
 			t.Fatalf("failed to GET Server by hostname: %v - %v", serverName, err)
diff --git a/traffic_ops/testing/api/v1/traffic_control_test.go b/traffic_ops/testing/api/v1/traffic_control_test.go
index bc4f3b1..a4e48d3 100644
--- a/traffic_ops/testing/api/v1/traffic_control_test.go
+++ b/traffic_ops/testing/api/v1/traffic_control_test.go
@@ -41,7 +41,7 @@ type TrafficControl struct {
 	PhysLocations                        []tc.PhysLocation                       `json:"physLocations"`
 	Regions                              []tc.Region                             `json:"regions"`
 	Roles                                []tc.Role                               `json:"roles"`
-	Servers                              []tc.Server                             `json:"servers"`
+	Servers                              []tc.ServerV1                           `json:"servers"`
 	ServerServerCapabilities             []tc.ServerServerCapability             `json:"serverServerCapabilities"`
 	ServerCapabilities                   []tc.ServerCapability                   `json:"serverCapabilities"`
 	Statuses                             []tc.StatusNullable                     `json:"statuses"`
diff --git a/traffic_ops/testing/api/v2/tc-fixtures.json b/traffic_ops/testing/api/v2/tc-fixtures.json
index be9210d..2528a20 100644
--- a/traffic_ops/testing/api/v2/tc-fixtures.json
+++ b/traffic_ops/testing/api/v2/tc-fixtures.json
@@ -1474,6 +1474,7 @@
             "ip6Gateway": "2345:1234:12:8::1",
             "ipAddress": "127.0.0.21",
             "ipGateway": "127.0.0.21",
+            "ipIsService": true,
             "ipNetmask": "255.255.255.252",
             "lastUpdated": "2018-03-28T17:30:00.220351+00:00",
             "mgmtIpAddress": "",
@@ -1511,6 +1512,7 @@
             "ip6Gateway": "",
             "ipAddress": "0.0.0.0",
             "ipGateway": "0.0.0.0",
+            "ipIsService": true,
             "ipNetmask": "0.0.0.0",
             "lastUpdated": "2018-03-28T17:30:00.220351+00:00",
             "mgmtIpAddress": "",
@@ -1548,6 +1550,7 @@
             "ip6Gateway": "2345:1234:12:8::2",
             "ipAddress": "127.0.0.11",
             "ipGateway": "127.0.0.11",
+            "ipIsService": true,
             "ipNetmask": "255.255.252.0",
             "lastUpdated": "2018-03-28T17:30:00.220351+00:00",
             "mgmtIpAddress": "",
@@ -1585,6 +1588,7 @@
             "ip6Gateway": "2345:1234:12:8::3",
             "ipAddress": "127.0.0.12",
             "ipGateway": "127.0.0.1",
+            "ipIsService": true,
             "ipNetmask": "255.255.255.252",
             "lastUpdated": "2018-03-28T17:30:00.220351+00:00",
             "mgmtIpAddress": "",
@@ -1622,6 +1626,7 @@
             "ip6Gateway": "2345:1234:12:8::4",
             "ipAddress": "127.0.0.13",
             "ipGateway": "127.0.0.1",
+            "ipIsService": true,
             "ipNetmask": "255.255.255.252",
             "lastUpdated": "2018-03-28T17:30:00.220351+00:00",
             "mgmtIpAddress": "",
@@ -1659,6 +1664,7 @@
             "ip6Gateway": "2345:1234:12:8::5",
             "ipAddress": "127.0.0.14",
             "ipGateway": "127.0.0.1",
+            "ipIsService": true,
             "ipNetmask": "255.255.255.252",
             "lastUpdated": "2018-03-28T17:30:00.220351+00:00",
             "mgmtIpAddress": "",
@@ -1696,6 +1702,7 @@
             "ip6Gateway": "2345:1234:12:d::6",
             "ipAddress": "127.0.0.15",
             "ipGateway": "127.0.0.7",
+            "ipIsService": true,
             "ipNetmask": "255.255.255.252",
             "lastUpdated": "2018-03-28T17:30:00.220351+00:00",
             "mgmtIpAddress": "",
@@ -1733,6 +1740,7 @@
             "ip6Gateway": "2345:1234:12:d::7",
             "ipAddress": "127.0.0.16",
             "ipGateway": "127.0.0.7",
+            "ipIsService": true,
             "ipNetmask": "255.255.255.252",
             "lastUpdated": "2018-03-28T17:30:00.220351+00:00",
             "mgmtIpAddress": "",
@@ -1770,6 +1778,7 @@
             "ip6Gateway": "2345:1234:12:d::8",
             "ipAddress": "127.0.0.17",
             "ipGateway": "127.0.0.17",
+            "ipIsService": true,
             "ipNetmask": "255.255.255.252",
             "lastUpdated": "2018-03-28T17:30:00.220351+00:00",
             "mgmtIpAddress": "",
@@ -1807,6 +1816,7 @@
             "ip6Gateway": "2345:1234:12:d::9",
             "ipAddress": "127.0.0.18",
             "ipGateway": "127.0.0.18",
+            "ipIsService": true,
             "ipNetmask": "255.255.255.252",
             "lastUpdated": "2018-03-28T17:30:00.220351+00:00",
             "mgmtIpAddress": "",
@@ -1844,6 +1854,7 @@
             "ip6Gateway": "2345:1234:12:9::10",
             "ipAddress": "127.0.0.2",
             "ipGateway": "127.0.0.2",
+            "ipIsService": true,
             "ipNetmask": "255.255.255.252",
             "lastUpdated": "2018-03-28T17:30:00.220351+00:00",
             "mgmtIpAddress": "",
@@ -1880,6 +1891,7 @@
             "ip6Address": "2345:1234:12:b::11/64",
             "ip6Gateway": "2345:1234:12:b::11",
             "ipAddress": "127.0.0.4",
+            "ipIsService": true,
             "ipGateway": "127.0.0.4",
             "ipNetmask": "255.255.255.252",
             "lastUpdated": "2018-03-28T17:30:00.220351+00:00",
@@ -1917,6 +1929,7 @@
             "ip6Address": "2345:1234:12:b::13/64",
             "ip6Gateway": "2345:1234:12:b::13",
             "ipAddress": "127.0.0.31",
+            "ipIsService": true,
             "ipGateway": "127.0.0.4",
             "ipNetmask": "255.255.255.0",
             "mgmtIpAddress": "",
@@ -1953,6 +1966,7 @@
             "ip6Address": "2345:1234:12:b::12/64",
             "ip6Gateway": "2345:1234:12:b::12",
             "ipAddress": "127.0.0.1",
+            "ipIsService": true,
             "ipGateway": "127.0.0.1",
             "ipNetmask": "255.255.252.0",
             "lastUpdated": "2018-03-28T17:30:00.220351+00:00",
@@ -1990,6 +2004,7 @@
             "ip6Address": "2345:1234:12:8::20/64",
             "ip6Gateway": "2345:1234:12:8::20",
             "ipAddress": "127.0.0.1",
+            "ipIsService": true,
             "ipGateway": "127.0.0.1",
             "ipNetmask": "255.255.255.252",
             "lastUpdated": "2018-03-28T17:30:00.220351+00:00",
@@ -2027,6 +2042,7 @@
             "ip6Address": "::13/64",
             "ip6Gateway": "2345:1234:12:b::13",
             "ipAddress": "127.0.0.100",
+            "ipIsService": true,
             "ipGateway": "127.0.0.4",
             "ipNetmask": "255.255.255.0",
             "mgmtIpAddress": "",
@@ -2063,6 +2079,7 @@
             "ip6Address": "::14/64",
             "ip6Gateway": "2345:1234:12:b::13",
             "ipAddress": "127.0.0.101",
+            "ipIsService": true,
             "ipGateway": "127.0.0.4",
             "ipNetmask": "255.255.255.0",
             "mgmtIpAddress": "",
diff --git a/traffic_ops/traffic_ops_golang/server/servers.go b/traffic_ops/traffic_ops_golang/server/servers.go
index 3ba2000..966fb69 100644
--- a/traffic_ops/traffic_ops_golang/server/servers.go
+++ b/traffic_ops/traffic_ops_golang/server/servers.go
@@ -93,6 +93,7 @@ func (s *TOServer) Sanitize() {
 
 func (s *TOServer) Validate() error {
 	s.Sanitize()
+	version := s.APIInfo().Version
 	noSpaces := validation.NewStringRule(tovalidate.NoSpaces, "cannot contain spaces")
 
 	errs := []error{}
@@ -108,8 +109,10 @@ func (s *TOServer) Validate() error {
 		errs = append(errs, tc.EmptyAddressCannotBeAServiceAddressError)
 	}
 
-	if !*s.IPIsService && !*s.IP6IsService {
-		errs = append(errs, tc.NeedsAtLeastOneServiceAddressError)
+	if version.Major >= 2 {
+		if (s.IPIsService == nil || !*s.IPIsService) && (s.IP6IsService == nil || !*s.IP6IsService) {
+			errs = append(errs, tc.NeedsAtLeastOneServiceAddressError)
+		}
 	}
 
 	validateErrs := validation.Errors{
diff --git a/traffic_ops/traffic_ops_golang/server/servers_test.go b/traffic_ops/traffic_ops_golang/server/servers_test.go
index ecdac5c..da8b691 100644
--- a/traffic_ops/traffic_ops_golang/server/servers_test.go
+++ b/traffic_ops/traffic_ops_golang/server/servers_test.go
@@ -52,8 +52,10 @@ func getTestServers() []tc.Server {
 		InterfaceMtu:   9500,
 		InterfaceName:  "interfaceName",
 		IP6Address:     "ip6Address",
+		IP6IsService:   false,
 		IP6Gateway:     "ip6Gateway",
 		IPAddress:      "ipAddress",
+		IPIsService:    true,
 		IPGateway:      "ipGateway",
 		IPNetmask:      "ipNetmask",
 		LastUpdated:    tc.TimeNoMod{Time: time.Now()},
@@ -129,8 +131,10 @@ func TestGetServersByCachegroup(t *testing.T) {
 			ts.InterfaceMtu,
 			ts.InterfaceName,
 			ts.IP6Address,
+			ts.IP6IsService,
 			ts.IP6Gateway,
 			ts.IPAddress,
+			ts.IPIsService,
 			ts.IPNetmask,
 			ts.IPGateway,
 			ts.LastUpdated,
diff --git a/traffic_ops/v1-client/server.go b/traffic_ops/v1-client/server.go
index c2b1f59..247739b 100644
--- a/traffic_ops/v1-client/server.go
+++ b/traffic_ops/v1-client/server.go
@@ -34,7 +34,7 @@ const (
 )
 
 // Create a Server
-func (to *Session) CreateServer(server tc.Server) (tc.Alerts, ReqInf, error) {
+func (to *Session) CreateServer(server tc.ServerV1) (tc.Alerts, ReqInf, error) {
 
 	var remoteAddr net.Addr
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
@@ -118,7 +118,7 @@ func (to *Session) CreateServer(server tc.Server) (tc.Alerts, ReqInf, error) {
 }
 
 // Update a Server by ID
-func (to *Session) UpdateServerByID(id int, server tc.Server) (tc.Alerts, ReqInf, error) {
+func (to *Session) UpdateServerByID(id int, server tc.ServerV1) (tc.Alerts, ReqInf, error) {
 
 	var remoteAddr net.Addr
 	reqBody, err := json.Marshal(server)
@@ -138,7 +138,7 @@ func (to *Session) UpdateServerByID(id int, server tc.Server) (tc.Alerts, ReqInf
 }
 
 // Returns a list of Servers
-func (to *Session) GetServers() ([]tc.Server, ReqInf, error) {
+func (to *Session) GetServers() ([]tc.ServerV1, ReqInf, error) {
 	resp, remoteAddr, err := to.request(http.MethodGet, API_v13_Servers, nil)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
 	if err != nil {
@@ -146,13 +146,13 @@ func (to *Session) GetServers() ([]tc.Server, ReqInf, error) {
 	}
 	defer resp.Body.Close()
 
-	var data tc.ServersResponse
+	var data tc.ServersV1Response
 	err = json.NewDecoder(resp.Body).Decode(&data)
 	return data.Response, reqInf, nil
 }
 
 // GET a Server by the Server ID
-func (to *Session) GetServerByID(id int) ([]tc.Server, ReqInf, error) {
+func (to *Session) GetServerByID(id int) ([]tc.ServerV1, ReqInf, error) {
 	route := fmt.Sprintf("%s/%d", API_v13_Servers, id)
 	resp, remoteAddr, err := to.request(http.MethodGet, route, nil)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
@@ -161,7 +161,7 @@ func (to *Session) GetServerByID(id int) ([]tc.Server, ReqInf, error) {
 	}
 	defer resp.Body.Close()
 
-	var data tc.ServersResponse
+	var data tc.ServersV1Response
 	if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
 		return nil, reqInf, err
 	}
@@ -170,7 +170,7 @@ func (to *Session) GetServerByID(id int) ([]tc.Server, ReqInf, error) {
 }
 
 // GET a Server by the Server hostname
-func (to *Session) GetServerByHostName(hostName string) ([]tc.Server, ReqInf, error) {
+func (to *Session) GetServerByHostName(hostName string) ([]tc.ServerV1, ReqInf, error) {
 	url := fmt.Sprintf("%s?hostName=%s", API_v13_Servers, hostName)
 	resp, remoteAddr, err := to.request(http.MethodGet, url, nil)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
@@ -179,7 +179,7 @@ func (to *Session) GetServerByHostName(hostName string) ([]tc.Server, ReqInf, er
 	}
 	defer resp.Body.Close()
 
-	var data tc.ServersResponse
+	var data tc.ServersV1Response
 	if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
 		return nil, reqInf, err
 	}
@@ -201,7 +201,7 @@ func (to *Session) DeleteServerByID(id int) (tc.Alerts, ReqInf, error) {
 	return alerts, reqInf, nil
 }
 
-func (to *Session) GetServersByType(qparams url.Values) ([]tc.Server, ReqInf, error) {
+func (to *Session) GetServersByType(qparams url.Values) ([]tc.ServerV1, ReqInf, error) {
 	url := fmt.Sprintf("%s.json?%s", API_v13_Servers, qparams.Encode())
 	resp, remoteAddr, err := to.request(http.MethodGet, url, nil)
 	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
@@ -210,7 +210,7 @@ func (to *Session) GetServersByType(qparams url.Values) ([]tc.Server, ReqInf, er
 	}
 	defer resp.Body.Close()
 
-	var data tc.ServersResponse
+	var data tc.ServersV1Response
 	if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
 		return nil, reqInf, err
 	}