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

[trafficcontrol] branch master updated: Updating a non existent DS should return a 404, instead of a 500 (#5392)

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

zrhoffman 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 b491e85  Updating a non existent DS should return a 404, instead of a 500 (#5392)
b491e85 is described below

commit b491e85dac7bf8af404bfe947b30249cd36bfaff
Author: Srijeet Chatterjee <30...@users.noreply.github.com>
AuthorDate: Mon Jan 4 12:18:31 2021 -0700

    Updating a non existent DS should return a 404, instead of a 500 (#5392)
    
    * Updating a non existent DS should return a 404, instead of a 500
    
    * Changelog modification
    
    * code review fixes
---
 CHANGELOG.md                                       |  1 +
 .../deliveryservice/deliveryservices.go            | 28 +++++++++++++---------
 .../deliveryservice/deliveryservices_test.go       | 27 +++++++++++++++++++++
 3 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1b7ece9..ca7e3be 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
 - Traffic Ops: Added validation to ensure that the cachegroups of a delivery services' assigned ORG servers are present in the topology
 
 ### Fixed
+- [#5378](https://github.com/apache/trafficcontrol/issues/5378) - Updating a non existent DS should return a 404, instead of a 500
 - [#5380](https://github.com/apache/trafficcontrol/issues/5380) - Show the correct servers (including ORGs) when a topology based DS with required capabilities + ORG servers is queried for the assigned servers
 - [#5195](https://github.com/apache/trafficcontrol/issues/5195) - Correctly show CDN ID in Changelog during Snap
 - Fixed Traffic Router logging unnecessary warnings for IPv6-only caches
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
index 1d9a89d..da2b559 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
@@ -848,10 +848,13 @@ func updateV31(w http.ResponseWriter, r *http.Request, inf *api.APIInfo, dsV31 *
 	oldHostName := ""
 	oldCDNName := ""
 	oldRoutingName := ""
+	errCode := http.StatusOK
+	var userErr error
+	var sysErr error
 	if dsType.HasSSLKeys() {
-		oldHostName, oldCDNName, oldRoutingName, err = getOldDetails(*ds.ID, tx)
-		if err != nil {
-			return nil, http.StatusInternalServerError, nil, errors.New("getting existing delivery service hostname: " + err.Error())
+		oldHostName, oldCDNName, oldRoutingName, userErr, sysErr, errCode = getOldDetails(*ds.ID, tx)
+		if userErr != nil || sysErr != nil {
+			return nil, errCode, userErr, sysErr
 		}
 	}
 
@@ -861,7 +864,7 @@ func updateV31(w http.ResponseWriter, r *http.Request, inf *api.APIInfo, dsV31 *
 		deepCachingType = ds.DeepCachingType.String() // necessary, because DeepCachingType's default needs to insert the string, not "", and Query doesn't call .String().
 	}
 
-	userErr, sysErr, errCode := api.CheckIfUnModified(r.Header, inf.Tx, *ds.ID, "deliveryservice")
+	userErr, sysErr, errCode = api.CheckIfUnModified(r.Header, inf.Tx, *ds.ID, "deliveryservice")
 	if userErr != nil || sysErr != nil {
 		return nil, errCode, userErr, sysErr
 	}
@@ -1179,7 +1182,7 @@ func selectMaxLastUpdatedQuery(where string) string {
 	select max(last_updated) as t from last_deleted l where l.table_name='deliveryservice') as res`
 }
 
-func getOldDetails(id int, tx *sql.Tx) (string, string, string, error) {
+func getOldDetails(id int, tx *sql.Tx) (string, string, string, error, error, int) {
 	q := `
 SELECT ds.xml_id, ds.protocol, type.name, ds.routing_name, cdn.domain_name, cdn.name
 FROM  deliveryservice as ds
@@ -1194,25 +1197,28 @@ WHERE ds.id=$1
 	cdnDomain := ""
 	cdnName := ""
 	if err := tx.QueryRow(q, id).Scan(&xmlID, &protocol, &dsTypeStr, &routingName, &cdnDomain, &cdnName); err != nil {
-		return "", "", "", fmt.Errorf("querying delivery service %v host name: "+err.Error()+"\n", id)
+		if err == sql.ErrNoRows {
+			return "", "", "", fmt.Errorf("querying delivery service %v host name: no such delivery service exists", id), nil, http.StatusNotFound
+		}
+		return "", "", "", nil, fmt.Errorf("querying delivery service %v host name: "+err.Error(), id), http.StatusInternalServerError
 	}
 	dsType := tc.DSTypeFromString(dsTypeStr)
 	if dsType == tc.DSTypeInvalid {
-		return "", "", "", errors.New("getting delivery services matchlist: got invalid delivery service type '" + dsTypeStr + "'")
+		return "", "", "", errors.New("getting delivery services matchlist: got invalid delivery service type '" + dsTypeStr + "'"), nil, http.StatusBadRequest
 	}
 	matchLists, err := GetDeliveryServicesMatchLists([]string{xmlID}, tx)
 	if err != nil {
-		return "", "", "", errors.New("getting delivery services matchlist: " + err.Error())
+		return "", "", "", nil, errors.New("getting delivery services matchlist: " + err.Error()), http.StatusInternalServerError
 	}
 	matchList, ok := matchLists[xmlID]
 	if !ok {
-		return "", "", "", errors.New("delivery service has no match lists (is your delivery service missing regexes?)")
+		return "", "", "", errors.New("delivery service has no match lists (is your delivery service missing regexes?)"), nil, http.StatusBadRequest
 	}
 	host, err := getHostName(protocol, dsType, routingName, matchList, cdnDomain) // protocol defaults to 0: doesn't need to check Valid()
 	if err != nil {
-		return "", "", "", errors.New("getting hostname: " + err.Error())
+		return "", "", "", nil, errors.New("getting hostname: " + err.Error()), http.StatusInternalServerError
 	}
-	return host, cdnName, routingName, nil
+	return host, cdnName, routingName, nil, nil, http.StatusOK
 }
 
 func getTypeFromID(id int, tx *sql.Tx) (tc.DSType, error) {
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices_test.go
index 8394265..d89c043 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices_test.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices_test.go
@@ -20,6 +20,7 @@ package deliveryservice
  */
 
 import (
+	"net/http"
 	"reflect"
 	"testing"
 
@@ -30,6 +31,32 @@ import (
 	"gopkg.in/DATA-DOG/go-sqlmock.v1"
 )
 
+func TestGetOldDetails(t *testing.T) {
+	expected := `querying delivery service 1 host name: no such delivery service exists`
+	mockDB, mock, err := sqlmock.New()
+	if err != nil {
+		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+	}
+	defer mockDB.Close()
+
+	db := sqlx.NewDb(mockDB, "sqlmock")
+	defer db.Close()
+
+	rows := sqlmock.NewRows([]string{""})
+	mock.ExpectBegin()
+	mock.ExpectQuery("SELECT ds.xml_id, ds.protocol, type.name, ds.routing_name, cdn.domain_name, cdn.name").WillReturnRows(rows)
+	_, _, _, userErr, _, code := getOldDetails(1, db.MustBegin().Tx)
+	if userErr == nil {
+		t.Fatalf("expected error %v, but got none", expected)
+	}
+	if userErr.Error() != expected {
+		t.Errorf("expected error %v, but got %v", expected, userErr.Error())
+	}
+	if code != http.StatusNotFound {
+		t.Errorf("expected error code : %d, but got : %d", http.StatusNotFound, code)
+	}
+}
+
 func TestGetDeliveryServicesMatchLists(t *testing.T) {
 	// test to make sure that the DS matchlists query orders by set_number
 	mockDB, mock, err := sqlmock.New()