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

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


The following commit(s) were added to refs/heads/master by this push:
     new 7e4050d  Client steering forced diversity (#3573)
7e4050d is described below

commit 7e4050d3299342dd256a3c8f9abb2ad5851bd400
Author: Rawlin Peters <[email protected]>
AuthorDate: Tue Jun 4 15:29:29 2019 -0600

    Client steering forced diversity (#3573)
    
    * Add TR support for client.steering.forced.diversity feature
    
    * Add test to verify client.steering.forced.diversity support
    
    * Add docs and changelog for client.steering.forced.diversity
    
    * Modify client steering diversity logic
    
    Since the cache assignments can be different between targets, just
    remove any already-selected caches from the list of caches to choose
    from. If the resulting list is empty, then just choose from all
    available caches for the target.
    
    * CSFD: select from regular CG when deep CG caches have been selected
    
    * Ensure client_steering deep CZF hits still tracked as DEEP_CZ
    
    Even though forced-diversity causes a regular CZF lookup for initial
    deep CZF hits, that request should still be tracked as a deep hit.
    
    * Update CSD external test to cover the deep cachegroup case
---
 CHANGELOG.md                                       |   1 +
 docs/source/admin/traffic_ops/using.rst            |   2 +
 .../traffic_router/core/router/TrafficRouter.java  |  36 +-
 .../traffic_router/core/external/SteeringTest.java |  63 ++++
 .../core/router/TrafficRouterTest.java             |   1 +
 traffic_router/core/src/test/resources/dczmap.json |  12 +
 .../test/resources/internal/api/1.3/steering.json  |  26 ++
 .../core/src/test/resources/publish/CrConfig.json  | 372 +++++++++++++++++++++
 .../core/src/test/resources/publish/CrStates       |  29 +-
 9 files changed, 538 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3948912..bd9f5d5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ The format is based on [Keep a 
Changelog](http://keepachangelog.com/en/1.0.0/).
 - Traffic Router: TR now generates a self-signed certificate at startup and 
uses it as the default TLS cert.
   The default certificate is used whenever a client attempts an SSL handshake 
for an SNI host which does not match
   any of the other certificates.
+- Client Steering Forced Diversity: force Traffic Router to return more unique 
edge caches in CLIENT_STEERING results instead of the default behavior which 
can sometimes return a result of multiple targets using the same edge cache. In 
the case of edge cache failures, this feature will give clients a chance to 
retry a different edge cache. This can be enabled with the new 
"client.steering.forced.diversity" Traffic Router profile parameter.
 - Traffic Ops Golang Endpoints
   - /api/1.4/deliveryservices `(GET,POST,PUT)`
   - /api/1.4/users `(GET,POST,PUT)`
diff --git a/docs/source/admin/traffic_ops/using.rst 
b/docs/source/admin/traffic_ops/using.rst
index 8e444a4..6dc0f63 100644
--- a/docs/source/admin/traffic_ops/using.rst
+++ b/docs/source/admin/traffic_ops/using.rst
@@ -413,6 +413,8 @@ Traffic Router Profile
 
+-----------------------------------------+------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
 | deepcoveragezone.polling.url            | CRConfig.json          | The 
location (URL) to retrieve the deep coverage zone map file in JSON format from. 
                                                             |
 
+-----------------------------------------+------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
+| client.steering.forced.diversity        | CRConfig.json          | Enable 
the Client Steering Forced Diversity feature (value = "true") to diversify 
CLIENT_STEERING results by including more unique edge caches   |
++-----------------------------------------+------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
 | tld.soa.expire                          | CRConfig.json          | The value 
for the expire field the Traffic Router DNS Server will respond with on Start 
of Authority (SOA) records.                              |
 
+-----------------------------------------+------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
 | tld.soa.minimum                         | CRConfig.json          | The value 
for the minimum field the Traffic Router DNS Server will respond with on SOA 
records.                                                  |
diff --git 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouter.java
 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouter.java
index 4ba3e99..a58cdef 100644
--- 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouter.java
+++ 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouter.java
@@ -81,6 +81,7 @@ import 
com.comcast.cdn.traffic_control.traffic_router.core.loc.AnonymousIpDataba
 public class TrafficRouter {
        public static final Logger LOGGER = 
Logger.getLogger(TrafficRouter.class);
        public static final String XTC_STEERING_OPTION = "x-tc-steering-option";
+       public static final String CLIENT_STEERING_DIVERSITY = 
"client.steering.forced.diversity";
 
        private final CacheRegister cacheRegister;
        private final ZoneManager zoneManager;
@@ -89,6 +90,7 @@ public class TrafficRouter {
        private final AnonymousIpDatabaseService anonymousIpService;
        private final FederationRegistry federationRegistry;
        private final boolean consistentDNSRouting;
+       private final boolean clientSteeringDiversityEnabled;
 
        private final Random random = new Random(System.nanoTime());
        private Set<String> requestHeaders = new HashSet<String>();
@@ -114,6 +116,7 @@ public class TrafficRouter {
                this.anonymousIpService = anonymousIpService;
                this.federationRegistry = federationRegistry;
                this.consistentDNSRouting = 
JsonUtils.optBoolean(cr.getConfig(), "consistent.dns.routing");
+               this.clientSteeringDiversityEnabled = 
JsonUtils.optBoolean(cr.getConfig(), CLIENT_STEERING_DIVERSITY);
                this.zoneManager = new ZoneManager(this, statTracker, 
trafficOpsUtils, trafficRouterManager);
 
                if (cr.getConfig() != null) {
@@ -279,11 +282,15 @@ public class TrafficRouter {
                return null;
        }
 
-       @SuppressWarnings("PMD.CyclomaticComplexity")
        protected List<Cache> selectCaches(final HTTPRequest request, final 
DeliveryService ds, final Track track) throws GeolocationException {
+               return selectCaches(request, ds, track, true);
+       }
+
+       @SuppressWarnings("PMD.CyclomaticComplexity")
+       protected List<Cache> selectCaches(final HTTPRequest request, final 
DeliveryService ds, final Track track, final boolean enableDeep) throws 
GeolocationException {
                CacheLocation cacheLocation;
                ResultType result = ResultType.CZ;
-               final boolean useDeep = (ds.getDeepCache() == 
DeliveryService.DeepCachingType.ALWAYS);
+               final boolean useDeep = enableDeep && (ds.getDeepCache() == 
DeliveryService.DeepCachingType.ALWAYS);
 
                if (useDeep) {
                        // Deep caching is enabled. See if there are deep 
caches available
@@ -523,6 +530,7 @@ public class TrafficRouter {
         * @param track A {@link Track} object used to track routing statistics
         * @return The list of routes available to service the client's request.
         */
+       @SuppressWarnings("PMD.CyclomaticComplexity")
        public HTTPRouteResult multiRoute(final HTTPRequest request, final 
Track track) throws MalformedURLException, GeolocationException {
                final DeliveryService entryDeliveryService = 
cacheRegister.getDeliveryService(request, true);
 
@@ -537,19 +545,37 @@ public class TrafficRouter {
 
                final List<SteeringResult> resultsToRemove = new ArrayList<>();
 
+               final Set<Cache> selectedCaches = new HashSet<>();
+
                // Pattern based consistent hashing - use consistentHashRegex 
from steering DS instead of targets
                final String steeringHash = 
buildPatternBasedHashString(entryDeliveryService.getConsistentHashRegex(), 
request.getPath());
                for (final SteeringResult steeringResult : steeringResults) {
                        final DeliveryService ds = 
steeringResult.getDeliveryService();
 
-                       final List<Cache> caches = selectCaches(request, ds, 
track);
+                       List<Cache> caches = selectCaches(request, ds, track);
 
                        // child Delivery Services can use their query 
parameters
                        final String pathToHash = steeringHash + 
ds.extractSignificantQueryParams(request);
 
                        if (caches != null && !caches.isEmpty()) {
+                               if (isClientSteeringDiversityEnabled()) {
+                                       List<Cache> tryCaches = new 
ArrayList<>(caches);
+                                       tryCaches.removeAll(selectedCaches);
+                                       if (!tryCaches.isEmpty()) {
+                                               caches = tryCaches;
+                                       } else if (track.result == 
ResultType.DEEP_CZ) {
+                                               // deep caches have been 
selected already, try non-deep selection
+                                               tryCaches = 
selectCaches(request, ds, track, false);
+                                               
track.setResult(ResultType.DEEP_CZ); // request should still be tracked as a 
DEEP_CZ hit
+                                               
tryCaches.removeAll(selectedCaches);
+                                               if (!tryCaches.isEmpty()) {
+                                                       caches = tryCaches;
+                                               }
+                                       }
+                               }
                                final Cache cache = 
consistentHasher.selectHashable(caches, ds.getDispersion(), pathToHash);
                                steeringResult.setCache(cache);
+                               selectedCaches.add(cache);
                        } else {
                                resultsToRemove.add(steeringResult);
                        }
@@ -1226,6 +1252,10 @@ public class TrafficRouter {
                return consistentDNSRouting;
        }
 
+       public boolean isClientSteeringDiversityEnabled() {
+               return clientSteeringDiversityEnabled;
+       }
+
        private List<Cache> enforceGeoRedirect(final Track track, final 
DeliveryService ds, final String clientIp, final Geolocation 
queriedClientLocation) {
                final String urlType = ds.getGeoRedirectUrlType();
                track.setResult(ResultType.GEO_REDIRECT);
diff --git 
a/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/external/SteeringTest.java
 
b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/external/SteeringTest.java
index 7342670..0986623 100644
--- 
a/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/external/SteeringTest.java
+++ 
b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/external/SteeringTest.java
@@ -37,11 +37,14 @@ import org.junit.runners.MethodSorters;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
+import java.util.Set;
 
 import static org.hamcrest.Matchers.endsWith;
 import static org.hamcrest.Matchers.greaterThan;
@@ -553,4 +556,64 @@ public class SteeringTest {
                        if (response != null) { response.close(); }
                }
        }
+
+       @Test
+       public void itSupportsClientSteeringDiversity() throws Exception {
+               final String path = "/foo?fakeClientIpAddress=192.168.42.10"; 
// this IP should get a DEEP_CZ hit (via dczmap.json)
+               HttpGet httpGet = new HttpGet("http://localhost:"; + 
routerHttpPort + path);
+               httpGet.addHeader("Host", 
"cdn.client-steering-diversity-test.thecdn.example.com");
+
+               CloseableHttpResponse response = null;
+
+               try {
+                       response = httpClient.execute(httpGet);
+
+                       HttpEntity entity = response.getEntity();
+                       assertThat("Failed getting 302 for request " + 
httpGet.getFirstHeader("Host").getValue(), 
response.getStatusLine().getStatusCode(), equalTo(302));
+
+                       ObjectMapper objectMapper = new ObjectMapper(new 
JsonFactory());
+
+                       assertThat(entity.getContent(), not(nullValue()));
+
+                       JsonNode json = 
objectMapper.readTree(entity.getContent());
+
+                       assertThat(json.has("locations"), equalTo(true));
+                       assertThat(json.get("locations").size(), equalTo(5));
+
+                       List<String> actualEdgesList = new ArrayList<>();
+                       Set<String> actualTargets = new HashSet<>();
+
+                       for (JsonNode n : json.get("locations")) {
+                               String l = n.asText();
+                               l = l.replaceFirst("http://";, "");
+                               String[] parts = l.split("\\.");
+                               actualEdgesList.add(parts[0]);
+                               actualTargets.add(parts[1]);
+                       }
+
+                       // assert that:
+                       // - 1st and 2nd targets are edges from the deep 
cachegroup (because this is a deep hit)
+                       // - 3rd target is the last unselected edge, which is 
*not* in the deep cachegroup
+                       //   (because once all the deep edges have been 
selected, we select from the regular cachegroup)
+                       // - 4th and 5th targets are any of the three edges 
(because all available edges have already been selected)
+                       Set<String> deepEdges = new HashSet<>();
+                       deepEdges.add("edge-cache-csd-1");
+                       deepEdges.add("edge-cache-csd-2");
+                       Set<String> allEdges = new HashSet<>(deepEdges);
+                       allEdges.add("edge-cache-csd-3");
+                       assertThat(actualEdgesList.get(0), isIn(deepEdges));
+                       assertThat(actualEdgesList.get(1), isIn(deepEdges));
+                       assertThat(actualEdgesList.get(2), 
equalTo("edge-cache-csd-3"));
+                       assertThat(actualEdgesList.get(3), isIn(allEdges));
+                       assertThat(actualEdgesList.get(4), isIn(allEdges));
+
+                       // assert that all 5 steering targets are included in 
the response
+                       String[] expectedTargetsArray = {"csd-target-1", 
"csd-target-2", "csd-target-3", "csd-target-4", "csd-target-5"};
+                       Set<String> expectedTargets = new 
HashSet<>(Arrays.asList(expectedTargetsArray));
+                       assertThat(actualTargets, equalTo(expectedTargets));
+
+               } finally {
+                       if (response != null) { response.close(); }
+               }
+       }
 }
diff --git 
a/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouterTest.java
 
b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouterTest.java
index 16d6fe2..ad8abd2 100644
--- 
a/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouterTest.java
+++ 
b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouterTest.java
@@ -170,6 +170,7 @@ public class TrafficRouterTest {
         
when(deliveryService.filterAvailableLocations(any(Collection.class))).thenCallRealMethod();
 
         when(trafficRouter.selectCaches(any(HTTPRequest.class), 
any(DeliveryService.class), any(Track.class))).thenCallRealMethod();
+        when(trafficRouter.selectCaches(any(HTTPRequest.class), 
any(DeliveryService.class), any(Track.class), 
anyBoolean())).thenCallRealMethod();
         when(trafficRouter.selectCachesByGeo(anyString(), 
any(DeliveryService.class), any(CacheLocation.class), 
any(Track.class))).thenCallRealMethod();
 
         Geolocation clientLocation = new Geolocation(40, -100);
diff --git a/traffic_router/core/src/test/resources/dczmap.json 
b/traffic_router/core/src/test/resources/dczmap.json
index bfc5c5b..9d46750 100644
--- a/traffic_router/core/src/test/resources/dczmap.json
+++ b/traffic_router/core/src/test/resources/dczmap.json
@@ -20,6 +20,18 @@
                                "host3",
                                "host4"
                        ]
+               },
+               "csd-group": {
+                       "network6": [
+                               "fd12:3456::/64"
+                       ],
+                       "network": [
+                               "192.168.42.0/24"
+                       ],
+                       "caches": [
+                               "edge-cache-csd-1",
+                               "edge-cache-csd-2"
+                       ]
                }
        }
 }
diff --git 
a/traffic_router/core/src/test/resources/internal/api/1.3/steering.json 
b/traffic_router/core/src/test/resources/internal/api/1.3/steering.json
index ccb9a31..f522933 100644
--- a/traffic_router/core/src/test/resources/internal/api/1.3/steering.json
+++ b/traffic_router/core/src/test/resources/internal/api/1.3/steering.json
@@ -45,6 +45,32 @@
       "clientSteering": true
     },
     {
+      "deliveryService": "client-steering-diversity-test",
+      "targets": [
+        {
+          "deliveryService": "csd-target-1",
+          "weight": "5000"
+        },
+        {
+          "deliveryService": "csd-target-2",
+          "weight": "5000"
+        },
+        {
+          "deliveryService": "csd-target-3",
+          "weight": "5000"
+        },
+        {
+          "deliveryService": "csd-target-4",
+          "weight": "5000"
+        },
+        {
+          "deliveryService": "csd-target-5",
+          "weight": "5000"
+        }
+      ],
+      "clientSteering": true
+    },
+    {
       "deliveryService": "client-steering-test-2",
       "targets": [
         {
diff --git a/traffic_router/core/src/test/resources/publish/CrConfig.json 
b/traffic_router/core/src/test/resources/publish/CrConfig.json
index e3cdaf0..b41a917 100644
--- a/traffic_router/core/src/test/resources/publish/CrConfig.json
+++ b/traffic_router/core/src/test/resources/publish/CrConfig.json
@@ -479,6 +479,69 @@
       "deliveryServices": {
         "http-and-https-test": [ 
"edge-cache-082.http-and-https-test.thecdn.example.com"]
       }
+    },
+    "edge-cache-csd-1": {
+      "type": "EDGE",
+      "profile": "EDGE_STATIC",
+      "status": "REPORTED",
+      "hashId": "[email protected]",
+      "fqdn": "edge-cache-csd-1.thecdn.example.com",
+      "port": "8090",
+      "ip": "12.34.8.201",
+      "ip6": "2001:dead:beef:8:C::81/64",
+      "cacheGroup": "cache-group-csd",
+      "locationId": "location-csd",
+      "hashCount": 1000,
+      "interfaceName": "bond0",
+      "deliveryServices": {
+        "csd-target-1": ["edge-cache-csd-1.csd-target-1.thecdn.example.com"],
+        "csd-target-2": ["edge-cache-csd-1.csd-target-2.thecdn.example.com"],
+        "csd-target-3": ["edge-cache-csd-1.csd-target-3.thecdn.example.com"],
+        "csd-target-4": ["edge-cache-csd-1.csd-target-4.thecdn.example.com"],
+        "csd-target-5": ["edge-cache-csd-1.csd-target-5.thecdn.example.com"]
+      }
+    },
+    "edge-cache-csd-2": {
+      "type": "EDGE",
+      "profile": "EDGE_STATIC",
+      "status": "REPORTED",
+      "hashId": "[email protected]",
+      "fqdn": "edge-cache-csd-2.thecdn.example.com",
+      "port": "8090",
+      "ip": "12.34.8.202",
+      "ip6": "2001:dead:beef:8:C::82/64",
+      "cacheGroup": "cache-group-csd",
+      "locationId": "location-csd",
+      "hashCount": 1000,
+      "interfaceName": "bond0",
+      "deliveryServices": {
+        "csd-target-1": ["edge-cache-csd-2.csd-target-1.thecdn.example.com"],
+        "csd-target-2": ["edge-cache-csd-2.csd-target-2.thecdn.example.com"],
+        "csd-target-3": ["edge-cache-csd-2.csd-target-3.thecdn.example.com"],
+        "csd-target-4": ["edge-cache-csd-2.csd-target-4.thecdn.example.com"],
+        "csd-target-5": ["edge-cache-csd-2.csd-target-5.thecdn.example.com"]
+      }
+    },
+    "edge-cache-csd-3": {
+      "type": "EDGE",
+      "profile": "EDGE_STATIC",
+      "status": "REPORTED",
+      "hashId": "[email protected]",
+      "fqdn": "edge-cache-csd-3.thecdn.example.com",
+      "port": "8090",
+      "ip": "12.34.8.203",
+      "ip6": "2001:dead:beef:8:C::83/64",
+      "cacheGroup": "cache-group-csd",
+      "locationId": "location-csd",
+      "hashCount": 1000,
+      "interfaceName": "bond0",
+      "deliveryServices": {
+        "csd-target-1": ["edge-cache-csd-3.csd-target-1.thecdn.example.com"],
+        "csd-target-2": ["edge-cache-csd-3.csd-target-2.thecdn.example.com"],
+        "csd-target-3": ["edge-cache-csd-3.csd-target-3.thecdn.example.com"],
+        "csd-target-4": ["edge-cache-csd-3.csd-target-4.thecdn.example.com"],
+        "csd-target-5": ["edge-cache-csd-3.csd-target-5.thecdn.example.com"]
+      }
     }
   },
   "contentRouters": {
@@ -666,6 +729,308 @@
       "geolocationProvider": "maxmindGeolocationService",
       "staticDnsEntries": []
     },
+    "client-steering-diversity-test": {
+      "sslEnabled": "false",
+      "protocol": {
+        "acceptHttp" : "true",
+        "acceptHttps" : "false",
+        "redirectToHttps" : "false"
+      },
+      "requestHeaders": ["X-MoneyTrace"],
+      "domains": ["client-steering-diversity-test.thecdn.example.com"],
+      "missLocation": {
+        "long": "-87.627778",
+        "lat": "41.881944"
+      },
+      "ttls": {
+        "AAAA": "3600",
+        "SOA": "7200",
+        "A": "3600",
+        "NS": "3600"
+      },
+      "ttl": "3600",
+      "ip6RoutingEnabled": "true",
+      "bypassDestination": {"HTTP": {
+        "port": "80",
+        "fqdn": "client-steering-diversity-test.overflowcdn.net"
+      }},
+      "dispersion": {
+        "limit": 1,
+        "shuffled": "true"
+      },
+      "coverageZoneOnly": "false",
+      "routingName": "cdn",
+      "regionalGeoBlocking": "false",
+      "matchsets": [{
+        "protocol": "HTTP",
+        "matchlist": [{
+          "regex": ".*\\.client-steering-diversity-test\\..*",
+          "match-type": "HOST"
+        }]
+      }],
+      "soa": {
+        "expire": "604800",
+        "minimum": "30",
+        "admin": "[email protected]",
+        "retry": "7200",
+        "refresh": "28800"
+      },
+      "geolocationProvider": "maxmindGeolocationService",
+      "staticDnsEntries": []
+    },
+    "csd-target-1": {
+      "sslEnabled": "false",
+      "protocol": {
+        "acceptHttp" : "true",
+        "acceptHttps" : "false",
+        "redirectToHttps" : "false"
+      },
+      "requestHeaders": [
+        "User-Agent",
+        "MyHeader",
+        "Date"
+      ],
+      "deepCachingType": "ALWAYS",
+      "dispersion": {
+        "limit": 1,
+        "shuffled": "true"
+      },
+      "domains": ["csd-target-1.thecdn.example.com"],
+      "coverageZoneOnly": "false",
+      "routingName": "cdn",
+      "matchsets": [
+        {
+          "protocol": "HTTP",
+          "matchlist": [{
+            "regex": ".*\\.csd-target-1\\..*",
+            "match-type": "HOST"
+          }]
+        }
+      ],
+      "regionalGeoBlocking": "false",
+      "ttls": {
+        "AAAA": "3600",
+        "SOA": "7200",
+        "A": "3600",
+        "NS": "3600"
+      },
+      "missLocation": {
+        "long": "-87.627778",
+        "lat": "41.881944"
+      },
+      "soa": {
+        "expire": "604800",
+        "minimum": "3 0",
+        "admin": "[email protected]",
+        "retry": "7200",
+        "refresh": "28800"
+      },
+      "geolocationProvider": "maxmindGeolocationService",
+      "ttl": "3600",
+      "ip6RoutingEnabled": "false"
+    },
+    "csd-target-2": {
+      "sslEnabled": "false",
+      "protocol": {
+        "acceptHttp" : "true",
+        "acceptHttps" : "false",
+        "redirectToHttps" : "false"
+      },
+      "requestHeaders": [
+        "User-Agent",
+        "MyHeader",
+        "Date"
+      ],
+      "deepCachingType": "ALWAYS",
+      "dispersion": {
+        "limit": 1,
+        "shuffled": "true"
+      },
+      "domains": ["csd-target-2.thecdn.example.com"],
+      "coverageZoneOnly": "false",
+      "routingName": "cdn",
+      "matchsets": [
+        {
+          "protocol": "HTTP",
+          "matchlist": [{
+            "regex": ".*\\.csd-target-2\\..*",
+            "match-type": "HOST"
+          }]
+        }
+      ],
+      "regionalGeoBlocking": "false",
+      "ttls": {
+        "AAAA": "3600",
+        "SOA": "7200",
+        "A": "3600",
+        "NS": "3600"
+      },
+      "missLocation": {
+        "long": "-87.627778",
+        "lat": "41.881944"
+      },
+      "soa": {
+        "expire": "604800",
+        "minimum": "3 0",
+        "admin": "[email protected]",
+        "retry": "7200",
+        "refresh": "28800"
+      },
+      "geolocationProvider": "maxmindGeolocationService",
+      "ttl": "3600",
+      "ip6RoutingEnabled": "false"
+    },
+    "csd-target-3": {
+      "sslEnabled": "false",
+      "protocol": {
+        "acceptHttp" : "true",
+        "acceptHttps" : "false",
+        "redirectToHttps" : "false"
+      },
+      "requestHeaders": [
+        "User-Agent",
+        "MyHeader",
+        "Date"
+      ],
+      "deepCachingType": "ALWAYS",
+      "dispersion": {
+        "limit": 1,
+        "shuffled": "true"
+      },
+      "domains": ["csd-target-3.thecdn.example.com"],
+      "coverageZoneOnly": "false",
+      "routingName": "cdn",
+      "matchsets": [
+        {
+          "protocol": "HTTP",
+          "matchlist": [{
+            "regex": ".*\\.csd-target-3\\..*",
+            "match-type": "HOST"
+          }]
+        }
+      ],
+      "regionalGeoBlocking": "false",
+      "ttls": {
+        "AAAA": "3600",
+        "SOA": "7200",
+        "A": "3600",
+        "NS": "3600"
+      },
+      "missLocation": {
+        "long": "-87.627778",
+        "lat": "41.881944"
+      },
+      "soa": {
+        "expire": "604800",
+        "minimum": "3 0",
+        "admin": "[email protected]",
+        "retry": "7200",
+        "refresh": "28800"
+      },
+      "geolocationProvider": "maxmindGeolocationService",
+      "ttl": "3600",
+      "ip6RoutingEnabled": "false"
+    },
+    "csd-target-4": {
+      "sslEnabled": "false",
+      "protocol": {
+        "acceptHttp" : "true",
+        "acceptHttps" : "false",
+        "redirectToHttps" : "false"
+      },
+      "requestHeaders": [
+        "User-Agent",
+        "MyHeader",
+        "Date"
+      ],
+      "dispersion": {
+        "limit": 1,
+        "shuffled": "true"
+      },
+      "domains": ["csd-target-4.thecdn.example.com"],
+      "coverageZoneOnly": "false",
+      "routingName": "cdn",
+      "matchsets": [
+        {
+          "protocol": "HTTP",
+          "matchlist": [{
+            "regex": ".*\\.csd-target-4\\..*",
+            "match-type": "HOST"
+          }]
+        }
+      ],
+      "regionalGeoBlocking": "false",
+      "ttls": {
+        "AAAA": "3600",
+        "SOA": "7200",
+        "A": "3600",
+        "NS": "3600"
+      },
+      "missLocation": {
+        "long": "-87.627778",
+        "lat": "41.881944"
+      },
+      "soa": {
+        "expire": "604800",
+        "minimum": "3 0",
+        "admin": "[email protected]",
+        "retry": "7200",
+        "refresh": "28800"
+      },
+      "geolocationProvider": "maxmindGeolocationService",
+      "ttl": "3600",
+      "ip6RoutingEnabled": "false"
+    },
+    "csd-target-5": {
+      "sslEnabled": "false",
+      "protocol": {
+        "acceptHttp" : "true",
+        "acceptHttps" : "false",
+        "redirectToHttps" : "false"
+      },
+      "requestHeaders": [
+        "User-Agent",
+        "MyHeader",
+        "Date"
+      ],
+      "dispersion": {
+        "limit": 1,
+        "shuffled": "true"
+      },
+      "domains": ["csd-target-5.thecdn.example.com"],
+      "coverageZoneOnly": "false",
+      "routingName": "cdn",
+      "matchsets": [
+        {
+          "protocol": "HTTP",
+          "matchlist": [{
+            "regex": ".*\\.csd-target-5\\..*",
+            "match-type": "HOST"
+          }]
+        }
+      ],
+      "regionalGeoBlocking": "false",
+      "ttls": {
+        "AAAA": "3600",
+        "SOA": "7200",
+        "A": "3600",
+        "NS": "3600"
+      },
+      "missLocation": {
+        "long": "-87.627778",
+        "lat": "41.881944"
+      },
+      "soa": {
+        "expire": "604800",
+        "minimum": "3 0",
+        "admin": "[email protected]",
+        "retry": "7200",
+        "refresh": "28800"
+      },
+      "geolocationProvider": "maxmindGeolocationService",
+      "ttl": "3600",
+      "ip6RoutingEnabled": "false"
+    },
     "client-steering-target-1": {
       "sslEnabled": "false",
       "protocol": {
@@ -1450,10 +1815,16 @@
       "localizationMethods": ["CZ", "DEEP_CZ", "GEO"],
       "longitude": -86.0,
       "latitude": 36.0
+    },
+    "location-csd": {
+      "localizationMethods": ["CZ", "DEEP_CZ", "GEO"],
+      "longitude": -87.0,
+      "latitude": 37.0
     }
   },
   "config": {
     "certificate.api.url": 
"http://${toHostname}/api/1.3/cdns/name/${cdnName}/sslkeys.json";,
+    "client.steering.forced.diversity": "true",
     "federationmapping.polling.url": 
"http://${toHostname}/internal/api/1.3/federations.json";,
     "federationmapping.polling.interval": "600000",
     "steeringmapping.polling.url": 
"http://${toHostname}/internal/api/1.3/steering.json";,
@@ -1488,6 +1859,7 @@
       "refresh": "28800"
     },
     "coveragezone.polling.url": "http://localhost:8889/czf.json";,
+    "deepcoveragezone.polling.url": "http://localhost:8889/dczmap.json";,
     "api.auth.url": "http://${toHostname}/api/1.3/user/login";,
     "certificates.polling.interval": "10000",
     "dnssec.enabled": "false"
diff --git a/traffic_router/core/src/test/resources/publish/CrStates 
b/traffic_router/core/src/test/resources/publish/CrStates
index 679c596..923bfb4 100644
--- a/traffic_router/core/src/test/resources/publish/CrStates
+++ b/traffic_router/core/src/test/resources/publish/CrStates
@@ -99,7 +99,10 @@
     "edge-cache-096": {"isAvailable": true},
     "edge-cache-097": {"isAvailable": true},
     "edge-cache-098": {"isAvailable": true},
-    "edge-cache-099": {"isAvailable": true}
+    "edge-cache-099": {"isAvailable": true},
+    "edge-cache-csd-1": {"isAvailable": true},
+    "edge-cache-csd-2": {"isAvailable": true},
+    "edge-cache-csd-3": {"isAvailable": true}
   },
   "deliveryServices": {
     "steering-test-1": {
@@ -146,6 +149,30 @@
       "disabledLocations": [],
       "isAvailable": true
     },
+    "client-steering-diversity-test": {
+      "disabledLocations": [],
+      "isAvailable": true
+    },
+    "csd-target-1": {
+      "disabledLocations": [],
+      "isAvailable": true
+    },
+    "csd-target-2": {
+      "disabledLocations": [],
+      "isAvailable": true
+    },
+    "csd-target-3": {
+      "disabledLocations": [],
+      "isAvailable": true
+    },
+    "csd-target-4": {
+      "disabledLocations": [],
+      "isAvailable": true
+    },
+    "csd-target-5": {
+      "disabledLocations": [],
+      "isAvailable": true
+    },
     "client-steering-test-1": {
       "disabledLocations": [],
       "isAvailable": true

Reply via email to