diff --git a/docs/source/api/v4/deliveryservices_id_servers.rst b/docs/source/api/v4/deliveryservices_id_servers.rst index 69a64377f8..bb8c9676fa 100644 --- a/docs/source/api/v4/deliveryservices_id_servers.rst +++ b/docs/source/api/v4/deliveryservices_id_servers.rst @@ -40,6 +40,9 @@ Request Structure Response Structure ------------------ +:asns: The :abbr:`ASN (Autonomous System Number)` associated with the cachegroups of the current server. + + .. versionadded:: 4.1 :cachegroup: A string that is the :ref:`name of the Cache Group ` to which the server belongs :cachegroupId: An integer that is the :ref:`ID of the Cache Group ` to which the server belongs :cdnId: An integral, unique identifier the CDN to which the server belongs @@ -142,6 +145,7 @@ Response Structure "type": "EDGE", "typeId": 11, "updPending": false, + "asns": [1,2], "interfaces": [{ "ipAddresses": [ { diff --git a/docs/source/api/v4/deliveryservices_id_servers_eligible.rst b/docs/source/api/v4/deliveryservices_id_servers_eligible.rst index 903b661aba..20fdb73511 100644 --- a/docs/source/api/v4/deliveryservices_id_servers_eligible.rst +++ b/docs/source/api/v4/deliveryservices_id_servers_eligible.rst @@ -46,6 +46,9 @@ Request Structure Response Structure ------------------ +:asns: The :abbr:`ASN (Autonomous System Number)` associated with the cachegroups of the current server. + + .. versionadded:: 4.1 :cachegroup: A string which is the :ref:`Name of the Cache Group ` to which the server belongs :cachegroupId: An integer that is the :ref:`ID of the Cache Group ` to which the server belongs :cdnId: An integral, unique identifier the CDN to which the server belongs @@ -140,6 +143,7 @@ Response Structure "type": "EDGE", "typeId": 11, "updPending": false, + "asns": [1,2], "interfaces": [{ "ipAddresses": [ { diff --git a/docs/source/api/v4/servers_id.rst b/docs/source/api/v4/servers_id.rst index 881323b709..df366f36c8 100644 --- a/docs/source/api/v4/servers_id.rst +++ b/docs/source/api/v4/servers_id.rst @@ -160,6 +160,9 @@ Request Structure Response Structure ------------------ +:asns: The :abbr:`ASN (Autonomous System Number)` associated with the cachegroups of the current server. + + .. versionadded:: 4.1 :cachegroup: A string that is the :ref:`name of the Cache Group ` to which the server belongs :cachegroupId: An integer that is the :ref:`ID of the Cache Group ` to which the server belongs :cdnId: The integral, unique identifier of the CDN to which the server belongs @@ -262,6 +265,7 @@ Response Structure } ], "response": { + "asns": [1,2], "cachegroup": "CDN_in_a_Box_Mid", "cachegroupId": 6, "cdnId": 2, @@ -355,6 +359,9 @@ Request Structure Response Structure ------------------ +:asns: The :abbr:`ASN (Autonomous System Number)` associated with the cachegroups of the current server. + + .. versionadded:: 4.1 :cachegroup: A string that is the :ref:`name of the Cache Group ` to which the server belonged :cachegroupId: An integer that is the :ref:`ID of the Cache Group ` to which the server belonged :cdnId: The integral, unique identifier of the CDN to which the server belonged @@ -453,6 +460,7 @@ Response Structure } ], "response": { + "asns": [1,2], "cachegroup": "CDN_in_a_Box_Mid", "cachegroupId": 6, "cdnId": 2, diff --git a/docs/source/api/v5/deliveryservices_id_servers.rst b/docs/source/api/v5/deliveryservices_id_servers.rst index 02e578982a..a2e82abae5 100644 --- a/docs/source/api/v5/deliveryservices_id_servers.rst +++ b/docs/source/api/v5/deliveryservices_id_servers.rst @@ -40,6 +40,7 @@ Request Structure Response Structure ------------------ +:asns: The :abbr:`ASN (Autonomous System Number)` associated with the cachegroups of the current server. :cachegroup: A string that is the :ref:`name of the Cache Group ` to which the server belongs :cachegroupId: An integer that is the :ref:`ID of the Cache Group ` to which the server belongs :cdnId: An integral, unique identifier the CDN to which the server belongs @@ -142,6 +143,7 @@ Response Structure "type": "EDGE", "typeId": 11, "updPending": false, + "asns": [1,2], "interfaces": [{ "ipAddresses": [ { diff --git a/docs/source/api/v5/deliveryservices_id_servers_eligible.rst b/docs/source/api/v5/deliveryservices_id_servers_eligible.rst index f51c34f946..b0c04f0550 100644 --- a/docs/source/api/v5/deliveryservices_id_servers_eligible.rst +++ b/docs/source/api/v5/deliveryservices_id_servers_eligible.rst @@ -46,6 +46,7 @@ Request Structure Response Structure ------------------ +:asns: The :abbr:`ASN (Autonomous System Number)` associated with the cachegroups of the current server. :cachegroup: A string which is the :ref:`Name of the Cache Group ` to which the server belongs :cachegroupId: An integer that is the :ref:`ID of the Cache Group ` to which the server belongs :cdnId: An integral, unique identifier the CDN to which the server belongs @@ -140,6 +141,7 @@ Response Structure "type": "EDGE", "typeId": 11, "updPending": false, + "asns": [1,2], "interfaces": [{ "ipAddresses": [ { diff --git a/docs/source/api/v5/servers_id.rst b/docs/source/api/v5/servers_id.rst index 712b1fb209..cfd25dd80b 100644 --- a/docs/source/api/v5/servers_id.rst +++ b/docs/source/api/v5/servers_id.rst @@ -160,6 +160,7 @@ Request Structure Response Structure ------------------ +:asns: The :abbr:`ASN (Autonomous System Number)` associated with the cachegroups of the current server. :cachegroup: A string that is the :ref:`name of the Cache Group ` to which the server belongs :cachegroupId: An integer that is the :ref:`ID of the Cache Group ` to which the server belongs :cdnId: The integral, unique identifier of the CDN to which the server belongs @@ -262,6 +263,7 @@ Response Structure } ], "response": { + "asns": [1,2], "cachegroup": "CDN_in_a_Box_Mid", "cachegroupId": 6, "cdnId": 2, @@ -355,6 +357,7 @@ Request Structure Response Structure ------------------ +:asns: The :abbr:`ASN (Autonomous System Number)` associated with the cachegroups of the current server. :cachegroup: A string that is the :ref:`name of the Cache Group ` to which the server belonged :cachegroupId: An integer that is the :ref:`ID of the Cache Group ` to which the server belonged :cdnId: The integral, unique identifier of the CDN to which the server belonged @@ -453,6 +456,7 @@ Response Structure } ], "response": { + "asns": [1,2], "cachegroup": "CDN_in_a_Box_Mid", "cachegroupId": 6, "cdnId": 2, diff --git a/lib/go-tc/deliveryservice_servers.go b/lib/go-tc/deliveryservice_servers.go index 7f1d1a1570..25b5ce2096 100644 --- a/lib/go-tc/deliveryservice_servers.go +++ b/lib/go-tc/deliveryservice_servers.go @@ -189,6 +189,12 @@ type DSServerResponseV30 struct { // DSServerV4 contains information for a V4.x Delivery Service Server. type DSServerV4 struct { + DSServerV40 + ASNs []int64 `json:"asns"` +} + +// DSServerV40 contains information for a V4.0 Delivery Service Server. +type DSServerV40 struct { DSServerBaseV4 ServerInterfaces *[]ServerInterfaceInfoV40 `json:"interfaces" db:"interfaces"` } @@ -196,6 +202,13 @@ type DSServerV4 struct { // DSServerResponseV40 is the type of a response from Traffic Ops to a request // for servers assigned to a Delivery Service - in API version 4.0. type DSServerResponseV40 struct { + Response []DSServerV40 `json:"response"` + Alerts +} + +// DSServerResponseV41 is the type of a response from Traffic Ops to a request +// for servers assigned to a Delivery Service - in API version 4.1. +type DSServerResponseV41 struct { Response []DSServerV4 `json:"response"` Alerts } @@ -203,7 +216,7 @@ type DSServerResponseV40 struct { // DSServerResponseV4 is the type of a response from Traffic Ops to a request // for servers assigned to a Delivery Service - in the latest minor version of // API version 4. -type DSServerResponseV4 = DSServerResponseV40 +type DSServerResponseV4 = DSServerResponseV41 // ToDSServerBaseV4 upgrades the DSServerBase to the structure used by the // latest minor version of version 4 of Traffic Ops's API. diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go b/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go index d863aa423b..33e2efb9ab 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go @@ -96,6 +96,15 @@ func GetServersEligible(w http.ResponseWriter, r *http.Request) { api.WriteResp(w, r, v3ServerList) return } + if inf.Version.Major == 4 && inf.Version.Minor < 1 { + v40ServerList := []tc.DSServerV40{} + for _, s := range servers { + sV40 := s.DSServerV40 + v40ServerList = append(v40ServerList, sV40) + } + api.WriteResp(w, r, v40ServerList) + return + } api.WriteResp(w, r, servers) } @@ -147,7 +156,8 @@ t.name as server_type, s.type as server_type_id, s.config_update_time > s.config_apply_time AS upd_pending, ARRAY(select ssc.server_capability from server_server_capability ssc where ssc.server = s.id order by ssc.server_capability) as server_capabilities, -ARRAY(select drc.required_capability from deliveryservices_required_capability drc where drc.deliveryservice_id = (select v from ds_id) order by drc.required_capability) as deliveryservice_capabilities +ARRAY(select drc.required_capability from deliveryservices_required_capability drc where drc.deliveryservice_id = (select v from ds_id) order by drc.required_capability) as deliveryservice_capabilities, +(SELECT ARRAY_AGG(asn) AS asns FROM asn a WHERE a.cachegroup = s.cachegroup) AS asns ` idRows, err := tx.Query(fmt.Sprintf(queryFormatString, "", queryWhereClause), dsID) if err != nil { @@ -209,6 +219,7 @@ ARRAY(select drc.required_capability from deliveryservices_required_capability d &s.UpdPending, pq.Array(&s.ServerCapabilities), pq.Array(&s.DeliveryServiceCapabilities), + pq.Array(&s.ASNs), ) if err != nil { return nil, errors.New("scanning delivery service eligible servers: " + err.Error()) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/eligible_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/eligible_test.go index a45833aac8..c0692959df 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/eligible_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/eligible_test.go @@ -84,7 +84,9 @@ func TestGetEligibleServers(t *testing.T) { "server_type_id", "upd_pending", "server_capabilities", - "deliveryservice_capabilities"} + "deliveryservice_capabilities", + "asns", + } eligbleRows := sqlmock.NewRows(cols) for _, s := range testServers { @@ -120,6 +122,7 @@ func TestGetEligibleServers(t *testing.T) { s.UpdPending, []byte(`{""}`), []byte(`{""}`), + []byte(`{1,2}`), ) } mock.ExpectQuery("SELECT s.id ,").WillReturnRows(eligbleRows) @@ -149,18 +152,14 @@ func TestGetEligibleServers(t *testing.T) { } func getMockDSServers() []tc.DSServerV4 { - base := tc.DSServerBaseV4{ - ID: util.IntPtr(1), - Cachegroup: util.StrPtr("cgTest"), - CachegroupID: util.IntPtr(1), - CDNID: util.IntPtr(1), - CDNName: util.StrPtr("cdnTest"), - DomainName: util.StrPtr("domain"), - } - srv := tc.DSServerV4{ - DSServerBaseV4: base, - ServerInterfaces: &[]tc.ServerInterfaceInfoV40{}, // left empty because it must be written as json above since sqlmock does not support nested arrays - } + srv := tc.DSServerV4{} + srv.ID = util.IntPtr(1) + srv.Cachegroup = util.StrPtr("cgTest") + srv.CachegroupID = util.IntPtr(1) + srv.CDNID = util.IntPtr(1) + srv.CDNName = util.StrPtr("cdnTest") + srv.DomainName = util.StrPtr("domain") + srv.ServerInterfaces = &[]tc.ServerInterfaceInfoV40{} srvsExpected := []tc.DSServerV4{srv} return srvsExpected } diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go index c300d3bb44..f7f31fd21d 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go @@ -724,7 +724,15 @@ func GetReadAssigned(w http.ResponseWriter, r *http.Request) { api.WriteAlertsObj(w, r, http.StatusOK, alerts, v3ServerList) return } - + if inf.Version.Major == 4 && inf.Version.Minor < 1 { + v40ServerList := []tc.DSServerV40{} + for _, s := range servers { + sV40 := s.DSServerV40 + v40ServerList = append(v40ServerList, sV40) + } + api.WriteAlertsObj(w, r, http.StatusOK, alerts, v40ServerList) + return + } api.WriteAlertsObj(w, r, http.StatusOK, alerts, servers) } @@ -758,7 +766,8 @@ s.status as status_id, s.tcp_port, t.name as server_type, s.type as server_type_id, -s.config_update_time > s.config_apply_time AS upd_pending +s.config_update_time > s.config_apply_time AS upd_pending, +(SELECT ARRAY_AGG(asn) AS asns FROM asn a WHERE a.cachegroup = s.cachegroup) AS asns ` queryFormatString := ` @@ -833,6 +842,7 @@ WHERE s.id in (select server from deliveryservice_server where deliveryservice = &s.Type, &s.TypeID, &s.UpdPending, + pq.Array(&s.ASNs), ) if err != nil { return nil, errors.New("error scanning dss rows: " + err.Error()) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go index 9c04a80ff3..aa6f4ec409 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go @@ -115,7 +115,9 @@ func TestReadServers(t *testing.T) { "tcp_port", "server_type", "server_type_id", - "upd_pending"} + "upd_pending", + "asns", + } rows := sqlmock.NewRows(cols) @@ -150,6 +152,7 @@ func TestReadServers(t *testing.T) { s.Type, s.TypeID, s.UpdPending, + []byte(`{1,2}`), ) } @@ -184,18 +187,14 @@ func TestReadServers(t *testing.T) { } func getMockDSServers() []tc.DSServerV4 { - base := tc.DSServerBaseV4{ - ID: util.IntPtr(1), - Cachegroup: util.StrPtr("cgTest"), - CachegroupID: util.IntPtr(1), - CDNID: util.IntPtr(1), - CDNName: util.StrPtr("cdnTest"), - DomainName: util.StrPtr("domain"), - } - srv := tc.DSServerV4{ - DSServerBaseV4: base, - ServerInterfaces: &[]tc.ServerInterfaceInfoV40{}, // left empty because it must be written as json above since sqlmock does not support nested arrays - } + srv := tc.DSServerV4{} + srv.ID = util.IntPtr(1) + srv.Cachegroup = util.StrPtr("cgTest") + srv.CachegroupID = util.IntPtr(1) + srv.CDNID = util.IntPtr(1) + srv.CDNName = util.StrPtr("cdnTest") + srv.DomainName = util.StrPtr("domain") + srv.ServerInterfaces = &[]tc.ServerInterfaceInfoV40{} srvsExpected := []tc.DSServerV4{srv} return srvsExpected } diff --git a/traffic_ops/traffic_ops_golang/server/servers.go b/traffic_ops/traffic_ops_golang/server/servers.go index e57d161258..4cd372f3d0 100644 --- a/traffic_ops/traffic_ops_golang/server/servers.go +++ b/traffic_ops/traffic_ops_golang/server/servers.go @@ -137,7 +137,7 @@ SELECT s.offline_reason, pl.name AS phys_location, s.phys_location AS phys_location_id, - (SELECT ARRAY_AGG(sp.profile_name) FROM server_profile AS sp where sp.server=s.id) AS profile_name, + (SELECT ARRAY_AGG(sp.profile_name ORDER BY sp.priority ASC) FROM server_profile AS sp where sp.server=s.id) AS profile_name, s.rack, s.revalidate_update_time > s.revalidate_apply_time AS reval_pending, s.revalidate_update_time, @@ -329,7 +329,7 @@ RETURNING offline_reason, (SELECT name FROM phys_location WHERE phys_location.id=server.phys_location) AS phys_location, phys_location AS phys_location_id, - (SELECT ARRAY_AGG(profile_name) FROM server_profile WHERE server_profile.server=server.id) AS profile_name, + (SELECT ARRAY_AGG(profile_name ORDER BY priority ASC) FROM server_profile WHERE server_profile.server=server.id) AS profile_name, rack, (SELECT name FROM status WHERE status.id=server.status) AS status, status AS status_id, @@ -1631,7 +1631,27 @@ func Update(w http.ResponseWriter, r *http.Request) { api.HandleErr(w, r, tx, errCode, userErr, sysErr) return } - api.WriteRespAlertObj(w, r, tc.SuccessLevel, "Server updated", srvr.ServerV40) + if inf.Version.Major >= 5 { + api.WriteRespAlertObj(w, r, tc.SuccessLevel, "Server updated", srvr) + } else if inf.Version.Major >= 4 { + if version.Minor >= 1 { + api.WriteRespAlertObj(w, r, tc.SuccessLevel, "Server updated", srvr) + } else { + api.WriteRespAlertObj(w, r, tc.SuccessLevel, "Server updated", srvr.ServerV40) + } + } else if inf.Version.Major >= 3 { + csp, err := dbhelpers.GetCommonServerPropertiesFromV4(srvr, inf.Tx.Tx) + if err != nil { + api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, err) + return + } + srvrV30, err := srvr.ServerV40.ToServerV3FromV4(csp) + if err != nil { + api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, err) + return + } + api.WriteRespAlertObj(w, r, tc.SuccessLevel, "Server updated", srvrV30) + } changeLogMsg := fmt.Sprintf("SERVER: %s.%s, ID: %d, ACTION: updated", *srvr.HostName, *srvr.DomainName, *srvr.ID) api.CreateChangeLogRawTx(api.ApiChange, changeLogMsg, inf.User, tx) @@ -1980,7 +2000,15 @@ func createV4(inf *api.APIInfo, w http.ResponseWriter, r *http.Request) { srvr.Interfaces = server.Interfaces alerts := tc.CreateAlerts(tc.SuccessLevel, "Server created") - api.WriteAlertsObj(w, r, http.StatusCreated, alerts, srvr.ServerV40) + if inf.Version.Major == 5 { + api.WriteAlertsObj(w, r, http.StatusCreated, alerts, srvr) + } else { + if inf.Version.Minor >= 1 { + api.WriteAlertsObj(w, r, http.StatusCreated, alerts, srvr) + } else { + api.WriteAlertsObj(w, r, http.StatusCreated, alerts, srvr.ServerV40) + } + } changeLogMsg := fmt.Sprintf("SERVER: %s.%s, ID: %d, ACTION: created", *srvr.HostName, *srvr.DomainName, *srvr.ID) api.CreateChangeLogRawTx(api.ApiChange, changeLogMsg, inf.User, inf.Tx.Tx) @@ -2243,7 +2271,11 @@ func Delete(w http.ResponseWriter, r *http.Request) { } if inf.Version.Major >= 4 { - api.WriteRespAlertObj(w, r, tc.SuccessLevel, "Server deleted", server.ServerV40) + if inf.Version.Minor >= 1 || inf.Version.Major == 5 { + api.WriteRespAlertObj(w, r, tc.SuccessLevel, "Server deleted", server) + } else { + api.WriteRespAlertObj(w, r, tc.SuccessLevel, "Server deleted", server.ServerV40) + } } else { csp, err := dbhelpers.GetCommonServerPropertiesFromV4(server, tx) if err != nil {