blob: 3c14f0d319c58dfa46925f5c3dbc9094cd98574d [file] [log] [blame]
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<div class="x_panel">
<div class="x_title">
<ol class="breadcrumb pull-left">
<li ng-if="!settings.isRequest"><a ng-click="navigateToPath('/delivery-services')">Delivery Services</a></li>
<li ng-if="settings.isRequest"><a ng-click="navigateToPath('/delivery-service-requests')">Delivery Service Requests</a></li>
<li ng-if="settings.isRequest" class="active">{{dsRequest.changeType}}</li>
<li class="active">{{deliveryServiceName}}</li>
</ol>
<div class="pull-right" role="group" ng-if="settings.isRequest">
<div class="btn-group" role="group" uib-dropdown is-open="status.isopen">
<button ng-disabled="dsRequest.status == 'rejected' || dsRequest.status == 'pending' || dsRequest.status == 'complete'" type="button" class="btn btn-link dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
{{dsRequest.status | uppercase }}&nbsp;
<span ng-show="dsRequest.status == 'draft' || dsRequest.status == 'submitted'" class="caret"></span>
</button>
<ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
<li role="menuitem"><a ng-if="dsRequest.status == 'submitted'" ng-click="editStatus('draft')">Change status to: DRAFT</a></li>
<li role="menuitem"><a ng-if="dsRequest.status == 'draft'" ng-click="editStatus('submitted')">Change status to: SUBMITTED</a></li>
</ul>
</div>
</div>
<div class="pull-right" role="group">
<button type="button" class="btn btn-danger" ng-if="!settings.isNew && !settings.isRequest" ng-disabled="!deletable()" ng-click="confirmDelete(deliveryService)">{{settings.deleteLabel}}</button>
<button class="btn btn-success" ng-if="!settings.isRequest" ng-disabled="deliveryServiceForm.$pristine || deliveryServiceForm.$invalid || !saveable()" ng-click="save(deliveryService)">{{settings.saveLabel}}</button>
<button type="button" class="btn btn-primary" ng-if="!settings.isRequest && !settings.isNew" title="Delivery Service Charts" ng-if="showChartsButton" ng-click="openCharts(deliveryService)"><i class="fa fa-bar-chart fa-fw"></i></button>
<div class="btn-group" ng-if="!settings.isRequest && !settings.isNew" role="group" uib-dropdown is-open="more.isopen">
<button name="moreBtn" type="button" class="btn btn-default dropdown-toggle" uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
More&nbsp;
<span class="caret"></span>
</button>
<ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
<li role="menuitem"><a ng-click="clone(deliveryService)">Clone Delivery Service</a></li>
<hr class="divider"/>
<li role="menuitem"><a ng-click="viewCharts()">View Charts</a></li>
<hr class="divider"/>
<li role="menuitem"><a ng-click="viewJobs()">Manage Invalidation Requests</a></li>
<li role="menuitem"><a ng-click="viewRegexes()">Manage Regexes</a></li>
<li role="menuitem"><a ng-click="viewCapabilities()">Manage Required Server Capabilities</a></li>
<li role="menuitem"><a ng-click="viewServers()">Manage Servers</a></li>
<li role="menuitem"><a ng-click="viewStaticDnsEntries()">Manage Static DNS Entries</a></li>
</ul>
</div>
</div>
<div class="clearfix"></div>
</div>
<div class="x_content">
<div id="deliveryServiceURLs">
<fieldset ng-if="!settings.isNew && !settings.isRequest">
<legend>Delivery Service URL(s)</legend>
<p ng-repeat="url in deliveryService.exampleURLs"><a href="{{::url}}" target="_blank">{{::url}}</a> </p>
</fieldset>
</div>
<form id="deliveryServiceForm" name="deliveryServiceForm" class="form-horizontal form-label-left">
<fieldset>
<legend ng-class="{'fieldset-error': generalConfig.$invalid}" ng-click="showGeneralConfig = !showGeneralConfig">General Configuration Settings <i class="fa" ng-class="showGeneralConfig ? 'fa-caret-down' : 'fa-caret-up'"></i></legend>
<ng-form name="generalConfig" ng-show="showGeneralConfig">
<div class="form-group" ng-class="{'has-error': hasError(generalConfig.xmlId), 'has-feedback': hasError(generalConfig.xmlId)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="xmlId">XML_ID (Key) *<div class="helptooltip">
<div class="helptext">This id becomes a part of the CDN service domain in the form <samp>http://cdn.service-key.company.com/</samp>. Must be all lowercase, no spaces or special characters. May contain dashes.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<input id="xmlId" name="xmlId" type="text" class="form-control" placeholder="Unique id used for the delivery service" ng-model="deliveryService.xmlId" required maxlength="48" pattern="[a-z0-9]([a-z0-9\-]*[a-z0-9])?" ng-readonly="(!settings.isRequest && !settings.isNew) || (settings.isRequest && changeType == 'update')">
<small class="input-error" ng-show="hasPropertyError(generalConfig.xmlId, 'required')">Required</small>
<small class="input-error" ng-show="hasPropertyError(generalConfig.xmlId, 'maxlength')">Too Long</small>
<small class="input-error" ng-show="hasPropertyError(generalConfig.xmlId, 'pattern')">Must be a valid DNS label (no special characters, capital letters, periods, underscores, or spaces and cannot begin or end with a hyphen)</small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.xmlId != dsCurrent.xmlId">
<h3>Current Value</h3>
<pre>{{::dsCurrent.xmlId}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(generalConfig.displayName), 'has-feedback': hasError(generalConfig.displayName)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="displayName">Display Name *<div class="helptooltip">
<div class="helptext">Name of the service that appears in the Traffic portal. No character restrictions.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<input id="displayName" name="displayName" type="text" class="form-control" ng-model="deliveryService.displayName" maxlength="48" required>
<small class="input-error" ng-show="hasPropertyError(generalConfig.displayName, 'required')">Required</small>
<small class="input-error" ng-show="hasPropertyError(generalConfig.displayName, 'maxlength')">Too Long</small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.displayName != dsCurrent.displayName">
<h3>Current Value</h3>
<pre>{{::dsCurrent.displayName}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(generalConfig.active), 'has-feedback': hasError(generalConfig.active)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="active">Active *<div class="helptooltip">
<div class="helptext">Whether or not this Delivery Service is active on the CDN and is capable of traffic.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<select id="active" name="active" class="form-control" ng-model="deliveryService.active" required>
<option disabled hidden value="">Select...</option>
<option ng-value="true">Active</option>
<option ng-value="false">Not Active</option>
</select>
<small class="input-error" ng-show="hasPropertyError(generalConfig.active, 'required')">Required</small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.active != dsCurrent.active">
<h3>Current Value</h3>
<pre>{{::dsCurrent.active ? 'Active' : 'Not Active'}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(generalConfig.type), 'has-feedback': hasError(generalConfig.type)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="type">Content Routing Type *<div class="helptooltip">
<div class="helptext">
DNS is the standard routing type for most CDN services. HTTP Redirect is a specialty routing service that is primarily used for video and large file downloads where localization and latency are significant concerns. A "Live" routing type should be used for all live services.
<br>
<br>
<a href="https://traffic-control-cdn.readthedocs.io/en/latest/overview/delivery_services.html#ds-types" target="_blank">See Delivery Service Types.</a>
</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<select id="type" name="type" class="form-control" ng-model="deliveryService.typeId" ng-options="type.id as type.name for type in types" required>
<option selected disabled hidden value="">Select...</option>
</select>
<small class="input-error" ng-show="hasPropertyError(generalConfig.type, 'required')">Required</small>
<small ng-show="deliveryService.typeId"><a href="/#!/types/{{deliveryService.typeId}}" target="_blank">View Details&nbsp;&nbsp;<i class="fa fs-xs fa-external-link"></i></a></small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.typeId != dsCurrent.typeId">
<h3>Current Value</h3>
<pre>{{::dsCurrent.type}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(generalConfig.tenantId), 'has-feedback': hasError(generalConfig.tenantId)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="tenantId">Tenant *<div class="helptooltip">
<div class="helptext">Name of company or division of company who owns account. Allows you to group your services and control access. Tenants are setup as a simple hierarchy where you may create parent / child accounts.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<select id="tenantId" name="tenantId" class="form-control" ng-model="deliveryService.tenantId" ng-options="tenant.id as tenantLabel(tenant) for tenant in tenants" required>
<option disabled hidden selected value="">Select...</option>
</select>
<small class="input-error" ng-show="hasPropertyError(generalConfig.tenantId, 'required')">Required</small>
<small ng-show="deliveryService.tenantId"><a href="/#!/tenants/{{deliveryService.tenantId}}" target="_blank">View Details&nbsp;&nbsp;<i class="fa fs-xs fa-external-link"></i></a></small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.tenantId != dsCurrent.tenantId">
<h3>Current Value</h3>
<pre>{{::dsCurrent.tenant}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(generalConfig.cdn), 'has-feedback': hasError(generalConfig.cdn)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="cdn">CDN *<div class="helptooltip">
<div class="helptext">The CDN to which the Delivery Service belongs.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<select id="cdn" name="cdn" class="form-control" ng-model="deliveryService.cdnId" ng-options="cdn.id as cdn.name for cdn in cdns" required>
<option hidden disabled selected value="">Select...</option>
</select>
<small class="input-error" ng-show="hasPropertyError(generalConfig.cdnId, 'required')">Required</small>
<small ng-show="deliveryService.cdnId"><a href="/#!/cdns/{{deliveryService.cdnId}}" target="_blank">View Details&nbsp;&nbsp;<i class="fa fs-xs fa-external-link"></i></a></small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.cdnId != dsCurrent.cdnId">
<h3>Current Value</h3>
<pre>{{::dsCurrent.cdnName}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(generalConfig.longDesc), 'has-feedback': hasError(generalConfig.longDesc)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="longDesc">Long Description 1<div class="helptooltip">
<div class="helptext">Free text field not currently used in configuration.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<textarea id="longDesc" name="longDesc" class="form-control" ng-model="deliveryService.longDesc" spellcheck="true" rows="3"></textarea>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.longDesc != dsCurrent.longDesc">
<h3>Current Value</h3>
<pre>{{::dsCurrent.longDesc}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(generalConfig.longDesc1), 'has-feedback': hasError(generalConfig.longDesc1)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="longDesc1">Long Description 2<div class="helptooltip">
<div class="helptext">Free text field not currently used in configuration.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<textarea id="longDesc1" name="longDesc1" class="form-control" ng-model="deliveryService.longDesc1" spellcheck="true" rows="3"></textarea>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.longDesc1 != dsCurrent.longDesc1">
<h3>Current Value</h3>
<pre>{{::dsCurrent.longDesc1}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(generalConfig.longDesc2), 'has-feedback': hasError(generalConfig.longDesc2)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12">Long Description 3<div class="helptooltip">
<div class="helptext">Free text field not currently used in configuration.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<textarea id="longDesc2" name="longDesc2" class="form-control" ng-model="deliveryService.longDesc2" rows="3" spellcheck="true"></textarea>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.longDesc2 != dsCurrent.longDesc2">
<h3>Current Value</h3>
<pre>{{::dsCurrent.longDesc2}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(generalConfig.profile), 'has-feedback': hasError(generalConfig.profile)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="profile">Profile<div class="helptooltip">
<div class="helptext">Only used if a Delivery Service uses configurations that specifically require a profile. Example: Multi-Site Origin configurations would require a Delivery Service Profile to be used.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<select id="profile" name="profile" class="form-control" ng-model="deliveryService.profileId" ng-options="profile.id as profile.name for profile in profiles">
<option selected value="">None</option>
</select>
<small ng-show="deliveryService.profileId"><a href="/#!/profiles/{{deliveryService.profileId}}" target="_blank">View Details&nbsp;&nbsp;<i class="fa fs-xs fa-external-link"></i></a></small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.profileId != dsCurrent.profileId">
<h3>Current Value</h3>
<pre>{{::dsCurrent.profileName}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(generalConfig.infoUrl), 'has-feedback': hasError(generalConfig.infoUrl)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="infoUrl">Info URL<div class="helptooltip">
<div class="helptext">Free text field used to enter a URL which provides information about the service.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<input id="infoUrl" name="infoUrl" type="url" title="Must be a valid URL." class="form-control" ng-model="deliveryService.infoUrl" maxlength="255">
<small class="input-error invalid-URL-error">Invalid URL</small>
<small class="input-error" ng-show="hasPropertyError(generalConfig.infoUrl, 'maxlength')">Too Long</small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.infoUrl != dsCurrent.infoUrl">
<h3>Current Value</h3>
<pre>{{::dsCurrent.infoUrl}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(generalConfig.checkPath), 'has-feedback': hasError(generalConfig.checkPath)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="checkPath">Check Path<div class="helptooltip">
<div class="helptext">A path (e.g. <samp>/crossdomain.xml</samp>) with which to verify the connection to the origin server. This can be used by Check Extension scripts to do periodic health checks against the Delivery Service.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<input id="checkPath" name="checkPath" type="text" class="form-control" ng-model="deliveryService.checkPath" maxlength="255">
<small class="input-error" ng-show="hasPropertyError(generalConfig.checkPath, 'maxlength')">Too Long</small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.checkPath != dsCurrent.checkPath">
<h3>Current Value</h3>
<pre>{{::dsCurrent.checkPath}}</pre>
</aside>
</div>
</div>
</ng-form>
</fieldset>
<fieldset>
<legend ng-class="{'fieldset-error': cacheConfig.$invalid}" ng-click="showCacheConfig = !showCacheConfig">Cache Configuration Settings <i class="fa" ng-class="showCacheConfig ? 'fa-caret-down' : 'fa-caret-up'"></i></legend>
<ng-form name="cacheConfig" ng-show="showCacheConfig">
<div class="form-group" ng-class="{'has-error': hasError(cacheConfig.remapText), 'has-feedback': hasError(cacheConfig.remapText)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="remapText">Raw remap text<div class="helptooltip">
<div class="helptext">For HTTP and DNS Delivery Services, this will get added to the end of the remap line verbatim on cache servers. For ANY_MAP Delivery Services this is the entire remap line.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<textarea id="remapText" name="remapText" class="form-control" ng-model="deliveryService.remapText" ng-pattern="/^[^\n\r]*$/" rows="3" required></textarea>
<small class="input-error" ng-show="hasPropertyError(cacheConfig.remapText, 'pattern')">No Line Breaks</small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.remapText != dsCurrent.remapText">
<h3>Current Value</h3>
<pre>{{::dsCurrent.remapText}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(cacheConfig.cacheurl), 'has-feedback': hasError(cacheConfig.cacheurl)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="cacheurl">Cache URL Expression<div class="helptooltip">
<div class="helptext">
Allows you to manipulate the cache key of the incoming requests. Normally, the cache key is the origin domain. This can be changed so that multiple services can share a cache key, can also be used to preserve cached content if service origin is changed.
<br>
<aside>
<h6>Note</h6>
<p>This only works with Edge-tier cache servers running <abbr title="Apache Traffic Server">ATS</abbr> version 6 and earlier. This <em>must</em> be empty if using <abbr title="Apache Traffic Server">ATS</abbr> 7 and / or the <a href="https://docs.trafficserver.apache.org/en/7.1.x/admin-guide/plugins/cachekey.en.html" target="_blank">cachekey plugin.</a></p>
<br>
<br>
See <a href="https://docs.trafficserver.apache.org/en/6.2.x/admin-guide/plugins/cacheurl.en.html" target="_blank">ATS documentation on cacheurl</a>
</aside>
<aside class="warning">
<h6>Warning</h6>
<p>This field is deprecated, and is subject to removal in upcoming releases. It is recommended that this be left blank.</p>
</aside>
</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<input id="cacheurl" name="cacheurl" type="text" class="form-control" ng-model="deliveryService.cacheurl" maxlength="1024">
<small class="input-error" ng-show="hasPropertyError(cacheConfig.cacheurl, 'maxlength')">Too Long</small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.cacheurl != dsCurrent.cacheurl">
<h3>Current Value</h3>
<pre>{{::dsCurrent.cacheurl}}</pre>
</aside>
</div>
</div>
</ng-form>
</fieldset>
<fieldset>
<legend ng-class="{'fieldset-error': routingConfig.$invalid}" ng-click="showRoutingConfig = !showRoutingConfig">Routing Configuration Settings <i class="fa" ng-class="showRoutingConfig ? 'fa-caret-down' : 'fa-caret-up'"></i></legend>
<ng-form name="routingConfig" ng-show="showRoutingConfig">
<div class="form-group" ng-class="{'has-error': hasError(routingConfig.regionalGeoBlocking), 'has-feedback': hasError(routingConfig.regionalGeoBlocking)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="regionalGeoBlocking">Regional Geoblocking *<div class="helptooltip">
<div class="helptext">
Define regional geo-blocking rules for Delivery Services in a JSON format and set this to 'Enabled' to use "Regional Geoblocking". <a href="https://traffic-control-cdn.readthedocs.io/en/latest/admin/quick_howto/regionalgeo.html" target="_blank">See Regional Geo-blocking</a>
</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<select id="regionalGeoBlocking" name="regionalGeoBlocking" class="form-control" ng-model="deliveryService.regionalGeoBlocking" required>
<option ng-value="true">Enabled</option>
<option ng-value="false" selected>Disabled</option>
</select>
<small class="input-error" ng-show="hasPropertyError(routingConfig.regionalGeoBlocking, 'required')">Required</small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.regionalGeoBlocking != dsCurrent.regionalGeoBlocking">
<h3>Current Value</h3>
<pre>{{::dsCurrent.regionalGeoBlocking ? 'Enabled' : 'Disabled'}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(routingConfig.geoProvider), 'has-feedback': hasError(routingConfig.geoProvider)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="geoProvider">Geolocation Provider *<div class="helptooltip">
<div class="helptext">Choose which Geolocation database provider - company that collects data on the location of IP addresses - to use.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<select id="geoProvider" name="geoProvider" class="form-control" ng-model="deliveryService.geoProvider" required>
<option ng-value="0" selected>MaxMind</option>
<option ng-value="1">Neustar</option>
</select>
<small class="input-error" ng-show="hasPropertyError(routingConfig.geoProvider, 'required')">Required</small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.geoProvider != dsCurrent.geoProvider">
<h3>Current Value</h3>
<pre>{{magicNumberLabel(geoProviders, dsCurrent.geoProvider)}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(routingConfig.geoLimit), 'has-feedback': hasError(routingConfig.geoLimit)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="geoLimit">Geo Limit *<div class="helptooltip">
<div class="helptext">
Some services are intended to be limited by geography. The possible settings are:
<br>
<br>
<dl>
<dt>None</dt><dd>Do not limit by geography.</dd>
<dt>Coverage Zone File only</dt><dd>If the requesting IP is not in the Coverage Zone File, do not serve the request.</dd>
<dt>Coverage Zone File and Country Code(s)</dt><dd>If the requesting IP is not in the Coverage Zone File or not in the United States, do not serve the request.</dd>
</dl>
</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<select id="geoLimit" name="geoLimit" class="form-control" ng-model="deliveryService.geoLimit" required>
<option ng-value="0" selected>None</option>
<option ng-value="1">Coverage Zone File only</option>
<option ng-value="2">Coverage Zone File and Country Code(s)</option>
</select>
<small class="input-error" ng-show="hasPropertyError(routingConfig.geoLimit, 'required')">Required</small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.geoLimit != dsCurrent.geoLimit">
<h3>Current Value</h3>
<pre>{{magicNumberLabel(geoLimits, dsCurrent.geoLimit)}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(routingConfig.geoLimitCountries), 'has-feedback': hasError(routingConfig.geoLimitCountries)}" ng-show="deliveryService.geoLimit === 1 || deliveryService.geoLimit === 2">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="geoLimitCountries">Geo Limit Countries<div class="helptooltip">
<div class="helptext">How (if at all) is this service to be limited by geography. Example Country Codes: <abbr title="Canada">CA</abbr>, <abbr title="India">IN</abbr>, <abbr title="Puerto Rico">PR</abbr>.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<input id="geoLimitCountries" name="geoLimitCountries" type="text" class="form-control" ng-model="deliveryService.geoLimitCountries" maxlength="255" pattern="[A-Z]+(,[A-Z]+)*">
<small class="input-error" ng-show="hasPropertyError(routingConfig.geoLimitCountries, 'maxlength')">Too Long</small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.geoLimitCountries != dsCurrent.geoLimitCountries">
<h3>Current Value</h3>
<pre>{{::dsCurrent.geoLimitCountries}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(routingConfig.geoLimitRedirectURL), 'has-feedback': hasError(routingConfig.geoLimitRedirectURL)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="geoLimitRedirectURL">Geo Limit Redirect URL<div class="helptooltip">
<div class="helptext">
Traffic Router will redirect to this URL when Geo Limit check fails.
<br>
<br>
See <a href="https://traffic-control-cdn.readthedocs.io/en/latest/admin/traffic_router.html#tr-ngb" target="_blank">GeoLimit Failure Redirect</a> feature...
</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<input id="geoLimitRedirectURL" name="geoLimitRedirectURL" title="Must be a valid URL" type="url" class="form-control" ng-model="deliveryService.geoLimitRedirectURL">
<small class="input-error invalid-URL-error">Invalid URL</small>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.geoLimitRedirectURL != dsCurrent.geoLimitRedirectURL">
<h3>Current Value</h3>
<pre>{{::dsCurrent.geoLimitRedirectURL}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(routingConfig.ccrDnsTtl), 'has-feedback': hasError(routingConfig.ccrDnsTtl)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="ccrDnsTtl">Delivery Service DNS TTL<div class="helptooltip">
<div class="helptext">The <abbr title="Time To Live">TTL</abbr> on the DNS record for the Traffic Router A and AAAA records. Setting too high or too low will result in poor caching performance.</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<input id="ccrDnsTtl" name="ccrDnsTtl" type="number" class="form-control" ng-model="deliveryService.ccrDnsTtl" step="1" min="0">
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.ccrDnsTtl != dsCurrent.ccrDnsTtl">
<h3>Current Value</h3>
<pre>{{::dsCurrent.ccrDnsTtl}}</pre>
</aside>
</div>
</div>
<div class="form-group" ng-class="{'has-error': hasError(routingConfig.trRequestHeaders), 'has-feedback': hasError(routingConfig.trRequestHeaders)}">
<label class="has-tooltip control-label col-md-2 col-sm-2 col-xs-12" for="trRequestHeaders">Traffic Router Log Request Headers<div class="helptooltip">
<div class="helptext">
List of header keys. One header key per line. Listed headers will be included in Traffic Router access log entries under the <samp>rh=</samp> token.
</div>
</div>
</label>
<div class="col-md-10 col-sm-10 col-xs-12">
<textarea id="trRequestHeaders" name="trRequestHeaders" class="form-control" ng-model="deliveryService.trRequestHeaders" rows="3"></textarea>
<aside class="current-value" ng-if="settings.isRequest" ng-show="open() && deliveryService.trRequestHeaders != dsCurrent.trRequestHeaders">
<h3>Current Value</h3>
<pre>{{::dsCurrent.trRequestHeaders}}</pre>
</aside>
</div>
</div>
</ng-form>
</fieldset>
<div class="modal-footer">
<button type="button" class="btn btn-danger" ng-if="!settings.isNew" ng-disabled="!deletable()" ng-click="confirmDelete(deliveryService)">{{settings.deleteLabel}}</button>
<button class="btn btn-success" ng-disabled="deliveryServiceForm.$pristine || deliveryServiceForm.$invalid || !saveable()" ng-click="save(deliveryService)">{{settings.saveLabel}}</button>
<button class="btn btn-primary" ng-if="settings.isRequest && fulfillable()" ng-disabled="deliveryServiceForm.$invalid" ng-click="fulfillRequest(deliveryService)">Fulfill Request</button>
</div>
</form>
</div>
</div>