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

mitchell852 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 ccf727f  Validating absolute DNS name requirement on Static DNS Entry 
Type (#4934)
ccf727f is described below

commit ccf727fd78f049208aeddbb3b00869188a104bdd
Author: rimashah25 <[email protected]>
AuthorDate: Wed Aug 12 08:33:10 2020 -0600

    Validating absolute DNS name requirement on Static DNS Entry Type (#4934)
    
    * Checking for a trailing period in TP wrt static DNS entry
    
    * Added test cases for adding adn deleting static DNS entry. Added name in 
table anf form js to support these test cases
    
    * Added CHANGELOG.md
    
    * Updated selenium test cases
    
    * Updated end-to-end test case. Removed patten from LocationUtil and added 
to DeliveryServiceUtils.
    
    * Removed regex patten from DeliveryServiceUtils and added logic to TO, to 
ensure both API calls and TP behave the same.
    
    * Added api test case for Update()
    
    * Updated html page for staticDNSEntry
    
    * Updated code per PR review comments.
    
    * Checking for address length.
    
    * Used correct html tags.
---
 CHANGELOG.md                                       |  1 +
 docs/source/api/v2/staticdnsentries.rst            | 32 ++++++++++----------
 docs/source/api/v3/staticdnsentries.rst            | 34 +++++++++++-----------
 .../testing/api/v2/staticdnsentries_test.go        | 22 ++++++++++++--
 .../testing/api/v3/staticdnsentries_test.go        | 24 ++++++++++++---
 .../staticdnsentry/staticdnsentry.go               |  8 +++++
 .../form.deliveryServiceStaticDnsEntry.tpl.html    | 15 ++++++++--
 .../table.deliveryServiceStaticDnsEntries.tpl.html |  4 +--
 .../deliveryServices/delivery-services-spec.js     | 29 +++++++++++++++++-
 .../test/end_to_end/deliveryServices/pageData.js   |  9 +++++-
 .../test/end_to_end/servers/servers-spec.js        |  4 +--
 11 files changed, 134 insertions(+), 48 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e47f1ce..ab40f6e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -35,6 +35,7 @@ The format is based on [Keep a 
Changelog](http://keepachangelog.com/en/1.0.0/).
 - Added debugging functionality to CDN-in-a-Box for Traffic Stats.
 
 ### Fixed
+- Fixed #4743 - Validate absolute DNS name requirement on Static DNS entry for 
CNAME type [Related github 
issue](https://github.com/apache/trafficcontrol/issues/4743)
 - Fixed #4848 - `GET /api/x/cdns/capacity` gives back 500, with the message 
`capacity was zero`
 - Fixed #2156 - Renaming a host in TC, does not impact xmpp_id and thereby 
hashid [Related github 
issue](https://github.com/apache/trafficcontrol/issues/2156)
 - Fixed #3661 - Anonymous Proxy ipv4 whitelist does not work
diff --git a/docs/source/api/v2/staticdnsentries.rst 
b/docs/source/api/v2/staticdnsentries.rst
index afae0a7..6dc7c06 100644
--- a/docs/source/api/v2/staticdnsentries.rst
+++ b/docs/source/api/v2/staticdnsentries.rst
@@ -75,7 +75,7 @@ Request Structure
 
 Response Structure
 ------------------
-:address:    If ``typeId`` identifies a ``CNAME`` type record, this is the 
Canonical Name (CNAME) of the server, otherwise it is the IP address to which 
``host`` shall be resolved
+:address:    If ``typeId`` identifies a ``CNAME`` type record, this is the 
Canonical Name (CNAME) of the server with a trailing period, otherwise it is 
the IP address to which ``host`` shall be resolved
 :cachegroup: An optional string containing the :ref:`Name of a Cache Group 
<cache-group-name>` which will service this static DNS entry
 
        .. note:: This field has no effect, and is not used by any part of 
Traffic Control. It exists for legacy compatibility reasons.
@@ -109,7 +109,7 @@ Response Structure
 
        { "response": [
                {
-                       "address": "foo.bar",
+                       "address": "foo.bar.",
                        "cachegroup": null,
                        "cachegroupId": null,
                        "deliveryservice": "demo1",
@@ -119,7 +119,7 @@ Response Structure
                        "lastUpdated": "2018-12-10 19:59:56+00",
                        "ttl": 300,
                        "type": "CNAME_RECORD",
-                       "typeId": 40
+                       "typeId": 41
                }
        ]}
 
@@ -133,7 +133,7 @@ Creates a new, static DNS entry.
 
 Request Structure
 -----------------
-:address:      If ``typeId`` identifies a ``CNAME`` type record, this is the 
Canonical Name (CNAME) of the server, otherwise it is the IP address to which 
``host`` shall be resolved
+:address:      If ``typeId`` identifies a ``CNAME`` type record, this is the 
Canonical Name (CNAME) of the server with a trailing period, otherwise it is 
the IP address to which ``host`` shall be resolved
 :cachegroupId: An optional, integer that is the :ref:`ID of a Cache Group 
<cache-group-id>` which will service this static DNS entry
 
        .. note:: This field has no effect, and is not used by any part of 
Traffic Control. It exists for legacy compatibility reasons.
@@ -155,16 +155,16 @@ Request Structure
        Content-Type: application/json
 
        {
-               "address": "test.quest",
+               "address": "test.quest.",
                "deliveryserviceId": 1,
                "host": "test",
                "ttl": 300,
-               "typeId": 40
+               "typeId": 41
        }
 
 Response Structure
 ------------------
-:address:           If ``typeId`` identifies a ``CNAME`` type record, this is 
the Canonical Name (CNAME) of the server, otherwise it is the IP address to 
which ``host`` shall be resolved
+:address:           If ``typeId`` identifies a ``CNAME`` type record, this is 
the Canonical Name (CNAME) of the server with a trailing period, otherwise it 
is the IP address to which ``host`` shall be resolved
 :cachegroup: An optional string containing the :ref:`Name of a Cache Group 
<cache-group-name>` which will service this static DNS entry
 
        .. note:: This field has no effect, and is not used by any part of 
Traffic Control. It exists for legacy compatibility reasons.
@@ -203,7 +203,7 @@ Response Structure
                }
        ],
        "response": {
-               "address": "test.quest",
+               "address": "test.quest.",
                "cachegroup": null,
                "cachegroupId": null,
                "deliveryservice": null,
@@ -212,8 +212,8 @@ Response Structure
                "id": 2,
                "lastUpdated": "2018-12-10 19:54:19+00",
                "ttl": 300,
-               "type": null,
-               "typeId": 40
+               "type": "CNAME_RECORD",
+               "typeId": 41
        }}
 
 ``PUT``
@@ -234,7 +234,7 @@ Request Structure
        |  id  | The integral, unique identifier of the static DNS entry to 
modify |
        
+------+-------------------------------------------------------------------+
 
-:address:           If ``typeId`` identifies a ``CNAME`` type record, this is 
the Canonical Name (CNAME) of the server, otherwise it is the IP address to 
which ``host`` shall be resolved
+:address:           If ``typeId`` identifies a ``CNAME`` type record, this is 
the Canonical Name (CNAME) of the server with a trailing period, otherwise it 
is the IP address to which ``host`` shall be resolved
 :cachegroupId: An optional, integer that is the :ref:`ID of a Cache Group 
<cache-group-id>` which will service this static DNS entry
 
        .. note:: This field has no effect, and is not used by any part of 
Traffic Control. It exists for legacy compatibility reasons.
@@ -256,16 +256,16 @@ Request Structure
        Content-Type: application/json
 
        {
-               "address": "foo.bar",
+               "address": "foo.bar.",
                "deliveryserviceId": 1,
                "host": "test",
                "ttl": 300,
-               "typeId": 40
+               "typeId": 41
        }
 
 Response Structure
 ------------------
-:address:    If ``typeId`` identifies a ``CNAME`` type record, this is the 
Canonical Name (CNAME) of the server, otherwise it is the IP address to which 
``host`` shall be resolved
+:address:    If ``typeId`` identifies a ``CNAME`` type record, this is the 
Canonical Name (CNAME) of the server with a trailing period, otherwise it is 
the IP address to which ``host`` shall be resolved
 :cachegroup: An optional string containing the :ref:`Name of a Cache Group 
<cache-group-name>` which will service this static DNS entry
 
        .. note:: This field has no effect, and is not used by any part of 
Traffic Control. It exists for legacy compatibility reasons.
@@ -304,7 +304,7 @@ Response Structure
                }
        ],
        "response": {
-               "address": "foo.bar",
+               "address": "foo.bar.",
                "cachegroup": null,
                "cachegroupId": null,
                "deliveryservice": null,
@@ -314,7 +314,7 @@ Response Structure
                "lastUpdated": "2018-12-10 19:59:56+00",
                "ttl": 300,
                "type": null,
-               "typeId": 40
+               "typeId": 41
        }}
 
 
diff --git a/docs/source/api/v3/staticdnsentries.rst 
b/docs/source/api/v3/staticdnsentries.rst
index 57ce60a..039ed51 100644
--- a/docs/source/api/v3/staticdnsentries.rst
+++ b/docs/source/api/v3/staticdnsentries.rst
@@ -75,7 +75,7 @@ Request Structure
 
 Response Structure
 ------------------
-:address:    If ``typeId`` identifies a ``CNAME`` type record, this is the 
Canonical Name (CNAME) of the server, otherwise it is the IP address to which 
``host`` shall be resolved
+:address:    If ``typeId`` identifies a ``CNAME`` type record, this is the 
Canonical Name (CNAME) of the server with a trailing period, otherwise it is 
the IP address to which ``host`` shall be resolved
 :cachegroup: An optional string containing the :ref:`Name of a Cache Group 
<cache-group-name>` which will service this static DNS entry
 
        .. note:: This field has no effect, and is not used by any part of 
Traffic Control. It exists for legacy compatibility reasons.
@@ -109,7 +109,7 @@ Response Structure
 
        { "response": [
                {
-                       "address": "foo.bar",
+                       "address": "foo.bar.",
                        "cachegroup": null,
                        "cachegroupId": null,
                        "deliveryservice": "demo1",
@@ -119,7 +119,7 @@ Response Structure
                        "lastUpdated": "2018-12-10 19:59:56+00",
                        "ttl": 300,
                        "type": "CNAME_RECORD",
-                       "typeId": 40
+                       "typeId": 41
                }
        ]}
 
@@ -133,7 +133,7 @@ Creates a new, static DNS entry.
 
 Request Structure
 -----------------
-:address:      If ``typeId`` identifies a ``CNAME`` type record, this is the 
Canonical Name (CNAME) of the server, otherwise it is the IP address to which 
``host`` shall be resolved
+:address:      If ``typeId`` identifies a ``CNAME`` type record, this is the 
Canonical Name (CNAME) of the server with a trailing period, otherwise it is 
the IP address to which ``host`` shall be resolved
 :cachegroupId: An optional, integer that is the :ref:`ID of a Cache Group 
<cache-group-id>` which will service this static DNS entry
 
        .. note:: This field has no effect, and is not used by any part of 
Traffic Control. It exists for legacy compatibility reasons.
@@ -155,16 +155,16 @@ Request Structure
        Content-Type: application/json
 
        {
-               "address": "test.quest",
+               "address": "test.quest.",
                "deliveryserviceId": 1,
                "host": "test",
                "ttl": 300,
-               "typeId": 40
+               "typeId": 41
        }
 
 Response Structure
 ------------------
-:address:           If ``typeId`` identifies a ``CNAME`` type record, this is 
the Canonical Name (CNAME) of the server, otherwise it is the IP address to 
which ``host`` shall be resolved
+:address:           If ``typeId`` identifies a ``CNAME`` type record, this is 
the Canonical Name (CNAME) of the server with a trailing period, otherwise it 
is the IP address to which ``host`` shall be resolved
 :cachegroup: An optional string containing the :ref:`Name of a Cache Group 
<cache-group-name>` which will service this static DNS entry
 
        .. note:: This field has no effect, and is not used by any part of 
Traffic Control. It exists for legacy compatibility reasons.
@@ -203,7 +203,7 @@ Response Structure
                }
        ],
        "response": {
-               "address": "test.quest",
+               "address": "test.quest.",
                "cachegroup": null,
                "cachegroupId": null,
                "deliveryservice": null,
@@ -212,8 +212,8 @@ Response Structure
                "id": 2,
                "lastUpdated": "2018-12-10 19:54:19+00",
                "ttl": 300,
-               "type": null,
-               "typeId": 40
+               "type": "CNAME_RECORD",
+               "typeId": 41
        }}
 
 ``PUT``
@@ -234,7 +234,7 @@ Request Structure
        |  id  | The integral, unique identifier of the static DNS entry to 
modify |
        
+------+-------------------------------------------------------------------+
 
-:address:           If ``typeId`` identifies a ``CNAME`` type record, this is 
the Canonical Name (CNAME) of the server, otherwise it is the IP address to 
which ``host`` shall be resolved
+:address:           If ``typeId`` identifies a ``CNAME`` type record, this is 
the Canonical Name (CNAME) of the server with a trailing period, otherwise it 
is the IP address to which ``host`` shall be resolved
 :cachegroupId: An optional, integer that is the :ref:`ID of a Cache Group 
<cache-group-id>` which will service this static DNS entry
 
        .. note:: This field has no effect, and is not used by any part of 
Traffic Control. It exists for legacy compatibility reasons.
@@ -256,16 +256,16 @@ Request Structure
        Content-Type: application/json
 
        {
-               "address": "foo.bar",
+               "address": "foo.bar.",
                "deliveryserviceId": 1,
                "host": "test",
                "ttl": 300,
-               "typeId": 40
+               "typeId": 41
        }
 
 Response Structure
 ------------------
-:address:    If ``typeId`` identifies a ``CNAME`` type record, this is the 
Canonical Name (CNAME) of the server, otherwise it is the IP address to which 
``host`` shall be resolved
+:address:    If ``typeId`` identifies a ``CNAME`` type record, this is the 
Canonical Name (CNAME) of the server with a trailing period, otherwise it is 
the IP address to which ``host`` shall be resolved
 :cachegroup: An optional string containing the :ref:`Name of a Cache Group 
<cache-group-name>` which will service this static DNS entry
 
        .. note:: This field has no effect, and is not used by any part of 
Traffic Control. It exists for legacy compatibility reasons.
@@ -304,7 +304,7 @@ Response Structure
                }
        ],
        "response": {
-               "address": "foo.bar",
+               "address": "foo.bar.",
                "cachegroup": null,
                "cachegroupId": null,
                "deliveryservice": null,
@@ -313,8 +313,8 @@ Response Structure
                "id": 2,
                "lastUpdated": "2018-12-10 19:59:56+00",
                "ttl": 300,
-               "type": null,
-               "typeId": 40
+               "type": "CNAME_RECORD",
+               "typeId": 41
        }}
 
 
diff --git a/traffic_ops/testing/api/v2/staticdnsentries_test.go 
b/traffic_ops/testing/api/v2/staticdnsentries_test.go
index 41c2fa0..0bedbfa 100644
--- a/traffic_ops/testing/api/v2/staticdnsentries_test.go
+++ b/traffic_ops/testing/api/v2/staticdnsentries_test.go
@@ -74,7 +74,11 @@ func UpdateTestStaticDNSEntries(t *testing.T) {
 
 func UpdateTestStaticDNSEntriesInvalidAddress(t *testing.T) {
 
-       expectedAlerts := []tc.Alerts{tc.Alerts{[]tc.Alert{tc.Alert{"'address' 
must be a valid IPv4 address", "error"}}}, 
tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid DNS name", "error"}}}, 
tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid IPv6 address", 
"error"}}}}
+       expectedAlerts := []tc.Alerts{
+               tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid IPv4 
address", "error"}}},
+               tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid DNS 
name", "error"}}},
+               tc.Alerts{[]tc.Alert{tc.Alert{"'address' for type: CNAME_RECORD 
must have a trailing period", "error"}}},
+               tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid IPv6 
address", "error"}}}}
 
        // A_RECORD
        firstStaticDNSEntry := testData.StaticDNSEntries[0]
@@ -116,6 +120,18 @@ func UpdateTestStaticDNSEntriesInvalidAddress(t 
*testing.T) {
                t.Errorf("got alerts: %v but expected alerts: %v", alert, 
expectedAlerts[1])
        }
 
+       //CNAME_RECORD: missing a trailing period
+       expectedAddressMissingPeriod := "cdn.test.com"
+       remoteStaticDNSEntry.Address = expectedAddressMissingPeriod
+       alert, _, status, err = 
TOSession.UpdateStaticDNSEntryByID(remoteStaticDNSEntry.ID, 
remoteStaticDNSEntry)
+       t.Log("Status Code [expect 400]: ", status)
+       if err != nil {
+               t.Logf("cannot UPDATE StaticDNSEntries using url: %v - %v\n", 
err, alert)
+       }
+       if !reflect.DeepEqual(alert, expectedAlerts[2]) {
+               t.Errorf("got alerts: %v but expected alerts: %v", alert, 
expectedAlerts[2])
+       }
+
        // AAAA_RECORD
        thirdStaticDNSEntry := testData.StaticDNSEntries[2]
        // Retrieve the StaticDNSEntries by name so we can get the id for the 
Update
@@ -131,8 +147,8 @@ func UpdateTestStaticDNSEntriesInvalidAddress(t *testing.T) 
{
        if err != nil {
                t.Logf("cannot UPDATE StaticDNSEntries using url: %v - %v\n", 
err, alert)
        }
-       if !reflect.DeepEqual(alert, expectedAlerts[2]) {
-               t.Errorf("got alerts: %v but expected alerts: %v", alert, 
expectedAlerts[2])
+       if !reflect.DeepEqual(alert, expectedAlerts[3]) {
+               t.Errorf("got alerts: %v but expected alerts: %v", alert, 
expectedAlerts[3])
        }
 }
 
diff --git a/traffic_ops/testing/api/v3/staticdnsentries_test.go 
b/traffic_ops/testing/api/v3/staticdnsentries_test.go
index 85811d3..46d7149 100644
--- a/traffic_ops/testing/api/v3/staticdnsentries_test.go
+++ b/traffic_ops/testing/api/v3/staticdnsentries_test.go
@@ -69,7 +69,7 @@ func GetTestStaticDNSEntriesIMSAfterChange(t *testing.T, 
header http.Header) {
 func GetTestStaticDNSEntriesIMS(t *testing.T) {
        var header http.Header
        header = make(map[string][]string)
-       futureTime := time.Now().AddDate(0,0,1)
+       futureTime := time.Now().AddDate(0, 0, 1)
        time := futureTime.Format(time.RFC1123)
        header.Set(rfc.IfModifiedSince, time)
 
@@ -128,7 +128,11 @@ func UpdateTestStaticDNSEntries(t *testing.T) {
 
 func UpdateTestStaticDNSEntriesInvalidAddress(t *testing.T) {
 
-       expectedAlerts := []tc.Alerts{tc.Alerts{[]tc.Alert{tc.Alert{"'address' 
must be a valid IPv4 address", "error"}}}, 
tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid DNS name", "error"}}}, 
tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid IPv6 address", 
"error"}}}}
+       expectedAlerts := []tc.Alerts{
+               tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid IPv4 
address", "error"}}},
+               tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid DNS 
name", "error"}}},
+               tc.Alerts{[]tc.Alert{tc.Alert{"'address' for type: CNAME_RECORD 
must have a trailing period", "error"}}},
+               tc.Alerts{[]tc.Alert{tc.Alert{"'address' must be a valid IPv6 
address", "error"}}}}
 
        // A_RECORD
        firstStaticDNSEntry := testData.StaticDNSEntries[0]
@@ -170,6 +174,18 @@ func UpdateTestStaticDNSEntriesInvalidAddress(t 
*testing.T) {
                t.Errorf("got alerts: %v but expected alerts: %v", alert, 
expectedAlerts[1])
        }
 
+       //CNAME_RECORD: missing a trailing period
+       expectedAddressMissingPeriod := "cdn.test.com"
+       remoteStaticDNSEntry.Address = expectedAddressMissingPeriod
+       alert, _, status, err = 
TOSession.UpdateStaticDNSEntryByID(remoteStaticDNSEntry.ID, 
remoteStaticDNSEntry)
+       t.Log("Status Code [expect 400]: ", status)
+       if err != nil {
+               t.Logf("cannot UPDATE StaticDNSEntries using url: %v - %v\n", 
err, alert)
+       }
+       if !reflect.DeepEqual(alert, expectedAlerts[2]) {
+               t.Errorf("got alerts: %v but expected alerts: %v", alert, 
expectedAlerts[2])
+       }
+
        // AAAA_RECORD
        thirdStaticDNSEntry := testData.StaticDNSEntries[2]
        // Retrieve the StaticDNSEntries by name so we can get the id for the 
Update
@@ -185,8 +201,8 @@ func UpdateTestStaticDNSEntriesInvalidAddress(t *testing.T) 
{
        if err != nil {
                t.Logf("cannot UPDATE StaticDNSEntries using url: %v - %v\n", 
err, alert)
        }
-       if !reflect.DeepEqual(alert, expectedAlerts[2]) {
-               t.Errorf("got alerts: %v but expected alerts: %v", alert, 
expectedAlerts[2])
+       if !reflect.DeepEqual(alert, expectedAlerts[3]) {
+               t.Errorf("got alerts: %v but expected alerts: %v", alert, 
expectedAlerts[3])
        }
 }
 
diff --git a/traffic_ops/traffic_ops_golang/staticdnsentry/staticdnsentry.go 
b/traffic_ops/traffic_ops_golang/staticdnsentry/staticdnsentry.go
index 7c5f30b..a0e0e04 100644
--- a/traffic_ops/traffic_ops_golang/staticdnsentry/staticdnsentry.go
+++ b/traffic_ops/traffic_ops_golang/staticdnsentry/staticdnsentry.go
@@ -20,6 +20,7 @@ package staticdnsentry
  */
 
 import (
+       "fmt"
        "net/http"
        "strconv"
        "time"
@@ -103,6 +104,13 @@ func (staticDNSEntry TOStaticDNSEntry) Validate() error {
                addressErr = validation.Validate(staticDNSEntry.Address, 
validation.Required, is.IPv6)
        case "CNAME_RECORD":
                addressErr = validation.Validate(staticDNSEntry.Address, 
validation.Required, is.DNSName)
+               address := *staticDNSEntry.Address
+               if addressErr == nil {
+                       lastChar := address[len(address)-1:]
+                       if lastChar != "." {
+                               addressErr = fmt.Errorf("for type: CNAME_RECORD 
must have a trailing period")
+                       }
+               }
        default:
                addressErr = validation.Validate(staticDNSEntry.Address, 
validation.Required)
        }
diff --git 
a/traffic_portal/app/src/common/modules/form/deliveryServiceStaticDnsEntry/form.deliveryServiceStaticDnsEntry.tpl.html
 
b/traffic_portal/app/src/common/modules/form/deliveryServiceStaticDnsEntry/form.deliveryServiceStaticDnsEntry.tpl.html
index 2519630..aac08b2 100644
--- 
a/traffic_portal/app/src/common/modules/form/deliveryServiceStaticDnsEntry/form.deliveryServiceStaticDnsEntry.tpl.html
+++ 
b/traffic_portal/app/src/common/modules/form/deliveryServiceStaticDnsEntry/form.deliveryServiceStaticDnsEntry.tpl.html
@@ -57,9 +57,20 @@ under the License.
                 </div>
             </div>
             <div class="form-group" ng-class="{'has-error': 
hasError(dsStaticDnsEntryForm.address), 'has-feedback': 
hasError(dsStaticDnsEntryForm.address)}">
-                <label for="address" class="control-label col-md-2 col-sm-2 
col-xs-12">Address *</label>
+                <label for="address" class="has-tooltip control-label col-md-2 
col-sm-2 col-xs-12">Address *<div class="helptooltip">
+                    <div class="helptext">The Address Rules.
+                        <ul>
+                            <li>Type:A_RECORD, address should be an IPv4 
address.</li>
+                            <li>Type:AAAA_RECORD, address should be an IPv6 
address.</li>
+                            <li>Type:CNAME, address must be a valid DNS name 
ending with a trailing period.</li>
+                            <li>Type:TXT_RECORD, address cannot be blank.</li>
+                        </ul>
+                    </div>
+                </div>
+                </label>
                 <div class="col-md-10 col-sm-10 col-xs-12">
-                    <input id="address" name="address" type="text" 
class="form-control" ng-model="staticDnsEntry.address" required>
+                    <input id="address" name="address" type="text" 
class="form-control" ng-model="staticDnsEntry.address"
+                           required title="Address must be: an IPv4, if 
type:A_RECORD; an IPv6, if type: AAAA_RECORD; valid DNS name ending with a 
trailing period, if type:CNAME_RECORD; cannot be blank, if type: TXT_RECORD">
                     <small class="input-error" 
ng-show="hasPropertyError(dsStaticDnsEntryForm.address, 
'required')">Required</small>
                     <span ng-show="hasError(dsStaticDnsEntryForm.address)" 
class="form-control-feedback"><i class="fa fa-times"></i></span>
                 </div>
diff --git 
a/traffic_portal/app/src/common/modules/table/deliveryServiceStaticDnsEntries/table.deliveryServiceStaticDnsEntries.tpl.html
 
b/traffic_portal/app/src/common/modules/table/deliveryServiceStaticDnsEntries/table.deliveryServiceStaticDnsEntries.tpl.html
index 1d7b6b7..f3cebbf 100644
--- 
a/traffic_portal/app/src/common/modules/table/deliveryServiceStaticDnsEntries/table.deliveryServiceStaticDnsEntries.tpl.html
+++ 
b/traffic_portal/app/src/common/modules/table/deliveryServiceStaticDnsEntries/table.deliveryServiceStaticDnsEntries.tpl.html
@@ -21,11 +21,11 @@ under the License.
     <div class="x_title">
         <ol class="breadcrumb pull-left">
             <li><a ng-click="navigateToPath('/delivery-services')">Delivery 
Services</a></li>
-            <li><a ng-click="navigateToPath('/delivery-services/' + 
deliveryService.id + '?type=' + 
deliveryService.type)">{{::deliveryService.xmlId}}</a></li>
+            <li><a name="dsLink" 
ng-click="navigateToPath('/delivery-services/' + deliveryService.id + '?type=' 
+ deliveryService.type)">{{::deliveryService.xmlId}}</a></li>
             <li class="active">Static DNS Entries</li>
         </ol>
         <div class="pull-right">
-            <button class="btn btn-primary" title="Create Delivery Service 
Static Dns Entry" ng-click="createStaticDnsEntry(deliveryService.id)"><i 
class="fa fa-plus"></i></button>
+            <button name="addStaticDNSBtn" class="btn btn-primary" 
title="Create Delivery Service Static Dns Entry" 
ng-click="createStaticDnsEntry(deliveryService.id)"><i class="fa 
fa-plus"></i></button>
             <button class="btn btn-default" title="Refresh" 
ng-click="refresh()"><i class="fa fa-refresh"></i></button>
         </div>
         <div class="clearfix"></div>
diff --git 
a/traffic_portal/test/end_to_end/deliveryServices/delivery-services-spec.js 
b/traffic_portal/test/end_to_end/deliveryServices/delivery-services-spec.js
index 94a7021..90ffb25 100644
--- a/traffic_portal/test/end_to_end/deliveryServices/delivery-services-spec.js
+++ b/traffic_portal/test/end_to_end/deliveryServices/delivery-services-spec.js
@@ -50,7 +50,11 @@ describe('Traffic Portal Delivery Services Suite', 
function() {
                dnsXmlId: "dns-xml-id-" + 
commonFunctions.shuffle('abcdefghijklmonpqrstuvwxyz'),
                httpXmlId: "http-xml-id-" + 
commonFunctions.shuffle('abcdefghijklmonpqrstuvwxyz'),
                steeringXmlId: "http-xml-id-" + 
commonFunctions.shuffle('abcdefghijklmonpqrstuvwxyz'),
-               longDesc: "This is only a test delivery service that should be 
disposed of by Automated UI Testing."
+               longDesc: "This is only a test delivery service that should be 
disposed of by Automated UI Testing.",
+               staticDNShostName: "static-dns-xml-id-" + 
commonFunctions.shuffle('abcdefghijklmonpqrstuvwxyz'),
+               staticDNSTTL: 50,
+               staticDNSAddress: "cdn.test.com."
+
        };
 
        it('should open delivery services page', function() {
@@ -327,6 +331,29 @@ describe('Traffic Portal Delivery Services Suite', 
function() {
                });
        });
 
+       it('should add a required Static DNS entry to the HTTP delivery 
service', function() {
+               pageData.dsLink.click();
+               console.log('Adding Static DNS entry to ' + mockVals.httpXmlId);
+               pageData.moreBtn.click();
+               pageData.viewStaticCapabilitiesMenuItem.click();
+               
expect(browser.getCurrentUrl().then(commonFunctions.urlPath)).toMatch(commonFunctions.urlPath(browser.baseUrl)+"#!/delivery-services/[0-9]+/static-dns-entries");
+               pageData.addStaticDNSBtn.click();
+               // set host name
+               pageData.host.sendKeys(mockVals.staticDNShostName);
+               // set type ID to CNAME_RECORD's id
+               pageData.staticDNStypeId.click();
+               commonFunctions.selectDropdownbyNum(pageData.staticDNStypeId, 
3);
+               // set ttl
+               pageData.ttl.sendKeys(mockVals.staticDNSTTL);
+               // set address
+               pageData.address.sendKeys(mockVals.staticDNSAddress);
+               expect(pageData.createButton.isEnabled()).toBe(true);
+               pageData.createButton.click();
+               element.all(by.css('tbody tr')).then(function(totalRows) {
+                       expect(totalRows.length).toBe(1);
+               });
+       });
+
        it('should navigate back to the HTTP delivery service and delete it', 
function() {
                console.log('Deleting ' + mockVals.httpXmlId);
                pageData.dsLink.click();
diff --git a/traffic_portal/test/end_to_end/deliveryServices/pageData.js 
b/traffic_portal/test/end_to_end/deliveryServices/pageData.js
index d1c5b91..9df8a01 100644
--- a/traffic_portal/test/end_to_end/deliveryServices/pageData.js
+++ b/traffic_portal/test/end_to_end/deliveryServices/pageData.js
@@ -19,7 +19,7 @@
 
 module.exports = function(){
        this.moreBtn=element(by.name('moreBtn'));
-       
this.viewCapabilitiesMenuItem=element(by.css('a[ng-click*=viewCapabilities]'));
+       
this.viewStaticCapabilitiesMenuItem=element(by.css('a[ng-click*=viewStaticDnsEntries]'));
        this.addCapabilityBtn=element(by.name('addCapabilityBtn'));
        this.manageServersMenuItem=element(by.css('a[ng-click*=viewServers]'));
        this.selectServersBtn=element(by.name('selectServersBtn'));
@@ -43,4 +43,11 @@ module.exports = function(){
        
this.searchFilter=element(by.id('deliveryServicesTable_filter')).element(by.css('label
 input'));
        this.confirmWithNameInput=element(by.name('confirmWithNameInput'));
        this.deletePermanentlyButton=element(by.buttonText('Delete 
Permanently'));
+       // delivery service static dns entry fields
+       
this.viewCapabilitiesMenuItem=element(by.css('a[ng-click*=viewCapabilities]'));
+       this.addStaticDNSBtn=element(by.name('addStaticDNSBtn'));
+       this.host=element(by.name('host'));
+       this.staticDNStypeId=element(by.name('typeId'));
+       this.ttl=element(by.name('ttl'));
+       this.address=element(by.name('address'));
 };
\ No newline at end of file
diff --git a/traffic_portal/test/end_to_end/servers/servers-spec.js 
b/traffic_portal/test/end_to_end/servers/servers-spec.js
index 218d4bb..a8cc41e 100644
--- a/traffic_portal/test/end_to_end/servers/servers-spec.js
+++ b/traffic_portal/test/end_to_end/servers/servers-spec.js
@@ -34,7 +34,7 @@ describe('Traffic Portal Servers Test Suite', function() {
        };
 
        it('should go to the Servers page', function() {
-               console.log('Looading Configure/Servers');
+               console.log('Loading Configure/Servers');
                browser.setLocation("servers");
                
expect(browser.getCurrentUrl().then(commonFunctions.urlPath)).toEqual(commonFunctions.urlPath(browser.baseUrl)+"#!/servers");
        });
@@ -78,7 +78,7 @@ describe('Traffic Portal Servers Test Suite', function() {
        it('should verify the new Server and then update Server', function() {
                console.log('Verifying new server added and updating ' + 
mockVals.hostName);
                browser.sleep(1000);
-               element(by.cssContainingText('.ag-cell', 
mockVals.hostName)).click()
+               element(by.cssContainingText('.ag-cell', 
mockVals.hostName)).click();
                browser.sleep(1000);
                pageData.domainName.clear();
                pageData.domainName.sendKeys('testupdated.com');

Reply via email to