You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by ra...@apache.org on 2019/03/04 16:52:47 UTC

[trafficcontrol] branch master updated: Fix Traffic Ops GET statuses to allow null descriptions (#3148)

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

rawlin 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 875970a  Fix Traffic Ops GET statuses to allow null descriptions (#3148)
875970a is described below

commit 875970a5e3dce333247f4ca4cdab3a4005179545
Author: Robert Butts <ro...@users.noreply.github.com>
AuthorDate: Mon Mar 4 09:52:38 2019 -0700

    Fix Traffic Ops GET statuses to allow null descriptions (#3148)
    
    * Fix TO GET statuses for null descriptions
    
    Fixes #3146
    
    * Add TO client CreateStatusNullable
    
    Allows creating a status with a null description.
    
    Necessary to create an API Test to get a status with a null desc.
    
    * Add Test TO status null desc create and get
---
 lib/go-tc/statuses.go                             |  2 +-
 traffic_ops/client/status.go                      | 18 +++++++++++++
 traffic_ops/testing/api/v14/statuses_test.go      | 23 +++++++++++-----
 traffic_ops/testing/api/v14/tc-fixtures.json      |  3 +++
 traffic_ops/testing/api/v14/traffic_control.go    |  2 +-
 traffic_ops/traffic_ops_golang/status/statuses.go | 32 +++++++++++++++++++----
 6 files changed, 67 insertions(+), 13 deletions(-)

diff --git a/lib/go-tc/statuses.go b/lib/go-tc/statuses.go
index 4b00c19..e5bb8e0 100644
--- a/lib/go-tc/statuses.go
+++ b/lib/go-tc/statuses.go
@@ -58,7 +58,7 @@ type Status struct {
 }
 
 type StatusNullable struct {
-	Description *string    `json:"description" db:"description"`
+	Description *string    `json:"description"`
 	ID          *int       `json:"id" db:"id"`
 	LastUpdated *TimeNoMod `json:"lastUpdated" db:"last_updated"`
 	Name        *string    `json:"name" db:"name"`
diff --git a/traffic_ops/client/status.go b/traffic_ops/client/status.go
index 0c9b15b..521a836 100644
--- a/traffic_ops/client/status.go
+++ b/traffic_ops/client/status.go
@@ -47,6 +47,24 @@ func (to *Session) CreateStatus(status tc.Status) (tc.Alerts, ReqInf, error) {
 	return alerts, reqInf, nil
 }
 
+func (to *Session) CreateStatusNullable(status tc.StatusNullable) (tc.Alerts, ReqInf, error) {
+
+	var remoteAddr net.Addr
+	reqBody, err := json.Marshal(status)
+	reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
+	if err != nil {
+		return tc.Alerts{}, reqInf, err
+	}
+	resp, remoteAddr, err := to.request(http.MethodPost, API_v13_STATUSES, reqBody)
+	if err != nil {
+		return tc.Alerts{}, reqInf, err
+	}
+	defer resp.Body.Close()
+	var alerts tc.Alerts
+	err = json.NewDecoder(resp.Body).Decode(&alerts)
+	return alerts, reqInf, nil
+}
+
 // Update a Status by ID
 func (to *Session) UpdateStatusByID(id int, status tc.Status) (tc.Alerts, ReqInf, error) {
 
diff --git a/traffic_ops/testing/api/v14/statuses_test.go b/traffic_ops/testing/api/v14/statuses_test.go
index c7af98e..912cd47 100644
--- a/traffic_ops/testing/api/v14/statuses_test.go
+++ b/traffic_ops/testing/api/v14/statuses_test.go
@@ -32,7 +32,7 @@ func TestStatuses(t *testing.T) {
 func CreateTestStatuses(t *testing.T) {
 
 	for _, status := range testData.Statuses {
-		resp, _, err := TOSession.CreateStatus(status)
+		resp, _, err := TOSession.CreateStatusNullable(status)
 		log.Debugln("Response: ", resp)
 		if err != nil {
 			t.Errorf("could not CREATE types: %v\n", err)
@@ -44,8 +44,12 @@ func CreateTestStatuses(t *testing.T) {
 func UpdateTestStatuses(t *testing.T) {
 
 	firstStatus := testData.Statuses[0]
+	if firstStatus.Name == nil {
+		t.Fatalf("cannot update test statuses: first test data status must have a name\n")
+	}
+
 	// Retrieve the Status by name so we can get the id for the Update
-	resp, _, err := TOSession.GetStatusByName(firstStatus.Name)
+	resp, _, err := TOSession.GetStatusByName(*firstStatus.Name)
 	if err != nil {
 		t.Errorf("cannot GET Status by name: %v - %v\n", firstStatus.Name, err)
 	}
@@ -73,7 +77,10 @@ func UpdateTestStatuses(t *testing.T) {
 func GetTestStatuses(t *testing.T) {
 
 	for _, status := range testData.Statuses {
-		resp, _, err := TOSession.GetStatusByName(status.Name)
+		if status.Name == nil {
+			t.Fatalf("cannot get ftest statuses: test data statuses must have names\n")
+		}
+		resp, _, err := TOSession.GetStatusByName(*status.Name)
 		if err != nil {
 			t.Errorf("cannot GET Status by name: %v - %v\n", err, resp)
 		}
@@ -83,8 +90,12 @@ func GetTestStatuses(t *testing.T) {
 func DeleteTestStatuses(t *testing.T) {
 
 	for _, status := range testData.Statuses {
+		if status.Name == nil {
+			t.Fatalf("cannot get ftest statuses: test data statuses must have names\n")
+		}
+
 		// Retrieve the Status by name so we can get the id for the Update
-		resp, _, err := TOSession.GetStatusByName(status.Name)
+		resp, _, err := TOSession.GetStatusByName(*status.Name)
 		if err != nil {
 			t.Errorf("cannot GET Status by name: %v - %v\n", status.Name, err)
 		}
@@ -96,12 +107,12 @@ func DeleteTestStatuses(t *testing.T) {
 		}
 
 		// Retrieve the Status to see if it got deleted
-		types, _, err := TOSession.GetStatusByName(status.Name)
+		types, _, err := TOSession.GetStatusByName(*status.Name)
 		if err != nil {
 			t.Errorf("error deleting Status name: %s\n", err.Error())
 		}
 		if len(types) > 0 {
-			t.Errorf("expected Status name: %s to be deleted\n", status.Name)
+			t.Errorf("expected Status name: %s to be deleted\n", *status.Name)
 		}
 	}
 }
diff --git a/traffic_ops/testing/api/v14/tc-fixtures.json b/traffic_ops/testing/api/v14/tc-fixtures.json
index 9d097d9..eb7be84 100644
--- a/traffic_ops/testing/api/v14/tc-fixtures.json
+++ b/traffic_ops/testing/api/v14/tc-fixtures.json
@@ -1680,6 +1680,9 @@
         {
             "description": "Pre Production. Not active in any configuration.",
             "name": "PRE_PROD"
+        },
+        {
+            "name": "TEST_NULL_DESCRIPTION"
         }
     ],
     "tenants": [
diff --git a/traffic_ops/testing/api/v14/traffic_control.go b/traffic_ops/testing/api/v14/traffic_control.go
index c27bb95..64148ff 100644
--- a/traffic_ops/testing/api/v14/traffic_control.go
+++ b/traffic_ops/testing/api/v14/traffic_control.go
@@ -38,7 +38,7 @@ type TrafficControl struct {
 	Regions                        []tc.Region                        `json:"regions"`
 	Roles                          []tc.Role                          `json:"roles"`
 	Servers                        []tc.Server                        `json:"servers"`
-	Statuses                       []tc.Status                        `json:"statuses"`
+	Statuses                       []tc.StatusNullable                `json:"statuses"`
 	StaticDNSEntries               []tc.StaticDNSEntry                `json:"staticdnsentries"`
 	Tenants                        []tc.Tenant                        `json:"tenants"`
 	Types                          []tc.Type                          `json:"types"`
diff --git a/traffic_ops/traffic_ops_golang/status/statuses.go b/traffic_ops/traffic_ops_golang/status/statuses.go
index 725ca29..ed76bb6 100644
--- a/traffic_ops/traffic_ops_golang/status/statuses.go
+++ b/traffic_ops/traffic_ops_golang/status/statuses.go
@@ -20,6 +20,9 @@ package status
  */
 
 import (
+	"database/sql"
+	"fmt"
+	"net/http"
 	"strconv"
 
 	"github.com/apache/trafficcontrol/lib/go-tc"
@@ -35,11 +38,12 @@ import (
 type TOStatus struct {
 	api.APIInfoImpl `json:"-"`
 	tc.StatusNullable
+	SQLDescription sql.NullString `json:"-" db:"description"`
 }
 
 func (v *TOStatus) SetLastUpdated(t tc.TimeNoMod) { v.LastUpdated = &t }
 func (v *TOStatus) InsertQuery() string           { return insertQuery() }
-func (v *TOStatus) NewReadObj() interface{}       { return &tc.Status{} }
+func (v *TOStatus) NewReadObj() interface{}       { return &TOStatus{} }
 func (v *TOStatus) SelectQuery() string           { return selectQuery() }
 func (v *TOStatus) ParamColumns() map[string]dbhelpers.WhereColumnInfo {
 	return map[string]dbhelpers.WhereColumnInfo{
@@ -87,10 +91,28 @@ func (status TOStatus) Validate() error {
 	return util.JoinErrs(tovalidate.ToErrors(errs))
 }
 
-func (st *TOStatus) Read() ([]interface{}, error, error, int) { return api.GenericRead(st) }
-func (st *TOStatus) Update() (error, error, int)              { return api.GenericUpdate(st) }
-func (st *TOStatus) Create() (error, error, int)              { return api.GenericCreate(st) }
-func (st *TOStatus) Delete() (error, error, int)              { return api.GenericDelete(st) }
+func (st *TOStatus) Read() ([]interface{}, error, error, int) {
+	readVals, userErr, sysErr, errCode := api.GenericRead(st)
+	if userErr != nil || sysErr != nil {
+		return nil, userErr, sysErr, errCode
+	}
+
+	for _, iStatus := range readVals {
+		status, ok := iStatus.(*TOStatus)
+		if !ok {
+			return nil, nil, fmt.Errorf("TOStatus.Read: api.GenericRead returned unexpected type %T\n", iStatus), http.StatusInternalServerError
+		}
+		if status.SQLDescription.Valid {
+			status.Description = &status.SQLDescription.String
+		}
+	}
+
+	return readVals, nil, nil, http.StatusOK
+}
+
+func (st *TOStatus) Update() (error, error, int) { return api.GenericUpdate(st) }
+func (st *TOStatus) Create() (error, error, int) { return api.GenericCreate(st) }
+func (st *TOStatus) Delete() (error, error, int) { return api.GenericDelete(st) }
 
 func selectQuery() string {
 	return `