This is an automated email from the ASF dual-hosted git repository.
ocket8888 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 79a1b24 Geo limit countries can now be parsed as an array and a
string (#6441)
79a1b24 is described below
commit 79a1b24cb8f0c426dd2310cc9355115f09a4c4db
Author: Srijeet Chatterjee <[email protected]>
AuthorDate: Mon Jan 24 19:47:58 2022 -0700
Geo limit countries can now be parsed as an array and a string (#6441)
* Parse Geo Limit as a string as well as an array
* changelog entry
* change sanitize method
* remove npe
* adding validations and tests
* formatting changes, error msgs changed
* adding some more checks
* code review fixes
* fix test
* code review changes
* remove unneeded code
* address code review
* fix tests, go vet
* go fmt
* code review fixes
* code review changes
---
CHANGELOG.md | 1 +
cache-config/t3c-generate/cfgfile/cfgfile_test.go | 2 +-
docs/source/api/v4/deliveryservices.rst | 6 +-
docs/source/api/v4/deliveryservices_id.rst | 4 +-
docs/source/api/v4/deliveryservices_id_safe.rst | 2 +-
docs/source/api/v4/servers_id_deliveryservices.rst | 2 +-
docs/source/overview/delivery_services.rst | 2 +-
lib/go-tc/deliveryservices.go | 50 ++++++++++++-
lib/go-tc/deliveryservices_test.go | 9 ++-
.../testing/api/v4/deliveryservices_test.go | 62 ++++++++++++++++
.../crconfig/deliveryservice_test.go | 82 ++++++++++++++++++++--
.../deliveryservice/deliveryservices.go | 48 ++++++++++---
traffic_ops/v4-client/server.go | 4 +-
13 files changed, 246 insertions(+), 28 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4aa1f36..6091b7d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -53,6 +53,7 @@ The format is based on [Keep a
Changelog](http://keepachangelog.com/en/1.0.0/).
### Changed
- Updated `t3c` to request less unnecessary deliveryservice-server assignment
and invalidation jobs data via new query params supported by Traffic Ops
- [#6179](https://github.com/apache/trafficcontrol/issues/6179) Updated the
Traffic Ops rpm to include the `ToDnssecRefresh` binary and make the
`trafops_dnssec_refresh` cron job use it
+- [#6382](https://github.com/apache/trafficcontrol/issues/6382) Accept Geo
Limit Countries as strings and arrays.
- Traffic Portal no longer uses `ruby compass` to compile sass and now uses
`dart-sass`.
- Changed Invalidation Jobs throughout (TO, TP, T3C, etc.) to account for the
ability to do both REFRESH and REFETCH requests for resources.
- Changed the `maxConnections` value on Traffic Router, to prevent the
thundering herd problem (TR).
diff --git a/cache-config/t3c-generate/cfgfile/cfgfile_test.go
b/cache-config/t3c-generate/cfgfile/cfgfile_test.go
index 2864753..60817f2 100644
--- a/cache-config/t3c-generate/cfgfile/cfgfile_test.go
+++ b/cache-config/t3c-generate/cfgfile/cfgfile_test.go
@@ -214,7 +214,7 @@ func randDS() *atscfg.DeliveryService {
ds.DSCP = randInt()
ds.EdgeHeaderRewrite = randStr()
ds.GeoLimit = randInt()
- ds.GeoLimitCountries = randStr()
+ ds.GeoLimitCountries = nil
ds.GeoLimitRedirectURL = randStr()
ds.GeoProvider = randInt()
ds.GlobalMaxMBPS = randInt()
diff --git a/docs/source/api/v4/deliveryservices.rst
b/docs/source/api/v4/deliveryservices.rst
index c4bdaeb..9996bcf 100644
--- a/docs/source/api/v4/deliveryservices.rst
+++ b/docs/source/api/v4/deliveryservices.rst
@@ -104,7 +104,7 @@ Response Structure
:firstHeaderRewrite: A set of :ref:`ds-first-header-rw-rules`
:fqPacingRate: The :ref:`ds-fqpr`
:geoLimit: An integer that defines the :ref:`ds-geo-limit`
-:geoLimitCountries: A string containing a comma-separated list
defining the :ref:`ds-geo-limit-countries`
+:geoLimitCountries: An array of strings defining the
:ref:`ds-geo-limit-countries`
:geoLimitRedirectUrl: A :ref:`ds-geo-limit-redirect-url`
:geoProvider: The :ref:`ds-geo-provider`
:globalMaxMbps: The :ref:`ds-global-max-mbps`
@@ -296,7 +296,7 @@ Request Structure
:firstHeaderRewrite: A set of :ref:`ds-first-header-rw-rules`
:fqPacingRate: The :ref:`ds-fqpr`
:geoLimit: An integer that defines the :ref:`ds-geo-limit`
-:geoLimitCountries: A string containing a comma-separated list
defining the :ref:`ds-geo-limit-countries`\ [#geolimit]_
+:geoLimitCountries: A string containing a comma-separated list, or an
array of strings defining the :ref:`ds-geo-limit-countries`\ [#geolimit]_
:geoLimitRedirectUrl: A :ref:`ds-geo-limit-redirect-url`\ [#geolimit]_
:geoProvider: The :ref:`ds-geo-provider`
:globalMaxMbps: The :ref:`ds-global-max-mbps`
@@ -447,7 +447,7 @@ Response Structure
:firstHeaderRewrite: A set of :ref:`ds-first-header-rw-rules`
:fqPacingRate: The :ref:`ds-fqpr`
:geoLimit: An integer that defines the :ref:`ds-geo-limit`
-:geoLimitCountries: A string containing a comma-separated list
defining the :ref:`ds-geo-limit-countries`
+:geoLimitCountries: An array of strings defining the
:ref:`ds-geo-limit-countries`
:geoLimitRedirectUrl: A :ref:`ds-geo-limit-redirect-url`
:geoProvider: The :ref:`ds-geo-provider`
:globalMaxMbps: The :ref:`ds-global-max-mbps`
diff --git a/docs/source/api/v4/deliveryservices_id.rst
b/docs/source/api/v4/deliveryservices_id.rst
index 8223317..3ba01c0 100644
--- a/docs/source/api/v4/deliveryservices_id.rst
+++ b/docs/source/api/v4/deliveryservices_id.rst
@@ -52,7 +52,7 @@ Request Structure
:firstHeaderRewrite: A set of :ref:`ds-first-header-rw-rules`
:fqPacingRate: The :ref:`ds-fqpr`
:geoLimit: An integer that defines the :ref:`ds-geo-limit`
-:geoLimitCountries: A string containing a comma-separated list
defining the :ref:`ds-geo-limit-countries`\ [#geolimit]_
+:geoLimitCountries: A string containing a comma-separated list, or an
array of strings defining the :ref:`ds-geo-limit-countries`\ [#geolimit]_
:geoLimitRedirectUrl: A :ref:`ds-geo-limit-redirect-url`\ [#geolimit]_
:geoProvider: The :ref:`ds-geo-provider`
:globalMaxMbps: The :ref:`ds-global-max-mbps`
@@ -204,7 +204,7 @@ Response Structure
:firstHeaderRewrite: A set of :ref:`ds-first-header-rw-rules`
:fqPacingRate: The :ref:`ds-fqpr`
:geoLimit: An integer that defines the :ref:`ds-geo-limit`
-:geoLimitCountries: A string containing a comma-separated list
defining the :ref:`ds-geo-limit-countries`
+:geoLimitCountries: An array of strings defining the
:ref:`ds-geo-limit-countries`
:geoLimitRedirectUrl: A :ref:`ds-geo-limit-redirect-url`
:geoProvider: The :ref:`ds-geo-provider`
:globalMaxMbps: The :ref:`ds-global-max-mbps`
diff --git a/docs/source/api/v4/deliveryservices_id_safe.rst
b/docs/source/api/v4/deliveryservices_id_safe.rst
index 0501499..c6a529b 100644
--- a/docs/source/api/v4/deliveryservices_id_safe.rst
+++ b/docs/source/api/v4/deliveryservices_id_safe.rst
@@ -83,7 +83,7 @@ Response Structure
:firstHeaderRewrite: A set of :ref:`ds-first-header-rw-rules`
:fqPacingRate: The :ref:`ds-fqpr`
:geoLimit: An integer that defines the :ref:`ds-geo-limit`
-:geoLimitCountries: A string containing a comma-separated list
defining the :ref:`ds-geo-limit-countries`
+:geoLimitCountries: An array of strings defining the
:ref:`ds-geo-limit-countries`
:geoLimitRedirectUrl: A :ref:`ds-geo-limit-redirect-url`
:geoProvider: The :ref:`ds-geo-provider`
:globalMaxMbps: The :ref:`ds-global-max-mbps`
diff --git a/docs/source/api/v4/servers_id_deliveryservices.rst
b/docs/source/api/v4/servers_id_deliveryservices.rst
index 69112b9..a04d7fc 100644
--- a/docs/source/api/v4/servers_id_deliveryservices.rst
+++ b/docs/source/api/v4/servers_id_deliveryservices.rst
@@ -91,7 +91,7 @@ Response Structure
:firstHeaderRewrite: A set of :ref:`ds-first-header-rw-rules`
:fqPacingRate: The :ref:`ds-fqpr`
:geoLimit: An integer that defines the :ref:`ds-geo-limit`
-:geoLimitCountries: A string containing a comma-separated list
defining the :ref:`ds-geo-limit-countries`
+:geoLimitCountries: An array of strings defining the
:ref:`ds-geo-limit-countries`
:geoLimitRedirectUrl: A :ref:`ds-geo-limit-redirect-url`
:geoProvider: The :ref:`ds-geo-provider`
:globalMaxMbps: The :ref:`ds-global-max-mbps`
diff --git a/docs/source/overview/delivery_services.rst
b/docs/source/overview/delivery_services.rst
index 4bc218f..389779a 100644
--- a/docs/source/overview/delivery_services.rst
+++ b/docs/source/overview/delivery_services.rst
@@ -277,7 +277,7 @@ Limits access to a Delivery Service by geographic location.
The only practical d
Geo Limit Countries
-------------------
-When `Geo Limit`_ is being used with this Delivery Service (and is set to
exactly ``2``), this is optionally a list of country codes to which access to
content provided by the Delivery Service will be restricted. Normally, this is
a comma-delimited string of said country codes. When creating a Delivery
Service with this field or modifying the Geo Limit Countries field on an
existing Delivery Service, any amount of whitespace between country codes is
permissible, as it will be removed on [...]
+When `Geo Limit`_ is being used with this Delivery Service (and is set to
exactly ``2``), this is optionally a list of country codes to which access to
content provided by the Delivery Service will be restricted. Normally, this is
a comma-delimited string of said country codes, or an array of strings
representing the country codes. When creating a Delivery Service with this
field or modifying the Geo Limit Countries field on an existing Delivery
Service, any amount of whitespace between [...]
.. table:: Aliases
diff --git a/lib/go-tc/deliveryservices.go b/lib/go-tc/deliveryservices.go
index 6e729af..4462a27 100644
--- a/lib/go-tc/deliveryservices.go
+++ b/lib/go-tc/deliveryservices.go
@@ -245,7 +245,8 @@ type DeliveryServiceV40 struct {
// TLSVersions is the list of explicitly supported TLS versions for
cache
// servers serving the Delivery Service's content.
- TLSVersions []string `json:"tlsVersions" db:"tls_versions"`
+ TLSVersions []string `json:"tlsVersions"
db:"tls_versions"`
+ GeoLimitCountries GeoLimitCountriesType `json:"geoLimitCountries"`
}
// DeliveryServiceV4 is a Delivery Service as it appears in version 4 of the
@@ -577,6 +578,40 @@ type DeliveryServiceNullableV11 struct {
DeliveryServiceRemovedFieldsV11
}
+// GeoLimitCountriesType is the type alias that is used to represent the
GeoLimitCountries attribute of the DeliveryService struct.
+type GeoLimitCountriesType []string
+
+// UnmarshalJSON will unmarshal a byte slice into type GeoLimitCountriesType.
+func (g *GeoLimitCountriesType) UnmarshalJSON(data []byte) error {
+ var err error
+ var initial = make([]string, 0)
+ var initialStr string
+ if err = json.Unmarshal(data, &initial); err != nil {
+ if err = json.Unmarshal(data, &initialStr); err != nil {
+ return err
+ }
+ if strings.Contains(initialStr, ",") {
+ initial = strings.Split(initialStr, ",")
+ } else {
+ initial = append(initial, initialStr)
+ }
+ }
+
+ if initial == nil || len(initial) == 0 {
+ g = nil
+ return nil
+ }
+ *g = initial
+ return nil
+
+}
+
+// MarshalJSON will marshal a GeoLimitCountriesType into a byte slice.
+func (g GeoLimitCountriesType) MarshalJSON() ([]byte, error) {
+ arr := ([]string)(g)
+ return json.Marshal(arr)
+}
+
// DeliveryServiceNullableFieldsV11 contains properties that Delivery Services
// as they appeared in Traffic Ops API v1.1 had, AND were not removed by ANY
// later API version.
@@ -813,6 +848,10 @@ func (ds *DeliveryServiceV4) RemoveLD1AndLD2()
DeliveryServiceV4 {
// DowngradeToV3 converts the 4.x DS to a 3.x DS.
func (ds *DeliveryServiceV4) DowngradeToV3() DeliveryServiceNullableV30 {
+ nullableFields := ds.DeliveryServiceNullableFieldsV11
+ geoLimitCountries := ([]string)(ds.GeoLimitCountries)
+ geo := strings.Join(geoLimitCountries, ",")
+ nullableFields.GeoLimitCountries = &geo
return DeliveryServiceNullableV30{
DeliveryServiceV30: DeliveryServiceV30{
DeliveryServiceNullableV15: DeliveryServiceNullableV15{
@@ -820,7 +859,7 @@ func (ds *DeliveryServiceV4) DowngradeToV3()
DeliveryServiceNullableV30 {
DeliveryServiceNullableV13:
DeliveryServiceNullableV13{
DeliveryServiceNullableV12:
DeliveryServiceNullableV12{
DeliveryServiceNullableV11: DeliveryServiceNullableV11{
-
DeliveryServiceNullableFieldsV11: ds.DeliveryServiceNullableFieldsV11,
+
DeliveryServiceNullableFieldsV11: nullableFields,
},
},
DeliveryServiceFieldsV13:
ds.DeliveryServiceFieldsV13,
@@ -837,6 +876,12 @@ func (ds *DeliveryServiceV4) DowngradeToV3()
DeliveryServiceNullableV30 {
// UpgradeToV4 converts the 3.x DS to a 4.x DS.
func (ds *DeliveryServiceNullableV30) UpgradeToV4() DeliveryServiceV4 {
+ var geo GeoLimitCountriesType
+ if ds.GeoLimitCountries != nil {
+ str := *ds.GeoLimitCountries
+ geo = make([]string, 0)
+ geo = strings.Split(str, ",")
+ }
return DeliveryServiceV4{
DeliveryServiceFieldsV31: ds.DeliveryServiceFieldsV31,
DeliveryServiceFieldsV30: ds.DeliveryServiceFieldsV30,
@@ -845,6 +890,7 @@ func (ds *DeliveryServiceNullableV30) UpgradeToV4()
DeliveryServiceV4 {
DeliveryServiceFieldsV13: ds.DeliveryServiceFieldsV13,
DeliveryServiceNullableFieldsV11:
ds.DeliveryServiceNullableFieldsV11,
TLSVersions: nil,
+ GeoLimitCountries: geo,
}
}
diff --git a/lib/go-tc/deliveryservices_test.go
b/lib/go-tc/deliveryservices_test.go
index 3ba0f6a..8491ed3 100644
--- a/lib/go-tc/deliveryservices_test.go
+++ b/lib/go-tc/deliveryservices_test.go
@@ -16,6 +16,7 @@ package tc
import (
"fmt"
+ "strings"
"testing"
)
@@ -412,7 +413,9 @@ func dsUpgradeAndDowngradeTestingPair()
(DeliveryServiceNullableV30, DeliverySer
firstHeaderRewrite := "firstHeaderRewrite"
fqPacingRate := 1337
geoLimit := 2
- geoLimitCountries := "geo,Limit,Countries"
+ geoLimitCountries := []string{"geo", "Limit", "Countries"}
+ geo := (GeoLimitCountriesType)(geoLimitCountries)
+ geoStr := strings.Join(geoLimitCountries, ",")
geoLimitRedirectURL := "wss://geoLimitRedirectURL"
geoProvider := 1
globalMaxMBPS := -72485
@@ -484,7 +487,7 @@ func dsUpgradeAndDowngradeTestingPair()
(DeliveryServiceNullableV30, DeliverySer
newDS.FirstHeaderRewrite = &firstHeaderRewrite
newDS.FQPacingRate = &fqPacingRate
newDS.GeoLimit = &geoLimit
- newDS.GeoLimitCountries = &geoLimitCountries
+ newDS.GeoLimitCountries = geo
newDS.GeoLimitRedirectURL = &geoLimitRedirectURL
newDS.GeoProvider = &geoProvider
newDS.GlobalMaxMBPS = &globalMaxMBPS
@@ -560,7 +563,7 @@ func dsUpgradeAndDowngradeTestingPair()
(DeliveryServiceNullableV30, DeliverySer
EdgeHeaderRewrite: &edgeHeaderRewrite,
ExampleURLs: exampleURLs,
GeoLimit: &geoLimit,
-
GeoLimitCountries: &geoLimitCountries,
+
GeoLimitCountries: &geoStr,
GeoLimitRedirectURL: &geoLimitRedirectURL,
GeoProvider: &geoProvider,
GlobalMaxMBPS: &globalMaxMBPS,
diff --git a/traffic_ops/testing/api/v4/deliveryservices_test.go
b/traffic_ops/testing/api/v4/deliveryservices_test.go
index 6109921..25b21d9 100644
--- a/traffic_ops/testing/api/v4/deliveryservices_test.go
+++ b/traffic_ops/testing/api/v4/deliveryservices_test.go
@@ -54,6 +54,7 @@ func TestDeliveryServices(t *testing.T) {
t.Run("Create and retrieve SSL keys for a Delivery
Service", DeliveryServiceSSLKeys)
}
+ t.Run("Create a Delivery Service with geo limit countries",
CreateTestDeliveryServiceWithGeoLimitCountries)
t.Run("Create a Delivery Service with the removed Long
Description 2 and 3 fields", CreateTestDeliveryServiceWithLongDescFields)
t.Run("Update a Delivery Service, setting its removed Long
Description 2 and 3 fields", UpdateTestDeliveryServiceWithLongDescFields)
t.Run("Getting unmodified Delivery Services using the
If-Modified-Since header", GetTestDeliveryServicesIMS)
@@ -98,6 +99,67 @@ func TestDeliveryServices(t *testing.T) {
})
}
+func CreateTestDeliveryServiceWithGeoLimitCountries(t *testing.T) {
+
+ if len(testData.DeliveryServices) == 0 {
+ t.Fatalf("no deliveryservices to run the test on, quitting")
+ }
+
+ cdn := createBlankCDN("geoLimitCDN", t)
+ opts := client.NewRequestOptions()
+ opts.QueryParameters.Set("name", "HTTP")
+ types, _, err := TOSession.GetTypes(opts)
+ if err != nil {
+ t.Fatalf("unable to get Types: %v - alerts: %+v", err,
types.Alerts)
+ }
+ if len(types.Response) < 1 {
+ t.Fatal("expected at least one type")
+ }
+ customDS := getCustomDS(cdn.ID, types.Response[0].ID,
"geo-limit-countries-test-ds-name", "edge", "https://test-geo-limit.com",
"geo-limit-countries-test-ds-xml-id")
+ customDS.Protocol = util.IntPtr(0)
+ customDS.GeoLimit = util.IntPtr(2)
+ //geoLimitCountries := []string{"US ", "CA"}
+ customDS.GeoLimitCountries = []string{"US ", "CA"}
+
+ resp, _, err := TOSession.CreateDeliveryService(customDS,
client.RequestOptions{})
+ if err != nil {
+ t.Errorf("expected no error while creating a new ds, but got
%v", err)
+ }
+ if len(resp.Response) != 1 {
+ t.Fatalf("expected 1 response in return of a create DS request,
but got %d", len(resp.Response))
+ }
+ if resp.Response[0].GeoLimitCountries == nil {
+ t.Fatalf("got nothing in geo limit countries")
+ }
+ arr := ([]string)(resp.Response[0].GeoLimitCountries)
+ if len(arr) != 2 || arr[0] != "US" || arr[1] != "CA" {
+ t.Errorf("expected geo limit countries: US,CA; actual: %s", arr)
+ }
+ opts = client.NewRequestOptions()
+ opts.QueryParameters.Set("xmlId", *customDS.XMLID)
+ deliveryServices, _, err := TOSession.GetDeliveryServices(opts)
+ if err != nil {
+ t.Fatalf("couldn't get ds: %v", err)
+ }
+ if len(deliveryServices.Response) != 1 {
+ t.Fatal("couldn't get exactly one ds in the response, quitting")
+ }
+ dsID := deliveryServices.Response[0].ID
+ if dsID == nil {
+ t.Fatalf("got a delivery service with no ID")
+ }
+ customDS.GeoLimitCountries = []string{"US ", "CA", "12"}
+ _, _, err = TOSession.UpdateDeliveryService(*dsID, customDS,
client.RequestOptions{})
+ if err == nil {
+ t.Error("expected an error while updating geo limit countries
of a ds with an invalid country code, but got nothing")
+ }
+
+ _, _, err = TOSession.DeleteDeliveryService(*dsID,
client.NewRequestOptions())
+ if err != nil {
+ t.Errorf("expected no error while deleting ds, but got %v", err)
+ }
+}
+
func CUDDeliveryServiceWithLocks(t *testing.T) {
// Create a new user with operations level privileges
user1 := tc.UserV4{
diff --git a/traffic_ops/traffic_ops_golang/crconfig/deliveryservice_test.go
b/traffic_ops/traffic_ops_golang/crconfig/deliveryservice_test.go
index 3904834..5ff78ee 100644
--- a/traffic_ops/traffic_ops_golang/crconfig/deliveryservice_test.go
+++ b/traffic_ops/traffic_ops_golang/crconfig/deliveryservice_test.go
@@ -123,7 +123,11 @@ func ExpectedMakeDSes()
map[string]tc.CRConfigDeliveryService {
}
}
-func MockMakeDSes(mock sqlmock.Sqlmock, expected
map[string]tc.CRConfigDeliveryService, cdn string) {
+func MockMakeDSes(mock sqlmock.Sqlmock, expected
map[string]tc.CRConfigDeliveryService, cdn string, geoEnabled string) {
+ geoLimit := 0
+ if len(geoEnabled) != 0 {
+ geoLimit = 2
+ }
rows := sqlmock.NewRows([]string{
"anonymous_blocking_enabled",
"consistent_hash_regex",
@@ -173,8 +177,8 @@ func MockMakeDSes(mock sqlmock.Sqlmock, expected
map[string]tc.CRConfigDeliveryS
*ds.TTL,
*ds.EcsEnabled,
false,
- 0,
- "",
+ geoLimit,
+ geoEnabled,
"",
0,
*ds.BypassDestination["HTTP"].FQDN,
@@ -195,6 +199,76 @@ func MockMakeDSes(mock sqlmock.Sqlmock, expected
map[string]tc.CRConfigDeliveryS
mock.ExpectQuery("select").WithArgs(cdn).WillReturnRows(rows)
}
+func TestMakeDSesGeoLimit(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub
database connection", err)
+ }
+ defer db.Close()
+
+ cdn := "mycdn"
+ domain := "mycdn.invalid"
+
+ expected := ExpectedMakeDSes()
+ delete(expected, "ds2")
+ expectedDS := expected["ds1"]
+ geoEnabled := make([]tc.CRConfigGeoEnabled, 0)
+ geoEnabledCountry := tc.CRConfigGeoEnabled{CountryCode: "US"}
+ geoEnabled = append(geoEnabled, geoEnabledCountry)
+ geoEnabledCountry = tc.CRConfigGeoEnabled{CountryCode: "CA"}
+ geoEnabled = append(geoEnabled, geoEnabledCountry)
+ expectedDS.GeoEnabled = geoEnabled
+ expected["ds1"] = expectedDS
+
+ expectedParams := ExpectedGetServerProfileParams(expected)
+ expectedDSParams, err := getDSParams(expectedParams)
+ if err != nil {
+ t.Fatalf("getDSParams error expected: nil, actual: %v", err)
+ }
+ expectedMatchsets, expectedDomains :=
ExpectedGetDSRegexesDomains(expectedDSParams)
+ expectedStaticDNSEntries := ExpectedGetStaticDNSEntries(expected)
+
+ mock.ExpectBegin()
+ MockGetServerProfileParams(mock, expectedParams, cdn)
+ MockGetDSRegexesDomains(mock, expectedMatchsets, expectedDomains, cdn)
+ MockGetStaticDNSEntries(mock, expectedStaticDNSEntries, cdn)
+ MockMakeDSes(mock, expected, cdn, "US,CA")
+ mock.ExpectCommit()
+
+ dbCtx, cancelTx := context.WithTimeout(context.TODO(), 10*time.Second)
+ defer cancelTx()
+ tx, err := db.BeginTx(dbCtx, nil)
+ if err != nil {
+ t.Fatalf("creating transaction: %v", err)
+ }
+ defer tx.Commit()
+
+ actual, err := makeDSes(cdn, domain, tx)
+ if err != nil {
+ t.Fatalf("makeDSes expected: nil error, actual: %v", err)
+ }
+
+ if len(actual) != len(expected) {
+ t.Fatalf("makeDses len expected: %v, actual: %v",
len(expected), len(actual))
+ }
+
+ for dsName, ds := range expected {
+ actualDS, ok := actual[dsName]
+ if !ok {
+ t.Errorf("makeDSes expected: %v, actual: missing",
dsName)
+ continue
+ }
+ if len(ds.GeoEnabled) != len(actualDS.GeoEnabled) {
+ t.Fatalf("expected DS Geoenabled length %d != actual DS
Geoenabled length %d", len(ds.GeoEnabled), len(actualDS.GeoEnabled))
+ }
+ for i, countryCode := range ds.GeoEnabled {
+ if countryCode != actualDS.GeoEnabled[i] {
+ t.Errorf("mismatch in geo enabled countries of
expected DS and actual DS, expected: %s, actual: %s", countryCode,
actualDS.GeoEnabled[i])
+ }
+ }
+ }
+}
+
func TestMakeDSes(t *testing.T) {
db, mock, err := sqlmock.New()
if err != nil {
@@ -218,7 +292,7 @@ func TestMakeDSes(t *testing.T) {
MockGetServerProfileParams(mock, expectedParams, cdn)
MockGetDSRegexesDomains(mock, expectedMatchsets, expectedDomains, cdn)
MockGetStaticDNSEntries(mock, expectedStaticDNSEntries, cdn)
- MockMakeDSes(mock, expected, cdn)
+ MockMakeDSes(mock, expected, cdn, "")
mock.ExpectCommit()
dbCtx, cancelTx := context.WithTimeout(context.TODO(), 10*time.Second)
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
index abbfb7d..56500c8 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
@@ -211,7 +211,6 @@ func CreateV40(w http.ResponseWriter, r *http.Request) {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest,
errors.New("decoding: "+err.Error()), nil)
return
}
-
res, status, userErr, sysErr := createV40(w, r, inf, ds, true)
if userErr != nil || sysErr != nil {
api.HandleErr(w, r, inf.Tx.Tx, status, userErr, sysErr)
@@ -303,6 +302,7 @@ func createV40(w http.ResponseWriter, r *http.Request, inf
*api.APIInfo, dsV40 t
tx := inf.Tx.Tx
ds := tc.DeliveryServiceV4(dsV40)
err := Validate(tx, &ds)
+ var geoLimitCountries string
if err != nil {
return nil, http.StatusBadRequest, errors.New("invalid request:
" + err.Error()), nil
}
@@ -327,6 +327,8 @@ func createV40(w http.ResponseWriter, r *http.Request, inf
*api.APIInfo, dsV40 t
if userErr != nil || sysErr != nil {
return nil, errCode, userErr, sysErr
}
+ geo := ([]string)(ds.GeoLimitCountries)
+ geoLimitCountries = strings.Join(geo, ",")
var resultRows *sql.Rows
if omitExtraLongDescFields {
if ds.LongDesc1 != nil || ds.LongDesc2 != nil {
@@ -349,7 +351,7 @@ func createV40(w http.ResponseWriter, r *http.Request, inf
*api.APIInfo, dsV40 t
&ds.EdgeHeaderRewrite,
&ds.GeoLimitRedirectURL,
&ds.GeoLimit,
- &ds.GeoLimitCountries,
+ &geoLimitCountries,
&ds.GeoProvider,
&ds.GlobalMaxMBPS,
&ds.GlobalMaxTPS,
@@ -409,7 +411,7 @@ func createV40(w http.ResponseWriter, r *http.Request, inf
*api.APIInfo, dsV40 t
&ds.EdgeHeaderRewrite,
&ds.GeoLimitRedirectURL,
&ds.GeoLimit,
- &ds.GeoLimitCountries,
+ &geoLimitCountries,
&ds.GeoProvider,
&ds.GlobalMaxMBPS,
&ds.GlobalMaxTPS,
@@ -593,7 +595,6 @@ func (ds *TODeliveryService) Read(h http.Header, useIMS
bool) ([]interface{}, er
returnable := []interface{}{}
dses, userErr, sysErr, errCode, maxTime := readGetDeliveryServices(h,
ds.APIInfo().Params, ds.APIInfo().Tx, ds.APIInfo().User, useIMS)
-
if sysErr != nil {
sysErr = errors.New("reading dses: " + sysErr.Error())
errCode = http.StatusInternalServerError
@@ -913,6 +914,11 @@ func updateV40(w http.ResponseWriter, r *http.Request, inf
*api.APIInfo, dsV40 *
}
}
+ var geoLimitCountries string
+ if ds.GeoLimitCountries != nil {
+ geo := ([]string)(ds.GeoLimitCountries)
+ geoLimitCountries = strings.Join(geo, ",")
+ }
var resultRows *sql.Rows
if omitExtraLongDescFields {
if ds.LongDesc1 != nil || ds.LongDesc2 != nil {
@@ -933,7 +939,7 @@ func updateV40(w http.ResponseWriter, r *http.Request, inf
*api.APIInfo, dsV40 *
&ds.EdgeHeaderRewrite,
&ds.GeoLimitRedirectURL,
&ds.GeoLimit,
- &ds.GeoLimitCountries,
+ &geoLimitCountries,
&ds.GeoProvider,
&ds.GlobalMaxMBPS,
&ds.GlobalMaxTPS,
@@ -993,7 +999,7 @@ func updateV40(w http.ResponseWriter, r *http.Request, inf
*api.APIInfo, dsV40 *
&ds.EdgeHeaderRewrite,
&ds.GeoLimitRedirectURL,
&ds.GeoLimit,
- &ds.GeoLimitCountries,
+ &geoLimitCountries,
&ds.GeoProvider,
&ds.GlobalMaxMBPS,
&ds.GlobalMaxTPS,
@@ -1372,6 +1378,9 @@ func Validate(tx *sql.Tx, ds *tc.DeliveryServiceV4) error
{
},
)),
})
+ if err := validateGeoLimitCountries(ds); err != nil {
+ errs = append(errs, err)
+ }
if err := validateTopologyFields(ds); err != nil {
errs = append(errs, err)
}
@@ -1384,6 +1393,20 @@ func Validate(tx *sql.Tx, ds *tc.DeliveryServiceV4)
error {
return util.JoinErrs(errs)
}
+func validateGeoLimitCountries(ds *tc.DeliveryServiceV4) error {
+ var IsLetter = regexp.MustCompile(`^[A-Z]+$`).MatchString
+ if ds.GeoLimitCountries == nil {
+ return nil
+ }
+ countryCodes := ([]string)(ds.GeoLimitCountries)
+ for _, cc := range countryCodes {
+ if cc != "" && !IsLetter(cc) {
+ return fmt.Errorf("country codes can only contain
alphabets")
+ }
+ }
+ return nil
+}
+
func validateTopologyFields(ds *tc.DeliveryServiceV4) error {
if ds.Topology != nil && (ds.EdgeHeaderRewrite != nil ||
ds.MidHeaderRewrite != nil) {
return errors.New("cannot set edgeHeaderRewrite or
midHeaderRewrite while a Topology is assigned. Use firstHeaderRewrite,
innerHeaderRewrite, and/or lastHeaderRewrite instead")
@@ -1652,6 +1675,7 @@ func GetDeliveryServices(query string, queryValues
map[string]interface{}, tx *s
// ensure json generated from this slice won't come out as `null` if
empty
dsQueryParams := []string{}
+ geoLimitCountries := util.StrPtr("")
for rows.Next() {
ds := tc.DeliveryServiceV4{}
cdnDomain := ""
@@ -1674,7 +1698,7 @@ func GetDeliveryServices(query string, queryValues
map[string]interface{}, tx *s
&ds.FirstHeaderRewrite,
&ds.GeoLimitRedirectURL,
&ds.GeoLimit,
- &ds.GeoLimitCountries,
+ &geoLimitCountries,
&ds.GeoProvider,
&ds.GlobalMaxMBPS,
&ds.GlobalMaxTPS,
@@ -1730,6 +1754,10 @@ func GetDeliveryServices(query string, queryValues
map[string]interface{}, tx *s
return nil, nil, fmt.Errorf("getting delivery services:
%v", err), http.StatusInternalServerError
}
+ if geoLimitCountries != nil && *geoLimitCountries != "" {
+ geo := strings.Split(*geoLimitCountries, ",")
+ ds.GeoLimitCountries = geo
+ }
ds.ConsistentHashQueryParams = []string{}
if len(dsQueryParams) >= 0 {
// ensure unique and in consistent order
@@ -2138,7 +2166,11 @@ func setNilIfEmpty(ptrs ...**string) {
func sanitize(ds *tc.DeliveryServiceV4) {
if ds.GeoLimitCountries != nil {
- *ds.GeoLimitCountries =
strings.ToUpper(strings.Replace(*ds.GeoLimitCountries, " ", "", -1))
+ geo := ([]string)(ds.GeoLimitCountries)
+ for i, _ := range geo {
+ geo[i] = strings.ToUpper(strings.Replace(geo[i], " ",
"", -1))
+ }
+ ds.GeoLimitCountries = geo
}
if ds.ProfileID != nil && *ds.ProfileID == -1 {
ds.ProfileID = nil
diff --git a/traffic_ops/v4-client/server.go b/traffic_ops/v4-client/server.go
index 2c3299e..272f15c 100644
--- a/traffic_ops/v4-client/server.go
+++ b/traffic_ops/v4-client/server.go
@@ -176,9 +176,9 @@ func (to *Session)
AssignDeliveryServiceIDsToServerID(server int, dsIDs []int, r
// GetServerIDDeliveryServices returns all of the Delivery Services assigned
to the server identified
// by the integral, unique identifier 'server'.
-func (to *Session) GetServerIDDeliveryServices(server int, opts
RequestOptions) (tc.DeliveryServicesNullableResponse, toclientlib.ReqInf,
error) {
+func (to *Session) GetServerIDDeliveryServices(server int, opts
RequestOptions) (tc.DeliveryServicesResponseV4, toclientlib.ReqInf, error) {
endpoint := fmt.Sprintf(apiServerDeliveryServices, server)
- var data tc.DeliveryServicesNullableResponse
+ var data tc.DeliveryServicesResponseV4
reqInf, err := to.get(endpoint, opts, &data)
return data, reqInf, err
}