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

shamrick 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 48ec14ec2d Use RFC 3339 for lastUpdated timestamp in /statuses (#7707)
48ec14ec2d is described below

commit 48ec14ec2dd10c5ceb3119c5cc641333a80c1bd3
Author: Zach Hoffman <[email protected]>
AuthorDate: Fri Aug 11 11:50:01 2023 -0600

    Use RFC 3339 for lastUpdated timestamp in /statuses (#7707)
---
 CHANGELOG.md                                       |   1 +
 docs/source/api/v5/statuses.rst                    |   8 +-
 docs/source/api/v5/statuses_id.rst                 | 215 ---------------------
 lib/go-tc/statuses.go                              |  36 ++++
 traffic_ops/testing/api/v5/statuses_test.go        |  21 +-
 traffic_ops/testing/api/v5/traffic_control_test.go |   2 +-
 traffic_ops/traffic_ops_golang/routing/routes.go   |   8 +-
 traffic_ops/traffic_ops_golang/status/statuses.go  | 109 +++++++++++
 traffic_ops/v5-client/status.go                    |   4 +-
 9 files changed, 168 insertions(+), 236 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8dd14d625a..b0431b750d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -94,6 +94,7 @@ The format is based on [Keep a 
Changelog](http://keepachangelog.com/en/1.0.0/).
 - [#7465](https://github.com/apache/trafficcontrol/issues/7465) *Traffic Ops* 
Fixes server_capabilities v5 apis to respond with RFC3339 date/time Format
 - [#7441](https://github.com/apache/trafficcontrol/pull/7441) *Traffic Ops* 
Fixed the invalidation jobs endpoint to respect CDN locks.
 - [#7413](https://github.com/apache/trafficcontrol/issues/7413) *Traffic Ops* 
Fixes service_category apis to respond with RFC3339 date/time Format
+- [#7413](https://github.com/apache/trafficcontrol/issues/7706) *Traffic Ops* 
Fixes /statuses apis to respond with RFC3339 date/time format
 - [#7414](https://github.com/apache/trafficcontrol/pull/7414) * Traffic 
Portal* Fixed DSR difference for DS required capability.
 - [#7130](https://github.com/apache/trafficcontrol/issues/7130) *Traffic Ops* 
Fixes service_categories response to POST API.
 - [#7340](https://github.com/apache/trafficcontrol/pull/7340) *Traffic Router* 
Fixed TR logging for the `cqhv` field when absent.
diff --git a/docs/source/api/v5/statuses.rst b/docs/source/api/v5/statuses.rst
index 73a64ca762..2ff89a52c6 100644
--- a/docs/source/api/v5/statuses.rst
+++ b/docs/source/api/v5/statuses.rst
@@ -69,7 +69,7 @@ Response Structure
 ------------------
 :description: A short description of the status
 :id:          The integral, unique identifier of this status
-:lastUpdated: The date and time at which this status was last modified, in 
:ref:`non-rfc-datetime`
+:lastUpdated: The date and time at which this status was last modified, in 
:rfc:`3339` format
 :name:        The name of the status
 
 .. code-block:: http
@@ -91,7 +91,7 @@ Response Structure
                {
                        "description": "Server is online and reported in the 
health protocol.",
                        "id": 3,
-                       "lastUpdated": "2018-12-10 19:11:17+00",
+                       "lastUpdated": "2023-08-09T14:25:11.017999Z",
                        "name": "REPORTED"
                }
        ]}
@@ -125,7 +125,7 @@ Response Structure
 ------------------
 :description: A short description of the status
 :id:          The integral, unique identifier of this status
-:lastUpdated: The date and time at which this status was last modified, in 
:ref:`non-rfc-datetime`
+:lastUpdated: The date and time at which this status was last modified, in 
:rfc:`3339` format
 :name:        The name of the status
 
 .. code-block:: http
@@ -153,6 +153,6 @@ Response Structure
                        "description": "test",
                        "name": "example"
                        "id": 3,
-                       "lastUpdated": "2018-12-10 19:11:17+00",
+                       "lastUpdated": "2023-08-09T14:25:11.017999Z",
                }
        ]}
diff --git a/docs/source/api/v5/statuses_id.rst 
b/docs/source/api/v5/statuses_id.rst
deleted file mode 100644
index 1ecb83a0fd..0000000000
--- a/docs/source/api/v5/statuses_id.rst
+++ /dev/null
@@ -1,215 +0,0 @@
-..
-..
-.. Licensed under the Apache License, Version 2.0 (the "License");
-.. you may not use this file except in compliance with the License.
-.. You may obtain a copy of the License at
-..
-..     http://www.apache.org/licenses/LICENSE-2.0
-..
-.. Unless required by applicable law or agreed to in writing, software
-.. distributed under the License is distributed on an "AS IS" BASIS,
-.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-.. See the License for the specific language governing permissions and
-.. limitations under the License.
-..
-
-.. _to-api-statuses-id:
-
-*******************
-``statuses/{{ID}}``
-*******************
-
-``GET``
-=======
-Retrieves a list of all server :term:`Statuses`.
-
-:Auth. Required: Yes
-:Roles Required: None
-:Permissions Required: STATUS:READ
-:Response Type:  Array
-
-Request Structure
------------------
-.. table:: Request Query Parameters
-
-       
+-------------+----------+------------------------------------------------------------------------------------------------------+
-       | Name        | Required | Description                                  
                                                        |
-       
+=============+==========+======================================================================================================+
-       | description | no       | Return only :term:`Statuses` with this 
*exact* description                                           |
-       
+-------------+----------+------------------------------------------------------------------------------------------------------+
-       | id          | no       | Return only the :term:`Status` with this 
integral, unique identifier                                 |
-       
+-------------+----------+------------------------------------------------------------------------------------------------------+
-       | name        | no       | Return only :term:`Statuses` with this name  
                                                        |
-       
+-------------+----------+------------------------------------------------------------------------------------------------------+
-       | orderby     | no       | Choose the ordering of the results - must be 
the name of one                                         |
-       |             |          | of the fields of the objects in the 
``response`` array                                               |
-       
+-------------+----------+------------------------------------------------------------------------------------------------------+
-       | sortOrder   | no       | Changes the order of sorting. Either 
ascending (default or "asc") or                                 |
-       |             |          | descending ("desc")                          
                                                        |
-       
+-------------+----------+------------------------------------------------------------------------------------------------------+
-       | limit       | no       | Choose the maximum number of results to 
return                                                       |
-       
+-------------+----------+------------------------------------------------------------------------------------------------------+
-       | offset      | no       | The number of results to skip before 
beginning to return results. Must use in conjunction with limit |
-       
+-------------+----------+------------------------------------------------------------------------------------------------------+
-       | page        | no       | Return the n\ :sup:`th` page of results, 
where "n" is the value of this parameter, pages are         |
-       |             |          | ``limit`` long and the first page is 1. If 
``offset`` was defined, this query parameter has no       |
-       |             |          | effect. ``limit`` must be defined to make 
use of ``page``.                                           |
-       
+-------------+----------+------------------------------------------------------------------------------------------------------+
-
-.. code-block:: http
-       :caption: Request Example
-
-       GET /api/5.0/statuses/3 HTTP/1.1
-       Host: trafficops.infra.ciab.test
-       User-Agent: curl/7.47.0
-       Accept: */*
-       Cookie: mojolicious=...
-
-Response Structure
-------------------
-:description: A short description of the status
-:id:          The integral, unique identifier of this status
-:lastUpdated: The date and time at which this status was last modified, in 
:ref:`non-rfc-datetime`
-:name:        The name of the status
-
-.. code-block:: http
-       :caption: Response Example
-
-       HTTP/1.1 200 OK
-       Access-Control-Allow-Credentials: true
-       Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, 
Accept, Set-Cookie, Cookie
-       Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE
-       Access-Control-Allow-Origin: *
-       Content-Type: application/json
-       Set-Cookie: mojolicious=...; Path=/; Expires=Mon, 18 Nov 2019 17:40:54 
GMT; Max-Age=3600; HttpOnly
-       Whole-Content-Sha512: 
dHNip9kpTGGS1w39/fWcFehNktgmXZus8XaufnmDpv0PyG/3fK/KfoCO3ZOj9V74/CCffps7doEygWeL/xRtKA==
-       X-Server-Name: traffic_ops_golang/
-       Date: Mon, 10 Dec 2018 20:56:59 GMT
-       Content-Length: 150
-
-       { "response": [
-               {
-                       "description": "Server is online and reported in the 
health protocol.",
-                       "id": 3,
-                       "lastUpdated": "2018-12-10 19:11:17+00",
-                       "name": "REPORTED"
-               }
-       ]}
-
-``PUT``
-=======
-Updates a :term:`Status`.
-
-:Auth. Required: Yes
-:Roles Required: None
-:Permissions Required: STATUS:UPDATE, STATUS:READ
-:Response Type:  Array
-
-Request Structure
------------------
-:description:  The description of the updated :term:`Status`
-:name:                 The name of the updated :term:`Status`
-
-.. code-block:: http
-       :caption: Request Example
-
-       PUT /api/5.0/statuses/3 HTTP/1.1
-       Host: trafficops.infra.ciab.test
-       User-Agent: curl/7.47.0
-       Accept: */*
-       Cookie: mojolicious=...
-
-       { "description": "test", "name": "example" }
-
-Response Structure
-------------------
-:description: A short description of the status
-:id:          The integral, unique identifier of this status
-:lastUpdated: The date and time at which this status was last modified, in 
:ref:`non-rfc-datetime`
-:name:        The name of the status
-
-.. code-block:: http
-       :caption: Response Example
-
-       HTTP/1.1 200 OK
-       Access-Control-Allow-Credentials: true
-       Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, 
Accept, Set-Cookie, Cookie
-       Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE
-       Access-Control-Allow-Origin: *
-       Content-Type: application/json
-       Set-Cookie: mojolicious=...; Path=/; Expires=Mon, 18 Nov 2019 17:40:54 
GMT; Max-Age=3600; HttpOnly
-       Whole-Content-Sha512: 
dHNip9kpTGGS1w39/fWcFehNktgmXZus8XaufnmDpv0PyG/3fK/KfoCO3ZOj9V74/CCffps7doEygWeL/xRtKA==
-       X-Server-Name: traffic_ops_golang/
-       Date: Mon, 10 Dec 2018 20:56:59 GMT
-       Content-Length: 167
-
-       { "alerts": [
-               {
-                       "text": "status was created.",
-                       "level": "success"
-               }
-       ],"response": [
-               {
-                       "description": "test",
-                       "name": "example"
-                       "id": 3,
-                       "lastUpdated": "2018-12-10 19:11:17+00",
-               }
-       ]}
-
-``DELETE``
-==========
-Deletes a :term:`Status`.
-
-:Auth. Required: Yes
-:Roles Required: "admin" or "operations"
-:Permissions Required: STATUS:DELETE, STATUS:READ
-:Response Type:  Object
-
-Request Structure
------------------
-.. table:: Request Path Parameters
-
-       
+------+----------+---------------------------------------------------------------------------------------------+
-       | Name | Required | Description                                         
                                        |
-       
+======+==========+=============================================================================================+
-       | id   | yes      | The integral, unique identifier of the desired 
:abbr:`Status`-to-:term:`Server` association |
-       
+------+----------+---------------------------------------------------------------------------------------------+
-
-.. code-block:: http
-       :caption: Request Example
-
-       DELETE /api/5.0/statuses/18 HTTP/1.1
-       User-Agent: curl/8.1.2
-       Accept-Encoding: gzip, deflate
-       Accept: */*
-       Connection: keep-alive
-       Cookie: mojolicious=...
-       Content-Length: 0
-
-Response Structure
-------------------
-.. code-block:: http
-       :caption: Response Example
-
-       HTTP/1.1 200 OK
-       Access-Control-Allow-Credentials: true
-       Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, 
Accept, Set-Cookie, Cookie
-       Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE
-       Access-Control-Allow-Origin: *
-       Content-Encoding: gzip
-       Content-Type: application/json
-       Set-Cookie: mojolicious=...; Path=/; Expires=Thu, 15 Jun 2023 22:37:37 
GMT; Max-Age=3600; HttpOnly
-       Whole-Content-Sha512: 
T8wtKKwyOKKVwDwoNCNvETllsByDiEe4CrpeS7Zdox+rXMgPb3FBlKmmgu4CpxbWdhpiODKqKn+gsSq5K4yvIQ==
-       X-Server-Name: traffic_ops_golang/
-       Date: Thu, 15 Jun 2023 21:41:18 GMT
-       Content-Length: 62
-
-       {
-               "alerts": [
-                       {
-                               "text": "status was deleted.",
-                               "level": "success"
-                       }
-               ]
-       }
diff --git a/lib/go-tc/statuses.go b/lib/go-tc/statuses.go
index 74c847b4a3..4587dc8ae9 100644
--- a/lib/go-tc/statuses.go
+++ b/lib/go-tc/statuses.go
@@ -19,6 +19,21 @@ package tc
  * under the License.
  */
 
+import "time"
+
+// StatusResponseV5 is the type of a response from the
+// /api/5.x/statuses Traffic Ops endpoint.
+// It always points to the type for the latest minor version of APIv5.
+type StatusesResponseV5 = StatusesResponseV50
+
+// StatusesResponseV50 is a list of Statuses as a response that depicts the 
state
+// of a server.
+type StatusesResponseV50 struct {
+       // in: body
+       Response []StatusV50 `json:"response"`
+       Alerts
+}
+
 // StatusesResponse is a list of Statuses as a response that depicts the state
 // of a server.
 // swagger:response StatusesResponse
@@ -28,6 +43,14 @@ type StatusesResponse struct {
        Alerts
 }
 
+// StatusResponseV5 is the type of a response for API endponts
+// returning a single Status in Traffic Ops API version 5.
+type StatusResponseV5 struct {
+       // in: body
+       Response StatusV5 `json:"response"`
+       Alerts
+}
+
 // StatusResponse is a single Status response for Update and Create to depict
 // what changed.
 // swagger:response StatusResponse
@@ -62,6 +85,19 @@ type Status struct {
        Name string `json:"name" db:"name"`
 }
 
+// StatusV5 is a Status as it appears in version 5 of the
+// Traffic Ops API - it always points to the highest minor version in APIv5.
+type StatusV5 = StatusV50
+
+// StatusNullableV5 is a nullable single Status response for Update and Create 
to
+// depict what changed.
+type StatusV50 struct {
+       Description *string    `json:"description" db:"description"`
+       ID          *int       `json:"id" db:"id"`
+       LastUpdated *time.Time `json:"lastUpdated" db:"last_updated"`
+       Name        *string    `json:"name" db:"name"`
+}
+
 // StatusNullable is a nullable single Status response for Update and Create to
 // depict what changed.
 type StatusNullable struct {
diff --git a/traffic_ops/testing/api/v5/statuses_test.go 
b/traffic_ops/testing/api/v5/statuses_test.go
index a12be126cc..0ac1000a49 100644
--- a/traffic_ops/testing/api/v5/statuses_test.go
+++ b/traffic_ops/testing/api/v5/statuses_test.go
@@ -24,6 +24,7 @@ import (
 
        "github.com/apache/trafficcontrol/lib/go-rfc"
        "github.com/apache/trafficcontrol/lib/go-tc"
+       "github.com/apache/trafficcontrol/lib/go-util"
        "github.com/apache/trafficcontrol/lib/go-util/assert"
        "github.com/apache/trafficcontrol/traffic_ops/testing/api/utils"
        "github.com/apache/trafficcontrol/traffic_ops/toclientlib"
@@ -37,7 +38,7 @@ func TestStatuses(t *testing.T) {
                currentTimeRFC := currentTime.Format(time.RFC1123)
                tomorrow := currentTime.AddDate(0, 0, 1).Format(time.RFC1123)
 
-               methodTests := utils.TestCase[client.Session, 
client.RequestOptions, tc.Status]{
+               methodTests := utils.TestCase[client.Session, 
client.RequestOptions, tc.StatusV5]{
                        "GET": {
                                "NOT MODIFIED when NO CHANGES made": {
                                        ClientSession: TOSession,
@@ -64,9 +65,9 @@ func TestStatuses(t *testing.T) {
                                "OK when VALID request": {
                                        EndpointID:    GetStatusID(t, 
"TEST_NULL_DESCRIPTION"),
                                        ClientSession: TOSession,
-                                       RequestBody: tc.Status{
-                                               Description: "new description",
-                                               Name:        
"TEST_NULL_DESCRIPTION",
+                                       RequestBody: tc.StatusV5{
+                                               Description: util.Ptr("new 
description"),
+                                               Name:        
util.Ptr("TEST_NULL_DESCRIPTION"),
                                        },
                                        Expectations: 
utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
                                                
validateStatusesUpdateCreateFields("TEST_NULL_DESCRIPTION", 
map[string]interface{}{"Description": "new description"})),
@@ -75,18 +76,18 @@ func TestStatuses(t *testing.T) {
                                        EndpointID:    GetStatusID(t, 
"TEST_NULL_DESCRIPTION"),
                                        ClientSession: TOSession,
                                        RequestOpts:   
client.RequestOptions{Header: http.Header{rfc.IfUnmodifiedSince: 
{currentTimeRFC}}},
-                                       RequestBody: tc.Status{
-                                               Description: "new description",
-                                               Name:        
"TEST_NULL_DESCRIPTION",
+                                       RequestBody: tc.StatusV5{
+                                               Description: util.Ptr("new 
description"),
+                                               Name:        
util.Ptr("TEST_NULL_DESCRIPTION"),
                                        },
                                        Expectations: 
utils.CkRequest(utils.HasError(), 
utils.HasStatus(http.StatusPreconditionFailed)),
                                },
                                "PRECONDITION FAILED when updating with IFMATCH 
ETAG Header": {
                                        EndpointID:    GetStatusID(t, 
"TEST_NULL_DESCRIPTION"),
                                        ClientSession: TOSession,
-                                       RequestBody: tc.Status{
-                                               Description: "new description",
-                                               Name:        
"TEST_NULL_DESCRIPTION",
+                                       RequestBody: tc.StatusV5{
+                                               Description: util.Ptr("new 
description"),
+                                               Name:        
util.Ptr("TEST_NULL_DESCRIPTION"),
                                        },
                                        RequestOpts:  
client.RequestOptions{Header: http.Header{rfc.IfMatch: 
{rfc.ETag(currentTime)}}},
                                        Expectations: 
utils.CkRequest(utils.HasError(), 
utils.HasStatus(http.StatusPreconditionFailed)),
diff --git a/traffic_ops/testing/api/v5/traffic_control_test.go 
b/traffic_ops/testing/api/v5/traffic_control_test.go
index 4263f50faa..a31ede33cc 100644
--- a/traffic_ops/testing/api/v5/traffic_control_test.go
+++ b/traffic_ops/testing/api/v5/traffic_control_test.go
@@ -49,7 +49,7 @@ type TrafficControl struct {
        ServerServerCapabilities                          
[]tc.ServerServerCapability             `json:"serverServerCapabilities"`
        ServerCapabilities                                
[]tc.ServerCapabilityV5                 `json:"serverCapabilities"`
        ServiceCategories                                 
[]tc.ServiceCategoryV5                  `json:"serviceCategories"`
-       Statuses                                          []tc.StatusNullable   
                  `json:"statuses"`
+       Statuses                                          []tc.StatusV5         
                  `json:"statuses"`
        StaticDNSEntries                                  []tc.StaticDNSEntry   
                  `json:"staticdnsentries"`
        StatsSummaries                                    []tc.StatsSummaryV5   
                  `json:"statsSummaries"`
        Tenants                                           []tc.Tenant           
                  `json:"tenants"`
diff --git a/traffic_ops/traffic_ops_golang/routing/routes.go 
b/traffic_ops/traffic_ops_golang/routing/routes.go
index 26b5a0c171..57d9c9aa16 100644
--- a/traffic_ops/traffic_ops_golang/routing/routes.go
+++ b/traffic_ops/traffic_ops_golang/routing/routes.go
@@ -336,10 +336,10 @@ func Routes(d ServerData) ([]Route, http.Handler, error) {
                {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodDelete, Path: `server_server_capabilities/?$`, Handler: 
api.DeleteHandler(&server.TOServerServerCapability{}), RequiredPrivLevel: 
auth.PrivLevelOperations, RequiredPermissions: []string{"SERVER:UPDATE", 
"SERVER:READ", "SERVER-CAPABILITY:READ"}, Authenticated: Authenticated, 
Middlewares: nil, ID: 405871405831},
 
                //Status: CRUD
-               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodGet, Path: `statuses/?$`, Handler: 
api.ReadHandler(&status.TOStatus{}), RequiredPrivLevel: auth.PrivLevelReadOnly, 
RequiredPermissions: []string{"STATUS:READ"}, Authenticated: Authenticated, 
Middlewares: nil, ID: 424490565631},
-               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodPut, Path: `statuses/{id}$`, Handler: 
api.UpdateHandler(&status.TOStatus{}), RequiredPrivLevel: 
auth.PrivLevelOperations, RequiredPermissions: []string{"STATUS:UPDATE", 
"STATUS:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 
420796650431},
-               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodPost, Path: `statuses/?$`, Handler: 
api.CreateHandler(&status.TOStatus{}), RequiredPrivLevel: 
auth.PrivLevelOperations, RequiredPermissions: []string{"STATUS:CREATE", 
"STATUS:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 
436912361231},
-               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodDelete, Path: `statuses/{id}$`, Handler: 
api.DeleteHandler(&status.TOStatus{}), RequiredPrivLevel: 
auth.PrivLevelOperations, RequiredPermissions: []string{"STATUS:DELETE", 
"STATUS:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 
45511136031},
+               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodGet, Path: `statuses/?$`, Handler: 
api.ReadHandler(&status.TOStatusV5{}), RequiredPrivLevel: 
auth.PrivLevelReadOnly, RequiredPermissions: []string{"STATUS:READ"}, 
Authenticated: Authenticated, Middlewares: nil, ID: 424490565631},
+               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodPut, Path: `statuses/{id}$`, Handler: 
api.UpdateHandler(&status.TOStatusV5{}), RequiredPrivLevel: 
auth.PrivLevelOperations, RequiredPermissions: []string{"STATUS:UPDATE", 
"STATUS:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 
420796650431},
+               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodPost, Path: `statuses/?$`, Handler: 
api.CreateHandler(&status.TOStatusV5{}), RequiredPrivLevel: 
auth.PrivLevelOperations, RequiredPermissions: []string{"STATUS:CREATE", 
"STATUS:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 
436912361231},
+               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodDelete, Path: `statuses/{id}$`, Handler: 
api.DeleteHandler(&status.TOStatusV5{}), RequiredPrivLevel: 
auth.PrivLevelOperations, RequiredPermissions: []string{"STATUS:DELETE", 
"STATUS:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 
45511136031},
 
                //System
                {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodGet, Path: `system/info/?$`, Handler: systeminfo.Get, 
RequiredPrivLevel: auth.PrivLevelReadOnly, RequiredPermissions: nil, 
Authenticated: Authenticated, Middlewares: nil, ID: 42104747531},
diff --git a/traffic_ops/traffic_ops_golang/status/statuses.go 
b/traffic_ops/traffic_ops_golang/status/statuses.go
index 18754da62a..a48884af0f 100644
--- a/traffic_ops/traffic_ops_golang/status/statuses.go
+++ b/traffic_ops/traffic_ops_golang/status/statuses.go
@@ -34,6 +34,115 @@ import (
        validation "github.com/go-ozzo/ozzo-validation"
 )
 
+// we need a type alias to define functions on
+type TOStatusV5 struct {
+       api.APIInfoImpl `json:"-"`
+       tc.StatusV5
+}
+
+func (v *TOStatusV5) GetLastUpdated() (*time.Time, bool, error) {
+       return api.GetLastUpdated(v.APIInfo().Tx, *v.ID, "status")
+}
+
+func (v *TOStatusV5) SelectMaxLastUpdatedQuery(where, orderBy, pagination, 
tableName string) string {
+       return `SELECT max(t) from (
+               SELECT max(last_updated) as t from ` + tableName + ` s ` + 
where + orderBy + pagination +
+               ` UNION ALL
+       select max(last_updated) as t from last_deleted l where l.table_name='` 
+ tableName + `') as res`
+}
+
+func (v *TOStatusV5) SetLastUpdated(t tc.TimeNoMod) { v.LastUpdated = &t.Time }
+func (v *TOStatusV5) InsertQuery() string           { return insertQuery() }
+func (v *TOStatusV5) NewReadObj() interface{}       { return &TOStatusV5{} }
+func (v *TOStatusV5) SelectQuery() string           { return selectQuery() }
+func (v *TOStatusV5) ParamColumns() map[string]dbhelpers.WhereColumnInfo {
+       return map[string]dbhelpers.WhereColumnInfo{
+               "id":          dbhelpers.WhereColumnInfo{Column: "id", Checker: 
api.IsInt},
+               "description": dbhelpers.WhereColumnInfo{Column: "description"},
+               "name":        dbhelpers.WhereColumnInfo{Column: "name"},
+       }
+}
+func (v *TOStatusV5) UpdateQuery() string { return updateQuery() }
+func (v *TOStatusV5) DeleteQuery() string { return deleteQuery() }
+
+func (status TOStatusV5) GetKeyFieldsInfo() []api.KeyFieldInfo {
+       return []api.KeyFieldInfo{{Field: "id", Func: api.GetIntKey}}
+}
+
+// Implementation of the Identifier, Validator interface functions
+func (status TOStatusV5) GetKeys() (map[string]interface{}, bool) {
+       if status.ID == nil {
+               return map[string]interface{}{"id": 0}, false
+       }
+       return map[string]interface{}{"id": *status.ID}, true
+}
+
+func (status *TOStatusV5) SetKeys(keys map[string]interface{}) {
+       i, _ := keys["id"].(int) //this utilizes the non panicking type 
assertion, if the thrown away ok variable is false i will be the zero of the 
type, 0 here.
+       status.ID = &i
+}
+
+func (status TOStatusV5) GetAuditName() string {
+       if status.Name != nil {
+               return *status.Name
+       }
+       if status.ID != nil {
+               return strconv.Itoa(*status.ID)
+       }
+       return "unknown"
+}
+
+func (status TOStatusV5) GetType() string { return "status" }
+
+func (status TOStatusV5) Validate() (error, error) {
+       errs := validation.Errors{
+               "name": validation.Validate(status.Name, validation.NotNil, 
validation.Required),
+       }
+       return util.JoinErrs(tovalidate.ToErrors(errs)), nil
+}
+
+func (st *TOStatusV5) Read(h http.Header, useIMS bool) ([]interface{}, error, 
error, int, *time.Time) {
+       errCode := http.StatusOK
+       api.DefaultSort(st.APIInfo(), "name")
+       readVals, userErr, sysErr, errCode, maxTime := api.GenericRead(h, st, 
useIMS)
+       if userErr != nil || sysErr != nil {
+               return nil, userErr, sysErr, errCode, nil
+       }
+
+       for _, iStatus := range readVals {
+               _, ok := iStatus.(*TOStatusV5)
+               if !ok {
+                       return nil, nil, fmt.Errorf("TOStatusV5.Read: 
api.GenericRead returned unexpected type %T\n", iStatus), 
http.StatusInternalServerError, nil
+               }
+       }
+
+       return readVals, nil, nil, errCode, maxTime
+}
+
+func (st *TOStatusV5) Update(h http.Header) (error, error, int) {
+       var statusName string
+       err := st.APIInfo().Tx.QueryRow(`SELECT name from status WHERE id = 
$1`, *st.ID).Scan(&statusName)
+       if err != nil {
+               return nil, fmt.Errorf("error querying status name from ID: 
%w", err), http.StatusInternalServerError
+       }
+       if tc.IsReservedStatus(statusName) {
+               return fmt.Errorf("cannot modify %s status", statusName), nil, 
http.StatusForbidden
+       }
+       return api.GenericUpdate(h, st)
+}
+func (st *TOStatusV5) Create() (error, error, int) { return 
api.GenericCreate(st) }
+func (st *TOStatusV5) Delete() (error, error, int) {
+       var statusName string
+       err := st.APIInfo().Tx.QueryRow(`SELECT name from status WHERE id = 
$1`, *st.ID).Scan(&statusName)
+       if err != nil {
+               return nil, fmt.Errorf("error querying status name from ID: 
%w", err), http.StatusInternalServerError
+       }
+       if tc.IsReservedStatus(statusName) {
+               return fmt.Errorf("cannot delete %s status", statusName), nil, 
http.StatusForbidden
+       }
+       return api.GenericDelete(st)
+}
+
 // we need a type alias to define functions on
 type TOStatus struct {
        api.APIInfoImpl `json:"-"`
diff --git a/traffic_ops/v5-client/status.go b/traffic_ops/v5-client/status.go
index 4da8b778f5..0448f5280d 100644
--- a/traffic_ops/v5-client/status.go
+++ b/traffic_ops/v5-client/status.go
@@ -26,14 +26,14 @@ import (
 const apiStatuses = "/statuses"
 
 // CreateStatus creates the given Status.
-func (to *Session) CreateStatus(status tc.StatusNullable, opts RequestOptions) 
(tc.Alerts, toclientlib.ReqInf, error) {
+func (to *Session) CreateStatus(status tc.StatusV5, opts RequestOptions) 
(tc.Alerts, toclientlib.ReqInf, error) {
        var alerts tc.Alerts
        reqInf, err := to.post(apiStatuses, opts, status, &alerts)
        return alerts, reqInf, err
 }
 
 // UpdateStatus replaces the Status identified by 'id' with the one provided.
-func (to *Session) UpdateStatus(id int, status tc.Status, opts RequestOptions) 
(tc.Alerts, toclientlib.ReqInf, error) {
+func (to *Session) UpdateStatus(id int, status tc.StatusV5, opts 
RequestOptions) (tc.Alerts, toclientlib.ReqInf, error) {
        route := fmt.Sprintf("%s/%d", apiStatuses, id)
        var alerts tc.Alerts
        reqInf, err := to.put(route, opts, status, &alerts)

Reply via email to