You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by oc...@apache.org on 2022/04/26 19:25:00 UTC
[trafficcontrol] branch master updated: Layered Server Feature for `GET` API endpoint `servers/details` (#6593)
This is an automated email from the ASF dual-hosted git repository.
ocket8888 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 225f91c5fe Layered Server Feature for `GET` API endpoint `servers/details` (#6593)
225f91c5fe is described below
commit 225f91c5febe8155ed01cb36b501c213de420ad8
Author: Rima Shah <22...@users.noreply.github.com>
AuthorDate: Tue Apr 26 13:24:55 2022 -0600
Layered Server Feature for `GET` API endpoint `servers/details` (#6593)
* Updated server struct and type for V4 and added commonpropertiesV40 function and struct
* Added db migration files
* Added backward compatibility to get (GET) and update (PUT) /server
* Updated docs for GET /server and PUT /server/{id}
* Updated migration script, doc, /server API endpoint for GET and PUT
* Updated query for profile_names
* Updated profile_names type
* Passing in the original transaction id
* Update servers.go for PUT servers/{id} API
* Moved function having db transactions to dbhelpers.
* Fixed go vet
* Fixed testing/api/v4 test
* Updated cache config and lib test
* Fixed fmt to log
* Fixed server profile to profiles
* Updated docs and tests(cache-config).
* Updated tests to accept first profile to ensure current tests pass.
* Updated tests to accept first profile to ensure current tests pass-1.
* Added changelog entry
* Fixed unit tests
* Removed fmt statement.
* Tc_fixture updated for profiles (v4).
* Added logic for POST servers/
* Updated server_profile foreign key constraint for delete servers/{id} API
* Updated db_helper functions to return err
* Updated parentdotconfig.go and server.go for profile
* Fixed test related to profile
* Updated API/v4 test related to profile.
Updated tc_fixtures tp remove duplicate interface ip.
* Removed extra if clause.
* Removed database transaction from api/v4/ tests
* Updated changelog and server params
* Removed fmt statements
* updated select statement for v2/v3 and added logic to fill in server_profile table for v2/v3 when creating a server
* replaced profileId with profileNames in traffic portal data
* replaced profileId with profileNames in traffic portal data-1
* Updated ServerDetail struct and getDetailServers() to handle array of profile_names for V4
* Removed changes from checkTypeChangeSafety() in servers.go
* Updated unit test for servers_test.go and added multiple profiles to one of the servers in v4/tc_fixtures
* Changed enroller server_template.json for CIAB
* Traffic Portal changes
* Removed db_helpers function from cache-config
* Updated TP server's integration test
* Removed get profile name request by profile ID since we already have a profile name.
* updated profile field in server
* updated unit test
* updated error message in validatedCommonV40 and server integration tests
* updated API.ts to add random characters for profileNames
* updated APIv4 docs
* Made profile-names singular to match current documentation.
* Update based on review comments.
* Changed Profiles field in go struct to ProfileNames to match JSON.
* Fixed unit test.
* Changed ProfileNames field type in struct ServerV40 to []string from pq.StringArray
* Removed additional code from TP.
* Updated code and queries for PUT and POST call.
* Updated function call param
* Changed CommonServerPropertiesV40 field ProfileNames from a pointer of string slice to a slice of string. Created new migration file to make them as latest date.
* Created new migration file to make them as latest date.
* Updated conversion.go
* Fixed queries and scan() to correct GH failures.
* Updated profile to a []string from a string and removed profileDesc from ServerDetailsV40
* Added error check and renamed Profiles back to Profile for V3/V2
* Added changelog entry and updated doc
* removed incorrect migration file and revert changes in v4/tc_fixtures.json
* removed ServerDetailsV40{}.
* updated based on review comments.
---
CHANGELOG.md | 1 +
docs/source/api/v4/servers_details.rst | 6 +--
lib/go-tc/servers.go | 29 ++++++++++++-
traffic_ops/testing/api/v4/tc-fixtures.json | 32 +++++++--------
.../traffic_ops_golang/dbhelpers/db_helpers.go | 37 +++++++++++++++++
traffic_ops/traffic_ops_golang/server/detail.go | 48 +++++++++++++++++++---
.../traffic_ops_golang/server/detail_test.go | 16 +++-----
7 files changed, 132 insertions(+), 37 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3aaee21caa..043163cbf3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- [Traffic Ops | Traffic Go Clients | T3C] Add additional timestamp fields to server for queuing and dequeueing config and revalidate updates.
- Added layered profile feature to 4.0 for `GET` /servers/, `POST` /servers/, `PUT` /servers/{id} and `DELETE` /servers/{id}.
- Added a Traffic Ops endpoint and Traffic Portal page to view all CDNi configuration update requests and approve or deny.
+- Added layered profile feature to 4.0 for `GET` /servers/details.
- Added layered profile feature to 4.0 for `GET` /deliveryservices/{id}/servers/ and /deliveryservices/{id}/servers/eligible.
### Fixed
diff --git a/docs/source/api/v4/servers_details.rst b/docs/source/api/v4/servers_details.rst
index afc95ed6ae..dc0a917b50 100644
--- a/docs/source/api/v4/servers_details.rst
+++ b/docs/source/api/v4/servers_details.rst
@@ -98,8 +98,7 @@ Response Structure
:mgmtIpNetmask: The IPv4 subnet mask of the server's management port
:offlineReason: A user-entered reason why the server is in ADMIN_DOWN or OFFLINE status
:physLocation: The name of the physical location where the server resides
- :profile: The :ref:`profile-name` of the :term:`Profile` used by this server
- :profileDesc: A :ref:`profile-description` of the :term:`Profile` used by this server
+ :profileNames: List of :ref:`profile-name` of the :term:`Profiles` used by this server
:rack: A string indicating "server rack" location
:status: The status of the server
@@ -157,8 +156,7 @@ Response Structure
"mgmtIpNetmask": "",
"offlineReason": "",
"physLocation": "Apachecon North America 2018",
- "profile": "ATS_EDGE_TIER_CACHE",
- "profileDesc": "Edge Cache - Apache Traffic Server",
+ "profileNames": ["ATS_EDGE_TIER_CACHE"],
"rack": "",
"status": "REPORTED",
"tcpPort": 80,
diff --git a/lib/go-tc/servers.go b/lib/go-tc/servers.go
index 23971316b5..2f435cdb3f 100644
--- a/lib/go-tc/servers.go
+++ b/lib/go-tc/servers.go
@@ -87,8 +87,33 @@ type ServerDetailV30 struct {
// ServerDetailV40 is the details for a server for API v4.
type ServerDetailV40 struct {
- ServerDetail
- ServerInterfaces []ServerInterfaceInfoV40 `json:"interfaces"`
+ CacheGroup *string `json:"cachegroup" db:"cachegroup"`
+ CDNName *string `json:"cdnName" db:"cdn_name"`
+ DeliveryServiceIDs []int64 `json:"deliveryservices,omitempty"`
+ DomainName *string `json:"domainName" db:"domain_name"`
+ GUID *string `json:"guid" db:"guid"`
+ HardwareInfo map[string]string `json:"hardwareInfo"`
+ HostName *string `json:"hostName" db:"host_name"`
+ HTTPSPort *int `json:"httpsPort" db:"https_port"`
+ ID *int `json:"id" db:"id"`
+ ILOIPAddress *string `json:"iloIpAddress" db:"ilo_ip_address"`
+ ILOIPGateway *string `json:"iloIpGateway" db:"ilo_ip_gateway"`
+ ILOIPNetmask *string `json:"iloIpNetmask" db:"ilo_ip_netmask"`
+ ILOPassword *string `json:"iloPassword" db:"ilo_password"`
+ ILOUsername *string `json:"iloUsername" db:"ilo_username"`
+ MgmtIPAddress *string `json:"mgmtIpAddress" db:"mgmt_ip_address"`
+ MgmtIPGateway *string `json:"mgmtIpGateway" db:"mgmt_ip_gateway"`
+ MgmtIPNetmask *string `json:"mgmtIpNetmask" db:"mgmt_ip_netmask"`
+ OfflineReason *string `json:"offlineReason" db:"offline_reason"`
+ PhysLocation *string `json:"physLocation" db:"phys_location"`
+ ProfileNames []string `json:"profileNames" db:"profile_name"`
+ Rack *string `json:"rack" db:"rack"`
+ Status *string `json:"status" db:"status"`
+ TCPPort *int `json:"tcpPort" db:"tcp_port"`
+ Type string `json:"type" db:"server_type"`
+ XMPPID *string `json:"xmppId" db:"xmpp_id"`
+ XMPPPasswd *string `json:"xmppPasswd" db:"xmpp_passwd"`
+ ServerInterfaces []ServerInterfaceInfoV40 `json:"interfaces"`
}
// ServersV1DetailResponse is the JSON object returned for a single server for v1.
diff --git a/traffic_ops/testing/api/v4/tc-fixtures.json b/traffic_ops/testing/api/v4/tc-fixtures.json
index 011a1a8042..ebf1fab2aa 100644
--- a/traffic_ops/testing/api/v4/tc-fixtures.json
+++ b/traffic_ops/testing/api/v4/tc-fixtures.json
@@ -5009,8 +5009,8 @@
{
"cachegroup": "cachegroup1",
"cdnName": "cdn1",
- "configUpdateTime": "2022-01-01T17:00:00-07:00",
- "configApplyTime": "1969-12-31T17:00:00-07:00",
+ "configUpdateTime": "2022-01-01T17:00:00-07:00",
+ "configApplyTime": "1969-12-31T17:00:00-07:00",
"domainName": "ga.atlanta.kabletown.net",
"guid": null,
"hostName": "config-update-time",
@@ -5060,8 +5060,8 @@
{
"cachegroup": "cachegroup1",
"cdnName": "cdn1",
- "configUpdateTime": "2022-01-01T17:00:00-07:00",
- "configApplyTime": "1969-12-31T17:00:00-07:00",
+ "configUpdateTime": "2022-01-01T17:00:00-07:00",
+ "configApplyTime": "1969-12-31T17:00:00-07:00",
"domainName": "ga.atlanta.kabletown.net",
"guid": null,
"hostName": "config-update-time-no-updpend",
@@ -5149,8 +5149,8 @@
"profileNames": ["EDGE1"],
"rack": "RR 119.02",
"revalPending": false,
- "revalUpdateTime": "2022-01-01T17:00:00-07:00",
- "revalApplyTime": "1969-12-31T17:00:00-07:00",
+ "revalUpdateTime": "2022-01-01T17:00:00-07:00",
+ "revalApplyTime": "1969-12-31T17:00:00-07:00",
"status": "REPORTED",
"tcpPort": 80,
"type": "EDGE",
@@ -5199,8 +5199,8 @@
"physLocation": "Denver",
"profileNames": ["EDGE1"],
"rack": "RR 119.02",
- "revalUpdateTime": "2022-01-01T17:00:00-07:00",
- "revalApplyTime": "1969-12-31T17:00:00-07:00",
+ "revalUpdateTime": "2022-01-01T17:00:00-07:00",
+ "revalApplyTime": "1969-12-31T17:00:00-07:00",
"status": "REPORTED",
"tcpPort": 80,
"type": "EDGE",
@@ -5211,8 +5211,8 @@
{
"cachegroup": "cachegroup1",
"cdnName": "cdn1",
- "configUpdateTime": "2022-01-01T17:00:00-07:00",
- "configApplyTime": "1969-12-31T17:00:00-07:00",
+ "configUpdateTime": "2022-01-01T17:00:00-07:00",
+ "configApplyTime": "1969-12-31T17:00:00-07:00",
"domainName": "ga.atlanta.kabletown.net",
"guid": null,
"hostName": "config-reval-update-time",
@@ -5252,8 +5252,8 @@
"profileNames": ["EDGE1"],
"rack": "RR 119.02",
"revalPending": false,
- "revalUpdateTime": "2022-01-01T17:00:00-07:00",
- "revalApplyTime": "1969-12-31T17:00:00-07:00",
+ "revalUpdateTime": "2022-01-01T17:00:00-07:00",
+ "revalApplyTime": "1969-12-31T17:00:00-07:00",
"status": "REPORTED",
"tcpPort": 80,
"type": "EDGE",
@@ -5264,8 +5264,8 @@
{
"cachegroup": "cachegroup1",
"cdnName": "cdn1",
- "configUpdateTime": "2022-01-01T17:00:00-07:00",
- "configApplyTime": "1969-12-31T17:00:00-07:00",
+ "configUpdateTime": "2022-01-01T17:00:00-07:00",
+ "configApplyTime": "1969-12-31T17:00:00-07:00",
"domainName": "ga.atlanta.kabletown.net",
"guid": null,
"hostName": "config-reval-update-time-only",
@@ -5304,8 +5304,8 @@
"physLocation": "Denver",
"profileNames": ["EDGE1"],
"rack": "RR 119.02",
- "revalUpdateTime": "2022-01-01T17:00:00-07:00",
- "revalApplyTime": "1969-12-31T17:00:00-07:00",
+ "revalUpdateTime": "2022-01-01T17:00:00-07:00",
+ "revalApplyTime": "1969-12-31T17:00:00-07:00",
"status": "REPORTED",
"tcpPort": 80,
"type": "EDGE",
diff --git a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
index e024126d01..dc029086bf 100644
--- a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
+++ b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
@@ -2091,6 +2091,43 @@ func UpdateServerProfileTableForV2V3(id *int, newProfile *string, origProfile st
return profileName, nil
}
+// GetServerDetailFromV4 function converts server details from V4 to V3/V2
+func GetServerDetailFromV4(sd tc.ServerDetailV40, tx *sql.Tx) (tc.ServerDetail, error) {
+ var profileDesc *string
+ if err := tx.QueryRow(`SELECT p.description FROM profile p WHERE p.name=$1`, sd.ProfileNames[0]).Scan(&profileDesc); err != nil {
+ return tc.ServerDetail{}, fmt.Errorf("querying profile description by profile name: %w", err)
+ }
+ return tc.ServerDetail{
+ CacheGroup: sd.CacheGroup,
+ CDNName: sd.CDNName,
+ DeliveryServiceIDs: sd.DeliveryServiceIDs,
+ DomainName: sd.DomainName,
+ GUID: sd.GUID,
+ HardwareInfo: sd.HardwareInfo,
+ HostName: sd.HostName,
+ HTTPSPort: sd.HTTPSPort,
+ ID: sd.ID,
+ ILOIPAddress: sd.ILOIPAddress,
+ ILOIPGateway: sd.ILOIPGateway,
+ ILOIPNetmask: sd.ILOIPNetmask,
+ ILOPassword: sd.ILOPassword,
+ ILOUsername: sd.ILOUsername,
+ MgmtIPAddress: sd.MgmtIPAddress,
+ MgmtIPGateway: sd.MgmtIPGateway,
+ MgmtIPNetmask: sd.MgmtIPNetmask,
+ OfflineReason: sd.OfflineReason,
+ PhysLocation: sd.PhysLocation,
+ Profile: &sd.ProfileNames[0],
+ ProfileDesc: profileDesc,
+ Rack: sd.Rack,
+ Status: sd.Status,
+ TCPPort: sd.TCPPort,
+ Type: sd.Type,
+ XMPPID: sd.XMPPID,
+ XMPPPasswd: sd.XMPPPasswd,
+ }, nil
+}
+
// GetProfileIDDesc gets profile ID and desc for V3 servers
func GetProfileIDDesc(tx *sql.Tx, name string) (id int, desc string) {
err := tx.QueryRow(`SELECT id, description from "profile" p WHERE p.name=$1`, name).Scan(&id, &desc)
diff --git a/traffic_ops/traffic_ops_golang/server/detail.go b/traffic_ops/traffic_ops_golang/server/detail.go
index 7f2eb9b1f7..aa45dd9552 100644
--- a/traffic_ops/traffic_ops_golang/server/detail.go
+++ b/traffic_ops/traffic_ops_golang/server/detail.go
@@ -91,7 +91,11 @@ func GetDetailParamHandler(w http.ResponseWriter, r *http.Request) {
routerPortName = interfaces[0].RouterPortName
}
v11server := tc.ServerDetailV11{}
- v11server.ServerDetail = server.ServerDetail
+ v11server.ServerDetail, err = dbhelpers.GetServerDetailFromV4(server, inf.Tx.Tx)
+ if err != nil {
+ api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("failed to GetServerDetailFromV4: %w", err))
+ return
+ }
v11server.RouterHostName = &routerHostName
v11server.RouterPortName = &routerPortName
legacyInterface, err := tc.V4InterfaceInfoToLegacyInterfaces(interfaces)
@@ -117,7 +121,11 @@ func GetDetailParamHandler(w http.ResponseWriter, r *http.Request) {
routerHostName = interfaces[0].RouterHostName
routerPortName = interfaces[0].RouterPortName
}
- v3Server.ServerDetail = server.ServerDetail
+ v3Server.ServerDetail, err = dbhelpers.GetServerDetailFromV4(server, inf.Tx.Tx)
+ if err != nil {
+ api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("failed to GetServerDetailFromV4: %w", err))
+ return
+ }
v3Server.RouterHostName = &routerHostName
v3Server.RouterPortName = &routerPortName
v3Interfaces, err := tc.V4InterfaceInfoToV3Interfaces(interfaces)
@@ -209,8 +217,7 @@ server.mgmt_ip_gateway,
server.mgmt_ip_netmask,
server.offline_reason,
pl.name as phys_location,
-p.name as profile,
-p.description as profile_desc,
+(SELECT ARRAY_AGG(profile_name) FROM server_profile WHERE server_profile.server=server.id) AS profile_name,
server.rack,
st.name as status,
server.tcp_port,
@@ -275,7 +282,38 @@ JOIN type t ON server.type = t.id
for rows.Next() {
s := tc.ServerDetailV40{}
- if err := rows.Scan(&s.ID, &s.CacheGroup, &s.CDNName, pq.Array(&s.DeliveryServiceIDs), &s.DomainName, &s.GUID, &s.HostName, &s.HTTPSPort, &s.ILOIPAddress, &s.ILOIPGateway, &s.ILOIPNetmask, &s.ILOPassword, &s.ILOUsername, &serviceAddress, &service6Address, &serviceGateway, &service6Gateway, &serviceNetmask, &serviceInterface, &serviceMtu, &s.MgmtIPAddress, &s.MgmtIPGateway, &s.MgmtIPNetmask, &s.OfflineReason, &s.PhysLocation, &s.Profile, &s.ProfileDesc, &s.Rack, &s.Status, &s.TCPPort, & [...]
+ if err := rows.Scan(&s.ID,
+ &s.CacheGroup,
+ &s.CDNName,
+ pq.Array(&s.DeliveryServiceIDs),
+ &s.DomainName,
+ &s.GUID,
+ &s.HostName,
+ &s.HTTPSPort,
+ &s.ILOIPAddress,
+ &s.ILOIPGateway,
+ &s.ILOIPNetmask,
+ &s.ILOPassword,
+ &s.ILOUsername,
+ &serviceAddress,
+ &service6Address,
+ &serviceGateway,
+ &service6Gateway,
+ &serviceNetmask,
+ &serviceInterface,
+ &serviceMtu,
+ &s.MgmtIPAddress,
+ &s.MgmtIPGateway,
+ &s.MgmtIPNetmask,
+ &s.OfflineReason,
+ &s.PhysLocation,
+ pq.Array(&s.ProfileNames),
+ &s.Rack,
+ &s.Status,
+ &s.TCPPort,
+ &s.Type,
+ &s.XMPPID,
+ &s.XMPPPasswd); err != nil {
return nil, errors.New("Error scanning detail server: " + err.Error())
}
s.ServerInterfaces = []tc.ServerInterfaceInfoV40{}
diff --git a/traffic_ops/traffic_ops_golang/server/detail_test.go b/traffic_ops/traffic_ops_golang/server/detail_test.go
index 9ad95ac564..bbcfa53788 100644
--- a/traffic_ops/traffic_ops_golang/server/detail_test.go
+++ b/traffic_ops/traffic_ops_golang/server/detail_test.go
@@ -13,7 +13,9 @@ package server
*/
import (
+ "fmt"
"strconv"
+ "strings"
"testing"
"github.com/apache/trafficcontrol/lib/go-tc"
@@ -75,8 +77,7 @@ func TestGetDetailServers(t *testing.T) {
"mgmt_ip_netmask",
"offline_reason",
"phys_location",
- "profile",
- "profile_desc",
+ "profile_name",
"rack",
"status",
"tcp_port",
@@ -93,8 +94,6 @@ func TestGetDetailServers(t *testing.T) {
serviceNetmask := util.StrPtr("")
serviceInterface := util.StrPtr("")
serviceMtu := util.StrPtr("")
- //routerHostName := util.StrPtr("")
- //routerPort := util.StrPtr("")
for _, sd := range testServerDetails {
detailRows = detailRows.AddRow(
@@ -123,8 +122,7 @@ func TestGetDetailServers(t *testing.T) {
sd.MgmtIPNetmask,
sd.OfflineReason,
sd.PhysLocation,
- sd.Profile,
- sd.ProfileDesc,
+ fmt.Sprintf("{%s}", strings.Join(sd.ProfileNames, ",")),
sd.Rack,
sd.Status,
sd.TCPPort,
@@ -143,7 +141,7 @@ func TestGetDetailServers(t *testing.T) {
mock.ExpectQuery("SELECT serverid").WillReturnRows(hwInfoRows)
mock.ExpectCommit()
- actualSrvs, err := getDetailServers(db.MustBegin().Tx, &auth.CurrentUser{PrivLevel: 30}, "test", 1, "id", 10, api.Version{Major: 3})
+ actualSrvs, err := getDetailServers(db.MustBegin().Tx, &auth.CurrentUser{PrivLevel: 30}, "test", 1, "id", 10, api.Version{Major: 4})
if err != nil {
t.Fatalf("an error '%s' occurred during read", err)
}
@@ -170,9 +168,7 @@ func TestGetDetailServers(t *testing.T) {
func getMockServerDetails() []tc.ServerDetailV40 {
srvData := tc.ServerDetailV40{
- ServerDetail: tc.ServerDetail{
- ID: util.IntPtr(1),
- },
+ ID: util.IntPtr(1),
ServerInterfaces: []tc.ServerInterfaceInfoV40{}, // left empty because it must be written as json above since sqlmock does not support nested arrays
}
return []tc.ServerDetailV40{srvData}