You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by ma...@apache.org on 2021/04/28 15:14:50 UTC

[trafficcontrol] branch master updated: Fix APIv4 /servers/{{host name}}/update_status to use 'response' object (#5778)

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

mattjackson 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 4d97b0e  Fix APIv4 /servers/{{host name}}/update_status to use 'response' object (#5778)
4d97b0e is described below

commit 4d97b0e7a3d651b78eb0a9b2c8bc42221d6bc049
Author: ocket8888 <oc...@apache.org>
AuthorDate: Wed Apr 28 09:14:31 2021 -0600

    Fix APIv4 /servers/{{host name}}/update_status to use 'response' object (#5778)
    
    * Fix APIv4 /servers/{{host name}}/update_status to use 'response' object
    
    (cherry picked from commit 3ed3f38049fb2f43df4ff54c96e4a92548ddc6a5)
    
    * Remove unused import
    
    * Update CHANGELOG
---
 CHANGELOG.md                                         |  1 +
 .../source/api/v4/servers_hostname_update_status.rst | 13 ++++++++-----
 lib/go-tc/servers.go                                 | 13 +++++++++++++
 .../testing/api/v4/serverupdatestatus_test.go        | 20 ++++++++++++++------
 .../server/servers_update_status.go                  |  6 +++++-
 traffic_ops/v4-client/server.go                      | 15 ++++-----------
 6 files changed, 45 insertions(+), 23 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7b4f8f9..104ff4d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -72,6 +72,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
 - Updated Apache Tomcat from 8.5.63 to 9.0.43
 - Delivery Service Requests now keep a record of the changes they make.
 - Changed the `goose` provider to the maintained fork [`github.com/kevinburke/goose`](https://github.com/kevinburke/goose)
+- The format of the `/servers/{{host name}}/update_status` Traffic Ops API endpoint has been changed to use a top-level `response` property, in keeping with (most of) the rest of the API.
 
 ### Deprecated
 - The `riak.conf` config file and its corresponding `--riakcfg` option in `traffic_ops_golang` have been deprecated. Please use `"traffic_vault_backend": "riak"` and `"traffic_vault_config"` (with the existing contents of riak.conf) instead.
diff --git a/docs/source/api/v4/servers_hostname_update_status.rst b/docs/source/api/v4/servers_hostname_update_status.rst
index d3a28a5..3187e57 100644
--- a/docs/source/api/v4/servers_hostname_update_status.rst
+++ b/docs/source/api/v4/servers_hostname_update_status.rst
@@ -27,7 +27,10 @@ Retrieves information regarding pending updates and revalidation jobs for a give
 
 :Auth. Required: Yes
 :Roles Required: None
-:Response Type: ``undefined`` - this endpoint will return a top-level array containing the response, as opposed to within a ``response`` object
+:Response Type: Array
+
+.. versionchanged:: 4.0
+	Prior to API version 4.0, the response was a top-level array rather than the normal ``response`` object.
 
 Request Structure
 -----------------
@@ -50,7 +53,7 @@ Request Structure
 
 Response Structure
 ------------------
-Each object in the returned array\ [1]_ will contain the following fields:
+Each object in the returned array\ [#uniqueness]_ will contain the following fields:
 
 :host_id:              The integral, unique identifier for the server for which the other fields in this object represent the pending updates and revalidation status
 :host_name:            The (short) hostname of the server for which the other fields in this object represent the pending updates and revalidation status
@@ -81,7 +84,7 @@ Each object in the returned array\ [1]_ will contain the following fields:
 	Date: Mon, 04 Feb 2019 16:24:01 GMT
 	Content-Length: 174
 
-	[{
+	{ "response": [{
 		"host_name": "edge",
 		"upd_pending": false,
 		"reval_pending": false,
@@ -90,6 +93,6 @@ Each object in the returned array\ [1]_ will contain the following fields:
 		"status": "REPORTED",
 		"parent_pending": false,
 		"parent_reval_pending": false
-	}]
+	}]}
 
-.. [1] The returned object is an array, and there is no guarantee that one server exists for a given hostname. However, for each server in the array, that server's update status will be accurate for the server with that particular server ID.
+.. [#uniqueness] The returned object is an array, and there is no guarantee that one server exists for a given hostname. However, for each server in the array, that server's update status will be accurate for the server with that particular server ID.
diff --git a/lib/go-tc/servers.go b/lib/go-tc/servers.go
index a7ebd2b..f45be88 100644
--- a/lib/go-tc/servers.go
+++ b/lib/go-tc/servers.go
@@ -1110,6 +1110,19 @@ type ServerUpdateStatus struct {
 	ParentRevalPending bool   `json:"parent_reval_pending"`
 }
 
+// ServerUpdateStatusResponseV40 is the type of a response from the Traffic
+// Ops API to a request to its /servers/{{host name}}/update_status endpoint
+// in API version 4.0.
+type ServerUpdateStatusResponseV40 struct {
+	Response []ServerUpdateStatus `json:"response"`
+	Alerts
+}
+
+// ServerUpdateStatusResponseV4 is the type of a response from the Traffic
+// Ops API to a request to its /servers/{{host name}}/update_status endpoint
+// in the latest minor version of API version 4.
+type ServerUpdateStatusResponseV4 = ServerUpdateStatusResponseV40
+
 type ServerPutStatus struct {
 	Status        util.JSONNameOrIDStr `json:"status"`
 	OfflineReason *string              `json:"offlineReason"`
diff --git a/traffic_ops/testing/api/v4/serverupdatestatus_test.go b/traffic_ops/testing/api/v4/serverupdatestatus_test.go
index 3fb7894..6e5c31d 100644
--- a/traffic_ops/testing/api/v4/serverupdatestatus_test.go
+++ b/traffic_ops/testing/api/v4/serverupdatestatus_test.go
@@ -448,10 +448,14 @@ func TestSetTopologiesServerUpdateStatuses(t *testing.T) {
 			cachesByCacheGroup[cacheGroupName] = srvs.Response[0]
 		}
 		for _, cacheGroupName := range cacheGroupNames {
-			updateStatusByCacheGroup[cacheGroupName], _, err = TOSession.GetServerUpdateStatus(*cachesByCacheGroup[cacheGroupName].HostName, nil)
+			updResp, _, err := TOSession.GetServerUpdateStatus(*cachesByCacheGroup[cacheGroupName].HostName, nil)
 			if err != nil {
-				t.Fatalf("unable to get a server from cachegroup %s: %s", cacheGroupName, err.Error())
+				t.Fatalf("unable to get update status for a server from Cache Group '%s': %v - alerts: %+v", cacheGroupName, err, updResp.Alerts)
+			}
+			if len(updResp.Response) < 1 {
+				t.Fatalf("Expected at least one server with Host Name '%s' to have an update status", *cachesByCacheGroup[cacheGroupName].HostName)
 			}
+			updateStatusByCacheGroup[cacheGroupName] = updResp.Response[0]
 		}
 		// updating the server status does not queue updates within the same cachegroup
 		if *cachesByCacheGroup[midCacheGroup].UpdPending {
@@ -477,10 +481,14 @@ func TestSetTopologiesServerUpdateStatuses(t *testing.T) {
 			t.Fatalf("cannot update server status on %s: %s", *cachesByCacheGroup[midCacheGroup].HostName, err.Error())
 		}
 		for _, cacheGroupName := range cacheGroupNames {
-			updateStatusByCacheGroup[cacheGroupName], _, err = TOSession.GetServerUpdateStatus(*cachesByCacheGroup[cacheGroupName].HostName, nil)
+			updResp, _, err := TOSession.GetServerUpdateStatus(*cachesByCacheGroup[cacheGroupName].HostName, nil)
 			if err != nil {
-				t.Fatalf("unable to get a server from cachegroup %s: %s", cacheGroupName, err.Error())
+				t.Fatalf("unable to get an update status for a server from Cache Group '%s': %v - alerts: %+v", cacheGroupName, err, updResp.Alerts)
+			}
+			if len(updResp.Response) < 1 {
+				t.Fatalf("Expected at least one server with Host Name '%s' to have an update status", *cachesByCacheGroup[cacheGroupName].HostName)
 			}
+			updateStatusByCacheGroup[cacheGroupName] = updResp.Response[0]
 		}
 
 		// edgeCacheGroup is a descendant of midCacheGroup
@@ -499,9 +507,9 @@ func TestSetTopologiesServerUpdateStatuses(t *testing.T) {
 			t.Fatalf("unable to update %s's hostname to %s: %s", edgeHostName, *cachesByCacheGroup[midCacheGroup].HostName, err)
 		}
 
-		_, _, err = TOSession.GetServerUpdateStatus(*cachesByCacheGroup[midCacheGroup].HostName, nil)
+		updResp, _, err := TOSession.GetServerUpdateStatus(*cachesByCacheGroup[midCacheGroup].HostName, nil)
 		if err != nil {
-			t.Fatalf("expected no error getting server updates for a non-unique hostname %s, got %s", *cachesByCacheGroup[midCacheGroup].HostName, err)
+			t.Fatalf("expected no error getting server updates for a non-unique hostname %s, got: %v - alerts: %+v", *cachesByCacheGroup[midCacheGroup].HostName, err, updResp.Alerts)
 		}
 
 		*cachesByCacheGroup[edgeCacheGroup].HostName = edgeHostName
diff --git a/traffic_ops/traffic_ops_golang/server/servers_update_status.go b/traffic_ops/traffic_ops_golang/server/servers_update_status.go
index 78bdd7f..6009002 100644
--- a/traffic_ops/traffic_ops_golang/server/servers_update_status.go
+++ b/traffic_ops/traffic_ops_golang/server/servers_update_status.go
@@ -44,7 +44,11 @@ func GetServerUpdateStatusHandler(w http.ResponseWriter, r *http.Request) {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, err)
 		return
 	}
-	api.WriteRespRaw(w, r, serverUpdateStatus)
+	if inf.Version == nil || inf.Version.Major < 4 {
+		api.WriteRespRaw(w, r, serverUpdateStatus)
+	} else {
+		api.WriteResp(w, r, serverUpdateStatus)
+	}
 }
 
 func getServerUpdateStatus(tx *sql.Tx, cfg *config.Config, hostName string) ([]tc.ServerUpdateStatus, error) {
diff --git a/traffic_ops/v4-client/server.go b/traffic_ops/v4-client/server.go
index 7f38f2f..5da47f5 100644
--- a/traffic_ops/v4-client/server.go
+++ b/traffic_ops/v4-client/server.go
@@ -16,7 +16,6 @@
 package client
 
 import (
-	"errors"
 	"fmt"
 	"net"
 	"net/http"
@@ -206,15 +205,9 @@ func (to *Session) GetServerIDDeliveryServices(server int, header http.Header) (
 
 // GetServerUpdateStatus retrieves the Server Update Status of the Server with
 // the given (short) hostname.
-func (to *Session) GetServerUpdateStatus(hostName string, header http.Header) (tc.ServerUpdateStatus, toclientlib.ReqInf, error) {
-	path := APIServers + `/` + hostName + `/update_status`
-	data := []tc.ServerUpdateStatus{}
+func (to *Session) GetServerUpdateStatus(hostName string, header http.Header) (tc.ServerUpdateStatusResponseV4, toclientlib.ReqInf, error) {
+	path := APIServers + `/` + url.PathEscape(hostName) + `/update_status`
+	var data tc.ServerUpdateStatusResponseV4
 	reqInf, err := to.get(path, header, &data)
-	if err != nil {
-		return tc.ServerUpdateStatus{}, reqInf, err
-	}
-	if len(data) == 0 {
-		return tc.ServerUpdateStatus{}, reqInf, errors.New("Traffic Ops returned no update statuses for that server")
-	}
-	return data[0], reqInf, nil
+	return data, reqInf, err
 }