You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by ne...@apache.org on 2020/07/13 21:13:49 UTC

[trafficcontrol] branch master updated: TP: Adds topology section to cdn snapshot diff (#4855)

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 d6d4d60  TP: Adds topology section to cdn snapshot diff (#4855)
d6d4d60 is described below

commit d6d4d60dd1ee391190f616312b624ac07fbd6839
Author: Jeremy Mitchell <mi...@users.noreply.github.com>
AuthorDate: Mon Jul 13 15:13:07 2020 -0600

    TP: Adds topology section to cdn snapshot diff (#4855)
    
    * adds topology section to cdn snapshot
    
    * adds changelog entry
    
    * adds a UI test for snapshotting a cdn
    
    * adds missing topology references in the docs
    
    * adds missing first/inner/last header rewrite values in ds tables
---
 CHANGELOG.md                                       |  1 +
 .../admin/traffic_portal/usingtrafficportal.rst    |  5 ++++
 docs/source/overview/delivery_services.rst         | 22 +++++++++-----
 .../src/common/modules/form/cdn/form.cdn.tpl.html  |  2 +-
 .../table.cdnDeliveryServices.tpl.html             |  6 ++++
 .../TableDeliveryServicesController.js             |  3 ++
 .../table.deliveryServices.tpl.html                |  6 ++++
 .../table.profileDeliveryServices.tpl.html         |  6 ++++
 .../table.serverDeliveryServices.tpl.html          |  6 ++++
 .../table.tenantDeliveryServices.tpl.html          |  6 ++++
 .../table.topologyDeliveryServices.tpl.html        |  6 ++++
 .../table.typeDeliveryServices.tpl.html            |  6 ++++
 .../private/cdns/config/ConfigController.js        | 11 +++++++
 .../modules/private/cdns/config/config.tpl.html    | 34 +++++++++++++++++++++-
 traffic_portal/test/end_to_end/CDNs/cdns-spec.js   | 10 +++++++
 traffic_portal/test/end_to_end/CDNs/pageData.js    |  4 ++-
 16 files changed, 123 insertions(+), 11 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8969ae5..bce39b4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
     - Traffic Portal: Added the ability to assign topologies to delivery services.
     - Traffic Portal: Added the ability to view all delivery services and cache groups associated with a topology.
     - Traffic Portal: Added the ability to define first, inner and last header rewrite values for DNS* and HTTP* delivery services that employ a topology.
+    - Traffic Portal: Added topology section to cdn snapshot diff.
     - Traffic Router: Added support for topology-based delivery services
 - Updated /servers/details to use multiple interfaces in API v3
 - Added [Edge Traffic Routing](https://traffic-control-cdn.readthedocs.io/en/latest/admin/traffic_router.html#edge-traffic-routing) feature which allows Traffic Router to localize more DNS record types than just the routing name for DNS delivery services
diff --git a/docs/source/admin/traffic_portal/usingtrafficportal.rst b/docs/source/admin/traffic_portal/usingtrafficportal.rst
index d77442a..801d3ae 100644
--- a/docs/source/admin/traffic_portal/usingtrafficportal.rst
+++ b/docs/source/admin/traffic_portal/usingtrafficportal.rst
@@ -230,6 +230,7 @@ Use the `Select Columns` menu to select the delivery service columns to view and
 - :ref:`ds-dscp` (visible by default)
 - :ref:`ds-edge-header-rw-rules`
 - :ref:`ds-fqpr`
+- :ref:`ds-first-header-rw-rules`
 - :ref:`ds-geo-limit`
 - :ref:`ds-geo-limit-countries`
 - :ref:`ds-geo-limit-redirect-url`
@@ -241,7 +242,9 @@ Use the `Select Columns` menu to select the delivery service columns to view and
 - :ref:`ds-http-bypass-fqdn`
 - :ref:`ds-info-url`
 - :ref:`ds-initial-dispersion`
+- :ref:`ds-inner-header-rw-rules`
 - :ref:`ds-ipv6-routing` (visible by default)
+- :ref:`ds-last-header-rw-rules`
 - :ref:`ds-longdesc`
 - :ref:`ds-longdesc2`
 - :ref:`ds-longdesc3`
@@ -254,12 +257,14 @@ Use the `Select Columns` menu to select the delivery service columns to view and
 - :ref:`ds-protocol` (visible by default)
 - :ref:`ds-qstring-handling` (visible by default)
 - :ref:`ds-range-request-handling`
+- :ref:`ds-slice-block-size`
 - :ref:`ds-raw-remap`
 - :ref:`ds-regex-remap`
 - :ref:`ds-regionalgeo`
 - :ref:`ds-routing-name`
 - :ref:`ds-signing-algorithm` (visible by default)
 - :ref:`ds-tenant` (visible by default)
+- :ref:`ds-topology`
 - :ref:`ds-tr-resp-headers`
 - :ref:`ds-tr-req-headers`
 - :ref:`ds-types` (visible by default)
diff --git a/docs/source/overview/delivery_services.rst b/docs/source/overview/delivery_services.rst
index 60e66ca..558ac4f 100644
--- a/docs/source/overview/delivery_services.rst
+++ b/docs/source/overview/delivery_services.rst
@@ -660,6 +660,14 @@ Describes how HTTP "Range Requests" should be handled by the Delivery Service at
 
 .. warning:: The definitions of each integral, unique identifier are hidden in implementations in each :abbr:`ATC (Apache Traffic Control)` component. Different components will handle invalid values differently, and there's no actual enforcement that the stored integral, unique identifier actually be within the representable range.
 
+.. _ds-slice-block-size:
+
+Range Slice Request Block Size
+-------------------------------------
+The block size in bytes that is used for `slice <https://github.com/apache/trafficserver/tree/master/plugins/experimental/slice>`_ plugin.
+
+This can only and must be set if the :ref:`ds-range-request-handling` is set to ``3``.
+
 .. _ds-raw-remap:
 
 Raw Remap Text
@@ -769,14 +777,6 @@ Keys for either algorithm can be generated within :ref:`Traffic Portal <tp-servi
 
 .. _ds-ssl-key-version:
 
-Range Slice Request Block Size
--------------------------------------
-The block size in bytes that is used for `slice <https://github.com/apache/trafficserver/tree/master/plugins/experimental/slice>`_ plugin.
-
-This can only and must be set if the :ref:`ds-range-request-handling` is set to ``3``.
-
-.. _ds-slice-block-size:
-
 SSL Key Version
 ---------------
 An integer that describes the version of the SSL key(s) - if any - used by this Delivery Service. This is incremented whenever Traffic Portal generates new SSL keys for the Delivery Service.
@@ -805,6 +805,12 @@ The :term:`Tenant` who owns this Delivery Service. They (and their parents, if a
 	| TenantID | Go code and :ref:`to-api` requests/responses | Integral, unique identifier (``bigint``, ``int`` etc.) |
 	+----------+----------------------------------------------+--------------------------------------------------------+
 
+.. _ds-topology:
+
+Topology
+--------
+A structure composed of :term:`Cache Groups` and parent relationships, which is assignable to one or more :term:`Delivery Services`.
+
 .. _ds-tr-resp-headers:
 
 Traffic Router Additional Response Headers
diff --git a/traffic_portal/app/src/common/modules/form/cdn/form.cdn.tpl.html b/traffic_portal/app/src/common/modules/form/cdn/form.cdn.tpl.html
index 5c3bd2e..21ae568 100644
--- a/traffic_portal/app/src/common/modules/form/cdn/form.cdn.tpl.html
+++ b/traffic_portal/app/src/common/modules/form/cdn/form.cdn.tpl.html
@@ -24,7 +24,7 @@ under the License.
             <li class="active">{{cdnName}}</li>
         </ol>
         <div class="pull-right" ng-show="!settings.isNew">
-            <button class="btn btn-primary" title="Diff CDN Snapshot" ng-click="viewConfig()"><i class="fa fa-camera"></i>&nbsp;&nbsp;Diff CDN Config Snapshot</button>
+            <button name="diffCDNbtn" class="btn btn-primary" title="Diff CDN Snapshot" ng-click="viewConfig()"><i class="fa fa-camera"></i>&nbsp;&nbsp;Diff CDN Config Snapshot</button>
             <div class="btn-group" role="group" uib-dropdown is-open="queue.isopen">
                 <button type="button" class="btn btn-primary dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
                     Queue Updates&nbsp;
diff --git a/traffic_portal/app/src/common/modules/table/cdnDeliveryServices/table.cdnDeliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/cdnDeliveryServices/table.cdnDeliveryServices.tpl.html
index 37520f3..6241997 100644
--- a/traffic_portal/app/src/common/modules/table/cdnDeliveryServices/table.cdnDeliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/cdnDeliveryServices/table.cdnDeliveryServices.tpl.html
@@ -63,6 +63,7 @@ under the License.
                     <th>DSCP</th>
                     <th>ECS Enabled</th>
                     <th>Edge Header Rewrite Rules</th>
+                    <th>First Header Rewrite Rules</th>
                     <th>FQ Pacing Rate</th>
                     <th>Geo Limit</th>
                     <th>Geo Limit Countries</th>
@@ -76,7 +77,9 @@ under the License.
                     <th>ID</th>
                     <th>Info URL</th>
                     <th>Initial Dispersion</th>
+                    <th>Inner Header Rewrite Rules</th>
                     <th>IPv6 Routing</th>
+                    <th>Last Header Rewrite Rules</th>
                     <th>Last Updated</th>
                     <th>Long Desc 1</th>
                     <th>Long Desc 2</th>
@@ -124,6 +127,7 @@ under the License.
                     <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
                     <td data-search="^{{::ds.ecsEnabled}}$">{{::ds.ecsEnabled}}</td>
                     <td data-search="^{{::ds.edgeHeaderRewrite}}$">{{::ds.edgeHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.firstHeaderRewrite}}$">{{::ds.firstHeaderRewrite}}</td>
                     <td data-search="^{{::ds.fqPacingRate}}$">{{::ds.fqPacingRate}}</td>
                     <td data-search="^{{::geoLimit(ds)}}$">{{::geoLimit(ds)}}</td>
                     <td data-search="^{{::ds.geoLimitCountries}}$">{{::ds.geoLimitCountries}}</td>
@@ -137,7 +141,9 @@ under the License.
                     <td data-search="^{{::ds.id}}$">{{::ds.id}}</td>
                     <td data-search="^{{::ds.infoUrl}}$">{{::ds.infoUrl}}</td>
                     <td data-search="^{{::ds.initialDispersion}}$">{{::ds.initialDispersion}}</td>
+                    <td data-search="^{{::ds.innerHeaderRewrite}}$">{{::ds.innerHeaderRewrite}}</td>
                     <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
+                    <td data-search="^{{::ds.lastHeaderRewrite}}$">{{::ds.lastHeaderRewrite}}</td>
                     <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
                     <td data-search="^{{::ds.longDesc}}$">{{::ds.longDesc}}</td>
                     <td data-search="^{{::ds.longDesc1}}$">{{::ds.longDesc1}}</td>
diff --git a/traffic_portal/app/src/common/modules/table/deliveryServices/TableDeliveryServicesController.js b/traffic_portal/app/src/common/modules/table/deliveryServices/TableDeliveryServicesController.js
index aa823dd..99b0d22 100644
--- a/traffic_portal/app/src/common/modules/table/deliveryServices/TableDeliveryServicesController.js
+++ b/traffic_portal/app/src/common/modules/table/deliveryServices/TableDeliveryServicesController.js
@@ -229,6 +229,7 @@ var TableDeliveryServicesController = function(deliveryServices, $anchorScroll,
         { "name": "DSCP", "visible": true, "searchable": true },
         { "name": "ECS Enabled", "visible": false, "searchable": false },
         { "name": "Edge Header Rewrite Rules", "visible": false, "searchable": false },
+        { "name": "First Header Rewrite Rules", "visible": false, "searchable": false },
         { "name": "FQ Pacing Rate", "visible": false, "searchable": false },
         { "name": "Geo Limit", "visible": false, "searchable": false },
         { "name": "Geo Limit Countries", "visible": false, "searchable": false },
@@ -242,7 +243,9 @@ var TableDeliveryServicesController = function(deliveryServices, $anchorScroll,
         { "name": "ID", "visible": false, "searchable": false },
         { "name": "Info URL", "visible": true, "searchable": true },
         { "name": "Initial Dispersion", "visible": false, "searchable": false },
+        { "name": "Inner Header Rewrite Rules", "visible": false, "searchable": false },
         { "name": "IPv6 Routing", "visible": false, "searchable": false },
+        { "name": "Last Header Rewrite Rules", "visible": false, "searchable": false },
         { "name": "Last Updated", "visible": false, "searchable": false },
         { "name": "Long Desc 1", "visible": false, "searchable": false },
         { "name": "Long Desc 2", "visible": false, "searchable": false },
diff --git a/traffic_portal/app/src/common/modules/table/deliveryServices/table.deliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/deliveryServices/table.deliveryServices.tpl.html
index 2642572..0a08425 100644
--- a/traffic_portal/app/src/common/modules/table/deliveryServices/table.deliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/deliveryServices/table.deliveryServices.tpl.html
@@ -71,6 +71,7 @@ under the License.
                     <th>DSCP</th>
                     <th>ECS Enabled</th>
                     <th>Edge Header Rewrite Rules</th>
+                    <th>First Header Rewrite Rules</th>
                     <th>FQ Pacing Rate</th>
                     <th>Geo Limit</th>
                     <th>Geo Limit Countries</th>
@@ -84,7 +85,9 @@ under the License.
                     <th>ID</th>
                     <th>Info URL</th>
                     <th>Initial Dispersion</th>
+                    <th>Inner Header Rewrite Rules</th>
                     <th>IPv6 Routing</th>
+                    <th>Last Header Rewrite Rules</th>
                     <th>Last Updated</th>
                     <th>Long Desc 1</th>
                     <th>Long Desc 2</th>
@@ -132,6 +135,7 @@ under the License.
                     <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
                     <td data-search="^{{::ds.ecsEnabled}}$">{{::ds.ecsEnabled}}</td>
                     <td data-search="^{{::ds.edgeHeaderRewrite}}$">{{::ds.edgeHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.firstHeaderRewrite}}$">{{::ds.firstHeaderRewrite}}</td>
                     <td data-search="^{{::ds.fqPacingRate}}$">{{::ds.fqPacingRate}}</td>
                     <td data-search="^{{::geoLimit(ds)}}$">{{::geoLimit(ds)}}</td>
                     <td data-search="^{{::ds.geoLimitCountries}}$">{{::ds.geoLimitCountries}}</td>
@@ -145,7 +149,9 @@ under the License.
                     <td data-search="^{{::ds.id}}$">{{::ds.id}}</td>
                     <td data-search="^{{::ds.infoUrl}}$">{{::ds.infoUrl}}</td>
                     <td data-search="^{{::ds.initialDispersion}}$">{{::ds.initialDispersion}}</td>
+                    <td data-search="^{{::ds.innerHeaderRewrite}}$">{{::ds.innerHeaderRewrite}}</td>
                     <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
+                    <td data-search="^{{::ds.lastHeaderRewrite}}$">{{::ds.lastHeaderRewrite}}</td>
                     <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
                     <td data-search="^{{::ds.longDesc}}$">{{::ds.longDesc}}</td>
                     <td data-search="^{{::ds.longDesc1}}$">{{::ds.longDesc1}}</td>
diff --git a/traffic_portal/app/src/common/modules/table/profileDeliveryServices/table.profileDeliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/profileDeliveryServices/table.profileDeliveryServices.tpl.html
index b8fdd07..cd06b37 100644
--- a/traffic_portal/app/src/common/modules/table/profileDeliveryServices/table.profileDeliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/profileDeliveryServices/table.profileDeliveryServices.tpl.html
@@ -63,6 +63,7 @@ under the License.
                     <th>DSCP</th>
                     <th>ECS Enabled</th>
                     <th>Edge Header Rewrite Rules</th>
+                    <th>First Header Rewrite Rules</th>
                     <th>FQ Pacing Rate</th>
                     <th>Geo Limit</th>
                     <th>Geo Limit Countries</th>
@@ -76,7 +77,9 @@ under the License.
                     <th>ID</th>
                     <th>Info URL</th>
                     <th>Initial Dispersion</th>
+                    <th>Inner Header Rewrite Rules</th>
                     <th>IPv6 Routing</th>
+                    <th>Last Header Rewrite Rules</th>
                     <th>Last Updated</th>
                     <th>Long Desc 1</th>
                     <th>Long Desc 2</th>
@@ -124,6 +127,7 @@ under the License.
                     <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
                     <td data-search="^{{::ds.ecsEnabled}}$">{{::ds.ecsEnabled}}</td>
                     <td data-search="^{{::ds.edgeHeaderRewrite}}$">{{::ds.edgeHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.firstHeaderRewrite}}$">{{::ds.firstHeaderRewrite}}</td>
                     <td data-search="^{{::ds.fqPacingRate}}$">{{::ds.fqPacingRate}}</td>
                     <td data-search="^{{::geoLimit(ds)}}$">{{::geoLimit(ds)}}</td>
                     <td data-search="^{{::ds.geoLimitCountries}}$">{{::ds.geoLimitCountries}}</td>
@@ -137,7 +141,9 @@ under the License.
                     <td data-search="^{{::ds.id}}$">{{::ds.id}}</td>
                     <td data-search="^{{::ds.infoUrl}}$">{{::ds.infoUrl}}</td>
                     <td data-search="^{{::ds.initialDispersion}}$">{{::ds.initialDispersion}}</td>
+                    <td data-search="^{{::ds.innerHeaderRewrite}}$">{{::ds.innerHeaderRewrite}}</td>
                     <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
+                    <td data-search="^{{::ds.lastHeaderRewrite}}$">{{::ds.lastHeaderRewrite}}</td>
                     <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
                     <td data-search="^{{::ds.longDesc}}$">{{::ds.longDesc}}</td>
                     <td data-search="^{{::ds.longDesc1}}$">{{::ds.longDesc1}}</td>
diff --git a/traffic_portal/app/src/common/modules/table/serverDeliveryServices/table.serverDeliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/serverDeliveryServices/table.serverDeliveryServices.tpl.html
index 5ee68e9..55c9b05 100644
--- a/traffic_portal/app/src/common/modules/table/serverDeliveryServices/table.serverDeliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/serverDeliveryServices/table.serverDeliveryServices.tpl.html
@@ -74,6 +74,7 @@ under the License.
                     <th>DSCP</th>
                     <th>ECS Enabled</th>
                     <th>Edge Header Rewrite Rules</th>
+                    <th>First Header Rewrite Rules</th>
                     <th>FQ Pacing Rate</th>
                     <th>Geo Limit</th>
                     <th>Geo Limit Countries</th>
@@ -87,7 +88,9 @@ under the License.
                     <th>ID</th>
                     <th>Info URL</th>
                     <th>Initial Dispersion</th>
+                    <th>Inner Header Rewrite Rules</th>
                     <th>IPv6 Routing</th>
+                    <th>Last Header Rewrite Rules</th>
                     <th>Last Updated</th>
                     <th>Long Desc 1</th>
                     <th>Long Desc 2</th>
@@ -136,6 +139,7 @@ under the License.
                     <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
                     <td data-search="^{{::ds.ecsEnabled}}$">{{::ds.ecsEnabled}}</td>
                     <td data-search="^{{::ds.edgeHeaderRewrite}}$">{{::ds.edgeHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.firstHeaderRewrite}}$">{{::ds.firstHeaderRewrite}}</td>
                     <td data-search="^{{::ds.fqPacingRate}}$">{{::ds.fqPacingRate}}</td>
                     <td data-search="^{{::geoLimit(ds)}}$">{{::geoLimit(ds)}}</td>
                     <td data-search="^{{::ds.geoLimitCountries}}$">{{::ds.geoLimitCountries}}</td>
@@ -149,7 +153,9 @@ under the License.
                     <td data-search="^{{::ds.id}}$">{{::ds.id}}</td>
                     <td data-search="^{{::ds.infoUrl}}$">{{::ds.infoUrl}}</td>
                     <td data-search="^{{::ds.initialDispersion}}$">{{::ds.initialDispersion}}</td>
+                    <td data-search="^{{::ds.innerHeaderRewrite}}$">{{::ds.innerHeaderRewrite}}</td>
                     <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
+                    <td data-search="^{{::ds.lastHeaderRewrite}}$">{{::ds.lastHeaderRewrite}}</td>
                     <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
                     <td data-search="^{{::ds.longDesc}}$">{{::ds.longDesc}}</td>
                     <td data-search="^{{::ds.longDesc1}}$">{{::ds.longDesc1}}</td>
diff --git a/traffic_portal/app/src/common/modules/table/tenantDeliveryServices/table.tenantDeliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/tenantDeliveryServices/table.tenantDeliveryServices.tpl.html
index b3f7b68..10480b5 100644
--- a/traffic_portal/app/src/common/modules/table/tenantDeliveryServices/table.tenantDeliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/tenantDeliveryServices/table.tenantDeliveryServices.tpl.html
@@ -63,6 +63,7 @@ under the License.
                     <th>DSCP</th>
                     <th>ECS Enabled</th>
                     <th>Edge Header Rewrite Rules</th>
+                    <th>First Header Rewrite Rules</th>
                     <th>FQ Pacing Rate</th>
                     <th>Geo Limit</th>
                     <th>Geo Limit Countries</th>
@@ -76,7 +77,9 @@ under the License.
                     <th>ID</th>
                     <th>Info URL</th>
                     <th>Initial Dispersion</th>
+                    <th>Inner Header Rewrite Rules</th>
                     <th>IPv6 Routing</th>
+                    <th>Last Header Rewrite Rules</th>
                     <th>Last Updated</th>
                     <th>Long Desc 1</th>
                     <th>Long Desc 2</th>
@@ -124,6 +127,7 @@ under the License.
                     <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
                     <td data-search="^{{::ds.ecsEnabled}}$">{{::ds.ecsEnabled}}</td>
                     <td data-search="^{{::ds.edgeHeaderRewrite}}$">{{::ds.edgeHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.firstHeaderRewrite}}$">{{::ds.firstHeaderRewrite}}</td>
                     <td data-search="^{{::ds.fqPacingRate}}$">{{::ds.fqPacingRate}}</td>
                     <td data-search="^{{::geoLimit(ds)}}$">{{::geoLimit(ds)}}</td>
                     <td data-search="^{{::ds.geoLimitCountries}}$">{{::ds.geoLimitCountries}}</td>
@@ -137,7 +141,9 @@ under the License.
                     <td data-search="^{{::ds.id}}$">{{::ds.id}}</td>
                     <td data-search="^{{::ds.infoUrl}}$">{{::ds.infoUrl}}</td>
                     <td data-search="^{{::ds.initialDispersion}}$">{{::ds.initialDispersion}}</td>
+                    <td data-search="^{{::ds.innerHeaderRewrite}}$">{{::ds.innerHeaderRewrite}}</td>
                     <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
+                    <td data-search="^{{::ds.lastHeaderRewrite}}$">{{::ds.lastHeaderRewrite}}</td>
                     <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
                     <td data-search="^{{::ds.longDesc}}$">{{::ds.longDesc}}</td>
                     <td data-search="^{{::ds.longDesc1}}$">{{::ds.longDesc1}}</td>
diff --git a/traffic_portal/app/src/common/modules/table/topologyDeliveryServices/table.topologyDeliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/topologyDeliveryServices/table.topologyDeliveryServices.tpl.html
index efb91cb..a5bcade 100644
--- a/traffic_portal/app/src/common/modules/table/topologyDeliveryServices/table.topologyDeliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/topologyDeliveryServices/table.topologyDeliveryServices.tpl.html
@@ -63,6 +63,7 @@ under the License.
                 <th>DSCP</th>
                 <th>ECS Enabled</th>
                 <th>Edge Header Rewrite Rules</th>
+                <th>First Header Rewrite Rules</th>
                 <th>FQ Pacing Rate</th>
                 <th>Geo Limit</th>
                 <th>Geo Limit Countries</th>
@@ -76,7 +77,9 @@ under the License.
                 <th>ID</th>
                 <th>Info URL</th>
                 <th>Initial Dispersion</th>
+                <th>Inner Header Rewrite Rules</th>
                 <th>IPv6 Routing</th>
+                <th>Last Header Rewrite Rules</th>
                 <th>Last Updated</th>
                 <th>Long Desc 1</th>
                 <th>Long Desc 2</th>
@@ -124,6 +127,7 @@ under the License.
                 <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
                 <td data-search="^{{::ds.ecsEnabled}}$">{{::ds.ecsEnabled}}</td>
                 <td data-search="^{{::ds.edgeHeaderRewrite}}$">{{::ds.edgeHeaderRewrite}}</td>
+                <td data-search="^{{::ds.firstHeaderRewrite}}$">{{::ds.firstHeaderRewrite}}</td>
                 <td data-search="^{{::ds.fqPacingRate}}$">{{::ds.fqPacingRate}}</td>
                 <td data-search="^{{::geoLimit(ds)}}$">{{::geoLimit(ds)}}</td>
                 <td data-search="^{{::ds.geoLimitCountries}}$">{{::ds.geoLimitCountries}}</td>
@@ -137,7 +141,9 @@ under the License.
                 <td data-search="^{{::ds.id}}$">{{::ds.id}}</td>
                 <td data-search="^{{::ds.infoUrl}}$">{{::ds.infoUrl}}</td>
                 <td data-search="^{{::ds.initialDispersion}}$">{{::ds.initialDispersion}}</td>
+                <td data-search="^{{::ds.innerHeaderRewrite}}$">{{::ds.innerHeaderRewrite}}</td>
                 <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
+                <td data-search="^{{::ds.lastHeaderRewrite}}$">{{::ds.lastHeaderRewrite}}</td>
                 <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
                 <td data-search="^{{::ds.longDesc}}$">{{::ds.longDesc}}</td>
                 <td data-search="^{{::ds.longDesc1}}$">{{::ds.longDesc1}}</td>
diff --git a/traffic_portal/app/src/common/modules/table/typeDeliveryServices/table.typeDeliveryServices.tpl.html b/traffic_portal/app/src/common/modules/table/typeDeliveryServices/table.typeDeliveryServices.tpl.html
index 5a40735..24c2139 100644
--- a/traffic_portal/app/src/common/modules/table/typeDeliveryServices/table.typeDeliveryServices.tpl.html
+++ b/traffic_portal/app/src/common/modules/table/typeDeliveryServices/table.typeDeliveryServices.tpl.html
@@ -63,6 +63,7 @@ under the License.
                     <th>DSCP</th>
                     <th>ECS Enabled</th>
                     <th>Edge Header Rewrite Rules</th>
+                    <th>First Header Rewrite Rules</th>
                     <th>FQ Pacing Rate</th>
                     <th>Geo Limit</th>
                     <th>Geo Limit Countries</th>
@@ -76,7 +77,9 @@ under the License.
                     <th>ID</th>
                     <th>Info URL</th>
                     <th>Initial Dispersion</th>
+                    <th>Inner Header Rewrite Rules</th>
                     <th>IPv6 Routing</th>
+                    <th>Last Header Rewrite Rules</th>
                     <th>Last Updated</th>
                     <th>Long Desc 1</th>
                     <th>Long Desc 2</th>
@@ -124,6 +127,7 @@ under the License.
                     <td data-search="^{{::ds.dscp}}$">{{::ds.dscp}}</td>
                     <td data-search="^{{::ds.ecsEnabled}}$">{{::ds.ecsEnabled}}</td>
                     <td data-search="^{{::ds.edgeHeaderRewrite}}$">{{::ds.edgeHeaderRewrite}}</td>
+                    <td data-search="^{{::ds.firstHeaderRewrite}}$">{{::ds.firstHeaderRewrite}}</td>
                     <td data-search="^{{::ds.fqPacingRate}}$">{{::ds.fqPacingRate}}</td>
                     <td data-search="^{{::geoLimit(ds)}}$">{{::geoLimit(ds)}}</td>
                     <td data-search="^{{::ds.geoLimitCountries}}$">{{::ds.geoLimitCountries}}</td>
@@ -137,7 +141,9 @@ under the License.
                     <td data-search="^{{::ds.id}}$">{{::ds.id}}</td>
                     <td data-search="^{{::ds.infoUrl}}$">{{::ds.infoUrl}}</td>
                     <td data-search="^{{::ds.initialDispersion}}$">{{::ds.initialDispersion}}</td>
+                    <td data-search="^{{::ds.innerHeaderRewrite}}$">{{::ds.innerHeaderRewrite}}</td>
                     <td data-search="^{{::ds.ipv6RoutingEnabled}}$">{{::ds.ipv6RoutingEnabled}}</td>
+                    <td data-search="^{{::ds.lastHeaderRewrite}}$">{{::ds.lastHeaderRewrite}}</td>
                     <td data-search="^{{::getRelativeTime(ds.lastUpdated)}}$" data-order="{{::ds.lastUpdated}}">{{::getRelativeTime(ds.lastUpdated)}}</td>
                     <td data-search="^{{::ds.longDesc}}$">{{::ds.longDesc}}</td>
                     <td data-search="^{{::ds.longDesc1}}$">{{::ds.longDesc1}}</td>
diff --git a/traffic_portal/app/src/modules/private/cdns/config/ConfigController.js b/traffic_portal/app/src/modules/private/cdns/config/ConfigController.js
index 6b8dc2e..84ea8c0 100644
--- a/traffic_portal/app/src/modules/private/cdns/config/ConfigController.js
+++ b/traffic_portal/app/src/modules/private/cdns/config/ConfigController.js
@@ -40,6 +40,9 @@ let ConfigController = function (cdn, currentSnapshot, newSnapshot, $scope, $sta
 	const oldTrafficRouterCacheGroups = currentSnapshot.trafficRouterLocations,
 		newTrafficRouterCacheGroups = newSnapshot.trafficRouterLocations;
 
+	const oldTopologies = currentSnapshot.topologies,
+		newTopologies = newSnapshot.topologies;
+
 	const oldStats = currentSnapshot.stats,
 		newStats = newSnapshot.stats;
 
@@ -126,6 +129,13 @@ let ConfigController = function (cdn, currentSnapshot, newSnapshot, $scope, $sta
 		templateUrl: 'tlPopoverTemplate.html'
 	};
 
+	$scope.topologiesCount = {
+		added: 0,
+		removed: 0,
+		updated: 0,
+		templateUrl: 'topPopoverTemplate.html'
+	};
+
 	$scope.statsCount = {
 		added: 0,
 		removed: 0,
@@ -190,6 +200,7 @@ let ConfigController = function (cdn, currentSnapshot, newSnapshot, $scope, $sta
 		performDiff(oldDeliveryServices, newDeliveryServices, 'deliveryServices');
 		performDiff(oldEdgeCacheGroups, newEdgeCacheGroups, 'edgeLocations');
 		performDiff(oldTrafficRouterCacheGroups, newTrafficRouterCacheGroups, 'trLocations');
+		performDiff(oldTopologies, newTopologies, 'topologies');
 		performDiff(oldStats, newStats, 'stats');
 	};
 	init();
diff --git a/traffic_portal/app/src/modules/private/cdns/config/config.tpl.html b/traffic_portal/app/src/modules/private/cdns/config/config.tpl.html
index 503947d..44354c8 100644
--- a/traffic_portal/app/src/modules/private/cdns/config/config.tpl.html
+++ b/traffic_portal/app/src/modules/private/cdns/config/config.tpl.html
@@ -26,7 +26,7 @@ under the License.
         </ol>
         <div class="pull-right" ng-show="!settings.isNew">
             <button type="button" class="btn btn-default" ng-click="navigateToPath('/cdns/' + cdn.id)">Cancel</button>
-            <button type="button" class="btn btn-primary" title="Perform {{cdn.name}} Snapshot" ng-click="confirmSnapshot(cdn)"><i class="fa fa-camera"></i>&nbsp;&nbsp;Perform Snapshot</button>
+            <button type="button" class="btn btn-primary" name="snapshotCDNbtn" title="Perform {{cdn.name}} Snapshot" ng-click="confirmSnapshot(cdn)"><i class="fa fa-camera"></i>&nbsp;&nbsp;Perform Snapshot</button>
         </div>
         <div class="clearfix"></div>
     </div>
@@ -215,6 +215,32 @@ under the License.
                 </div>
             </uib-tab>
             <uib-tab index="7" class="tab" select="tabSelected()">
+                <uib-tab-heading uib-popover-template="topologiesCount.templateUrl" popover-title="{{topologiesCount.added + topologiesCount.removed + topologiesCount.updated}} Total Changes" popover-trigger="mouseenter" popover-placement="top" popover-append-to-body="true">
+                    Topologies<br/>[ {{topologiesCount.added}} | {{topologiesCount.removed}} | {{topologiesCount.updated}} ]
+                </uib-tab-heading>
+                <div class="x_content">
+                    <br>
+                    <table id="topologiesChangesTable" class="table responsive-utilities jambo_table changes">
+                        <thead>
+                        <tr class="headings">
+                            <th>Change Type</th>
+                            <th>Path</th>
+                            <th>Current Value</th>
+                            <th>Pending Value</th>
+                        </tr>
+                        </thead>
+                        <tbody>
+                        <tr ng-repeat="top in ::topologiesChanges track by $index">
+                            <td data-search="^{{::top.op}}$">{{::top.op}}</td>
+                            <td data-search="^{{::top.path}}$">{{::top.path}}</td>
+                            <td class="value" data-search="^{{::top.oldValue}}$"><json-formatter open="expandLevel" json="top.oldValue"></json-formatter></td>
+                            <td class="value" data-search="^{{::top.value}}$"><json-formatter open="expandLevel" json="top.value"></json-formatter></td>
+                        </tr>
+                        </tbody>
+                    </table>
+                </div>
+            </uib-tab>
+            <uib-tab index="8" class="tab" select="tabSelected()">
                 <uib-tab-heading uib-popover-template="statsCount.templateUrl" popover-title="{{statsCount.added + statsCount.removed + statsCount.updated}} Total Changes" popover-trigger="mouseenter" popover-placement="top" popover-append-to-body="true">
                     Stats<br/>[ {{statsCount.added}} | {{statsCount.removed}} | {{statsCount.updated}} ]
                 </uib-tab-heading>
@@ -288,6 +314,12 @@ under the License.
     <div>{{trLocationsCount.updated}} updates</div>
 </script>
 
+<script type="text/ng-template" id="topPopoverTemplate.html">
+    <div>{{topologiesCount.added}} adds</div>
+    <div>{{topologiesCount.removed}} removes</div>
+    <div>{{topologiesCount.updated}} updates</div>
+</script>
+
 <script type="text/ng-template" id="statsPopoverTemplate.html">
     <div>{{statsCount.added}} adds</div>
     <div>{{statsCount.removed}} removes</div>
diff --git a/traffic_portal/test/end_to_end/CDNs/cdns-spec.js b/traffic_portal/test/end_to_end/CDNs/cdns-spec.js
index 11a317c..a3e142d 100644
--- a/traffic_portal/test/end_to_end/CDNs/cdns-spec.js
+++ b/traffic_portal/test/end_to_end/CDNs/cdns-spec.js
@@ -75,4 +75,14 @@ describe('Traffic Portal CDNs Test Suite', function() {
 		pageData.updateButton.click();
 		expect(pageData.domainName.getAttribute('value')).toEqual(myDomainName + 'updated.com');
 	});
+
+	it('should perform cdn snapshot', function() {
+		console.log('Performing cdn snapshot for ' + myNewCDN);
+		pageData.diffCDNSnapshotButton.click();
+		expect(browser.getCurrentUrl().then(commonFunctions.urlPath)).toMatch(commonFunctions.urlPath(browser.baseUrl)+"#!/cdns/[0-9]+/config/changes");
+		pageData.performCDNSnapshotButton.click();
+		pageData.yesButton.click();
+		expect(browser.getCurrentUrl().then(commonFunctions.urlPath)).toMatch(commonFunctions.urlPath(browser.baseUrl)+"#!/cdns/[0-9]+");
+	});
+
 });
diff --git a/traffic_portal/test/end_to_end/CDNs/pageData.js b/traffic_portal/test/end_to_end/CDNs/pageData.js
index 01dedde..c1c1db8 100644
--- a/traffic_portal/test/end_to_end/CDNs/pageData.js
+++ b/traffic_portal/test/end_to_end/CDNs/pageData.js
@@ -29,10 +29,12 @@ module.exports = function(){
 	this.moreButton=element(by.buttonText('More'));
 	this.manageDnssecKeysButton=element(by.linkText('Manage DNSSEC Keys'));
 	this.generateDnssecKeysButton=element(by.buttonText('Generate DNSSEC Keys'));
+	this.diffCDNSnapshotButton=element(by.name('diffCDNbtn'));
+	this.performCDNSnapshotButton=element(by.name('snapshotCDNbtn'));
 	this.kskExpirationDays=element(by.name('kskExpirationDays'));
 	this.regenerateButton=element(by.buttonText('Regenerate'));
 	this.confirmInput=element(by.name('confirmEnterForm')).element(by.tagName('input'));
-	this.confirmButton=element(by.buttonText('Confirm'));
+	this.yesButton=element(by.buttonText('Yes'));
 	this.expirationDate=element(by.name('expirationDate'));
 	this.regenerateDnssecKeysButton=element(by.buttonText('Regenerate DNSSEC Keys'));
 	this.regenerateKskButton=element(by.buttonText('Regenerate KSK'));