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 c09ecfd  Update ORT/atstccfg old client to V3 (#5551)
c09ecfd is described below

commit c09ecfd2a7cc5393ad93038647d40d99badca891
Author: Robert O Butts <[email protected]>
AuthorDate: Wed Mar 17 08:54:42 2021 -0600

    Update ORT/atstccfg old client to V3 (#5551)
    
    This updates the old client to V3.
    
    The new client is still V3, because the v4-client isn't done yet. It
    adds a TODO comment, so when v4 is ready, ORT should be changed to
    use it.
    
    It also refactors the client usage a bit, so the toreq user
    doesn't have to check and fall back itself, but rather the entire
    client falls back. Making it easier to use and more efficient.
---
 lib/go-atscfg/atscfg.go                            |  20 +-
 lib/go-atscfg/atscfg_test.go                       |   8 +-
 traffic_ops_ort/atstccfg/atstccfg.go               |   7 +-
 traffic_ops_ort/atstccfg/cfgfile/cfgfile.go        |  18 +-
 traffic_ops_ort/atstccfg/cfgfile/cfgfile_test.go   |  60 ++---
 traffic_ops_ort/atstccfg/config/config.go          |   4 +-
 traffic_ops_ort/atstccfg/getdata/getdata.go        |  46 +---
 traffic_ops_ort/atstccfg/toreq/client.go           |  99 ++++++++
 .../atstccfg/toreq/{toreq.go => clientfuncs.go}    | 264 +++++++++++----------
 traffic_ops_ort/atstccfg/toreq/conversions.go      |  38 +++
 traffic_ops_ort/atstccfg/toreqnew/toreqnew.go      | 191 ---------------
 traffic_ops_ort/atstccfg/toreqold/client.go        |  60 +++++
 .../{toreq/toreq.go => toreqold/clientfuncs.go}    | 188 +++++----------
 traffic_ops_ort/atstccfg/toreqold/conversions.go   |  55 +++++
 traffic_ops_ort/atstccfg/torequtil/torequtil.go    |  25 ++
 traffic_ops_ort/to_requester/config/config.go      |   4 +-
 traffic_ops_ort/to_requester/getdata/getdata.go    |  16 +-
 traffic_ops_ort/to_requester/to_requester.go       |  13 +-
 18 files changed, 531 insertions(+), 585 deletions(-)

diff --git a/lib/go-atscfg/atscfg.go b/lib/go-atscfg/atscfg.go
index 360b44e..b13d6b4 100644
--- a/lib/go-atscfg/atscfg.go
+++ b/lib/go-atscfg/atscfg.go
@@ -50,15 +50,15 @@ type ServerCapability string
 // Server is a tc.Server for the latest lib/go-tc and traffic_ops/vx-client 
type.
 // This allows atscfg to not have to change the type everywhere it's used, 
every time ATC changes the base type,
 // but to only have to change it here, and the places where breaking symbol 
changes were made.
-type Server tc.ServerV40
+type Server tc.ServerV30
 
 // DeliveryService is a tc.DeliveryService for the latest lib/go-tc and 
traffic_ops/vx-client type.
 // This allows atscfg to not have to change the type everywhere it's used, 
every time ATC changes the base type,
 // but to only have to change it here, and the places where breaking symbol 
changes were made.
-type DeliveryService tc.DeliveryServiceV4
+type DeliveryService tc.DeliveryServiceNullableV30
 
 // ToDeliveryServices converts a slice of the latest lib/go-tc and 
traffic_ops/vx-client type to the local alias.
-func ToDeliveryServices(dses []tc.DeliveryServiceV4) []DeliveryService {
+func ToDeliveryServices(dses []tc.DeliveryServiceNullableV30) 
[]DeliveryService {
        ad := []DeliveryService{}
        for _, ds := range dses {
                ad = append(ad, DeliveryService(ds))
@@ -66,23 +66,17 @@ func ToDeliveryServices(dses []tc.DeliveryServiceV4) 
[]DeliveryService {
        return ad
 }
 
-// OldToDeliveryServices converts a slice of the old traffic_ops/client type 
to the local alias.
-func OldToDeliveryServices(dses []tc.DeliveryServiceNullable) 
[]DeliveryService {
+// V30ToDeliveryServices converts a slice of the old traffic_ops/client type 
to the local alias.
+func V30ToDeliveryServices(dses []tc.DeliveryServiceNullableV30) 
[]DeliveryService {
        ad := []DeliveryService{}
        for _, ds := range dses {
-               upgradedDS := tc.DeliveryServiceNullableV30{
-                       DeliveryServiceV30: tc.DeliveryServiceV30{
-                               DeliveryServiceNullableV15: 
tc.DeliveryServiceNullableV15(ds),
-                       },
-               }
-
-               ad = append(ad, DeliveryService(upgradedDS.UpgradeToV4()))
+               ad = append(ad, DeliveryService(ds))
        }
        return ad
 }
 
 // ToServers converts a slice of the latest lib/go-tc and 
traffic_ops/vx-client type to the local alias.
-func ToServers(servers []tc.ServerV40) []Server {
+func ToServers(servers []tc.ServerV30) []Server {
        as := []Server{}
        for _, sv := range servers {
                as = append(as, Server(sv))
diff --git a/lib/go-atscfg/atscfg_test.go b/lib/go-atscfg/atscfg_test.go
index 513c7ec..806bd33 100644
--- a/lib/go-atscfg/atscfg_test.go
+++ b/lib/go-atscfg/atscfg_test.go
@@ -119,11 +119,9 @@ func setIP6(sv *Server, ip6Address string) {
 }
 
 func setIPInfo(sv *Server, interfaceName string, ipAddress string, ip6Address 
string) {
-       sv.Interfaces = []tc.ServerInterfaceInfoV40{
-               tc.ServerInterfaceInfoV40{
-                       ServerInterfaceInfo: tc.ServerInterfaceInfo{
-                               Name: interfaceName,
-                       },
+       sv.Interfaces = []tc.ServerInterfaceInfo{
+               tc.ServerInterfaceInfo{
+                       Name: interfaceName,
                },
        }
        if ipAddress != "" {
diff --git a/traffic_ops_ort/atstccfg/atstccfg.go 
b/traffic_ops_ort/atstccfg/atstccfg.go
index c535f8f..9a04f72 100644
--- a/traffic_ops_ort/atstccfg/atstccfg.go
+++ b/traffic_ops_ort/atstccfg/atstccfg.go
@@ -59,7 +59,6 @@ import (
        "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/getdata"
        "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/plugin"
        "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/toreq"
-       "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/toreqnew"
 )
 
 func main() {
@@ -94,9 +93,11 @@ func main() {
                os.Exit(config.ExitCodeErrGeneric)
        }
 
-       toClientNew, err := toreqnew.New(toClient.Cookies(cfg.TOURL), 
cfg.TOURL, cfg.TOUser, cfg.TOPass, cfg.TOInsecure, cfg.TOTimeout, 
config.UserAgent)
+       if toClient.FellBack() {
+               log.Warnln("Traffic Ops does not support the latest version 
supported by this app! Falling back to previous major Traffic Ops API version!")
+       }
 
-       tccfg := config.TCCfg{Cfg: cfg, TOClient: toClient, TOClientNew: 
toClientNew}
+       tccfg := config.TCCfg{Cfg: cfg, TOClient: toClient}
 
        if tccfg.GetData != "" {
                if err := getdata.WriteData(tccfg); err != nil {
diff --git a/traffic_ops_ort/atstccfg/cfgfile/cfgfile.go 
b/traffic_ops_ort/atstccfg/cfgfile/cfgfile.go
index 605bd59..df80290 100644
--- a/traffic_ops_ort/atstccfg/cfgfile/cfgfile.go
+++ b/traffic_ops_ort/atstccfg/cfgfile/cfgfile.go
@@ -77,11 +77,7 @@ func GetTOData(cfg config.TCCfg) (*config.TOData, 
[]net.Addr, error) {
        serversF := func() error {
                defer func(start time.Time) { log.Infof("serversF took %v\n", 
time.Since(start)) }(time.Now())
                // TODO TOAPI add /servers?cdn=1 query param
-               servers, toAddr, unsupported, err := 
cfg.TOClientNew.GetServers()
-               if err == nil && unsupported {
-                       log.Warnln("Traffic Ops newer than ORT, falling back to 
previous API Servers!")
-                       servers, toAddr, err = cfg.TOClient.GetServers()
-               }
+               servers, toAddr, err := cfg.TOClient.GetServers()
                if err != nil {
                        return errors.New("getting servers: " + err.Error())
                }
@@ -120,11 +116,7 @@ func GetTOData(cfg config.TCCfg) (*config.TOData, 
[]net.Addr, error) {
                dsF := func() error {
                        defer func(start time.Time) { log.Infof("dsF took 
%v\n", time.Since(start)) }(time.Now())
 
-                       dses, toAddr, unsupported, err := 
cfg.TOClientNew.GetCDNDeliveryServices(*server.CDNID)
-                       if err == nil && unsupported {
-                               log.Warnln("Traffic Ops newer than ORT, falling 
back to previous API Delivery Services!")
-                               dses, toAddr, err = 
cfg.TOClient.GetCDNDeliveryServices(*server.CDNID)
-                       }
+                       dses, toAddr, err := 
cfg.TOClient.GetCDNDeliveryServices(*server.CDNID)
                        if err != nil {
                                return errors.New("getting delivery services: " 
+ err.Error())
                        }
@@ -335,14 +327,10 @@ func GetTOData(cfg config.TCCfg) (*config.TOData, 
[]net.Addr, error) {
 
        topologiesF := func() error {
                defer func(start time.Time) { log.Infof("topologiesF took 
%v\n", time.Since(start)) }(time.Now())
-               topologies, toAddr, unsupported, err := 
cfg.TOClientNew.GetTopologies()
+               topologies, toAddr, err := cfg.TOClient.GetTopologies()
                if err != nil {
                        return errors.New("getting topologies: " + err.Error())
                }
-               if unsupported {
-                       log.Warnln("Traffic Ops didn't support Topologies, 
topologies will be not be used for config generation!")
-                       return nil
-               }
                toIPs.Store(toAddr, nil)
                toData.Topologies = topologies
                return nil
diff --git a/traffic_ops_ort/atstccfg/cfgfile/cfgfile_test.go 
b/traffic_ops_ort/atstccfg/cfgfile/cfgfile_test.go
index 4b4c4de..8cd261b 100644
--- a/traffic_ops_ort/atstccfg/cfgfile/cfgfile_test.go
+++ b/traffic_ops_ort/atstccfg/cfgfile/cfgfile_test.go
@@ -29,7 +29,7 @@ import (
        "github.com/apache/trafficcontrol/lib/go-atscfg"
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/lib/go-util"
-       client "github.com/apache/trafficcontrol/traffic_ops/v1-client"
+       client "github.com/apache/trafficcontrol/traffic_ops/v3-client"
        "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/config"
        "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/toreq"
 )
@@ -79,14 +79,12 @@ func TestPreprocessConfigFile(t *testing.T) {
        {
                server := &atscfg.Server{}
                server.TCPPort = util.IntPtr(8080)
-               server.Interfaces = []tc.ServerInterfaceInfoV40{
-                       tc.ServerInterfaceInfoV40{
-                               ServerInterfaceInfo: tc.ServerInterfaceInfo{
-                                       IPAddresses: []tc.ServerIPAddress{
-                                               tc.ServerIPAddress{
-                                                       Address:        
"127.0.2.1",
-                                                       ServiceAddress: true,
-                                               },
+               server.Interfaces = []tc.ServerInterfaceInfo{
+                       tc.ServerInterfaceInfo{
+                               IPAddresses: []tc.ServerIPAddress{
+                                       tc.ServerIPAddress{
+                                               Address:        "127.0.2.1",
+                                               ServiceAddress: true,
                                        },
                                },
                        },
@@ -107,14 +105,12 @@ func TestPreprocessConfigFile(t *testing.T) {
        {
                server := &atscfg.Server{}
                server.TCPPort = util.IntPtr(80)
-               server.Interfaces = []tc.ServerInterfaceInfoV40{
-                       tc.ServerInterfaceInfoV40{
-                               ServerInterfaceInfo: tc.ServerInterfaceInfo{
-                                       IPAddresses: []tc.ServerIPAddress{
-                                               tc.ServerIPAddress{
-                                                       Address:        
"127.0.2.1",
-                                                       ServiceAddress: true,
-                                               },
+               server.Interfaces = []tc.ServerInterfaceInfo{
+                       tc.ServerInterfaceInfo{
+                               IPAddresses: []tc.ServerIPAddress{
+                                       tc.ServerIPAddress{
+                                               Address:        "127.0.2.1",
+                                               ServiceAddress: true,
                                        },
                                },
                        },
@@ -337,25 +333,21 @@ func randServer() *atscfg.Server {
        sv.ILOPassword = randStr()
        sv.ILOUsername = randStr()
 
-       sv.Interfaces = []tc.ServerInterfaceInfoV40{
-               tc.ServerInterfaceInfoV40{
-                       ServerInterfaceInfo: tc.ServerInterfaceInfo{
-                               Name: *randStr(),
-                               IPAddresses: []tc.ServerIPAddress{
-                                       tc.ServerIPAddress{
-                                               Address:        *randStr(),
-                                               Gateway:        randStr(),
-                                               ServiceAddress: true,
-                                       },
-                                       tc.ServerIPAddress{
-                                               Address:        *randStr(),
-                                               Gateway:        randStr(),
-                                               ServiceAddress: true,
-                                       },
+       sv.Interfaces = []tc.ServerInterfaceInfo{
+               tc.ServerInterfaceInfo{
+                       Name: *randStr(),
+                       IPAddresses: []tc.ServerIPAddress{
+                               tc.ServerIPAddress{
+                                       Address:        *randStr(),
+                                       Gateway:        randStr(),
+                                       ServiceAddress: true,
+                               },
+                               tc.ServerIPAddress{
+                                       Address:        *randStr(),
+                                       Gateway:        randStr(),
+                                       ServiceAddress: true,
                                },
                        },
-                       RouterHostName: *randStr(),
-                       RouterPortName: *randStr(),
                },
        }
 
diff --git a/traffic_ops_ort/atstccfg/config/config.go 
b/traffic_ops_ort/atstccfg/config/config.go
index d829826..baa434c 100644
--- a/traffic_ops_ort/atstccfg/config/config.go
+++ b/traffic_ops_ort/atstccfg/config/config.go
@@ -31,7 +31,6 @@ import (
        "github.com/apache/trafficcontrol/lib/go-log"
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/toreq"
-       "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/toreqnew"
 
        flag "github.com/ogier/pflag"
 )
@@ -72,8 +71,7 @@ type Cfg struct {
 
 type TCCfg struct {
        Cfg
-       TOClient    *toreq.TOClient
-       TOClientNew *toreqnew.TOClient
+       TOClient *toreq.TOClient
 }
 
 func (cfg Cfg) ErrorLog() log.LogLocation   { return 
log.LogLocation(cfg.LogLocationErr) }
diff --git a/traffic_ops_ort/atstccfg/getdata/getdata.go 
b/traffic_ops_ort/atstccfg/getdata/getdata.go
index 1e364a1..f3c5156 100644
--- a/traffic_ops_ort/atstccfg/getdata/getdata.go
+++ b/traffic_ops_ort/atstccfg/getdata/getdata.go
@@ -24,10 +24,7 @@ package getdata
 import (
        "encoding/json"
        "errors"
-       "fmt"
        "io"
-       "io/ioutil"
-       "net/http"
        "os"
        "strings"
 
@@ -35,8 +32,7 @@ import (
        "github.com/apache/trafficcontrol/lib/go-log"
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/config"
-       "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/toreq"
-       "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/toreqnew"
+       "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/torequtil"
 )
 
 func GetDataFuncs() map[string]func(config.TCCfg, io.Writer) error {
@@ -114,11 +110,7 @@ func WriteStatuses(cfg config.TCCfg, output io.Writer) 
error {
 // WriteUpdateStatus writes the Traffic Ops server update status to output.
 // Note this is identical to /api/1.x/servers/name/update_status except it 
omits the '[]' wrapper.
 func WriteServerUpdateStatus(cfg config.TCCfg, output io.Writer) error {
-       status, _, unsupported, err := 
cfg.TOClientNew.GetServerUpdateStatus(tc.CacheName(cfg.CacheHostName))
-       if err == nil && unsupported {
-               log.Warnln("ORT newer than Traffic Ops, falling back to 
previous API Delivery Services!")
-               status, _, err = 
cfg.TOClient.GetServerUpdateStatus(tc.CacheName(cfg.CacheHostName))
-       }
+       status, _, err := 
cfg.TOClient.GetServerUpdateStatus(tc.CacheName(cfg.CacheHostName))
        if err != nil {
                return errors.New("getting server update status: " + 
err.Error())
        }
@@ -208,39 +200,9 @@ type ChkConfigEntry struct {
 
 // SetUpdateStatus sets the queue and reval status of serverName in Traffic 
Ops.
 func SetUpdateStatus(cfg config.TCCfg, serverName tc.CacheName, queue bool, 
revalPending bool) error {
-       reqInf, err := 
cfg.TOClientNew.C.SetUpdateServerStatuses(string(serverName), &queue, 
&revalPending)
-       if err != nil && toreqnew.IsUnsupportedErr(err) {
-               err = setUpdateStatusLegacy(cfg, serverName, queue, 
revalPending)
-       }
-       if err != nil {
-               return errors.New("setting update statuses (Traffic Ops '" + 
toreq.MaybeIPStr(reqInf.RemoteAddr) + "'): " + err.Error())
-       }
-       return nil
-}
-
-// setUpdateStatusLegacy sets the queue and reval status of serverName in 
Traffic Ops,
-// using the legacy pre-2.0 /update endpoint.
-func setUpdateStatusLegacy(cfg config.TCCfg, serverName tc.CacheName, queue 
bool, revalPending bool) error {
-       path := `/update/` + string(serverName) + `?updated=` + 
jsonBoolStr(queue) + `&reval_updated=` + jsonBoolStr(revalPending)
-       // C and RawRequest should generally never be used, but the alternatve 
here is to manually get the cookie and do an http.Get. We need to hit a non-API 
endpoint, no API endpoint exists for what we need.
-       resp, _, err := cfg.TOClient.C.RawRequest(http.MethodPost, path, nil)
+       reqInf, err := 
cfg.TOClient.C.SetUpdateServerStatuses(string(serverName), &queue, 
&revalPending)
        if err != nil {
-               return errors.New("setting update statuses: " + err.Error())
-       }
-       defer resp.Body.Close()
-       if resp.StatusCode != 200 {
-               bodyBts, err := ioutil.ReadAll(resp.Body)
-               if err == nil {
-                       return fmt.Errorf("Traffic Ops returned %v %v", 
resp.StatusCode, string(bodyBts))
-               }
-               return fmt.Errorf("Traffic Ops returned %v (error reading 
body)", resp.StatusCode)
+               return errors.New("setting update statuses (Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "'): " + err.Error())
        }
        return nil
 }
-
-func jsonBoolStr(b bool) string {
-       if b {
-               return `true`
-       }
-       return `false`
-}
diff --git a/traffic_ops_ort/atstccfg/toreq/client.go 
b/traffic_ops_ort/atstccfg/toreq/client.go
new file mode 100644
index 0000000..475a6ab
--- /dev/null
+++ b/traffic_ops_ort/atstccfg/toreq/client.go
@@ -0,0 +1,99 @@
+// toreq implements a Traffic Ops client for features in the latest version.
+//
+// This should only be used if an endpoint or field needed for config gen is 
in the latest.
+//
+// Users should always check the returned bool, and if it's false, call the 
vendored toreq client and set the proper defaults for the new feature(s).
+//
+// All TOClient functions should check for 404 or 503 and return a bool false 
if so.
+//
+package toreq
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+       "errors"
+       "net"
+       "net/url"
+       "strconv"
+       "strings"
+       "time"
+
+       "github.com/apache/trafficcontrol/lib/go-log"
+       toclient "github.com/apache/trafficcontrol/traffic_ops/v3-client" // 
TODO change to v4-client when it's stabilized
+       "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/toreqold"
+       "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/torequtil"
+)
+
+type TOClient struct {
+       C          *toclient.Session
+       Old        *toreqold.TOClient
+       NumRetries int
+}
+
+// New logs into Traffic Ops, returning the TOClient which contains the 
logged-in client.
+func New(url *url.URL, user string, pass string, insecure bool, timeout 
time.Duration, userAgent string) (*TOClient, error) {
+       log.Infoln("URL: '" + url.String() + "' User: '" + user + "' Pass len: 
'" + strconv.Itoa(len(pass)) + "'")
+
+       toFQDN := url.Scheme + "://" + url.Host
+       log.Infoln("TO FQDN: '" + toFQDN + "'")
+       log.Infoln("TO URL: '" + url.String() + "'")
+
+       toClient, toIP, err := toclient.LoginWithAgent(toFQDN, user, pass, 
insecure, userAgent, false, timeout)
+       if err != nil {
+               return nil, errors.New("Logging in to Traffic Ops '" + 
torequtil.MaybeIPStr(toIP) + "': " + err.Error())
+       }
+
+       log.Infoln("toreqnew.New Logged into in to Traffic Ops '" + 
torequtil.MaybeIPStr(toIP) + "'")
+
+       latestSupported, toAddr, err := IsLatestSupported(toClient)
+       if err != nil {
+               return nil, errors.New("checking Traffic Ops '" + 
torequtil.MaybeIPStr(toAddr) + "' support: " + err.Error())
+       }
+
+       client := &TOClient{C: toClient}
+       if !latestSupported {
+               log.Warnln("toreqnew.New Traffic Ops '" + 
torequtil.MaybeIPStr(toIP) + "' does not support the latest client, falling 
back ot the previous")
+
+               oldClient, err := toreqold.New(url, user, pass, insecure, 
timeout, userAgent)
+               if err != nil {
+                       return nil, errors.New("logging into old client: " + 
err.Error())
+               }
+               client.C = nil
+               client.Old = oldClient
+       }
+
+       return client, nil
+}
+
+// FellBack() returns whether the client fell back to the previous major 
version, because Traffic Ops didn't support the latest.
+func (cl *TOClient) FellBack() bool {
+       return cl.C == nil
+}
+
+func IsLatestSupported(toClient *toclient.Session) (bool, net.Addr, error) {
+       _, inf, err := toClient.Ping()
+       if err != nil {
+               if errS := strings.ToLower(err.Error()); strings.Contains(errS, 
"not found") || strings.Contains(errS, "not implemented") {
+                       return false, inf.RemoteAddr, nil
+               }
+               return false, inf.RemoteAddr, err
+       }
+       return true, inf.RemoteAddr, nil
+}
diff --git a/traffic_ops_ort/atstccfg/toreq/toreq.go 
b/traffic_ops_ort/atstccfg/toreq/clientfuncs.go
similarity index 74%
copy from traffic_ops_ort/atstccfg/toreq/toreq.go
copy to traffic_ops_ort/atstccfg/toreq/clientfuncs.go
index b8f812e..2eb68a8 100644
--- a/traffic_ops_ort/atstccfg/toreq/toreq.go
+++ b/traffic_ops_ort/atstccfg/toreq/clientfuncs.go
@@ -1,9 +1,3 @@
-// toreqnew implements a Traffic Ops client vendored one version back.
-//
-// This should be used for all requests, unless they require an endpoint or 
field added in the latest version.
-//
-// If a feature in the latest Traffic Ops is required, toreqnew should be used 
with a fallback to this client if the Traffic Ops is not the latest (which can 
be determined by the bool returned by all toreqnew.TOClient funcs).
-//
 package toreq
 
 /*
@@ -31,63 +25,28 @@ import (
        "net"
        "net/url"
        "strconv"
-       "time"
 
        "github.com/apache/trafficcontrol/lib/go-atscfg"
        "github.com/apache/trafficcontrol/lib/go-log"
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/lib/go-util"
-       toclient "github.com/apache/trafficcontrol/traffic_ops/v1-client"
        "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/torequtil"
 )
 
-type TOClient struct {
-       C          *toclient.Session
-       NumRetries int
-}
-
-// New logs into Traffic Ops, returning the TOClient which contains the 
logged-in client.
-func New(url *url.URL, user string, pass string, insecure bool, timeout 
time.Duration, userAgent string) (*TOClient, error) {
-       log.Infoln("URL: '" + url.String() + "' User: '" + user + "' Pass len: 
'" + strconv.Itoa(len(pass)) + "'")
-
-       toFQDN := url.Scheme + "://" + url.Host
-       log.Infoln("TO FQDN: '" + toFQDN + "'")
-       log.Infoln("TO URL: '" + url.String() + "'")
-
-       toClient, toIP, err := toclient.LoginWithAgent(toFQDN, user, pass, 
insecure, userAgent, false, timeout)
-       if err != nil {
-               return nil, errors.New("Logging in to Traffic Ops '" + 
MaybeIPStr(toIP) + "': " + err.Error())
-       }
-
-       return &TOClient{C: toClient}, nil
-}
-
-// Cookies returns the HTTP session cookies from the client.
-// It does not do any kind of validation, but assumes the HTTP cookies exist 
from a prior login and are valid for a Traffic Ops session.
-// The url is the Traffic Ops URL, and should match this client's Traffic Ops 
URL, and the URL of the new client this session cookie is presumably being 
fetched for.
-func (cl *TOClient) Cookies(url *url.URL) string {
-       return torequtil.CookiesToString(cl.C.Client.Jar.Cookies(url))
-}
-
-// MaybeIPStr returns the addr string if it isn't nil, or the empty string if 
it is.
-// This is intended for logging, to allow logging with one line, whether addr 
is nil or not.
-func MaybeIPStr(addr net.Addr) string {
-       if addr != nil {
-               return addr.String()
+func (cl *TOClient) GetProfileByName(profileName string) (tc.Profile, 
net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetProfileByName(profileName)
        }
-       return ""
-}
 
-func (cl *TOClient) GetProfileByName(profileName string) (tc.Profile, 
net.Addr, error) {
        profile := tc.Profile{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, "profile_"+profileName, 
&profile, func(obj interface{}) error {
                toProfiles, reqInf, err := cl.C.GetProfileByName(profileName)
                if err != nil {
-                       return errors.New("getting profile '" + profileName + 
"' from Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting profile '" + profileName + 
"' from Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + 
err.Error())
                }
                if len(toProfiles) != 1 {
-                       return errors.New("getting profile '" + profileName + 
"'from Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': expected 1 Profile, 
got " + strconv.Itoa(len(toProfiles)))
+                       return errors.New("getting profile '" + profileName + 
"'from Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': expected 
1 Profile, got " + strconv.Itoa(len(toProfiles)))
                }
 
                profile := obj.(*tc.Profile)
@@ -103,12 +62,16 @@ func (cl *TOClient) GetProfileByName(profileName string) 
(tc.Profile, net.Addr,
 }
 
 func (cl *TOClient) GetGlobalParameters() ([]tc.Parameter, net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetGlobalParameters()
+       }
+
        globalParams := []tc.Parameter{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, "profile_global_parameters", 
&globalParams, func(obj interface{}) error {
                toParams, reqInf, err := 
cl.C.GetParametersByProfileName(tc.GlobalProfileName)
                if err != nil {
-                       return errors.New("getting global profile '" + 
tc.GlobalProfileName + "' parameters from Traffic Ops '" + 
MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting global profile '" + 
tc.GlobalProfileName + "' parameters from Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                params := obj.(*[]tc.Parameter)
                *params = toParams
@@ -121,42 +84,22 @@ func (cl *TOClient) GetGlobalParameters() ([]tc.Parameter, 
net.Addr, error) {
        return globalParams, toAddr, nil
 }
 
-func GetTOToolNameAndURL(globalParams []tc.Parameter) (string, string) {
-       // TODO move somewhere generic
-       toToolName := ""
-       toURL := ""
-       for _, param := range globalParams {
-               if param.Name == "tm.toolname" {
-                       toToolName = param.Value
-               } else if param.Name == "tm.url" {
-                       toURL = param.Value
-               }
-               if toToolName != "" && toURL != "" {
-                       break
-               }
-       }
-       // TODO error here? Perl doesn't.
-       if toToolName == "" {
-               log.Warnln("Global Parameter tm.toolname not found, config may 
not be constructed properly!")
-       }
-       if toURL == "" {
-               log.Warnln("Global Parameter tm.url not found, config may not 
be constructed properly!")
+func (cl *TOClient) GetServers() ([]atscfg.Server, net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetServers()
        }
-       return toToolName, toURL
-}
 
-func (cl *TOClient) GetServers() ([]atscfg.Server, net.Addr, error) {
        servers := []atscfg.Server{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, "servers", &servers, func(obj 
interface{}) error {
-               toServers, reqInf, err := cl.C.GetServers()
+               toServers, reqInf, err := cl.C.GetServersWithHdr(nil, nil)
                if err != nil {
-                       return errors.New("getting servers from Traffic Ops '" 
+ MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting servers from Traffic Ops '" 
+ torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                servers := obj.(*[]atscfg.Server)
                *servers, err = serversToLatest(toServers)
                if err != nil {
-                       return errors.New("upgrading servers from Traffic Ops 
'" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("upgrading servers from Traffic Ops 
'" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                toAddr = reqInf.RemoteAddr
                return nil
@@ -167,48 +110,23 @@ func (cl *TOClient) GetServers() ([]atscfg.Server, 
net.Addr, error) {
        return servers, toAddr, nil
 }
 
-// serversToLatest converts a []tc.Server to []tc.ServerV30.
-// This is necessary, because the Traffic Ops API 1.x client doesn't return 
the same type as the latest client.
-func serversToLatest(svs []tc.ServerV1) ([]atscfg.Server, error) {
-       nss := []atscfg.Server{}
-       for _, sv := range svs {
-               svLatest, err := serverToLatest(&sv)
-               if err != nil {
-                       return nil, err // serverToLatest adds context
-               }
-               nss = append(nss, atscfg.Server(*svLatest))
-       }
-       return nss, nil
-}
-
-// serverToLatest converts a tc.Server to tc.ServerV30.
-// This is necessary, because the Traffic Ops API 1.x client doesn't return 
the same type as the latest client.
-func serverToLatest(sv *tc.ServerV1) (*atscfg.Server, error) {
-       svn := sv.ToNullable()
-       sv2 := tc.ServerNullableV2{
-               ServerNullableV11: svn,
-               IPIsService:       util.BoolPtr(true),
-               IP6IsService:      util.BoolPtr(svn.IP6Address != nil && 
*svn.IP6Address != ""),
-       }
-       svLatest, err := sv2.UpgradeToV40()
-       if err != nil {
-               return nil, errors.New("upgrading: " + err.Error())
+func (cl *TOClient) GetServerByHostName(serverHostName string) 
(*atscfg.Server, net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetServerByHostName(serverHostName)
        }
-       asv := atscfg.Server(svLatest)
-       return &asv, nil
-}
 
-func (cl *TOClient) GetServerByHostName(serverHostName string) 
(*atscfg.Server, net.Addr, error) {
        server := atscfg.Server{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, "server-name-"+serverHostName, 
&server, func(obj interface{}) error {
-               toServers, reqInf, err := 
cl.C.GetServerByHostName(serverHostName)
+               params := &url.Values{}
+               params.Add("hostName", serverHostName)
+               toServers, reqInf, err := cl.C.GetServersWithHdr(params, nil)
                if err != nil {
-                       return errors.New("getting server name '" + 
serverHostName + "' from Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " 
+ err.Error())
-               } else if len(toServers) < 1 {
-                       return errors.New("getting server name '" + 
serverHostName + "' from Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': 
no servers returned")
+                       return errors.New("getting server name '" + 
serverHostName + "' from Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+               } else if len(toServers.Response) < 1 {
+                       return errors.New("getting server name '" + 
serverHostName + "' from Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': no servers returned")
                }
-               asv, err := serverToLatest(&toServers[0])
+               asv, err := serverToLatest(&toServers.Response[0])
                if err != nil {
                        return errors.New("converting server to latest version: 
" + err.Error())
                }
@@ -224,12 +142,16 @@ func (cl *TOClient) GetServerByHostName(serverHostName 
string) (*atscfg.Server,
 }
 
 func (cl *TOClient) GetCacheGroups() ([]tc.CacheGroupNullable, net.Addr, 
error) {
+       if cl.C == nil {
+               return cl.Old.GetCacheGroups()
+       }
+
        cacheGroups := []tc.CacheGroupNullable{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, "cachegroups", &cacheGroups, 
func(obj interface{}) error {
                toCacheGroups, reqInf, err := cl.C.GetCacheGroupsNullable()
                if err != nil {
-                       return errors.New("getting cachegroups from Traffic Ops 
'" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting cachegroups from Traffic Ops 
'" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                cacheGroups := obj.(*[]tc.CacheGroupNullable)
                *cacheGroups = toCacheGroups
@@ -248,6 +170,10 @@ func (cl *TOClient) GetCacheGroups() 
([]tc.CacheGroupNullable, net.Addr, error)
 const DeliveryServiceServersAlwaysGetAll = true
 
 func (cl *TOClient) GetDeliveryServiceServers(dsIDs []int, serverIDs []int) 
([]tc.DeliveryServiceServer, net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetDeliveryServiceServers(dsIDs, serverIDs)
+       }
+
        const sortIDsInHash = true
        toAddr := net.Addr(nil)
        serverIDsStr := ""
@@ -270,7 +196,7 @@ func (cl *TOClient) GetDeliveryServiceServers(dsIDs []int, 
serverIDs []int) ([]t
                const noLimit = 999999 // TODO add "no limit" param to DSS 
endpoint
                toDSS, reqInf, err := 
cl.C.GetDeliveryServiceServersWithLimits(noLimit, dsIDsToFetch, sIDsToFetch)
                if err != nil {
-                       return errors.New("getting delivery service servers 
from Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting delivery service servers 
from Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + 
err.Error())
                }
                dss := obj.(*[]tc.DeliveryServiceServer)
                *dss = toDSS.Response
@@ -314,12 +240,16 @@ func (cl *TOClient) GetDeliveryServiceServers(dsIDs 
[]int, serverIDs []int) ([]t
 }
 
 func (cl *TOClient) GetServerProfileParameters(profileName string) 
([]tc.Parameter, net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetServerProfileParameters(profileName)
+       }
+
        serverProfileParameters := []tc.Parameter{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, 
"profile_"+profileName+"_parameters", &serverProfileParameters, func(obj 
interface{}) error {
                toParams, reqInf, err := 
cl.C.GetParametersByProfileName(profileName)
                if err != nil {
-                       return errors.New("getting server profile '" + 
profileName + "' parameters from Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) 
+ "': " + err.Error())
+                       return errors.New("getting server profile '" + 
profileName + "' parameters from Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                params := obj.(*[]tc.Parameter)
                *params = toParams
@@ -332,16 +262,23 @@ func (cl *TOClient) 
GetServerProfileParameters(profileName string) ([]tc.Paramet
        return serverProfileParameters, toAddr, nil
 }
 
+// GetCDNDeliveryServices returns the data, the Traffic Ops address, and any 
error.
 func (cl *TOClient) GetCDNDeliveryServices(cdnID int) 
([]atscfg.DeliveryService, net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetCDNDeliveryServices(cdnID)
+       }
+
        deliveryServices := []atscfg.DeliveryService{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, 
"cdn_"+strconv.Itoa(cdnID)+"_deliveryservices", &deliveryServices, func(obj 
interface{}) error {
-               toDSes, reqInf, err := cl.C.GetDeliveryServicesByCDNID(cdnID)
+               params := url.Values{}
+               params.Set("cdn", strconv.Itoa(cdnID))
+               toDSes, reqInf, err := cl.C.GetDeliveryServicesV30WithHdr(nil, 
params)
                if err != nil {
-                       return errors.New("getting delivery services from 
Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting delivery services from 
Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                dses := obj.(*[]atscfg.DeliveryService)
-               *dses = atscfg.OldToDeliveryServices(toDSes)
+               *dses = dsesToLatest(toDSes)
                toAddr = reqInf.RemoteAddr
                return nil
        })
@@ -351,13 +288,41 @@ func (cl *TOClient) GetCDNDeliveryServices(cdnID int) 
([]atscfg.DeliveryService,
        return deliveryServices, toAddr, nil
 }
 
+// GetTopologies returns the data, the Traffic Ops address, and any error.
+func (cl *TOClient) GetTopologies() ([]tc.Topology, net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetTopologies()
+       }
+
+       topologies := []tc.Topology{}
+       toAddr := net.Addr(nil)
+       err := torequtil.GetRetry(cl.NumRetries, "topologies", &topologies, 
func(obj interface{}) error {
+               toTopologies, reqInf, err := cl.C.GetTopologies()
+               if err != nil {
+                       return errors.New("getting topologies from Traffic Ops 
'" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+               }
+               topologies := obj.(*[]tc.Topology)
+               *topologies = toTopologies
+               toAddr = reqInf.RemoteAddr
+               return nil
+       })
+       if err != nil {
+               return nil, nil, errors.New("getting topologies: " + 
err.Error())
+       }
+       return topologies, toAddr, nil
+}
+
 func (cl *TOClient) GetConfigFileParameters(configFile string) 
([]tc.Parameter, net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetConfigFileParameters(configFile)
+       }
+
        params := []tc.Parameter{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, 
"config_file_"+configFile+"_parameters", &params, func(obj interface{}) error {
                toParams, reqInf, err := 
cl.C.GetParameterByConfigFile(configFile)
                if err != nil {
-                       return errors.New("getting delivery services from 
Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting delivery services from 
Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                params := obj.(*[]tc.Parameter)
                *params = toParams
@@ -371,15 +336,19 @@ func (cl *TOClient) GetConfigFileParameters(configFile 
string) ([]tc.Parameter,
 }
 
 func (cl *TOClient) GetCDN(cdnName tc.CDNName) (tc.CDN, net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetCDN(cdnName)
+       }
+
        cdn := tc.CDN{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, "cdn_"+string(cdnName), &cdn, 
func(obj interface{}) error {
                toCDNs, reqInf, err := cl.C.GetCDNByName(string(cdnName))
                if err != nil {
-                       return errors.New("getting cdn from Traffic Ops '" + 
MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting cdn from Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                if len(toCDNs) != 1 {
-                       return errors.New("getting cdn from Traffic Ops '" + 
MaybeIPStr(reqInf.RemoteAddr) + "': expected 1 CDN, got " + 
strconv.Itoa(len(toCDNs)))
+                       return errors.New("getting cdn from Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': expected 1 CDN, got " + 
strconv.Itoa(len(toCDNs)))
                }
                cdn := obj.(*tc.CDN)
                *cdn = toCDNs[0]
@@ -393,12 +362,16 @@ func (cl *TOClient) GetCDN(cdnName tc.CDNName) (tc.CDN, 
net.Addr, error) {
 }
 
 func (cl *TOClient) GetURLSigKeys(dsName string) (tc.URLSigKeys, net.Addr, 
error) {
+       if cl.C == nil {
+               return cl.Old.GetURLSigKeys(dsName)
+       }
+
        keys := tc.URLSigKeys{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, "urlsigkeys_"+string(dsName), 
&keys, func(obj interface{}) error {
                toKeys, reqInf, err := cl.C.GetDeliveryServiceURLSigKeys(dsName)
                if err != nil {
-                       return errors.New("getting url sig keys from Traffic 
Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting url sig keys from Traffic 
Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                keys := obj.(*tc.URLSigKeys)
                *keys = toKeys
@@ -412,12 +385,16 @@ func (cl *TOClient) GetURLSigKeys(dsName string) 
(tc.URLSigKeys, net.Addr, error
 }
 
 func (cl *TOClient) GetURISigningKeys(dsName string) ([]byte, net.Addr, error) 
{
+       if cl.C == nil {
+               return cl.Old.GetURISigningKeys(dsName)
+       }
+
        keys := []byte{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, 
"urisigningkeys_"+string(dsName), &keys, func(obj interface{}) error {
                toKeys, reqInf, err := 
cl.C.GetDeliveryServiceURISigningKeys(dsName)
                if err != nil {
-                       return errors.New("getting url sig keys from Traffic 
Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting url sig keys from Traffic 
Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
 
                keys := obj.(*[]byte)
@@ -432,12 +409,16 @@ func (cl *TOClient) GetURISigningKeys(dsName string) 
([]byte, net.Addr, error) {
 }
 
 func (cl *TOClient) GetParametersByName(paramName string) ([]tc.Parameter, 
net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetParametersByName(paramName)
+       }
+
        params := []tc.Parameter{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, "parameters_name_"+paramName, 
&params, func(obj interface{}) error {
                toParams, reqInf, err := cl.C.GetParameterByName(paramName)
                if err != nil {
-                       return errors.New("getting parameters name '" + 
paramName + "' from Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + 
err.Error())
+                       return errors.New("getting parameters name '" + 
paramName + "' from Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + 
"': " + err.Error())
                }
                params := obj.(*[]tc.Parameter)
                *params = toParams
@@ -451,12 +432,16 @@ func (cl *TOClient) GetParametersByName(paramName string) 
([]tc.Parameter, net.A
 }
 
 func (cl *TOClient) GetDeliveryServiceRegexes() ([]tc.DeliveryServiceRegexes, 
net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetDeliveryServiceRegexes()
+       }
+
        regexes := []tc.DeliveryServiceRegexes{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, "ds_regexes", &regexes, 
func(obj interface{}) error {
                toRegexes, reqInf, err := cl.C.GetDeliveryServiceRegexes()
                if err != nil {
-                       return errors.New("getting ds regexes from Traffic Ops 
'" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting ds regexes from Traffic Ops 
'" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                regexes := obj.(*[]tc.DeliveryServiceRegexes)
                *regexes = toRegexes
@@ -470,12 +455,16 @@ func (cl *TOClient) GetDeliveryServiceRegexes() 
([]tc.DeliveryServiceRegexes, ne
 }
 
 func (cl *TOClient) GetJobs() ([]tc.Job, net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetJobs()
+       }
+
        jobs := []tc.Job{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, "jobs", &jobs, func(obj 
interface{}) error {
                toJobs, reqInf, err := cl.C.GetJobs(nil, nil)
                if err != nil {
-                       return errors.New("getting jobs from Traffic Ops '" + 
MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting jobs from Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                jobs := obj.(*[]tc.Job)
                *jobs = toJobs
@@ -489,6 +478,10 @@ func (cl *TOClient) GetJobs() ([]tc.Job, net.Addr, error) {
 }
 
 func (cl *TOClient) GetServerCapabilitiesByID(serverIDs []int) 
(map[int]map[atscfg.ServerCapability]struct{}, net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetServerCapabilitiesByID(serverIDs)
+       }
+
        serverIDsStr := ""
        if len(serverIDs) > 0 {
                sortIDsInHash := true
@@ -501,7 +494,7 @@ func (cl *TOClient) GetServerCapabilitiesByID(serverIDs 
[]int) (map[int]map[atsc
                // TODO add list of IDs to API+Client
                toServerCaps, reqInf, err := 
cl.C.GetServerServerCapabilities(nil, nil, nil)
                if err != nil {
-                       return errors.New("getting server caps from Traffic Ops 
'" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting server caps from Traffic Ops 
'" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                serverCaps := 
obj.(*map[int]map[atscfg.ServerCapability]struct{})
 
@@ -527,6 +520,10 @@ func (cl *TOClient) GetServerCapabilitiesByID(serverIDs 
[]int) (map[int]map[atsc
 }
 
 func (cl *TOClient) GetDeliveryServiceRequiredCapabilitiesByID(dsIDs []int) 
(map[int]map[atscfg.ServerCapability]struct{}, net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetDeliveryServiceRequiredCapabilitiesByID(dsIDs)
+       }
+
        dsIDsStr := ""
        if len(dsIDs) > 0 {
                sortIDsInHash := true
@@ -539,7 +536,7 @@ func (cl *TOClient) 
GetDeliveryServiceRequiredCapabilitiesByID(dsIDs []int) (map
                // TODO add list of IDs to API+Client
                toDSCaps, reqInf, err := 
cl.C.GetDeliveryServicesRequiredCapabilities(nil, nil, nil)
                if err != nil {
-                       return errors.New("getting ds caps from Traffic Ops '" 
+ MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting ds caps from Traffic Ops '" 
+ torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                dsCaps := obj.(*map[int]map[atscfg.ServerCapability]struct{})
 
@@ -565,12 +562,16 @@ func (cl *TOClient) 
GetDeliveryServiceRequiredCapabilitiesByID(dsIDs []int) (map
 }
 
 func (cl *TOClient) GetCDNSSLKeys(cdnName tc.CDNName) ([]tc.CDNSSLKeys, 
net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetCDNSSLKeys(cdnName)
+       }
+
        keys := []tc.CDNSSLKeys{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, 
"cdn_sslkeys_"+string(cdnName), &keys, func(obj interface{}) error {
                toKeys, reqInf, err := cl.C.GetCDNSSLKeys(string(cdnName))
                if err != nil {
-                       return errors.New("getting cdn ssl keys from Traffic 
Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting cdn ssl keys from Traffic 
Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                keys := obj.(*[]tc.CDNSSLKeys)
                *keys = toKeys
@@ -584,12 +585,16 @@ func (cl *TOClient) GetCDNSSLKeys(cdnName tc.CDNName) 
([]tc.CDNSSLKeys, net.Addr
 }
 
 func (cl *TOClient) GetStatuses() ([]tc.Status, net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetStatuses()
+       }
+
        statuses := []tc.Status{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, "statuses", &statuses, 
func(obj interface{}) error {
                toStatus, reqInf, err := cl.C.GetStatuses()
                if err != nil {
-                       return errors.New("getting server update status from 
Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting server update status from 
Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                status := obj.(*[]tc.Status)
                *status = toStatus
@@ -602,13 +607,18 @@ func (cl *TOClient) GetStatuses() ([]tc.Status, net.Addr, 
error) {
        return statuses, toAddr, nil
 }
 
+// GetServerUpdateStatus returns the data, the Traffic Ops address, and any 
error.
 func (cl *TOClient) GetServerUpdateStatus(cacheHostName tc.CacheName) 
(tc.ServerUpdateStatus, net.Addr, error) {
+       if cl.C == nil {
+               return cl.Old.GetServerUpdateStatus(cacheHostName)
+       }
+
        status := tc.ServerUpdateStatus{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, 
"server_update_status_"+string(cacheHostName), &status, func(obj interface{}) 
error {
                toStatus, reqInf, err := 
cl.C.GetServerUpdateStatus(string(cacheHostName))
                if err != nil {
-                       return errors.New("getting server update status from 
Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting server update status from 
Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                status := obj.(*tc.ServerUpdateStatus)
                *status = toStatus
diff --git a/traffic_ops_ort/atstccfg/toreq/conversions.go 
b/traffic_ops_ort/atstccfg/toreq/conversions.go
new file mode 100644
index 0000000..0421e0e
--- /dev/null
+++ b/traffic_ops_ort/atstccfg/toreq/conversions.go
@@ -0,0 +1,38 @@
+package toreq
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+       "github.com/apache/trafficcontrol/lib/go-atscfg"
+       "github.com/apache/trafficcontrol/lib/go-tc"
+)
+
+func serversToLatest(svs tc.ServersV3Response) ([]atscfg.Server, error) {
+       return atscfg.ToServers(svs.Response), nil
+}
+
+func serverToLatest(oldSv *tc.ServerV30) (*atscfg.Server, error) {
+       asv := atscfg.Server(*oldSv)
+       return &asv, nil
+}
+
+func dsesToLatest(dses []tc.DeliveryServiceNullableV30) 
[]atscfg.DeliveryService {
+       return atscfg.V30ToDeliveryServices(dses)
+}
diff --git a/traffic_ops_ort/atstccfg/toreqnew/toreqnew.go 
b/traffic_ops_ort/atstccfg/toreqnew/toreqnew.go
deleted file mode 100644
index 4178c3d..0000000
--- a/traffic_ops_ort/atstccfg/toreqnew/toreqnew.go
+++ /dev/null
@@ -1,191 +0,0 @@
-// toreqnew implements a Traffic Ops client for features in the latest version.
-//
-// This should only be used if an endpoint or field needed for config gen is 
in the latest.
-//
-// Users should always check the returned bool, and if it's false, call the 
vendored toreq client and set the proper defaults for the new feature(s).
-//
-// All TOClient functions should check for 404 or 503 and return a bool false 
if so.
-//
-package toreqnew
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import (
-       "errors"
-       "net"
-       "net/http/cookiejar"
-       "net/url"
-       "strconv"
-       "strings"
-       "time"
-
-       "golang.org/x/net/publicsuffix"
-
-       "github.com/apache/trafficcontrol/lib/go-atscfg"
-       "github.com/apache/trafficcontrol/lib/go-log"
-       "github.com/apache/trafficcontrol/lib/go-tc"
-
-       toclient "github.com/apache/trafficcontrol/traffic_ops/v4-client"
-       "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/torequtil"
-)
-
-type TOClient struct {
-       C          *toclient.Session
-       NumRetries int
-}
-
-// New returns a TOClient with the given credentials.
-// Note it does not actually log in or try to make a request. Rather, it 
assumes the cookies are valid for a session. No external communication is made.
-func New(cookies string, url *url.URL, user string, pass string, insecure 
bool, timeout time.Duration, userAgent string) (*TOClient, error) {
-       log.Infoln("URL: '" + url.String() + "' User: '" + user + "' Pass len: 
'" + strconv.Itoa(len(pass)) + "'")
-
-       useCache := false
-       toClient := toclient.NewNoAuthSession(url.String(), insecure, 
userAgent, useCache, timeout)
-       toClient.UserName = user
-       toClient.Password = pass
-
-       jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: 
publicsuffix.List})
-       if err != nil {
-               return nil, errors.New("making cookie jar: " + err.Error())
-       }
-       toClient.Client.Jar = jar
-       toClient.Client.Jar.SetCookies(url, torequtil.StringToCookies(cookies))
-
-       return &TOClient{C: toClient}, nil
-}
-
-// GetCDNDeliveryServices returns the deliveryservices, whether this client's 
version is unsupported by the server, and any error.
-// Note if the server returns a 404 or 503, this returns false and a nil error.
-// Users should check the "not supported" bool, and use the vendored TOClient 
if it's set, and set proper defaults for the new feature(s).
-func (cl *TOClient) GetCDNDeliveryServices(cdnID int) 
([]atscfg.DeliveryService, net.Addr, bool, error) {
-       deliveryServices := []atscfg.DeliveryService{}
-       toAddr := net.Addr(nil)
-       unsupported := false
-       err := torequtil.GetRetry(cl.NumRetries, 
"cdn_"+strconv.Itoa(cdnID)+"_deliveryservices", &deliveryServices, func(obj 
interface{}) error {
-               params := url.Values{}
-               params.Set("cdn", strconv.Itoa(cdnID))
-               toDSes, reqInf, err := cl.C.GetDeliveryServicesV4(nil, params)
-               if err != nil {
-                       if IsUnsupportedErr(err) {
-                               unsupported = true
-                               return nil
-                       }
-                       return errors.New("getting delivery services from 
Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
-               }
-               dses := obj.(*[]atscfg.DeliveryService)
-               *dses = atscfg.ToDeliveryServices(toDSes)
-               toAddr = reqInf.RemoteAddr
-               return nil
-       })
-       if unsupported {
-               return nil, nil, true, nil
-       }
-       if err != nil {
-               return nil, nil, false, errors.New("getting delivery services: 
" + err.Error())
-       }
-       return deliveryServices, toAddr, false, nil
-}
-
-func (cl *TOClient) GetTopologies() ([]tc.Topology, net.Addr, bool, error) {
-       topologies := []tc.Topology{}
-       unsupported := false
-       toAddr := net.Addr(nil)
-       err := torequtil.GetRetry(cl.NumRetries, "topologies", &topologies, 
func(obj interface{}) error {
-               toTopologies, reqInf, err := cl.C.GetTopologies()
-               if err != nil {
-                       if IsUnsupportedErr(err) {
-                               unsupported = true
-                               return nil
-                       }
-                       return errors.New("getting topologies from Traffic Ops 
'" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
-               }
-               topologies := obj.(*[]tc.Topology)
-               *topologies = toTopologies
-               toAddr = reqInf.RemoteAddr
-               return nil
-       })
-       if unsupported {
-               return nil, nil, true, nil
-       }
-       if err != nil {
-               return nil, nil, false, errors.New("getting topologies: " + 
err.Error())
-       }
-       return topologies, toAddr, false, nil
-}
-
-func (cl *TOClient) GetServerUpdateStatus(cacheHostName tc.CacheName) 
(tc.ServerUpdateStatus, net.Addr, bool, error) {
-       status := tc.ServerUpdateStatus{}
-       unsupported := false
-       toAddr := net.Addr(nil)
-       err := torequtil.GetRetry(cl.NumRetries, 
"server_update_status_"+string(cacheHostName), &status, func(obj interface{}) 
error {
-               toStatus, reqInf, err := 
cl.C.GetServerUpdateStatus(string(cacheHostName), nil)
-               if err != nil {
-                       if IsUnsupportedErr(err) {
-                               unsupported = true
-                               return nil
-                       }
-                       return errors.New("getting server update status from 
Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
-               }
-               status := obj.(*tc.ServerUpdateStatus)
-               *status = toStatus
-               toAddr = reqInf.RemoteAddr
-               return nil
-       })
-       if unsupported {
-               return tc.ServerUpdateStatus{}, nil, true, nil
-       }
-       if err != nil {
-               return tc.ServerUpdateStatus{}, nil, false, errors.New("getting 
server update status: " + err.Error())
-       }
-       return status, toAddr, false, nil
-}
-
-func (cl *TOClient) GetServers() ([]atscfg.Server, net.Addr, bool, error) {
-       servers := []atscfg.Server{}
-       toAddr := net.Addr(nil)
-       unsupported := false
-       err := torequtil.GetRetry(cl.NumRetries, "servers", &servers, func(obj 
interface{}) error {
-               toServers, reqInf, err := cl.C.GetServersWithHdr(nil, nil)
-               if err != nil {
-                       if IsUnsupportedErr(err) {
-                               unsupported = true
-                               return nil
-                       }
-                       return errors.New("getting servers from Traffic Ops '" 
+ torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
-               }
-
-               servers := obj.(*[]atscfg.Server)
-               *servers = atscfg.ToServers(toServers.Response)
-               toAddr = reqInf.RemoteAddr
-               return nil
-       })
-       if unsupported {
-               return nil, nil, true, nil
-       }
-       if err != nil {
-               return nil, nil, false, errors.New("getting servers: " + 
err.Error())
-       }
-       return servers, toAddr, false, nil
-}
-
-func IsUnsupportedErr(err error) bool {
-       errStr := strings.ToLower(err.Error())
-       return strings.Contains(errStr, "not found") || 
strings.Contains(errStr, "not impl")
-}
diff --git a/traffic_ops_ort/atstccfg/toreqold/client.go 
b/traffic_ops_ort/atstccfg/toreqold/client.go
new file mode 100644
index 0000000..3eb52b9
--- /dev/null
+++ b/traffic_ops_ort/atstccfg/toreqold/client.go
@@ -0,0 +1,60 @@
+// toreqold implements a Traffic Ops client vendored one version back.
+//
+// This should be used for all requests, unless they require an endpoint or 
field added in the latest version.
+//
+// If a feature in the latest Traffic Ops is required, toreqnew should be used 
with a fallback to this client if the Traffic Ops is not the latest (which can 
be determined by the bool returned by all toreqnew.TOClient funcs).
+//
+package toreqold
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+       "errors"
+       "net/url"
+       "strconv"
+       "time"
+
+       "github.com/apache/trafficcontrol/lib/go-log"
+       toclient "github.com/apache/trafficcontrol/traffic_ops/v3-client"
+       "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/torequtil"
+)
+
+type TOClient struct {
+       C          *toclient.Session
+       NumRetries int
+}
+
+const isFallback = true
+
+// New logs into Traffic Ops, returning the TOClient which contains the 
logged-in client.
+func New(url *url.URL, user string, pass string, insecure bool, timeout 
time.Duration, userAgent string) (*TOClient, error) {
+       log.Infoln("URL: '" + url.String() + "' User: '" + user + "' Pass len: 
'" + strconv.Itoa(len(pass)) + "'")
+
+       toFQDN := url.Scheme + "://" + url.Host
+       log.Infoln("TO FQDN: '" + toFQDN + "'")
+       log.Infoln("TO URL: '" + url.String() + "'")
+
+       toClient, toIP, err := toclient.LoginWithAgent(toFQDN, user, pass, 
insecure, userAgent, false, timeout)
+       if err != nil {
+               return nil, errors.New("Logging in to Traffic Ops '" + 
torequtil.MaybeIPStr(toIP) + "': " + err.Error())
+       }
+
+       return &TOClient{C: toClient}, nil
+}
diff --git a/traffic_ops_ort/atstccfg/toreq/toreq.go 
b/traffic_ops_ort/atstccfg/toreqold/clientfuncs.go
similarity index 74%
rename from traffic_ops_ort/atstccfg/toreq/toreq.go
rename to traffic_ops_ort/atstccfg/toreqold/clientfuncs.go
index b8f812e..5f9735e 100644
--- a/traffic_ops_ort/atstccfg/toreq/toreq.go
+++ b/traffic_ops_ort/atstccfg/toreqold/clientfuncs.go
@@ -1,10 +1,4 @@
-// toreqnew implements a Traffic Ops client vendored one version back.
-//
-// This should be used for all requests, unless they require an endpoint or 
field added in the latest version.
-//
-// If a feature in the latest Traffic Ops is required, toreqnew should be used 
with a fallback to this client if the Traffic Ops is not the latest (which can 
be determined by the bool returned by all toreqnew.TOClient funcs).
-//
-package toreq
+package toreqold
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -31,63 +25,24 @@ import (
        "net"
        "net/url"
        "strconv"
-       "time"
 
        "github.com/apache/trafficcontrol/lib/go-atscfg"
        "github.com/apache/trafficcontrol/lib/go-log"
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/lib/go-util"
-       toclient "github.com/apache/trafficcontrol/traffic_ops/v1-client"
        "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/torequtil"
 )
 
-type TOClient struct {
-       C          *toclient.Session
-       NumRetries int
-}
-
-// New logs into Traffic Ops, returning the TOClient which contains the 
logged-in client.
-func New(url *url.URL, user string, pass string, insecure bool, timeout 
time.Duration, userAgent string) (*TOClient, error) {
-       log.Infoln("URL: '" + url.String() + "' User: '" + user + "' Pass len: 
'" + strconv.Itoa(len(pass)) + "'")
-
-       toFQDN := url.Scheme + "://" + url.Host
-       log.Infoln("TO FQDN: '" + toFQDN + "'")
-       log.Infoln("TO URL: '" + url.String() + "'")
-
-       toClient, toIP, err := toclient.LoginWithAgent(toFQDN, user, pass, 
insecure, userAgent, false, timeout)
-       if err != nil {
-               return nil, errors.New("Logging in to Traffic Ops '" + 
MaybeIPStr(toIP) + "': " + err.Error())
-       }
-
-       return &TOClient{C: toClient}, nil
-}
-
-// Cookies returns the HTTP session cookies from the client.
-// It does not do any kind of validation, but assumes the HTTP cookies exist 
from a prior login and are valid for a Traffic Ops session.
-// The url is the Traffic Ops URL, and should match this client's Traffic Ops 
URL, and the URL of the new client this session cookie is presumably being 
fetched for.
-func (cl *TOClient) Cookies(url *url.URL) string {
-       return torequtil.CookiesToString(cl.C.Client.Jar.Cookies(url))
-}
-
-// MaybeIPStr returns the addr string if it isn't nil, or the empty string if 
it is.
-// This is intended for logging, to allow logging with one line, whether addr 
is nil or not.
-func MaybeIPStr(addr net.Addr) string {
-       if addr != nil {
-               return addr.String()
-       }
-       return ""
-}
-
 func (cl *TOClient) GetProfileByName(profileName string) (tc.Profile, 
net.Addr, error) {
        profile := tc.Profile{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, "profile_"+profileName, 
&profile, func(obj interface{}) error {
                toProfiles, reqInf, err := cl.C.GetProfileByName(profileName)
                if err != nil {
-                       return errors.New("getting profile '" + profileName + 
"' from Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting profile '" + profileName + 
"' from Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + 
err.Error())
                }
                if len(toProfiles) != 1 {
-                       return errors.New("getting profile '" + profileName + 
"'from Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': expected 1 Profile, 
got " + strconv.Itoa(len(toProfiles)))
+                       return errors.New("getting profile '" + profileName + 
"'from Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': expected 
1 Profile, got " + strconv.Itoa(len(toProfiles)))
                }
 
                profile := obj.(*tc.Profile)
@@ -108,7 +63,7 @@ func (cl *TOClient) GetGlobalParameters() ([]tc.Parameter, 
net.Addr, error) {
        err := torequtil.GetRetry(cl.NumRetries, "profile_global_parameters", 
&globalParams, func(obj interface{}) error {
                toParams, reqInf, err := 
cl.C.GetParametersByProfileName(tc.GlobalProfileName)
                if err != nil {
-                       return errors.New("getting global profile '" + 
tc.GlobalProfileName + "' parameters from Traffic Ops '" + 
MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting global profile '" + 
tc.GlobalProfileName + "' parameters from Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                params := obj.(*[]tc.Parameter)
                *params = toParams
@@ -121,42 +76,18 @@ func (cl *TOClient) GetGlobalParameters() ([]tc.Parameter, 
net.Addr, error) {
        return globalParams, toAddr, nil
 }
 
-func GetTOToolNameAndURL(globalParams []tc.Parameter) (string, string) {
-       // TODO move somewhere generic
-       toToolName := ""
-       toURL := ""
-       for _, param := range globalParams {
-               if param.Name == "tm.toolname" {
-                       toToolName = param.Value
-               } else if param.Name == "tm.url" {
-                       toURL = param.Value
-               }
-               if toToolName != "" && toURL != "" {
-                       break
-               }
-       }
-       // TODO error here? Perl doesn't.
-       if toToolName == "" {
-               log.Warnln("Global Parameter tm.toolname not found, config may 
not be constructed properly!")
-       }
-       if toURL == "" {
-               log.Warnln("Global Parameter tm.url not found, config may not 
be constructed properly!")
-       }
-       return toToolName, toURL
-}
-
 func (cl *TOClient) GetServers() ([]atscfg.Server, net.Addr, error) {
        servers := []atscfg.Server{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, "servers", &servers, func(obj 
interface{}) error {
-               toServers, reqInf, err := cl.C.GetServers()
+               toServers, reqInf, err := cl.C.GetServersWithHdr(nil, nil)
                if err != nil {
-                       return errors.New("getting servers from Traffic Ops '" 
+ MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting servers from Traffic Ops '" 
+ torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                servers := obj.(*[]atscfg.Server)
                *servers, err = serversToLatest(toServers)
                if err != nil {
-                       return errors.New("upgrading servers from Traffic Ops 
'" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("upgrading servers from Traffic Ops 
'" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                toAddr = reqInf.RemoteAddr
                return nil
@@ -167,48 +98,19 @@ func (cl *TOClient) GetServers() ([]atscfg.Server, 
net.Addr, error) {
        return servers, toAddr, nil
 }
 
-// serversToLatest converts a []tc.Server to []tc.ServerV30.
-// This is necessary, because the Traffic Ops API 1.x client doesn't return 
the same type as the latest client.
-func serversToLatest(svs []tc.ServerV1) ([]atscfg.Server, error) {
-       nss := []atscfg.Server{}
-       for _, sv := range svs {
-               svLatest, err := serverToLatest(&sv)
-               if err != nil {
-                       return nil, err // serverToLatest adds context
-               }
-               nss = append(nss, atscfg.Server(*svLatest))
-       }
-       return nss, nil
-}
-
-// serverToLatest converts a tc.Server to tc.ServerV30.
-// This is necessary, because the Traffic Ops API 1.x client doesn't return 
the same type as the latest client.
-func serverToLatest(sv *tc.ServerV1) (*atscfg.Server, error) {
-       svn := sv.ToNullable()
-       sv2 := tc.ServerNullableV2{
-               ServerNullableV11: svn,
-               IPIsService:       util.BoolPtr(true),
-               IP6IsService:      util.BoolPtr(svn.IP6Address != nil && 
*svn.IP6Address != ""),
-       }
-       svLatest, err := sv2.UpgradeToV40()
-       if err != nil {
-               return nil, errors.New("upgrading: " + err.Error())
-       }
-       asv := atscfg.Server(svLatest)
-       return &asv, nil
-}
-
 func (cl *TOClient) GetServerByHostName(serverHostName string) 
(*atscfg.Server, net.Addr, error) {
        server := atscfg.Server{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, "server-name-"+serverHostName, 
&server, func(obj interface{}) error {
-               toServers, reqInf, err := 
cl.C.GetServerByHostName(serverHostName)
+               params := &url.Values{}
+               params.Add("hostName", serverHostName)
+               toServers, reqInf, err := cl.C.GetServersWithHdr(params, nil)
                if err != nil {
-                       return errors.New("getting server name '" + 
serverHostName + "' from Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " 
+ err.Error())
-               } else if len(toServers) < 1 {
-                       return errors.New("getting server name '" + 
serverHostName + "' from Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': 
no servers returned")
+                       return errors.New("getting server name '" + 
serverHostName + "' from Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+               } else if len(toServers.Response) < 1 {
+                       return errors.New("getting server name '" + 
serverHostName + "' from Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': no servers returned")
                }
-               asv, err := serverToLatest(&toServers[0])
+               asv, err := serverToLatest(&toServers.Response[0])
                if err != nil {
                        return errors.New("converting server to latest version: 
" + err.Error())
                }
@@ -229,7 +131,7 @@ func (cl *TOClient) GetCacheGroups() 
([]tc.CacheGroupNullable, net.Addr, error)
        err := torequtil.GetRetry(cl.NumRetries, "cachegroups", &cacheGroups, 
func(obj interface{}) error {
                toCacheGroups, reqInf, err := cl.C.GetCacheGroupsNullable()
                if err != nil {
-                       return errors.New("getting cachegroups from Traffic Ops 
'" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting cachegroups from Traffic Ops 
'" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                cacheGroups := obj.(*[]tc.CacheGroupNullable)
                *cacheGroups = toCacheGroups
@@ -270,7 +172,7 @@ func (cl *TOClient) GetDeliveryServiceServers(dsIDs []int, 
serverIDs []int) ([]t
                const noLimit = 999999 // TODO add "no limit" param to DSS 
endpoint
                toDSS, reqInf, err := 
cl.C.GetDeliveryServiceServersWithLimits(noLimit, dsIDsToFetch, sIDsToFetch)
                if err != nil {
-                       return errors.New("getting delivery service servers 
from Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting delivery service servers 
from Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + 
err.Error())
                }
                dss := obj.(*[]tc.DeliveryServiceServer)
                *dss = toDSS.Response
@@ -319,7 +221,7 @@ func (cl *TOClient) GetServerProfileParameters(profileName 
string) ([]tc.Paramet
        err := torequtil.GetRetry(cl.NumRetries, 
"profile_"+profileName+"_parameters", &serverProfileParameters, func(obj 
interface{}) error {
                toParams, reqInf, err := 
cl.C.GetParametersByProfileName(profileName)
                if err != nil {
-                       return errors.New("getting server profile '" + 
profileName + "' parameters from Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) 
+ "': " + err.Error())
+                       return errors.New("getting server profile '" + 
profileName + "' parameters from Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                params := obj.(*[]tc.Parameter)
                *params = toParams
@@ -332,16 +234,19 @@ func (cl *TOClient) 
GetServerProfileParameters(profileName string) ([]tc.Paramet
        return serverProfileParameters, toAddr, nil
 }
 
+// GetCDNDeliveryServices returns the data, the Traffic Ops address, and any 
error.
 func (cl *TOClient) GetCDNDeliveryServices(cdnID int) 
([]atscfg.DeliveryService, net.Addr, error) {
        deliveryServices := []atscfg.DeliveryService{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, 
"cdn_"+strconv.Itoa(cdnID)+"_deliveryservices", &deliveryServices, func(obj 
interface{}) error {
-               toDSes, reqInf, err := cl.C.GetDeliveryServicesByCDNID(cdnID)
+               params := url.Values{}
+               params.Set("cdn", strconv.Itoa(cdnID))
+               toDSes, reqInf, err := cl.C.GetDeliveryServicesV30WithHdr(nil, 
params)
                if err != nil {
-                       return errors.New("getting delivery services from 
Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting delivery services from 
Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                dses := obj.(*[]atscfg.DeliveryService)
-               *dses = atscfg.OldToDeliveryServices(toDSes)
+               *dses = dsesToLatest(toDSes)
                toAddr = reqInf.RemoteAddr
                return nil
        })
@@ -351,13 +256,33 @@ func (cl *TOClient) GetCDNDeliveryServices(cdnID int) 
([]atscfg.DeliveryService,
        return deliveryServices, toAddr, nil
 }
 
+// GetTopologies returns the data, the Traffic Ops address, and any error.
+func (cl *TOClient) GetTopologies() ([]tc.Topology, net.Addr, error) {
+       topologies := []tc.Topology{}
+       toAddr := net.Addr(nil)
+       err := torequtil.GetRetry(cl.NumRetries, "topologies", &topologies, 
func(obj interface{}) error {
+               toTopologies, reqInf, err := cl.C.GetTopologies()
+               if err != nil {
+                       return errors.New("getting topologies from Traffic Ops 
'" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+               }
+               topologies := obj.(*[]tc.Topology)
+               *topologies = toTopologies
+               toAddr = reqInf.RemoteAddr
+               return nil
+       })
+       if err != nil {
+               return nil, nil, errors.New("getting topologies: " + 
err.Error())
+       }
+       return topologies, toAddr, nil
+}
+
 func (cl *TOClient) GetConfigFileParameters(configFile string) 
([]tc.Parameter, net.Addr, error) {
        params := []tc.Parameter{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, 
"config_file_"+configFile+"_parameters", &params, func(obj interface{}) error {
                toParams, reqInf, err := 
cl.C.GetParameterByConfigFile(configFile)
                if err != nil {
-                       return errors.New("getting delivery services from 
Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting delivery services from 
Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                params := obj.(*[]tc.Parameter)
                *params = toParams
@@ -376,10 +301,10 @@ func (cl *TOClient) GetCDN(cdnName tc.CDNName) (tc.CDN, 
net.Addr, error) {
        err := torequtil.GetRetry(cl.NumRetries, "cdn_"+string(cdnName), &cdn, 
func(obj interface{}) error {
                toCDNs, reqInf, err := cl.C.GetCDNByName(string(cdnName))
                if err != nil {
-                       return errors.New("getting cdn from Traffic Ops '" + 
MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting cdn from Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                if len(toCDNs) != 1 {
-                       return errors.New("getting cdn from Traffic Ops '" + 
MaybeIPStr(reqInf.RemoteAddr) + "': expected 1 CDN, got " + 
strconv.Itoa(len(toCDNs)))
+                       return errors.New("getting cdn from Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': expected 1 CDN, got " + 
strconv.Itoa(len(toCDNs)))
                }
                cdn := obj.(*tc.CDN)
                *cdn = toCDNs[0]
@@ -398,7 +323,7 @@ func (cl *TOClient) GetURLSigKeys(dsName string) 
(tc.URLSigKeys, net.Addr, error
        err := torequtil.GetRetry(cl.NumRetries, "urlsigkeys_"+string(dsName), 
&keys, func(obj interface{}) error {
                toKeys, reqInf, err := cl.C.GetDeliveryServiceURLSigKeys(dsName)
                if err != nil {
-                       return errors.New("getting url sig keys from Traffic 
Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting url sig keys from Traffic 
Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                keys := obj.(*tc.URLSigKeys)
                *keys = toKeys
@@ -417,7 +342,7 @@ func (cl *TOClient) GetURISigningKeys(dsName string) 
([]byte, net.Addr, error) {
        err := torequtil.GetRetry(cl.NumRetries, 
"urisigningkeys_"+string(dsName), &keys, func(obj interface{}) error {
                toKeys, reqInf, err := 
cl.C.GetDeliveryServiceURISigningKeys(dsName)
                if err != nil {
-                       return errors.New("getting url sig keys from Traffic 
Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting url sig keys from Traffic 
Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
 
                keys := obj.(*[]byte)
@@ -437,7 +362,7 @@ func (cl *TOClient) GetParametersByName(paramName string) 
([]tc.Parameter, net.A
        err := torequtil.GetRetry(cl.NumRetries, "parameters_name_"+paramName, 
&params, func(obj interface{}) error {
                toParams, reqInf, err := cl.C.GetParameterByName(paramName)
                if err != nil {
-                       return errors.New("getting parameters name '" + 
paramName + "' from Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + 
err.Error())
+                       return errors.New("getting parameters name '" + 
paramName + "' from Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + 
"': " + err.Error())
                }
                params := obj.(*[]tc.Parameter)
                *params = toParams
@@ -456,7 +381,7 @@ func (cl *TOClient) GetDeliveryServiceRegexes() 
([]tc.DeliveryServiceRegexes, ne
        err := torequtil.GetRetry(cl.NumRetries, "ds_regexes", &regexes, 
func(obj interface{}) error {
                toRegexes, reqInf, err := cl.C.GetDeliveryServiceRegexes()
                if err != nil {
-                       return errors.New("getting ds regexes from Traffic Ops 
'" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting ds regexes from Traffic Ops 
'" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                regexes := obj.(*[]tc.DeliveryServiceRegexes)
                *regexes = toRegexes
@@ -475,7 +400,7 @@ func (cl *TOClient) GetJobs() ([]tc.Job, net.Addr, error) {
        err := torequtil.GetRetry(cl.NumRetries, "jobs", &jobs, func(obj 
interface{}) error {
                toJobs, reqInf, err := cl.C.GetJobs(nil, nil)
                if err != nil {
-                       return errors.New("getting jobs from Traffic Ops '" + 
MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting jobs from Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                jobs := obj.(*[]tc.Job)
                *jobs = toJobs
@@ -501,7 +426,7 @@ func (cl *TOClient) GetServerCapabilitiesByID(serverIDs 
[]int) (map[int]map[atsc
                // TODO add list of IDs to API+Client
                toServerCaps, reqInf, err := 
cl.C.GetServerServerCapabilities(nil, nil, nil)
                if err != nil {
-                       return errors.New("getting server caps from Traffic Ops 
'" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting server caps from Traffic Ops 
'" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                serverCaps := 
obj.(*map[int]map[atscfg.ServerCapability]struct{})
 
@@ -539,7 +464,7 @@ func (cl *TOClient) 
GetDeliveryServiceRequiredCapabilitiesByID(dsIDs []int) (map
                // TODO add list of IDs to API+Client
                toDSCaps, reqInf, err := 
cl.C.GetDeliveryServicesRequiredCapabilities(nil, nil, nil)
                if err != nil {
-                       return errors.New("getting ds caps from Traffic Ops '" 
+ MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting ds caps from Traffic Ops '" 
+ torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                dsCaps := obj.(*map[int]map[atscfg.ServerCapability]struct{})
 
@@ -570,7 +495,7 @@ func (cl *TOClient) GetCDNSSLKeys(cdnName tc.CDNName) 
([]tc.CDNSSLKeys, net.Addr
        err := torequtil.GetRetry(cl.NumRetries, 
"cdn_sslkeys_"+string(cdnName), &keys, func(obj interface{}) error {
                toKeys, reqInf, err := cl.C.GetCDNSSLKeys(string(cdnName))
                if err != nil {
-                       return errors.New("getting cdn ssl keys from Traffic 
Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting cdn ssl keys from Traffic 
Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                keys := obj.(*[]tc.CDNSSLKeys)
                *keys = toKeys
@@ -589,7 +514,7 @@ func (cl *TOClient) GetStatuses() ([]tc.Status, net.Addr, 
error) {
        err := torequtil.GetRetry(cl.NumRetries, "statuses", &statuses, 
func(obj interface{}) error {
                toStatus, reqInf, err := cl.C.GetStatuses()
                if err != nil {
-                       return errors.New("getting server update status from 
Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting server update status from 
Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                status := obj.(*[]tc.Status)
                *status = toStatus
@@ -602,13 +527,14 @@ func (cl *TOClient) GetStatuses() ([]tc.Status, net.Addr, 
error) {
        return statuses, toAddr, nil
 }
 
+// GetServerUpdateStatus returns the data, the Traffic Ops address, and any 
error.
 func (cl *TOClient) GetServerUpdateStatus(cacheHostName tc.CacheName) 
(tc.ServerUpdateStatus, net.Addr, error) {
        status := tc.ServerUpdateStatus{}
        toAddr := net.Addr(nil)
        err := torequtil.GetRetry(cl.NumRetries, 
"server_update_status_"+string(cacheHostName), &status, func(obj interface{}) 
error {
                toStatus, reqInf, err := 
cl.C.GetServerUpdateStatus(string(cacheHostName))
                if err != nil {
-                       return errors.New("getting server update status from 
Traffic Ops '" + MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
+                       return errors.New("getting server update status from 
Traffic Ops '" + torequtil.MaybeIPStr(reqInf.RemoteAddr) + "': " + err.Error())
                }
                status := obj.(*tc.ServerUpdateStatus)
                *status = toStatus
diff --git a/traffic_ops_ort/atstccfg/toreqold/conversions.go 
b/traffic_ops_ort/atstccfg/toreqold/conversions.go
new file mode 100644
index 0000000..83bf687
--- /dev/null
+++ b/traffic_ops_ort/atstccfg/toreqold/conversions.go
@@ -0,0 +1,55 @@
+package toreqold
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+       "github.com/apache/trafficcontrol/lib/go-atscfg"
+       "github.com/apache/trafficcontrol/lib/go-tc"
+)
+
+// serversToLatest converts a []tc.Server to []tc.ServerV30.
+// This is necessary, because the old Traffic Ops client doesn't return the 
same type as the latest client.
+func serversToLatest(svs tc.ServersV3Response) ([]atscfg.Server, error) {
+       nss := []atscfg.Server{}
+       for _, sv := range svs.Response {
+               svLatest, err := serverToLatest(&sv)
+               if err != nil {
+                       return nil, err // serverToLatest adds context
+               }
+               nss = append(nss, atscfg.Server(*svLatest))
+       }
+       return nss, nil
+}
+
+// serverToLatest converts a tc.Server to tc.ServerV30.
+// This is necessary, because the old Traffic Ops client doesn't return the 
same type as the latest client.
+func serverToLatest(oldSv *tc.ServerV30) (*atscfg.Server, error) {
+       // TODO uncomment, when toreqold is changed to v4-client
+       // sv, err := oldSv.UpgradeToV40()
+       // if err != nil {
+       //      return nil, err
+       // }
+       asv := atscfg.Server(*oldSv)
+       return &asv, nil
+}
+
+func dsesToLatest(dses []tc.DeliveryServiceNullableV30) 
[]atscfg.DeliveryService {
+       return atscfg.ToDeliveryServices(dses)
+}
diff --git a/traffic_ops_ort/atstccfg/torequtil/torequtil.go 
b/traffic_ops_ort/atstccfg/torequtil/torequtil.go
index 726858f..cf52e64 100644
--- a/traffic_ops_ort/atstccfg/torequtil/torequtil.go
+++ b/traffic_ops_ort/atstccfg/torequtil/torequtil.go
@@ -30,6 +30,7 @@ import (
        "time"
 
        "github.com/apache/trafficcontrol/lib/go-log"
+       "github.com/apache/trafficcontrol/lib/go-tc"
 )
 
 // GetRetry attempts to get the given object, retrying with exponential 
backoff up to cfg.NumRetries.
@@ -88,3 +89,27 @@ func CookiesToString(cookies []*http.Cookie) string {
        }
        return strings.Join(strs, "; ")
 }
+
+func GetTOToolNameAndURL(globalParams []tc.Parameter) (string, string) {
+       // TODO move somewhere generic
+       toToolName := ""
+       toURL := ""
+       for _, param := range globalParams {
+               if param.Name == "tm.toolname" {
+                       toToolName = param.Value
+               } else if param.Name == "tm.url" {
+                       toURL = param.Value
+               }
+               if toToolName != "" && toURL != "" {
+                       break
+               }
+       }
+       // TODO error here? Perl doesn't.
+       if toToolName == "" {
+               log.Warnln("Global Parameter tm.toolname not found, config may 
not be constructed properly!")
+       }
+       if toURL == "" {
+               log.Warnln("Global Parameter tm.url not found, config may not 
be constructed properly!")
+       }
+       return toToolName, toURL
+}
diff --git a/traffic_ops_ort/to_requester/config/config.go 
b/traffic_ops_ort/to_requester/config/config.go
index 79c2092..72a4cee 100644
--- a/traffic_ops_ort/to_requester/config/config.go
+++ b/traffic_ops_ort/to_requester/config/config.go
@@ -29,7 +29,6 @@ import (
 
        "github.com/apache/trafficcontrol/lib/go-log"
        "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/toreq"
-       "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/toreqnew"
        "github.com/pborman/getopt/v2"
 )
 
@@ -54,8 +53,7 @@ type Cfg struct {
 
 type TCCfg struct {
        Cfg
-       TOClient    *toreq.TOClient
-       TOClientNew *toreqnew.TOClient
+       TOClient *toreq.TOClient
 }
 
 func (cfg Cfg) DebugLog() log.LogLocation   { return 
log.LogLocation(cfg.LogLocationDebug) }
diff --git a/traffic_ops_ort/to_requester/getdata/getdata.go 
b/traffic_ops_ort/to_requester/getdata/getdata.go
index b2a0ac9..6d4d022 100644
--- a/traffic_ops_ort/to_requester/getdata/getdata.go
+++ b/traffic_ops_ort/to_requester/getdata/getdata.go
@@ -33,8 +33,7 @@ import (
        "github.com/apache/trafficcontrol/lib/go-atscfg"
        "github.com/apache/trafficcontrol/lib/go-log"
        "github.com/apache/trafficcontrol/lib/go-tc"
-       "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/toreq"
-       "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/toreqnew"
+       "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/torequtil"
        "github.com/apache/trafficcontrol/traffic_ops_ort/to_requester/config"
 )
 
@@ -97,11 +96,7 @@ func WriteStatuses(cfg config.TCCfg, output io.Writer) error 
{
 // WriteUpdateStatus writes the Traffic Ops server update status to output.
 // Note this is identical to /api/1.x/servers/name/update_status except it 
omits the '[]' wrapper.
 func WriteServerUpdateStatus(cfg config.TCCfg, output io.Writer) error {
-       status, _, unsupported, err := 
cfg.TOClientNew.GetServerUpdateStatus(tc.CacheName(cfg.CacheHostName))
-       if err == nil && unsupported {
-               log.Warnln("ORT newer than Traffic Ops, falling back to 
previous API Delivery Services!")
-               status, _, err = 
cfg.TOClient.GetServerUpdateStatus(tc.CacheName(cfg.CacheHostName))
-       }
+       status, _, err := 
cfg.TOClient.GetServerUpdateStatus(tc.CacheName(cfg.CacheHostName))
        if err != nil {
                return errors.New("getting server update status: " + 
err.Error())
        }
@@ -191,12 +186,9 @@ type ChkConfigEntry struct {
 
 // SetUpdateStatus sets the queue and reval status of serverName in Traffic 
Ops.
 func SetUpdateStatus(cfg config.TCCfg, serverName tc.CacheName, queue bool, 
revalPending bool) error {
-       reqInf, err := 
cfg.TOClientNew.C.SetUpdateServerStatuses(string(serverName), &queue, 
&revalPending)
-       if err != nil && toreqnew.IsUnsupportedErr(err) {
-               err = setUpdateStatusLegacy(cfg, serverName, queue, 
revalPending)
-       }
+       reqInf, err := 
cfg.TOClient.C.SetUpdateServerStatuses(string(serverName), &queue, 
&revalPending)
        if err != nil {
-               return errors.New("setting update statuses (Traffic Ops '" + 
toreq.MaybeIPStr(reqInf.RemoteAddr) + "'): " + err.Error())
+               return errors.New("setting update statuses (Traffic Ops '" + 
torequtil.MaybeIPStr(reqInf.RemoteAddr) + "'): " + err.Error())
        }
        return nil
 }
diff --git a/traffic_ops_ort/to_requester/to_requester.go 
b/traffic_ops_ort/to_requester/to_requester.go
index ee55dda..7be297b 100644
--- a/traffic_ops_ort/to_requester/to_requester.go
+++ b/traffic_ops_ort/to_requester/to_requester.go
@@ -79,7 +79,6 @@ import (
 
        "github.com/apache/trafficcontrol/lib/go-log"
        "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/toreq"
-       "github.com/apache/trafficcontrol/traffic_ops_ort/atstccfg/toreqnew"
        "github.com/apache/trafficcontrol/traffic_ops_ort/to_requester/config"
        "github.com/apache/trafficcontrol/traffic_ops_ort/to_requester/getdata"
 )
@@ -118,16 +117,18 @@ func main() {
  * connect and login to traffic ops
  */
 func toConnect() (*config.TCCfg, error) {
-       _toClient, err := toreq.New(cfg.TOURL, cfg.TOUser, cfg.TOPass, 
cfg.TOInsecure, cfg.TOTimeoutMS, config.UserAgent)
+       toClient, err := toreq.New(cfg.TOURL, cfg.TOUser, cfg.TOPass, 
cfg.TOInsecure, cfg.TOTimeoutMS, config.UserAgent)
        if err != nil {
                return nil, errors.New("failed to connect to traffic ops: " + 
err.Error())
        }
-       _toClientNew, err := toreqnew.New(_toClient.Cookies(cfg.TOURL), 
cfg.TOURL, cfg.TOUser, cfg.TOPass, cfg.TOInsecure, cfg.TOTimeoutMS, 
config.UserAgent)
+
+       if toClient.FellBack() {
+               log.Warnln("Traffic Ops does not support the latest version 
supported by this app! Falling back to previous major Traffic Ops API version!")
+       }
 
        tccfg := config.TCCfg{
-               Cfg:         cfg,
-               TOClient:    _toClient,
-               TOClientNew: _toClientNew,
+               Cfg:      cfg,
+               TOClient: toClient,
        }
 
        return &tccfg, nil

Reply via email to