You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by oc...@apache.org on 2021/09/10 03:18:04 UTC

[trafficcontrol] branch master updated: Add support for "cdn" query parameter in GET /deliveryserviceserver API (#6167)

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 9ae69f5  Add support for "cdn" query parameter in GET /deliveryserviceserver API (#6167)
9ae69f5 is described below

commit 9ae69f5a3dedf6496dd7ed1ceb06a5e6b7796655
Author: Rawlin Peters <ra...@apache.org>
AuthorDate: Thu Sep 9 21:17:49 2021 -0600

    Add support for "cdn" query parameter in GET /deliveryserviceserver API (#6167)
    
    * Add support for "cdn" query parameter in GET /deliveryserviceserver API
    
    Allow filtering by CDN name via a new "cdn" query parameter. Also, don't
    sort by default due to this API being very expensive in terms of data
    already.
    
    * Fix test
    
    * Add back default 'orderby' value if not present in the request URL
    
    * Update docs to reflect 'orderby' default and empty value behavior
---
 CHANGELOG.md                                       |  1 +
 docs/source/api/v2/deliveryserviceserver.rst       | 20 ++---
 docs/source/api/v3/deliveryserviceserver.rst       | 20 ++---
 docs/source/api/v4/deliveryserviceserver.rst       | 20 ++---
 .../testing/api/v4/deliveryserviceservers_test.go  | 88 ++++++++++++++++++++++
 traffic_ops/testing/api/v4/tc-fixtures.json        | 62 +++++++++++++++
 .../deliveryservice/servers/servers.go             | 25 ++++--
 7 files changed, 202 insertions(+), 34 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6d79610..cfaca06 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
 ## unreleased (but not 6.0)
 ### Added
 - [#5674](https://github.com/apache/trafficcontrol/issues/5674) Added new query parameters `cdn` and `maxRevalDurationDays` to the `GET /api/x/jobs` Traffic Ops API to filter by CDN name and within the start_time window defined by the `maxRevalDurationDays` GLOBAL profile parameter, respectively.
+- [#6034](https://github.com/apache/trafficcontrol/issues/6034) Added new query parameter `cdn` to the `GET /api/x/deliveryserviceserver` Traffic Ops API to filter by CDN name
 
 ## unreleased
 ### Added
diff --git a/docs/source/api/v2/deliveryserviceserver.rst b/docs/source/api/v2/deliveryserviceserver.rst
index f186ab0..9e9d018 100644
--- a/docs/source/api/v2/deliveryserviceserver.rst
+++ b/docs/source/api/v2/deliveryserviceserver.rst
@@ -31,15 +31,17 @@ Request Structure
 -----------------
 .. table:: Request Query Parameters
 
-	+-----------+----------+-------------------+---------------------------------------------------------------------------------------------------------------------+
-	|    Name   | Required | Default           |                                                       Description                                                   |
-	+===========+==========+===================+=====================================================================================================================+
-	| page      | no       | 0                 | The page number for use in pagination - ``0`` means "no pagination"                                                 |
-	+-----------+----------+-------------------+---------------------------------------------------------------------------------------------------------------------+
-	| limit     | no       | 20                | Limits the results to a maximum of this number - if pagination is used, this defines the number of results per page |
-	+-----------+----------+-------------------+---------------------------------------------------------------------------------------------------------------------+
-	| orderby   | no       | "deliveryservice" | Choose the ordering of the results - must be the name of one of the fields of the objects in the ``response`` array |
-	+-----------+----------+-------------------+---------------------------------------------------------------------------------------------------------------------+
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+	|    Name   | Required | Default           |                                                       Description                                                                                                            |
+	+===========+==========+===================+==============================================================================================================================================================================+
+	| cdn       | no       | None              | Limit the results to delivery service servers for the given CDN name                                                                                                         |
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+	| page      | no       | 0                 | The page number for use in pagination - ``0`` means "no pagination"                                                                                                          |
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+	| limit     | no       | 20                | Limits the results to a maximum of this number - if pagination is used, this defines the number of results per page                                                          |
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+	| orderby   | no       | "deliveryService" | Choose the ordering of the results - the value must either be the name of one of the fields of the objects in the ``response`` array or be empty to skip ordering altogether |
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 
 .. code-block:: http
 	:caption: Request Example
diff --git a/docs/source/api/v3/deliveryserviceserver.rst b/docs/source/api/v3/deliveryserviceserver.rst
index 4f6e6ae..e31fac7 100644
--- a/docs/source/api/v3/deliveryserviceserver.rst
+++ b/docs/source/api/v3/deliveryserviceserver.rst
@@ -31,15 +31,17 @@ Request Structure
 -----------------
 .. table:: Request Query Parameters
 
-	+-----------+----------+-------------------+---------------------------------------------------------------------------------------------------------------------+
-	|    Name   | Required | Default           |                                                       Description                                                   |
-	+===========+==========+===================+=====================================================================================================================+
-	| page      | no       | 0                 | The page number for use in pagination - ``0`` means "no pagination"                                                 |
-	+-----------+----------+-------------------+---------------------------------------------------------------------------------------------------------------------+
-	| limit     | no       | 20                | Limits the results to a maximum of this number - if pagination is used, this defines the number of results per page |
-	+-----------+----------+-------------------+---------------------------------------------------------------------------------------------------------------------+
-	| orderby   | no       | "deliveryservice" | Choose the ordering of the results - must be the name of one of the fields of the objects in the ``response`` array |
-	+-----------+----------+-------------------+---------------------------------------------------------------------------------------------------------------------+
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+	|    Name   | Required | Default           |                                                       Description                                                                                                            |
+	+===========+==========+===================+==============================================================================================================================================================================+
+	| cdn       | no       | None              | Limit the results to delivery service servers for the given CDN name                                                                                                         |
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+	| page      | no       | 0                 | The page number for use in pagination - ``0`` means "no pagination"                                                                                                          |
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+	| limit     | no       | 20                | Limits the results to a maximum of this number - if pagination is used, this defines the number of results per page                                                          |
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+	| orderby   | no       | "deliveryService" | Choose the ordering of the results - the value must either be the name of one of the fields of the objects in the ``response`` array or be empty to skip ordering altogether |
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 
 .. code-block:: http
 	:caption: Request Example
diff --git a/docs/source/api/v4/deliveryserviceserver.rst b/docs/source/api/v4/deliveryserviceserver.rst
index b3c9ab4..169b358 100644
--- a/docs/source/api/v4/deliveryserviceserver.rst
+++ b/docs/source/api/v4/deliveryserviceserver.rst
@@ -31,15 +31,17 @@ Request Structure
 -----------------
 .. table:: Request Query Parameters
 
-	+-----------+----------+-------------------+---------------------------------------------------------------------------------------------------------------------+
-	|    Name   | Required | Default           |                                                       Description                                                   |
-	+===========+==========+===================+=====================================================================================================================+
-	| page      | no       | 0                 | The page number for use in pagination - ``0`` means "no pagination"                                                 |
-	+-----------+----------+-------------------+---------------------------------------------------------------------------------------------------------------------+
-	| limit     | no       | 20                | Limits the results to a maximum of this number - if pagination is used, this defines the number of results per page |
-	+-----------+----------+-------------------+---------------------------------------------------------------------------------------------------------------------+
-	| orderby   | no       | "deliveryservice" | Choose the ordering of the results - must be the name of one of the fields of the objects in the ``response`` array |
-	+-----------+----------+-------------------+---------------------------------------------------------------------------------------------------------------------+
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+	|    Name   | Required | Default           |                                                       Description                                                                                                            |
+	+===========+==========+===================+==============================================================================================================================================================================+
+	| cdn       | no       | None              | Limit the results to delivery service servers for the given CDN name                                                                                                         |
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+	| page      | no       | 0                 | The page number for use in pagination - ``0`` means "no pagination"                                                                                                          |
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+	| limit     | no       | 20                | Limits the results to a maximum of this number - if pagination is used, this defines the number of results per page                                                          |
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+	| orderby   | no       | "deliveryService" | Choose the ordering of the results - the value must either be the name of one of the fields of the objects in the ``response`` array or be empty to skip ordering altogether |
+	+-----------+----------+-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 
 .. code-block:: http
 	:caption: Request Example
diff --git a/traffic_ops/testing/api/v4/deliveryserviceservers_test.go b/traffic_ops/testing/api/v4/deliveryserviceservers_test.go
index b395109..6522737 100644
--- a/traffic_ops/testing/api/v4/deliveryserviceservers_test.go
+++ b/traffic_ops/testing/api/v4/deliveryserviceservers_test.go
@@ -38,6 +38,7 @@ func TestDeliveryServiceServers(t *testing.T) {
 		TryToRemoveLastServerInDeliveryService(t)
 		AssignServersToNonTopologyBasedDeliveryServiceThatUsesMidTier(t)
 		GetTestDSSIMS(t)
+		GetTestDSServerByCDN(t)
 	})
 }
 
@@ -513,6 +514,93 @@ func CreateTestDeliveryServiceServersWithRequiredCapabilities(t *testing.T) {
 	}
 }
 
+func GetTestDSServerByCDN(t *testing.T) {
+	opts := client.NewRequestOptions()
+	cdns, _, err := TOSession.GetCDNs(opts)
+	if err != nil {
+		t.Fatalf("unexpected error getting CDNs: %v", err)
+	} else if len(cdns.Response) < 2 {
+		t.Fatalf("expected at least 2 CDNs but got %d instead", len(cdns.Response))
+	}
+	dses, _, err := TOSession.GetDeliveryServices(opts)
+	if err != nil {
+		t.Fatalf("unexpected error getting delivery services: %v", err)
+	}
+	cdnNonTopologyDSMap := make(map[int][]int)
+	dsMap := make(map[int]tc.DeliveryServiceV4)
+	for _, ds := range dses.Response {
+		dsMap[*ds.ID] = ds
+		if ds.Topology != nil && *ds.Topology != "" {
+			continue
+		}
+		cdnNonTopologyDSMap[*ds.CDNID] = append(cdnNonTopologyDSMap[*ds.CDNID], *ds.ID)
+	}
+	servers, _, err := TOSession.GetServers(opts)
+	if err != nil {
+		t.Fatalf("unexpected error getting servers: %v", err)
+	}
+	serverMap := make(map[int]tc.ServerV4)
+	cdnEdgeMap := make(map[int][]int)
+	for _, server := range servers.Response {
+		serverMap[*server.ID] = server
+		if !strings.HasPrefix(server.Type, tc.EdgeTypePrefix) {
+			continue
+		}
+		cdnEdgeMap[*server.CDNID] = append(cdnEdgeMap[*server.CDNID], *server.ID)
+	}
+	emptyCDN := tc.CDN{}
+	cdn1 := tc.CDN{}
+	cdn2 := tc.CDN{}
+	for i, cdn := range cdns.Response {
+		if len(cdnNonTopologyDSMap[cdn.ID]) > 0 && len(cdnEdgeMap[cdn.ID]) > 0 {
+			if cdn1 == emptyCDN {
+				cdn1 = cdns.Response[i]
+			} else {
+				cdn2 = cdns.Response[i]
+				break
+			}
+		}
+	}
+	if cdn1 == emptyCDN || cdn2 == emptyCDN {
+		t.Fatalf("expected at least 2 CDNs with at least 1 non-topology-based deliveryservice and 1 edge each")
+	}
+	_, _, err = TOSession.CreateDeliveryServiceServers(cdnNonTopologyDSMap[cdn1.ID][0], []int{cdnEdgeMap[cdn1.ID][0]}, true, client.RequestOptions{})
+	if err != nil {
+		t.Fatalf("unexpected error creating delivery service servers: %v", err)
+	}
+	_, _, err = TOSession.CreateDeliveryServiceServers(cdnNonTopologyDSMap[cdn2.ID][0], []int{cdnEdgeMap[cdn2.ID][0]}, true, client.RequestOptions{})
+	if err != nil {
+		t.Fatalf("unexpected error creating delivery service servers: %v", err)
+	}
+
+	opts.QueryParameters.Set("cdn", cdn1.Name)
+	opts.QueryParameters.Set("limit", "999999999")
+	dss, _, err := TOSession.GetDeliveryServiceServers(opts)
+	if err != nil {
+		t.Fatalf("unexpected error getting delivery service servers by cdn: %v", err)
+	} else if len(dss.Response) < 1 {
+		t.Fatalf("getting delivery service servers - expected: at least 1, actual: %d", len(dss.Response))
+	}
+	for _, d := range dss.Response {
+		if *dsMap[*d.DeliveryService].CDNID != cdn1.ID {
+			t.Errorf("getting delivery service servers by cdn (%s) - found entry that did not match the given cdn (server hostname = %s, server CDN name = %s, delivery service xmlId = %s, delivery service CDN name = %s", cdn1.Name, *serverMap[*d.Server].HostName, *serverMap[*d.Server].CDNName, *dsMap[*d.DeliveryService].XMLID, *dsMap[*d.DeliveryService].CDNName)
+		}
+	}
+	opts.QueryParameters.Set("cdn", cdn2.Name)
+	dss, _, err = TOSession.GetDeliveryServiceServers(opts)
+	if err != nil {
+		t.Fatalf("unexpected error getting delivery service servers by cdn: %v", err)
+	} else if len(dss.Response) < 1 {
+		t.Fatalf("getting delivery service servers - expected: at least 1, actual: %d", len(dss.Response))
+	}
+	for _, d := range dss.Response {
+		if *dsMap[*d.DeliveryService].CDNID != cdn2.ID {
+			t.Errorf("getting delivery service servers by cdn (%s) - found entry that did not match the given cdn", cdn2.Name)
+			t.Errorf("getting delivery service servers by cdn (%s) - found entry that did not match the given cdn (server hostname = %s, server CDN name = %s, delivery service xmlId = %s, delivery service CDN name = %s", cdn2.Name, *serverMap[*d.Server].HostName, *serverMap[*d.Server].CDNName, *dsMap[*d.DeliveryService].XMLID, *dsMap[*d.DeliveryService].CDNName)
+		}
+	}
+}
+
 func CreateTestMSODSServerWithReqCap(t *testing.T) {
 	opts := client.NewRequestOptions()
 	opts.QueryParameters.Set("xmlID", "msods1")
diff --git a/traffic_ops/testing/api/v4/tc-fixtures.json b/traffic_ops/testing/api/v4/tc-fixtures.json
index c3b4cea..8bca765 100644
--- a/traffic_ops/testing/api/v4/tc-fixtures.json
+++ b/traffic_ops/testing/api/v4/tc-fixtures.json
@@ -1311,6 +1311,68 @@
             "checkPath": "",
             "consistentHashQueryParams": [],
             "deepCachingType": "NEVER",
+            "displayName": "basic-ds-in-cdn2",
+            "dnsBypassCname": null,
+            "dnsBypassIp": "",
+            "dnsBypassIp6": "",
+            "dnsBypassTtl": 30,
+            "dscp": 40,
+            "edgeHeaderRewrite": null,
+            "fqPacingRate": 0,
+            "geoLimit": 0,
+            "geoLimitCountries": "",
+            "geoLimitRedirectURL": null,
+            "geoProvider": 0,
+            "globalMaxMbps": 0,
+            "globalMaxTps": 0,
+            "httpBypassFqdn": "",
+            "infoUrl": "TBD",
+            "initialDispersion": 1,
+            "ipv6RoutingEnabled": true,
+            "logsEnabled": false,
+            "longDesc": "",
+            "longDesc1": "",
+            "longDesc2": "",
+            "matchList": [
+                {
+                    "pattern": ".*\\.basic-ds-in-cdn2\\..*",
+                    "setNumber": 0,
+                    "type": "HOST_REGEXP"
+                }
+            ],
+            "maxDnsAnswers": 0,
+            "midHeaderRewrite": null,
+            "missLat": 41.881944,
+            "missLong": -87.627778,
+            "multiSiteOrigin": false,
+            "orgServerFqdn": "http://example.org",
+            "originShield": null,
+            "profileDescription": null,
+            "profileName": null,
+            "protocol": 0,
+            "qstringIgnore": 0,
+            "rangeRequestHandling": 0,
+            "regexRemap": null,
+            "regionalGeoBlocking": false,
+            "remapText": null,
+            "routingName": "cdn",
+            "signed": false,
+            "signingAlgorithm": null,
+            "sslKeyVersion": 0,
+            "tenant": "tenant1",
+            "tenantName": "tenant1",
+            "type": "HTTP",
+            "xmlId": "basic-ds-in-cdn2",
+            "anonymousBlockingEnabled": false,
+            "maxRequestHeaderBytes": 131072
+        },
+        {
+            "active": true,
+            "cdnName": "cdn2",
+            "ccrDnsTtl": 3600,
+            "checkPath": "",
+            "consistentHashQueryParams": [],
+            "deepCachingType": "NEVER",
             "displayName": "top-ds-in-cdn2",
             "dnsBypassCname": null,
             "dnsBypassIp": "",
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
index 82b8dc0..e5bdc88 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
@@ -53,6 +53,7 @@ type TODeliveryServiceServer struct {
 	TenantIDs          pq.Int64Array `json:"-" db:"accessibleTenants"`
 	DeliveryServiceIDs pq.Int64Array `json:"-" db:"dsids"`
 	ServerIDs          pq.Int64Array `json:"-" db:"serverids"`
+	CDN                string        `json:"-" db:"cdn"`
 }
 
 func (dss TODeliveryServiceServer) GetKeyFieldsInfo() []api.KeyFieldInfo {
@@ -175,7 +176,13 @@ func ReadDSSHandler(w http.ResponseWriter, r *http.Request) {
 func (dss *TODeliveryServiceServer) readDSS(h http.Header, tx *sqlx.Tx, user *auth.CurrentUser, params map[string]string, intParams map[string]int, dsIDs []int64, serverIDs []int64, useIMS bool) (*tc.DeliveryServiceServerResponse, error, *time.Time) {
 	var maxTime time.Time
 	var runSecond bool
-	orderby := params["orderby"]
+	// NOTE: if the 'orderby' query param exists but has an empty value, that means no ordering should be done.
+	// If the 'orderby' query param does not exist, order by "deliveryService" by default. This allows clients to
+	// specifically skip sorting if it's unnecessary, reducing load on the DB.
+	orderby, ok := params["orderby"]
+	if !ok {
+		orderby = "deliveryService"
+	}
 	limit := 20
 	offset := 0
 	page := 0
@@ -191,9 +198,6 @@ func (dss *TODeliveryServiceServer) readDSS(h http.Header, tx *sqlx.Tx, user *au
 		}
 		offset *= limit
 	}
-	if orderby == "" {
-		orderby = "deliveryService"
-	}
 
 	tenantIDs, err := tenant.GetUserTenantIDListTx(tx.Tx, user.TenantID)
 	if err != nil {
@@ -204,7 +208,9 @@ func (dss *TODeliveryServiceServer) readDSS(h http.Header, tx *sqlx.Tx, user *au
 	}
 	dss.ServerIDs = serverIDs
 	dss.DeliveryServiceIDs = dsIDs
-	query1, err := selectQuery(orderby, strconv.Itoa(limit), strconv.Itoa(offset), dsIDs, serverIDs, true)
+	cdn := params["cdn"]
+	dss.CDN = cdn
+	query1, err := selectQuery(orderby, strconv.Itoa(limit), strconv.Itoa(offset), dsIDs, serverIDs, true, cdn)
 	if err != nil {
 		log.Warnf("Error getting the max last updated query %v", err)
 	}
@@ -221,7 +227,7 @@ func (dss *TODeliveryServiceServer) readDSS(h http.Header, tx *sqlx.Tx, user *au
 	} else {
 		log.Debugln("Non IMS request")
 	}
-	query, err := selectQuery(orderby, strconv.Itoa(limit), strconv.Itoa(offset), dsIDs, serverIDs, false)
+	query, err := selectQuery(orderby, strconv.Itoa(limit), strconv.Itoa(offset), dsIDs, serverIDs, false, cdn)
 	if err != nil {
 		return nil, errors.New("creating query for DeliveryserviceServers: " + err.Error()), nil
 	}
@@ -243,7 +249,7 @@ func (dss *TODeliveryServiceServer) readDSS(h http.Header, tx *sqlx.Tx, user *au
 	return &tc.DeliveryServiceServerResponse{Orderby: orderby, Response: servers, Size: page, Limit: limit}, nil, &maxTime
 }
 
-func selectQuery(orderBy string, limit string, offset string, dsIDs []int64, serverIDs []int64, getMaxQuery bool) (string, error) {
+func selectQuery(orderBy string, limit string, offset string, dsIDs []int64, serverIDs []int64, getMaxQuery bool, cdn string) (string, error) {
 	selectStmt := `SELECT
 	s.deliveryService,
 	s.server,
@@ -283,6 +289,11 @@ AND s.deliveryservice = ANY(:dsids)
 AND s.server = ANY(:serverids)
 `
 	}
+	if len(cdn) > 0 {
+		selectStmt += `
+AND d.cdn_id = (SELECT id FROM cdn WHERE name = :cdn)
+`
+	}
 
 	if getMaxQuery {
 		selectStmt += ` GROUP BY s.deliveryservice`