From 136c787867c25189cdc97a75a84f5202cc726b14 Mon Sep 17 00:00:00 2001 From: mjacks258 Date: Thu, 30 Apr 2020 12:55:31 -0600 Subject: [PATCH 1/9] updated /deliveryservices/{{ID}}/servers and /deliveryservices/{{ID}}/servers/eligible to use multiple interfaces --- CHANGELOG.md | 2 + .../api/v3/deliveryservices_id_servers.rst | 67 ++++++++---- .../deliveryservices_id_servers_eligible.rst | 67 ++++++++---- lib/go-tc/deliveryservice_servers.go | 24 ++--- lib/go-tc/servers.go | 102 ++++++++++++++++++ traffic_ops/client/deliveryservice.go | 6 +- .../deliveryservice/eligible.go | 71 +++++++----- .../deliveryservice/servers/servers.go | 99 ++++++++++++++--- traffic_ops/v1-client/deliveryservice.go | 6 +- traffic_ops/v2-client/deliveryservice.go | 6 +- 10 files changed, 343 insertions(+), 107 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e052f082fd..baaee5af9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Updated /servers/details to use multiple interfaces in API v3 - Added [Edge Traffic Routing](https://traffic-control-cdn.readthedocs.io/en/latest/admin/traffic_router.html#edge-traffic-routing) feature which allows Traffic Router to localize more DNS record types than just the routing name for DNS delivery services - Astats csv support - astats will now respond to `Accept: text/csv` and return a csv formatted stats list +- Updated /deliveryservices/{{ID}}/servers to use multiple interfaces in API v3 +- Updated /deliveryservices/{{ID}}/servers/eligible to use multiple interfaces in API v3 ### Fixed - Fixed the `GET /api/x/jobs` and `GET /api/x/jobs/:id` Traffic Ops API routes to allow falling back to Perl via the routing blacklist diff --git a/docs/source/api/v3/deliveryservices_id_servers.rst b/docs/source/api/v3/deliveryservices_id_servers.rst index 731050535a..75c2a30c8f 100644 --- a/docs/source/api/v3/deliveryservices_id_servers.rst +++ b/docs/source/api/v3/deliveryservices_id_servers.rst @@ -54,20 +54,23 @@ Response Structure :iloIpNetmask: The IPv4 subnet mask of the lights-out-management port\ [#ilowikipedia]_ :iloPassword: The password of the of the lights-out-management user - displays as ``******`` unless the requesting user has the 'admin' role)\ [#ilowikipedia]_ :iloUsername: The user name for lights-out-management\ [#ilowikipedia]_ -:interfaceMtu: The :abbr:`MTU (Maximum Transmission Unit)` to configure for ``interfaceName`` +:interfaces: An array of interface and IP address information - .. seealso:: `The Wikipedia article on Maximum Transmission Unit `_ + :max_bandwidth: The maximum allowed bandwidth for this interface to be considered "healthy" by Traffic Monitor. This has no effect if `monitor` is not true. Values are in kb/s. The value `0` means "no limit". + :monitor: A boolean indicating if Traffic Monitor should monitor this interface + :mtu: The :abbr:`MTU (Maximum Transmission Unit)` to configure for ``interfaceName`` + + .. seealso:: `The Wikipedia article on Maximum Transmission Unit `_ + + :name: The network interface name used by the server. A value of 'mgmt' indicates a management port. + + :ipAddresses: An array of the IP address information for the interface + + :ip6Address: The IPv4 or IPv6 address and subnet mask of the server - applicable for the interface ``name`` + :ip6Gateway: The IPv4 or IPv6 gateway address of the server - applicable for the interface ``name`` + :service_address: A boolean determining if content will be routed to the IP address -:interfaceName: The network interface name used by the server -:ip6Address: The IPv6 address and subnet mask of the server - applicable for the interface ``interfaceName`` -:ip6Gateway: The IPv6 gateway address of the server - applicable for the interface ``interfaceName`` -:ipAddress: The IPv4 address of the server- applicable for the interface ``interfaceName`` -:ipGateway: The IPv4 gateway of the server- applicable for the interface ``interfaceName`` -:ipNetmask: The IPv4 subnet mask of the server- applicable for the interface ``interfaceName`` :lastUpdated: The time and date at which this server was last updated, in an ISO-like format -:mgmtIpAddress: The IPv4 address of the server's management port -:mgmtIpGateway: The IPv4 gateway of the server's management port -: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 (will be empty if not offline) :physLocation: The name of the :term:`Physical Location` at which the server resides :physLocationId: An integral, unique identifier for the :term:`Physical Location` at which the server resides @@ -121,17 +124,7 @@ Response Structure "iloIpNetmask": "", "iloPassword": "", "iloUsername": "", - "interfaceMtu": 1500, - "interfaceName": "eth0", - "ip6Address": "fc01:9400:1000:8::100", - "ip6Gateway": "fc01:9400:1000:8::1", - "ipAddress": "172.16.239.100", - "ipGateway": "172.16.239.1", - "ipNetmask": "255.255.255.0", "lastUpdated": "2018-11-14 21:08:44+00", - "mgmtIpAddress": "", - "mgmtIpGateway": "", - "mgmtIpNetmask": "", "offlineReason": "", "physLocation": "Apachecon North America 2018", "physLocationId": 1, @@ -146,7 +139,37 @@ Response Structure "tcpPort": 80, "type": "EDGE", "typeId": 11, - "updPending": false + "updPending": false, + "interfaces": [{ + "ipAddresses": [ + { + "address": "172.16.239.101", + "gateway": "", + "service_address": false + } + ], + "max_bandwidth": 0, + "monitor": false, + "mtu": 9000, + "name": "mgmt" + }, + { "ipAddresses": [ + { + "address": "172.16.239.100", + "gateway": "172.16.239.1", + "service_address": true + }, + { + "address": "fc01:9400:1000:8::100", + "gateway": "fc01:9400:1000:8::1", + "service_address": true + } + ], + "max_bandwidth": 0, + "monitor": true, + "mtu": 1500, + "name": "eth0" + }] } ]} diff --git a/docs/source/api/v3/deliveryservices_id_servers_eligible.rst b/docs/source/api/v3/deliveryservices_id_servers_eligible.rst index f6bd15b11b..865f384ec1 100644 --- a/docs/source/api/v3/deliveryservices_id_servers_eligible.rst +++ b/docs/source/api/v3/deliveryservices_id_servers_eligible.rst @@ -59,20 +59,23 @@ Response Structure :iloIpNetmask: The IPv4 subnet mask of the lights-out-management port\ [#ilowikipedia]_ :iloPassword: The password of the of the lights-out-management user - displays as ``******`` unless the requesting user has the 'admin' role)\ [#ilowikipedia]_ :iloUsername: The user name for lights-out-management\ [#ilowikipedia]_ -:interfaceMtu: The :abbr:`MTU (Maximum Transmission Unit)` to configure for ``interfaceName`` +:interfaces: An array of interface and IP address information - .. seealso:: `The Wikipedia article on Maximum Transmission Unit `_ + :max_bandwidth: The maximum allowed bandwidth for this interface to be considered "healthy" by Traffic Monitor. This has no effect if `monitor` is not true. Values are in kb/s. The value `0` means "no limit". + :monitor: A boolean indicating if Traffic Monitor should monitor this interface + :mtu: The :abbr:`MTU (Maximum Transmission Unit)` to configure for ``interfaceName`` + + .. seealso:: `The Wikipedia article on Maximum Transmission Unit `_ + + :name: The network interface name used by the server. A value of 'mgmt' indicates a management port. + + :ipAddresses: An array of the IP address information for the interface + + :ip6Address: The IPv4 or IPv6 address and subnet mask of the server - applicable for the interface ``name`` + :ip6Gateway: The IPv4 or IPv6 gateway address of the server - applicable for the interface ``name`` + :service_address: A boolean determining if content will be routed to the IP address -:interfaceName: The network interface name used by the server -:ip6Address: The IPv6 address and subnet mask of the server - applicable for the interface ``interfaceName`` -:ip6Gateway: The IPv6 gateway address of the server - applicable for the interface ``interfaceName`` -:ipAddress: The IPv4 address of the server- applicable for the interface ``interfaceName`` -:ipGateway: The IPv4 gateway of the server- applicable for the interface ``interfaceName`` -:ipNetmask: The IPv4 subnet mask of the server- applicable for the interface ``interfaceName`` :lastUpdated: The time and date at which this server was last updated, in an ISO-like format -:mgmtIpAddress: The IPv4 address of the server's management port -:mgmtIpGateway: The IPv4 gateway of the server's management port -: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 (will be empty if not offline) :physLocation: The name of the :term:`Physical Location` at which the server resides :physLocationId: An integral, unique identifier for the :term:`Physical Location` at which the server resides @@ -114,17 +117,7 @@ Response Structure "iloIpNetmask": "", "iloPassword": "", "iloUsername": "", - "interfaceMtu": 1500, - "interfaceName": "eth0", - "ip6Address": "fc01:9400:1000:8::100", - "ip6Gateway": "fc01:9400:1000:8::1", - "ipAddress": "172.16.239.100", - "ipGateway": "172.16.239.1", - "ipNetmask": "255.255.255.0", "lastUpdated": "2018-10-30 16:01:12+00", - "mgmtIpAddress": "", - "mgmtIpGateway": "", - "mgmtIpNetmask": "", "offlineReason": "", "physLocation": "Apachecon North America 2018", "physLocationId": 1, @@ -139,7 +132,37 @@ Response Structure "tcpPort": 80, "type": "EDGE", "typeId": 11, - "updPending": false + "updPending": false, + "interfaces": [{ + "ipAddresses": [ + { + "address": "172.16.239.101", + "gateway": "", + "service_address": false + } + ], + "max_bandwidth": 0, + "monitor": false, + "mtu": 9000, + "name": "mgmt" + }, + { "ipAddresses": [ + { + "address": "172.16.239.100", + "gateway": "172.16.239.1", + "service_address": true + }, + { + "address": "fc01:9400:1000:8::100", + "gateway": "fc01:9400:1000:8::1", + "service_address": true + } + ], + "max_bandwidth": 0, + "monitor": true, + "mtu": 1500, + "name": "eth0" + }] } ]} diff --git a/lib/go-tc/deliveryservice_servers.go b/lib/go-tc/deliveryservice_servers.go index b082b567b2..f5e634f0be 100644 --- a/lib/go-tc/deliveryservice_servers.go +++ b/lib/go-tc/deliveryservice_servers.go @@ -63,10 +63,6 @@ const ( Eligible ) -type DSServersAttrResponse struct { - Response []DSServer `json:"response"` -} - type DSServer struct { Cachegroup *string `json:"cachegroup" db:"cachegroup"` CachegroupID *int `json:"cachegroupId" db:"cachegroup_id"` @@ -85,17 +81,7 @@ type DSServer struct { ILOIPNetmask *string `json:"iloIpNetmask" db:"ilo_ip_netmask"` ILOPassword *string `json:"iloPassword" db:"ilo_password"` ILOUsername *string `json:"iloUsername" db:"ilo_username"` - InterfaceMtu *int `json:"interfaceMtu" db:"interface_mtu"` - InterfaceName *string `json:"interfaceName" db:"interface_name"` - IP6Address *string `json:"ip6Address" db:"ip6_address"` - IP6Gateway *string `json:"ip6Gateway" db:"ip6_gateway"` - IPAddress *string `json:"ipAddress" db:"ip_address"` - IPGateway *string `json:"ipGateway" db:"ip_gateway"` - IPNetmask *string `json:"ipNetmask" db:"ip_netmask"` LastUpdated *TimeNoMod `json:"lastUpdated" db:"last_updated"` - 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"` PhysLocationID *int `json:"physLocationId" db:"phys_location_id"` @@ -114,3 +100,13 @@ type DSServer struct { ServerCapabilities []string `json:"-" db:"server_capabilities"` DeliveryServiceCapabilities []string `json:"-" db:"deliveryservice_capabilities"` } + +type DSServerV11 struct { + DSServer + LegacyInterfaceDetails +} + +type DSServerV30 struct { + DSServer + ServerInterfaces *[]ServerInterfaceInfo `json:"interfaces" db:"interfaces"` +} diff --git a/lib/go-tc/servers.go b/lib/go-tc/servers.go index 0904a52590..bbaa88f501 100644 --- a/lib/go-tc/servers.go +++ b/lib/go-tc/servers.go @@ -8,6 +8,9 @@ import ( "net" "time" + "github.com/go-ozzo/ozzo-validation" + + "github.com/apache/trafficcontrol/lib/go-tc/tovalidate" "github.com/apache/trafficcontrol/lib/go-util" ) @@ -481,6 +484,20 @@ type ServerDetail struct { XMPPPasswd *string `json:"xmppPasswd" db:"xmpp_passwd"` } +// LegacyInterfaceDetails is the details for interfaces on servers for API v1 and v2 +type LegacyInterfaceDetails struct { + InterfaceMTU *int `json:"interfaceMtu" db:"interface_mtu"` + InterfaceName *string `json:"interfaceName" db:"interface_name"` + IP6Address *string `json:"ip6Address" db:"ip6_address"` + IP6Gateway *string `json:"ip6Gateway" db:"ip6_gateway"` + IPAddress *string `json:"ipAddress" db:"ip_address"` + IPGateway *string `json:"ipGateway" db:"ip_gateway"` + IPNetmask *string `json:"ipNetmask" db:"ip_netmask"` + MgmtIPAddress *string `json:"mgmtIpAddress" db:"mgmt_ip_address"` + MgmtIPGateway *string `json:"mgmtIpGateway" db:"mgmt_ip_gateway"` + MgmtIPNetmask *string `json:"mgmtIpNetmask" db:"mgmt_ip_netmask"` +} + // ServerQueueUpdateRequest encodes the request data for the POST // servers/{{ID}}/queue_update endpoint. type ServerQueueUpdateRequest struct { @@ -500,3 +517,88 @@ type ServerQueueUpdate struct { ServerID util.JSONIntStr `json:"serverId"` Action string `json:"action"` } + +// ServerInterface is the data associated with an interface +type ServerInterface struct { + MaxBandwidth int64 `json:"max_bandwidth" db:"max_bandwidth"` + Monitor bool `json:"monitor" db:"monitor"` + Mtu int64 `json:"mtu" db:"mtu"` + Name string `json:"name" db:"name"` + Server int `json:"server" db:"server"` +} + +// ServerIpAddress is the data associated with an IP address +type ServerIpAddress struct { + Address string `json:"address" db:"address"` + Gateway string `json:"gateway" db:"gateway"` + Interface string `json:"interface,omitempty" db:"interface"` + Server int `json:"server,omitempty" db:"server"` + ServiceAddress bool `json:"service_address" db:"service_address"` +} + +// ServerInterfaceInfo is the combined data from both IP address information and interface information +type ServerInterfaceInfo struct { + IpAddresses []ServerIpAddress `json:"ipAddresses" db:"ipAddresses"` + MaxBandwidth int64 `json:"max_bandwidth" db:"max_bandwidth"` + Monitor bool `json:"monitor" db:"monitor"` + Mtu int `json:"mtu" db:"mtu"` + Name string `json:"name" db:"name"` +} + +// Value implements the driver.Valuer interface +// marshals struct to json to pass back as a json.RawMessage +func (sii *ServerInterfaceInfo) Value() (driver.Value, error) { + b, err := json.Marshal(sii) + return b, err +} + +// Scan implements the sql.Scanner interface +// expects json.RawMessage and unmarshals to a deliveryservice struct +func (sii *ServerInterfaceInfo) Scan(src interface{}) error { + b, ok := src.([]byte) + if !ok { + return fmt.Errorf("expected deliveryservice in byte array form; got %T", src) + } + + return json.Unmarshal([]byte(b), sii) +} + +// ConvertInterfaceInfotoV11 converts ServerInterfaceInfo to LegacyInterfaceDetails for v1 and v2 compatibility +func ConvertInterfaceInfotoV11(serverInterfaces []ServerInterfaceInfo) (LegacyInterfaceDetails, error) { + legacyDetails := LegacyInterfaceDetails{} + for _, intFace := range serverInterfaces { + legacyDetails.InterfaceMTU = &intFace.Mtu + legacyDetails.InterfaceName = &intFace.Name + + for _, addr := range intFace.IpAddresses { + address := addr.Address + gateway := addr.Gateway + + parsedIp, netmask, err := net.ParseCIDR(address) + netmaskString := "" + if err == nil { + mask := netmask.Mask + netmaskString = fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3]) + } + + if intFace.Name == "mgmt" { + legacyDetails.MgmtIPAddress = &address + legacyDetails.MgmtIPGateway = &gateway + legacyDetails.MgmtIPNetmask = &netmaskString + continue + } + + if err = validation.Validate(&addr.Address, validation.By(tovalidate.IsValidIPv6CIDROrAddress)); err != nil { + ip := parsedIp.String() + legacyDetails.IPAddress = &ip + legacyDetails.IPGateway = &gateway + legacyDetails.IPNetmask = &netmaskString + } else { + legacyDetails.IP6Address = &address + legacyDetails.IP6Gateway = &gateway + } + } + } + + return legacyDetails, nil +} diff --git a/traffic_ops/client/deliveryservice.go b/traffic_ops/client/deliveryservice.go index 5cd866d36a..7ad1e4877e 100644 --- a/traffic_ops/client/deliveryservice.go +++ b/traffic_ops/client/deliveryservice.go @@ -322,10 +322,10 @@ func (to *Session) GetDeliveryServiceSSLKeysByID(XMLID string) (*tc.DeliveryServ // GetDeliveryServicesEligible returns the servers eligible for assignment to the Delivery // Service identified by the integral, unique identifier 'dsID'. -func (to *Session) GetDeliveryServicesEligible(dsID int) ([]tc.DSServer, ReqInf, error) { +func (to *Session) GetDeliveryServicesEligible(dsID int) ([]tc.DSServerV30, ReqInf, error) { resp := struct { - Response []tc.DSServer `json:"response"` - }{Response: []tc.DSServer{}} + Response []tc.DSServerV30 `json:"response"` + }{Response: []tc.DSServerV30{}} reqInf, err := get(to, fmt.Sprintf(API_DELIVERY_SERVICE_ELIGIBLE_SERVERS, dsID), &resp) if err != nil { diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go b/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go index cbc4edfe0f..0c16a8fdc6 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go @@ -23,7 +23,6 @@ import ( "database/sql" "errors" "net/http" - "strconv" "strings" "github.com/apache/trafficcontrol/lib/go-tc" @@ -63,12 +62,32 @@ func GetServersEligible(w http.ResponseWriter, r *http.Request) { api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting eligible servers: "+err.Error())) return } + + if inf.Version.Major < 3 { + v11ServerList := []tc.DSServerV11{} + for _, srv := range servers { + v11server := tc.DSServerV11{} + v11server.DSServer = srv.DSServer + + interfaces := *srv.ServerInterfaces + legacyInterface, err := tc.ConvertInterfaceInfotoV11(interfaces) + if err != nil { + api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("converting to server detail v11: "+err.Error())) + return + } + v11server.LegacyInterfaceDetails = legacyInterface + + v11ServerList = append(v11ServerList, v11server) + } + api.WriteResp(w, r, v11ServerList) + return + } api.WriteResp(w, r, servers) } const JumboFrameBPS = 9000 -func getEligibleServers(tx *sql.Tx, dsID int) ([]tc.DSServer, error) { +func getEligibleServers(tx *sql.Tx, dsID int) ([]tc.DSServerV30, error) { q := ` WITH ds_id as (SELECT $1::bigint as v) SELECT @@ -86,17 +105,27 @@ s.ilo_ip_gateway, s.ilo_ip_netmask, s.ilo_password, s.ilo_username, -COALESCE(s.interface_mtu, ` + strconv.Itoa(JumboFrameBPS) + `) as interface_mtu, -s.interface_name, -s.ip6_address, -s.ip6_gateway, -s.ip_address, -s.ip_gateway, -s.ip_netmask, + ARRAY ( +SELECT ( json_build_object ( +'ipAddresses', ARRAY ( +SELECT ( json_build_object ( +'address', ip_address.address, +'gateway', ip_address.gateway, +'service_address', ip_address.service_address +)) +FROM ip_address +WHERE ip_address.interface = interface.name +AND ip_address.server = s.id +), +'max_bandwidth', interface.max_bandwidth, +'monitor', interface.monitor, +'mtu', COALESCE (interface.mtu, 9000), +'name', interface.name +)) +FROM interface +WHERE interface.server = s.id +) AS interfaces, s.last_updated, -s.mgmt_ip_address, -s.mgmt_ip_gateway, -s.mgmt_ip_netmask, s.offline_reason, pl.name as phys_location, s.phys_location as phys_location_id, @@ -130,9 +159,10 @@ AND (t.name LIKE 'EDGE%' OR t.name LIKE 'ORG%') } defer rows.Close() - servers := []tc.DSServer{} + serverInterfaceInfo := []tc.ServerInterfaceInfo{} + servers := []tc.DSServerV30{} for rows.Next() { - s := tc.DSServer{} + s := tc.DSServerV30{} err := rows.Scan( &s.Cachegroup, &s.CachegroupID, @@ -148,17 +178,8 @@ AND (t.name LIKE 'EDGE%' OR t.name LIKE 'ORG%') &s.ILOIPNetmask, &s.ILOPassword, &s.ILOUsername, - &s.InterfaceMtu, - &s.InterfaceName, - &s.IP6Address, - &s.IP6Gateway, - &s.IPAddress, - &s.IPGateway, - &s.IPNetmask, + pq.Array(&serverInterfaceInfo), &s.LastUpdated, - &s.MgmtIPAddress, - &s.MgmtIPGateway, - &s.MgmtIPNetmask, &s.OfflineReason, &s.PhysLocation, &s.PhysLocationID, @@ -180,6 +201,8 @@ AND (t.name LIKE 'EDGE%' OR t.name LIKE 'ORG%') if err != nil { return nil, errors.New("scanning delivery service eligible servers: " + err.Error()) } + s.ServerInterfaces = &serverInterfaceInfo + eligible := true if !strings.HasPrefix(s.Type, "ORG") { diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go index 99d4bc4513..7602f54cd5 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go @@ -38,7 +38,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice" "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant" - validation "github.com/go-ozzo/ozzo-validation" + "github.com/go-ozzo/ozzo-validation" "github.com/jmoiron/sqlx" "github.com/lib/pq" ) @@ -523,10 +523,31 @@ func getRead(w http.ResponseWriter, r *http.Request, unassigned bool, alerts tc. api.WriteAlerts(w, r, http.StatusInternalServerError, alerts) return } - api.WriteAlertsObj(w, r, 200, alerts, servers) + + if inf.Version.Major < 3 { + v11ServerList := []tc.DSServerV11{} + for _, srv := range servers { + v11server := tc.DSServerV11{} + v11server.DSServer = srv.DSServer + + interfaces := *srv.ServerInterfaces + legacyInterface, err := tc.ConvertInterfaceInfotoV11(interfaces) + if err != nil { + api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("converting to server detail v11: "+err.Error())) + return + } + v11server.LegacyInterfaceDetails = legacyInterface + + v11ServerList = append(v11ServerList, v11server) + } + api.WriteAlertsObj(w, r, http.StatusOK, alerts, v11ServerList) + return + } + + api.WriteAlertsObj(w, r, http.StatusOK, alerts, servers) } -func read(tx *sqlx.Tx, dsID int, user *auth.CurrentUser, unassigned bool) ([]tc.DSServer, error) { +func read(tx *sqlx.Tx, dsID int, user *auth.CurrentUser, unassigned bool) ([]tc.DSServerV30, error) { where := `WHERE s.id in (select server from deliveryservice_server where deliveryservice = $1)` if unassigned { where = `WHERE s.id not in (select server from deliveryservice_server where deliveryservice = $1)` @@ -539,12 +560,48 @@ func read(tx *sqlx.Tx, dsID int, user *auth.CurrentUser, unassigned bool) ([]tc. } defer rows.Close() - servers := []tc.DSServer{} + serverInterfaceInfo := []tc.ServerInterfaceInfo{} + servers := []tc.DSServerV30{} for rows.Next() { - s := tc.DSServer{} - if err = rows.StructScan(&s); err != nil { + s := tc.DSServerV30{} + err := rows.Scan( + &s.Cachegroup, + &s.CachegroupID, + &s.CDNID, + &s.CDNName, + &s.DomainName, + &s.GUID, + &s.HostName, + &s.HTTPSPort, + &s.ID, + &s.ILOIPAddress, + &s.ILOIPGateway, + &s.ILOIPNetmask, + &s.ILOPassword, + &s.ILOUsername, + pq.Array(&serverInterfaceInfo), + &s.LastUpdated, + &s.OfflineReason, + &s.PhysLocation, + &s.PhysLocationID, + &s.Profile, + &s.ProfileDesc, + &s.ProfileID, + &s.Rack, + &s.RouterHostName, + &s.RouterPortName, + &s.Status, + &s.StatusID, + &s.TCPPort, + &s.Type, + &s.TypeID, + &s.UpdPending, + ) + if err != nil { return nil, errors.New("error scanning dss rows: " + err.Error()) } + s.ServerInterfaces = &serverInterfaceInfo + if user.PrivLevel < auth.PrivLevelAdmin { s.ILOPassword = util.StrPtr("") } @@ -574,17 +631,27 @@ func dssSelectQuery() string { s.ilo_ip_netmask, s.ilo_password, s.ilo_username, - COALESCE(s.interface_mtu, ` + strconv.Itoa(JumboFrameBPS) + `) as interface_mtu, - s.interface_name, - s.ip6_address, - s.ip6_gateway, - s.ip_address, - s.ip_gateway, - s.ip_netmask, + ARRAY ( +SELECT ( json_build_object ( +'ipAddresses', ARRAY ( +SELECT ( json_build_object ( +'address', ip_address.address, +'gateway', ip_address.gateway, +'service_address', ip_address.service_address +)) +FROM ip_address +WHERE ip_address.interface = interface.name +AND ip_address.server = s.id +), +'max_bandwidth', interface.max_bandwidth, +'monitor', interface.monitor, +'mtu', COALESCE (interface.mtu, 9000), +'name', interface.name +)) +FROM interface +WHERE interface.server = s.id +) AS interfaces, s.last_updated, - s.mgmt_ip_address, - s.mgmt_ip_gateway, - s.mgmt_ip_netmask, s.offline_reason, pl.name as phys_location, s.phys_location as phys_location_id, diff --git a/traffic_ops/v1-client/deliveryservice.go b/traffic_ops/v1-client/deliveryservice.go index 5fb7300b48..9f99b813a3 100644 --- a/traffic_ops/v1-client/deliveryservice.go +++ b/traffic_ops/v1-client/deliveryservice.go @@ -345,10 +345,10 @@ func (to *Session) GetDeliveryServiceMatches() ([]tc.DeliveryServicePatterns, Re return resp.Response, reqInf, nil } -func (to *Session) GetDeliveryServicesEligible(dsID int) ([]tc.DSServer, ReqInf, error) { +func (to *Session) GetDeliveryServicesEligible(dsID int) ([]tc.DSServerV11, ReqInf, error) { resp := struct { - Response []tc.DSServer `json:"response"` - }{Response: []tc.DSServer{}} + Response []tc.DSServerV11 `json:"response"` + }{Response: []tc.DSServerV11{}} uri := apiBase + `/deliveryservices/` + strconv.Itoa(dsID) + `/servers/eligible` reqInf, err := get(to, uri, &resp) if err != nil { diff --git a/traffic_ops/v2-client/deliveryservice.go b/traffic_ops/v2-client/deliveryservice.go index 7191391caa..e56aaed40a 100644 --- a/traffic_ops/v2-client/deliveryservice.go +++ b/traffic_ops/v2-client/deliveryservice.go @@ -317,10 +317,10 @@ func (to *Session) GetDeliveryServiceSSLKeysByID(XMLID string) (*tc.DeliveryServ // GetDeliveryServicesEligible returns the servers eligible for assignment to the Delivery // Service identified by the integral, unique identifier 'dsID'. -func (to *Session) GetDeliveryServicesEligible(dsID int) ([]tc.DSServer, ReqInf, error) { +func (to *Session) GetDeliveryServicesEligible(dsID int) ([]tc.DSServerV11, ReqInf, error) { resp := struct { - Response []tc.DSServer `json:"response"` - }{Response: []tc.DSServer{}} + Response []tc.DSServerV11 `json:"response"` + }{Response: []tc.DSServerV11{}} reqInf, err := get(to, fmt.Sprintf(API_DELIVERY_SERVICE_ELIGIBLE_SERVERS, dsID), &resp) if err != nil { From 40b4c7f19fd629d99a269064a1dcba4d580b4fc2 Mon Sep 17 00:00:00 2001 From: mjacks258 Date: Wed, 6 May 2020 08:36:01 -0600 Subject: [PATCH 2/9] updates per comments --- .../api/v3/deliveryservices_id_servers.rst | 2 +- .../deliveryservices_id_servers_eligible.rst | 2 +- lib/go-tc/deliveryservice_servers.go | 11 ++++--- lib/go-tc/servers.go | 29 +++++++------------ traffic_ops/client/deliveryservice.go | 6 ++-- .../deliveryservice/eligible.go | 8 ++--- .../deliveryservice/servers/servers.go | 8 ++--- 7 files changed, 30 insertions(+), 36 deletions(-) diff --git a/docs/source/api/v3/deliveryservices_id_servers.rst b/docs/source/api/v3/deliveryservices_id_servers.rst index 75c2a30c8f..79a3b0b542 100644 --- a/docs/source/api/v3/deliveryservices_id_servers.rst +++ b/docs/source/api/v3/deliveryservices_id_servers.rst @@ -56,7 +56,7 @@ Response Structure :iloUsername: The user name for lights-out-management\ [#ilowikipedia]_ :interfaces: An array of interface and IP address information - :max_bandwidth: The maximum allowed bandwidth for this interface to be considered "healthy" by Traffic Monitor. This has no effect if `monitor` is not true. Values are in kb/s. The value `0` means "no limit". + :max_bandwidth: The maximum allowed bandwidth for this interface to be considered "healthy" by Traffic Monitor. This has no effect if `monitor` is not true. Values are in kb/s. The value `null` means "no limit". :monitor: A boolean indicating if Traffic Monitor should monitor this interface :mtu: The :abbr:`MTU (Maximum Transmission Unit)` to configure for ``interfaceName`` diff --git a/docs/source/api/v3/deliveryservices_id_servers_eligible.rst b/docs/source/api/v3/deliveryservices_id_servers_eligible.rst index 865f384ec1..b502518bc1 100644 --- a/docs/source/api/v3/deliveryservices_id_servers_eligible.rst +++ b/docs/source/api/v3/deliveryservices_id_servers_eligible.rst @@ -61,7 +61,7 @@ Response Structure :iloUsername: The user name for lights-out-management\ [#ilowikipedia]_ :interfaces: An array of interface and IP address information - :max_bandwidth: The maximum allowed bandwidth for this interface to be considered "healthy" by Traffic Monitor. This has no effect if `monitor` is not true. Values are in kb/s. The value `0` means "no limit". + :max_bandwidth: The maximum allowed bandwidth for this interface to be considered "healthy" by Traffic Monitor. This has no effect if `monitor` is not true. Values are in kb/s. The value `null` means "no limit". :monitor: A boolean indicating if Traffic Monitor should monitor this interface :mtu: The :abbr:`MTU (Maximum Transmission Unit)` to configure for ``interfaceName`` diff --git a/lib/go-tc/deliveryservice_servers.go b/lib/go-tc/deliveryservice_servers.go index f5e634f0be..806dd34340 100644 --- a/lib/go-tc/deliveryservice_servers.go +++ b/lib/go-tc/deliveryservice_servers.go @@ -63,7 +63,8 @@ const ( Eligible ) -type DSServer struct { +// DSServerBase contains the base information for a Delivery Service Server. +type DSServerBase struct { Cachegroup *string `json:"cachegroup" db:"cachegroup"` CachegroupID *int `json:"cachegroupId" db:"cachegroup_id"` CDNID *int `json:"cdnId" db:"cdn_id"` @@ -101,12 +102,14 @@ type DSServer struct { DeliveryServiceCapabilities []string `json:"-" db:"deliveryservice_capabilities"` } +// DSServerV11 contains the legacy format for a Delivery Service Server. type DSServerV11 struct { - DSServer + DSServerBase LegacyInterfaceDetails } -type DSServerV30 struct { - DSServer +// DSServer contains information for a Delivery Service Server. +type DSServer struct { + DSServerBase ServerInterfaces *[]ServerInterfaceInfo `json:"interfaces" db:"interfaces"` } diff --git a/lib/go-tc/servers.go b/lib/go-tc/servers.go index bbaa88f501..a2b6957b34 100644 --- a/lib/go-tc/servers.go +++ b/lib/go-tc/servers.go @@ -484,9 +484,9 @@ type ServerDetail struct { XMPPPasswd *string `json:"xmppPasswd" db:"xmpp_passwd"` } -// LegacyInterfaceDetails is the details for interfaces on servers for API v1 and v2 +// LegacyInterfaceDetails is the details for interfaces on servers for API v1 and v2. type LegacyInterfaceDetails struct { - InterfaceMTU *int `json:"interfaceMtu" db:"interface_mtu"` + InterfaceMTU *uint `json:"interfaceMtu" db:"interface_mtu"` InterfaceName *string `json:"interfaceName" db:"interface_name"` IP6Address *string `json:"ip6Address" db:"ip6_address"` IP6Gateway *string `json:"ip6Gateway" db:"ip6_gateway"` @@ -518,16 +518,7 @@ type ServerQueueUpdate struct { Action string `json:"action"` } -// ServerInterface is the data associated with an interface -type ServerInterface struct { - MaxBandwidth int64 `json:"max_bandwidth" db:"max_bandwidth"` - Monitor bool `json:"monitor" db:"monitor"` - Mtu int64 `json:"mtu" db:"mtu"` - Name string `json:"name" db:"name"` - Server int `json:"server" db:"server"` -} - -// ServerIpAddress is the data associated with an IP address +// ServerIpAddress is the data associated with an IP address. type ServerIpAddress struct { Address string `json:"address" db:"address"` Gateway string `json:"gateway" db:"gateway"` @@ -536,24 +527,24 @@ type ServerIpAddress struct { ServiceAddress bool `json:"service_address" db:"service_address"` } -// ServerInterfaceInfo is the combined data from both IP address information and interface information +// ServerInterfaceInfo is the combined data from both IP address information and interface information. type ServerInterfaceInfo struct { IpAddresses []ServerIpAddress `json:"ipAddresses" db:"ipAddresses"` MaxBandwidth int64 `json:"max_bandwidth" db:"max_bandwidth"` Monitor bool `json:"monitor" db:"monitor"` - Mtu int `json:"mtu" db:"mtu"` + Mtu uint `json:"mtu" db:"mtu"` Name string `json:"name" db:"name"` } -// Value implements the driver.Valuer interface -// marshals struct to json to pass back as a json.RawMessage +// Value implements the driver.Valuer interface and +// marshals the struct to json to pass back as a json.RawMessage. func (sii *ServerInterfaceInfo) Value() (driver.Value, error) { b, err := json.Marshal(sii) return b, err } -// Scan implements the sql.Scanner interface -// expects json.RawMessage and unmarshals to a deliveryservice struct +// Scan implements the sql.Scanner interface. +// Scan expects a json.RawMessage and unmarshals it to a ServerInterfaceInfo struct. func (sii *ServerInterfaceInfo) Scan(src interface{}) error { b, ok := src.([]byte) if !ok { @@ -563,7 +554,7 @@ func (sii *ServerInterfaceInfo) Scan(src interface{}) error { return json.Unmarshal([]byte(b), sii) } -// ConvertInterfaceInfotoV11 converts ServerInterfaceInfo to LegacyInterfaceDetails for v1 and v2 compatibility +// ConvertInterfaceInfotoV11 converts ServerInterfaceInfo to LegacyInterfaceDetails for v1 and v2 compatibility. func ConvertInterfaceInfotoV11(serverInterfaces []ServerInterfaceInfo) (LegacyInterfaceDetails, error) { legacyDetails := LegacyInterfaceDetails{} for _, intFace := range serverInterfaces { diff --git a/traffic_ops/client/deliveryservice.go b/traffic_ops/client/deliveryservice.go index 7ad1e4877e..5cd866d36a 100644 --- a/traffic_ops/client/deliveryservice.go +++ b/traffic_ops/client/deliveryservice.go @@ -322,10 +322,10 @@ func (to *Session) GetDeliveryServiceSSLKeysByID(XMLID string) (*tc.DeliveryServ // GetDeliveryServicesEligible returns the servers eligible for assignment to the Delivery // Service identified by the integral, unique identifier 'dsID'. -func (to *Session) GetDeliveryServicesEligible(dsID int) ([]tc.DSServerV30, ReqInf, error) { +func (to *Session) GetDeliveryServicesEligible(dsID int) ([]tc.DSServer, ReqInf, error) { resp := struct { - Response []tc.DSServerV30 `json:"response"` - }{Response: []tc.DSServerV30{}} + Response []tc.DSServer `json:"response"` + }{Response: []tc.DSServer{}} reqInf, err := get(to, fmt.Sprintf(API_DELIVERY_SERVICE_ELIGIBLE_SERVERS, dsID), &resp) if err != nil { diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go b/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go index 0c16a8fdc6..c8667d1afe 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go @@ -67,7 +67,7 @@ func GetServersEligible(w http.ResponseWriter, r *http.Request) { v11ServerList := []tc.DSServerV11{} for _, srv := range servers { v11server := tc.DSServerV11{} - v11server.DSServer = srv.DSServer + v11server.DSServerBase = srv.DSServerBase interfaces := *srv.ServerInterfaces legacyInterface, err := tc.ConvertInterfaceInfotoV11(interfaces) @@ -87,7 +87,7 @@ func GetServersEligible(w http.ResponseWriter, r *http.Request) { const JumboFrameBPS = 9000 -func getEligibleServers(tx *sql.Tx, dsID int) ([]tc.DSServerV30, error) { +func getEligibleServers(tx *sql.Tx, dsID int) ([]tc.DSServer, error) { q := ` WITH ds_id as (SELECT $1::bigint as v) SELECT @@ -160,9 +160,9 @@ AND (t.name LIKE 'EDGE%' OR t.name LIKE 'ORG%') defer rows.Close() serverInterfaceInfo := []tc.ServerInterfaceInfo{} - servers := []tc.DSServerV30{} + servers := []tc.DSServer{} for rows.Next() { - s := tc.DSServerV30{} + s := tc.DSServer{} err := rows.Scan( &s.Cachegroup, &s.CachegroupID, diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go index 7602f54cd5..ed21cc4c4a 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go @@ -528,7 +528,7 @@ func getRead(w http.ResponseWriter, r *http.Request, unassigned bool, alerts tc. v11ServerList := []tc.DSServerV11{} for _, srv := range servers { v11server := tc.DSServerV11{} - v11server.DSServer = srv.DSServer + v11server.DSServerBase = srv.DSServerBase interfaces := *srv.ServerInterfaces legacyInterface, err := tc.ConvertInterfaceInfotoV11(interfaces) @@ -547,7 +547,7 @@ func getRead(w http.ResponseWriter, r *http.Request, unassigned bool, alerts tc. api.WriteAlertsObj(w, r, http.StatusOK, alerts, servers) } -func read(tx *sqlx.Tx, dsID int, user *auth.CurrentUser, unassigned bool) ([]tc.DSServerV30, error) { +func read(tx *sqlx.Tx, dsID int, user *auth.CurrentUser, unassigned bool) ([]tc.DSServer, error) { where := `WHERE s.id in (select server from deliveryservice_server where deliveryservice = $1)` if unassigned { where = `WHERE s.id not in (select server from deliveryservice_server where deliveryservice = $1)` @@ -561,9 +561,9 @@ func read(tx *sqlx.Tx, dsID int, user *auth.CurrentUser, unassigned bool) ([]tc. defer rows.Close() serverInterfaceInfo := []tc.ServerInterfaceInfo{} - servers := []tc.DSServerV30{} + servers := []tc.DSServer{} for rows.Next() { - s := tc.DSServerV30{} + s := tc.DSServer{} err := rows.Scan( &s.Cachegroup, &s.CachegroupID, From 456f4cb1cb21a3880bf4e5f5ca6ad7172bcf0669 Mon Sep 17 00:00:00 2001 From: mjacks258 Date: Wed, 6 May 2020 10:33:28 -0600 Subject: [PATCH 3/9] updates per comments --- docs/source/api/v3/deliveryservices_id_servers.rst | 4 ++-- docs/source/api/v3/deliveryservices_id_servers_eligible.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/api/v3/deliveryservices_id_servers.rst b/docs/source/api/v3/deliveryservices_id_servers.rst index 79a3b0b542..e02e344b47 100644 --- a/docs/source/api/v3/deliveryservices_id_servers.rst +++ b/docs/source/api/v3/deliveryservices_id_servers.rst @@ -66,8 +66,8 @@ Response Structure :ipAddresses: An array of the IP address information for the interface - :ip6Address: The IPv4 or IPv6 address and subnet mask of the server - applicable for the interface ``name`` - :ip6Gateway: The IPv4 or IPv6 gateway address of the server - applicable for the interface ``name`` + :address: The IPv4 or IPv6 address and subnet mask of the server - applicable for the interface ``name`` + :gateway: The IPv4 or IPv6 gateway address of the server - applicable for the interface ``name`` :service_address: A boolean determining if content will be routed to the IP address :lastUpdated: The time and date at which this server was last updated, in an ISO-like format diff --git a/docs/source/api/v3/deliveryservices_id_servers_eligible.rst b/docs/source/api/v3/deliveryservices_id_servers_eligible.rst index b502518bc1..82bc4c1cc2 100644 --- a/docs/source/api/v3/deliveryservices_id_servers_eligible.rst +++ b/docs/source/api/v3/deliveryservices_id_servers_eligible.rst @@ -71,8 +71,8 @@ Response Structure :ipAddresses: An array of the IP address information for the interface - :ip6Address: The IPv4 or IPv6 address and subnet mask of the server - applicable for the interface ``name`` - :ip6Gateway: The IPv4 or IPv6 gateway address of the server - applicable for the interface ``name`` + :address: The IPv4 or IPv6 address and subnet mask of the server - applicable for the interface ``name`` + :gateway: The IPv4 or IPv6 gateway address of the server - applicable for the interface ``name`` :service_address: A boolean determining if content will be routed to the IP address :lastUpdated: The time and date at which this server was last updated, in an ISO-like format From 968f4f4850f93db835d91349b05847caadc4a0dd Mon Sep 17 00:00:00 2001 From: mjacks258 Date: Fri, 8 May 2020 16:50:43 -0600 Subject: [PATCH 4/9] reverted mgmt ip info change and updated for parity with /servers work --- .../api/v3/deliveryservices_id_servers.rst | 18 ++-- .../deliveryservices_id_servers_eligible.rst | 18 ++-- lib/go-tc/deliveryservice_servers.go | 3 + lib/go-tc/servers.go | 93 ------------------- .../deliveryservice/eligible.go | 8 +- .../deliveryservice/servers/servers.go | 8 +- 6 files changed, 29 insertions(+), 119 deletions(-) diff --git a/docs/source/api/v3/deliveryservices_id_servers.rst b/docs/source/api/v3/deliveryservices_id_servers.rst index e02e344b47..4875a0a5dd 100644 --- a/docs/source/api/v3/deliveryservices_id_servers.rst +++ b/docs/source/api/v3/deliveryservices_id_servers.rst @@ -71,6 +71,9 @@ Response Structure :service_address: A boolean determining if content will be routed to the IP address :lastUpdated: The time and date at which this server was last updated, in an ISO-like format +:mgmtIpAddress: The IPv4 address of the server's management port +:mgmtIpGateway: The IPv4 gateway of the server's management port +: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 (will be empty if not offline) :physLocation: The name of the :term:`Physical Location` at which the server resides :physLocationId: An integral, unique identifier for the :term:`Physical Location` at which the server resides @@ -125,6 +128,9 @@ Response Structure "iloPassword": "", "iloUsername": "", "lastUpdated": "2018-11-14 21:08:44+00", + "mgmtIpAddress": "", + "mgmtIpGateway": "", + "mgmtIpNetmask": "", "offlineReason": "", "physLocation": "Apachecon North America 2018", "physLocationId": 1, @@ -142,18 +148,6 @@ Response Structure "updPending": false, "interfaces": [{ "ipAddresses": [ - { - "address": "172.16.239.101", - "gateway": "", - "service_address": false - } - ], - "max_bandwidth": 0, - "monitor": false, - "mtu": 9000, - "name": "mgmt" - }, - { "ipAddresses": [ { "address": "172.16.239.100", "gateway": "172.16.239.1", diff --git a/docs/source/api/v3/deliveryservices_id_servers_eligible.rst b/docs/source/api/v3/deliveryservices_id_servers_eligible.rst index 82bc4c1cc2..01c3c12c53 100644 --- a/docs/source/api/v3/deliveryservices_id_servers_eligible.rst +++ b/docs/source/api/v3/deliveryservices_id_servers_eligible.rst @@ -76,6 +76,9 @@ Response Structure :service_address: A boolean determining if content will be routed to the IP address :lastUpdated: The time and date at which this server was last updated, in an ISO-like format +:mgmtIpAddress: The IPv4 address of the server's management port +:mgmtIpGateway: The IPv4 gateway of the server's management port +: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 (will be empty if not offline) :physLocation: The name of the :term:`Physical Location` at which the server resides :physLocationId: An integral, unique identifier for the :term:`Physical Location` at which the server resides @@ -118,6 +121,9 @@ Response Structure "iloPassword": "", "iloUsername": "", "lastUpdated": "2018-10-30 16:01:12+00", + "mgmtIpAddress": "", + "mgmtIpGateway": "", + "mgmtIpNetmask": "", "offlineReason": "", "physLocation": "Apachecon North America 2018", "physLocationId": 1, @@ -135,18 +141,6 @@ Response Structure "updPending": false, "interfaces": [{ "ipAddresses": [ - { - "address": "172.16.239.101", - "gateway": "", - "service_address": false - } - ], - "max_bandwidth": 0, - "monitor": false, - "mtu": 9000, - "name": "mgmt" - }, - { "ipAddresses": [ { "address": "172.16.239.100", "gateway": "172.16.239.1", diff --git a/lib/go-tc/deliveryservice_servers.go b/lib/go-tc/deliveryservice_servers.go index 806dd34340..bb1314a60c 100644 --- a/lib/go-tc/deliveryservice_servers.go +++ b/lib/go-tc/deliveryservice_servers.go @@ -83,6 +83,9 @@ type DSServerBase struct { ILOPassword *string `json:"iloPassword" db:"ilo_password"` ILOUsername *string `json:"iloUsername" db:"ilo_username"` LastUpdated *TimeNoMod `json:"lastUpdated" db:"last_updated"` + 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"` PhysLocationID *int `json:"physLocationId" db:"phys_location_id"` diff --git a/lib/go-tc/servers.go b/lib/go-tc/servers.go index a2b6957b34..0904a52590 100644 --- a/lib/go-tc/servers.go +++ b/lib/go-tc/servers.go @@ -8,9 +8,6 @@ import ( "net" "time" - "github.com/go-ozzo/ozzo-validation" - - "github.com/apache/trafficcontrol/lib/go-tc/tovalidate" "github.com/apache/trafficcontrol/lib/go-util" ) @@ -484,20 +481,6 @@ type ServerDetail struct { XMPPPasswd *string `json:"xmppPasswd" db:"xmpp_passwd"` } -// LegacyInterfaceDetails is the details for interfaces on servers for API v1 and v2. -type LegacyInterfaceDetails struct { - InterfaceMTU *uint `json:"interfaceMtu" db:"interface_mtu"` - InterfaceName *string `json:"interfaceName" db:"interface_name"` - IP6Address *string `json:"ip6Address" db:"ip6_address"` - IP6Gateway *string `json:"ip6Gateway" db:"ip6_gateway"` - IPAddress *string `json:"ipAddress" db:"ip_address"` - IPGateway *string `json:"ipGateway" db:"ip_gateway"` - IPNetmask *string `json:"ipNetmask" db:"ip_netmask"` - MgmtIPAddress *string `json:"mgmtIpAddress" db:"mgmt_ip_address"` - MgmtIPGateway *string `json:"mgmtIpGateway" db:"mgmt_ip_gateway"` - MgmtIPNetmask *string `json:"mgmtIpNetmask" db:"mgmt_ip_netmask"` -} - // ServerQueueUpdateRequest encodes the request data for the POST // servers/{{ID}}/queue_update endpoint. type ServerQueueUpdateRequest struct { @@ -517,79 +500,3 @@ type ServerQueueUpdate struct { ServerID util.JSONIntStr `json:"serverId"` Action string `json:"action"` } - -// ServerIpAddress is the data associated with an IP address. -type ServerIpAddress struct { - Address string `json:"address" db:"address"` - Gateway string `json:"gateway" db:"gateway"` - Interface string `json:"interface,omitempty" db:"interface"` - Server int `json:"server,omitempty" db:"server"` - ServiceAddress bool `json:"service_address" db:"service_address"` -} - -// ServerInterfaceInfo is the combined data from both IP address information and interface information. -type ServerInterfaceInfo struct { - IpAddresses []ServerIpAddress `json:"ipAddresses" db:"ipAddresses"` - MaxBandwidth int64 `json:"max_bandwidth" db:"max_bandwidth"` - Monitor bool `json:"monitor" db:"monitor"` - Mtu uint `json:"mtu" db:"mtu"` - Name string `json:"name" db:"name"` -} - -// Value implements the driver.Valuer interface and -// marshals the struct to json to pass back as a json.RawMessage. -func (sii *ServerInterfaceInfo) Value() (driver.Value, error) { - b, err := json.Marshal(sii) - return b, err -} - -// Scan implements the sql.Scanner interface. -// Scan expects a json.RawMessage and unmarshals it to a ServerInterfaceInfo struct. -func (sii *ServerInterfaceInfo) Scan(src interface{}) error { - b, ok := src.([]byte) - if !ok { - return fmt.Errorf("expected deliveryservice in byte array form; got %T", src) - } - - return json.Unmarshal([]byte(b), sii) -} - -// ConvertInterfaceInfotoV11 converts ServerInterfaceInfo to LegacyInterfaceDetails for v1 and v2 compatibility. -func ConvertInterfaceInfotoV11(serverInterfaces []ServerInterfaceInfo) (LegacyInterfaceDetails, error) { - legacyDetails := LegacyInterfaceDetails{} - for _, intFace := range serverInterfaces { - legacyDetails.InterfaceMTU = &intFace.Mtu - legacyDetails.InterfaceName = &intFace.Name - - for _, addr := range intFace.IpAddresses { - address := addr.Address - gateway := addr.Gateway - - parsedIp, netmask, err := net.ParseCIDR(address) - netmaskString := "" - if err == nil { - mask := netmask.Mask - netmaskString = fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3]) - } - - if intFace.Name == "mgmt" { - legacyDetails.MgmtIPAddress = &address - legacyDetails.MgmtIPGateway = &gateway - legacyDetails.MgmtIPNetmask = &netmaskString - continue - } - - if err = validation.Validate(&addr.Address, validation.By(tovalidate.IsValidIPv6CIDROrAddress)); err != nil { - ip := parsedIp.String() - legacyDetails.IPAddress = &ip - legacyDetails.IPGateway = &gateway - legacyDetails.IPNetmask = &netmaskString - } else { - legacyDetails.IP6Address = &address - legacyDetails.IP6Gateway = &gateway - } - } - } - - return legacyDetails, nil -} diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go b/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go index c8667d1afe..65fa4d6922 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go @@ -70,7 +70,7 @@ func GetServersEligible(w http.ResponseWriter, r *http.Request) { v11server.DSServerBase = srv.DSServerBase interfaces := *srv.ServerInterfaces - legacyInterface, err := tc.ConvertInterfaceInfotoV11(interfaces) + legacyInterface, err := tc.InterfaceInfoToLegacyInterfaces(interfaces) if err != nil { api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("converting to server detail v11: "+err.Error())) return @@ -126,6 +126,9 @@ FROM interface WHERE interface.server = s.id ) AS interfaces, s.last_updated, +s.mgmt_ip_address, +s.mgmt_ip_gateway, +s.mgmt_ip_netmask, s.offline_reason, pl.name as phys_location, s.phys_location as phys_location_id, @@ -180,6 +183,9 @@ AND (t.name LIKE 'EDGE%' OR t.name LIKE 'ORG%') &s.ILOUsername, pq.Array(&serverInterfaceInfo), &s.LastUpdated, + &s.MgmtIPAddress, + &s.MgmtIPGateway, + &s.MgmtIPNetmask, &s.OfflineReason, &s.PhysLocation, &s.PhysLocationID, diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go index ed21cc4c4a..e689f92887 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go @@ -531,7 +531,7 @@ func getRead(w http.ResponseWriter, r *http.Request, unassigned bool, alerts tc. v11server.DSServerBase = srv.DSServerBase interfaces := *srv.ServerInterfaces - legacyInterface, err := tc.ConvertInterfaceInfotoV11(interfaces) + legacyInterface, err := tc.InterfaceInfoToLegacyInterfaces(interfaces) if err != nil { api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("converting to server detail v11: "+err.Error())) return @@ -581,6 +581,9 @@ func read(tx *sqlx.Tx, dsID int, user *auth.CurrentUser, unassigned bool) ([]tc. &s.ILOUsername, pq.Array(&serverInterfaceInfo), &s.LastUpdated, + &s.MgmtIPAddress, + &s.MgmtIPGateway, + &s.MgmtIPNetmask, &s.OfflineReason, &s.PhysLocation, &s.PhysLocationID, @@ -652,6 +655,9 @@ FROM interface WHERE interface.server = s.id ) AS interfaces, s.last_updated, + s.mgmt_ip_address, + s.mgmt_ip_gateway, + s.mgmt_ip_netmask, s.offline_reason, pl.name as phys_location, s.phys_location as phys_location_id, From 8bde2b0c4b452d632e764a37c5581e2e562162c4 Mon Sep 17 00:00:00 2001 From: mjacks258 Date: Fri, 8 May 2020 17:17:26 -0600 Subject: [PATCH 5/9] update to fix docs --- docs/source/api/v3/deliveryservices_id_servers.rst | 2 +- docs/source/api/v3/deliveryservices_id_servers_eligible.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/api/v3/deliveryservices_id_servers.rst b/docs/source/api/v3/deliveryservices_id_servers.rst index 4875a0a5dd..c6762eb53b 100644 --- a/docs/source/api/v3/deliveryservices_id_servers.rst +++ b/docs/source/api/v3/deliveryservices_id_servers.rst @@ -62,7 +62,7 @@ Response Structure .. seealso:: `The Wikipedia article on Maximum Transmission Unit `_ - :name: The network interface name used by the server. A value of 'mgmt' indicates a management port. + :name: The network interface name used by the server. :ipAddresses: An array of the IP address information for the interface diff --git a/docs/source/api/v3/deliveryservices_id_servers_eligible.rst b/docs/source/api/v3/deliveryservices_id_servers_eligible.rst index 01c3c12c53..57f6495bba 100644 --- a/docs/source/api/v3/deliveryservices_id_servers_eligible.rst +++ b/docs/source/api/v3/deliveryservices_id_servers_eligible.rst @@ -67,7 +67,7 @@ Response Structure .. seealso:: `The Wikipedia article on Maximum Transmission Unit `_ - :name: The network interface name used by the server. A value of 'mgmt' indicates a management port. + :name: The network interface name used by the server. :ipAddresses: An array of the IP address information for the interface From 0d6ed83aad3e0d82e12a2832e75ad81781b0c4c2 Mon Sep 17 00:00:00 2001 From: mjacks258 Date: Wed, 13 May 2020 08:11:17 -0600 Subject: [PATCH 6/9] added unit testing --- lib/go-tc/servers.go | 2 +- lib/go-util/ptr.go | 4 + .../deliveryservice/eligible_test.go | 156 ++++++++++++++++++ .../deliveryservice/servers/servers_test.go | 135 ++++++++++++++- 4 files changed, 295 insertions(+), 2 deletions(-) create mode 100644 traffic_ops/traffic_ops_golang/deliveryservice/eligible_test.go diff --git a/lib/go-tc/servers.go b/lib/go-tc/servers.go index 0904a52590..08c43d1a44 100644 --- a/lib/go-tc/servers.go +++ b/lib/go-tc/servers.go @@ -105,7 +105,7 @@ func (sii *ServerInterfaceInfo) Value() (driver.Value, error) { } // Scan implements the sql.Scanner interface -// expects json.RawMessage and unmarshals to a deliveryservice struct +// expects json.RawMessage and unmarshals to a ServerInterfaceInfo struct func (sii *ServerInterfaceInfo) Scan(src interface{}) error { b, ok := src.([]byte) if !ok { diff --git a/lib/go-util/ptr.go b/lib/go-util/ptr.go index eb795836a9..8cf013f6df 100644 --- a/lib/go-util/ptr.go +++ b/lib/go-util/ptr.go @@ -31,6 +31,10 @@ func UintPtr(u uint) *uint { return &u } +func Uint64Ptr(u uint64) *uint64 { + return &u +} + func Int64Ptr(i int64) *int64 { return &i } diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/eligible_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/eligible_test.go new file mode 100644 index 0000000000..243e14a4cc --- /dev/null +++ b/traffic_ops/traffic_ops_golang/deliveryservice/eligible_test.go @@ -0,0 +1,156 @@ +package deliveryservice + +/* + + 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. +*/ + +import ( + "testing" + + "github.com/apache/trafficcontrol/lib/go-tc" + "github.com/apache/trafficcontrol/lib/go-util" + "github.com/jmoiron/sqlx" + + "gopkg.in/DATA-DOG/go-sqlmock.v1" +) + +func TestGetEligibleServers(t *testing.T) { + 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() + + testServers := getMockDSServers() + cols := []string{"cachegroup", + "cachegroup_id", + "cdn_id", + "cdn_name", + "domain_name", + "guid", + "host_name", + "https_port", + "id", + "ilo_ip_address", + "ilo_ip_gateway", + "ilo_ip_netmask", + "ilo_password", + "ilo_username", + "interfaces", + "last_updated", + "mgmt_ip_address", + "mgmt_ip_gateway", + "mgmt_ip_netmask", + "offline_reason", + "phys_location", + "phys_location_id", + "profile", + "profile_desc", + "profile_id", + "rack", + "router_host_name", + "router_port_name", + "status", + "status_id", + "tcp_port", + "server_type", + "server_type_id", + "upd_pending", + "server_capabilities", + "deliveryservice_capabilities"} + + rows := sqlmock.NewRows(cols) + + for _, s := range testServers { + rows = rows.AddRow( + s.Cachegroup, + s.CachegroupID, + s.CDNID, + s.CDNName, + s.DomainName, + s.GUID, + s.HostName, + s.HTTPSPort, + s.ID, + s.ILOIPAddress, + s.ILOIPGateway, + s.ILOIPNetmask, + s.ILOPassword, + s.ILOUsername, + []byte(`{"{\"ipAddresses\" : [{\"address\" : \"127.0.0.0\", \"gateway\" : null, \"service_address\" : true}], \"max_bandwidth\" : null, \"monitor\" : true, \"mtu\" : 1500, \"name\" : \"eth0\"}"}`), + s.LastUpdated, + s.MgmtIPAddress, + s.MgmtIPGateway, + s.MgmtIPNetmask, + s.OfflineReason, + s.PhysLocation, + s.PhysLocationID, + s.Profile, + s.ProfileDesc, + s.ProfileID, + s.Rack, + s.RouterHostName, + s.RouterPortName, + s.Status, + s.StatusID, + s.TCPPort, + s.Type, + s.TypeID, + s.UpdPending, + []byte(`{""}`), + []byte(`{""}`), + ) + } + + mock.ExpectBegin() + mock.ExpectQuery("SELECT").WillReturnRows(rows) + mock.ExpectCommit() + + actualSrvs, err := getEligibleServers(db.MustBegin().Tx, 1) + if err != nil { + t.Fatalf("an error '%s' occurred during read", err) + } + + if len(actualSrvs) != 1 { + t.Fatalf("servers.read expected len(actualSrvs) == 1, actual = %v", len(actualSrvs)) + } + + srvInts := *(actualSrvs[0]).ServerInterfaces + if len(srvInts) != 1 { + t.Fatalf("servers.read expected len(srvInts) == 1, actual = %v", len(srvInts)) + } + + if len(srvInts[0].IpAddresses) != 1 { + t.Fatalf("servers.read expected len(srvInts[0].IpAddresses) == 1, actual = %v", len(srvInts[0].IpAddresses)) + } +} + +func getMockDSServers() []tc.DSServer { + base := tc.DSServerBase{ + Cachegroup: util.StrPtr("cgTest"), + CachegroupID: util.IntPtr(1), + CDNID: util.IntPtr(1), + CDNName: util.StrPtr("cdnTest"), + DomainName: util.StrPtr("domain"), + } + srv := tc.DSServer{ + base, + &[]tc.ServerInterfaceInfo{}, // left empty because it must be written as json above since sqlmock does not support nested arrays + } + srvsExpected := []tc.DSServer{srv} + return srvsExpected +} 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 319dfc5973..e5d573f929 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go @@ -20,8 +20,15 @@ package servers */ import ( - "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers" "testing" + + "github.com/apache/trafficcontrol/lib/go-tc" + "github.com/apache/trafficcontrol/lib/go-util" + "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth" + "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers" + "github.com/jmoiron/sqlx" + + "gopkg.in/DATA-DOG/go-sqlmock.v1" ) func TestValidateDSSAssignments(t *testing.T) { @@ -51,3 +58,129 @@ func TestValidateDSSAssignments(t *testing.T) { t.Fatalf("Expected no user error, got %v", userErr.Error()) } } + +func TestReadServers(t *testing.T) { + 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() + + testServers := getMockDSServers() + cols := []string{"cachegroup", + "cachegroup_id", + "cdn_id", + "cdn_name", + "domain_name", + "guid", + "host_name", + "https_port", + "id", + "ilo_ip_address", + "ilo_ip_gateway", + "ilo_ip_netmask", + "ilo_password", + "ilo_username", + "interfaces", + "last_updated", + "mgmt_ip_address", + "mgmt_ip_gateway", + "mgmt_ip_netmask", + "offline_reason", + "phys_location", + "phys_location_id", + "profile", + "profile_desc", + "profile_id", + "rack", + "router_host_name", + "router_port_name", + "status", + "status_id", + "tcp_port", + "server_type", + "server_type_id", + "upd_pending"} + + rows := sqlmock.NewRows(cols) + + for _, s := range testServers { + rows = rows.AddRow( + s.Cachegroup, + s.CachegroupID, + s.CDNID, + s.CDNName, + s.DomainName, + s.GUID, + s.HostName, + s.HTTPSPort, + s.ID, + s.ILOIPAddress, + s.ILOIPGateway, + s.ILOIPNetmask, + s.ILOPassword, + s.ILOUsername, + []byte(`{"{\"ipAddresses\" : [{\"address\" : \"127.0.0.0\", \"gateway\" : null, \"service_address\" : true}], \"max_bandwidth\" : null, \"monitor\" : true, \"mtu\" : 1500, \"name\" : \"eth0\"}"}`), + s.LastUpdated, + s.MgmtIPAddress, + s.MgmtIPGateway, + s.MgmtIPNetmask, + s.OfflineReason, + s.PhysLocation, + s.PhysLocationID, + s.Profile, + s.ProfileDesc, + s.ProfileID, + s.Rack, + s.RouterHostName, + s.RouterPortName, + s.Status, + s.StatusID, + s.TCPPort, + s.Type, + s.TypeID, + s.UpdPending, + ) + } + + mock.ExpectBegin() + mock.ExpectQuery("SELECT").WillReturnRows(rows) + mock.ExpectCommit() + + actualSrvs, err := read(db.MustBegin(), 1, &auth.CurrentUser{PrivLevel: 30}, false) + if err != nil { + t.Fatalf("an error '%s' occurred during read", err) + } + + if len(actualSrvs) != 1 { + t.Fatalf("servers.read expected len(actualSrvs) == 1, actual = %v", len(actualSrvs)) + } + + srvInts := *(actualSrvs[0]).ServerInterfaces + if len(srvInts) != 1 { + t.Fatalf("servers.read expected len(srvInts) == 1, actual = %v", len(srvInts)) + } + + if len(srvInts[0].IpAddresses) != 1 { + t.Fatalf("servers.read expected len(srvInts[0].IpAddresses) == 1, actual = %v", len(srvInts[0].IpAddresses)) + } +} + +func getMockDSServers() []tc.DSServer { + base := tc.DSServerBase{ + Cachegroup: util.StrPtr("cgTest"), + CachegroupID: util.IntPtr(1), + CDNID: util.IntPtr(1), + CDNName: util.StrPtr("cdnTest"), + DomainName: util.StrPtr("domain"), + } + srv := tc.DSServer{ + base, + &[]tc.ServerInterfaceInfo{}, // left empty because it must be written as json above since sqlmock does not support nested arrays + } + srvsExpected := []tc.DSServer{srv} + return srvsExpected +} From 0e7b22f472268177784b0c781b6759c7dfe65993 Mon Sep 17 00:00:00 2001 From: mattjackson220 Date: Tue, 26 May 2020 11:43:31 -0600 Subject: [PATCH 7/9] updates to integrate better with other PRs --- traffic_ops/traffic_ops_golang/deliveryservice/eligible.go | 2 +- .../traffic_ops_golang/deliveryservice/servers/servers.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go b/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go index 65fa4d6922..6a031c6eff 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go @@ -162,9 +162,9 @@ AND (t.name LIKE 'EDGE%' OR t.name LIKE 'ORG%') } defer rows.Close() - serverInterfaceInfo := []tc.ServerInterfaceInfo{} servers := []tc.DSServer{} for rows.Next() { + serverInterfaceInfo := []tc.ServerInterfaceInfo{} s := tc.DSServer{} err := rows.Scan( &s.Cachegroup, diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go index e689f92887..a10dd8a954 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go @@ -560,9 +560,9 @@ func read(tx *sqlx.Tx, dsID int, user *auth.CurrentUser, unassigned bool) ([]tc. } defer rows.Close() - serverInterfaceInfo := []tc.ServerInterfaceInfo{} servers := []tc.DSServer{} for rows.Next() { + serverInterfaceInfo := []tc.ServerInterfaceInfo{} s := tc.DSServer{} err := rows.Scan( &s.Cachegroup, From 093b98f31d4ac328f5a793690740425ef6cd52b2 Mon Sep 17 00:00:00 2001 From: mattjackson220 Date: Thu, 11 Jun 2020 13:46:50 -0600 Subject: [PATCH 8/9] updated to change IpAddresses to IPAddresses --- .../traffic_ops_golang/deliveryservice/eligible_test.go | 4 ++-- .../deliveryservice/servers/servers_test.go | 4 ++-- traffic_ops/traffic_ops_golang/server/detail_test.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/eligible_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/eligible_test.go index 243e14a4cc..f8d0c4101b 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/eligible_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/eligible_test.go @@ -134,8 +134,8 @@ func TestGetEligibleServers(t *testing.T) { t.Fatalf("servers.read expected len(srvInts) == 1, actual = %v", len(srvInts)) } - if len(srvInts[0].IpAddresses) != 1 { - t.Fatalf("servers.read expected len(srvInts[0].IpAddresses) == 1, actual = %v", len(srvInts[0].IpAddresses)) + if len(srvInts[0].IPAddresses) != 1 { + t.Fatalf("servers.read expected len(srvInts[0].IPAddresses) == 1, actual = %v", len(srvInts[0].IPAddresses)) } } 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 e5d573f929..0754bee705 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go @@ -164,8 +164,8 @@ func TestReadServers(t *testing.T) { t.Fatalf("servers.read expected len(srvInts) == 1, actual = %v", len(srvInts)) } - if len(srvInts[0].IpAddresses) != 1 { - t.Fatalf("servers.read expected len(srvInts[0].IpAddresses) == 1, actual = %v", len(srvInts[0].IpAddresses)) + if len(srvInts[0].IPAddresses) != 1 { + t.Fatalf("servers.read expected len(srvInts[0].IPAddresses) == 1, actual = %v", len(srvInts[0].IPAddresses)) } } diff --git a/traffic_ops/traffic_ops_golang/server/detail_test.go b/traffic_ops/traffic_ops_golang/server/detail_test.go index 3b937f8d8d..1eeaffb191 100644 --- a/traffic_ops/traffic_ops_golang/server/detail_test.go +++ b/traffic_ops/traffic_ops_golang/server/detail_test.go @@ -127,7 +127,7 @@ func TestGetDetailServers(t *testing.T) { } if len(srvInts[0].IPAddresses) != 1 { - t.Fatalf("servers.read expected len(srvInts[0].IpAddresses) == 1, actual = %v", len(srvInts[0].IPAddresses)) + t.Fatalf("servers.read expected len(srvInts[0].IPAddresses) == 1, actual = %v", len(srvInts[0].IPAddresses)) } if len(actualSrvs[0].HardwareInfo) != 3 { @@ -135,7 +135,7 @@ func TestGetDetailServers(t *testing.T) { } if !srvInts[0].IPAddresses[0].ServiceAddress { - t.Fatalf("srvInts[0].IpAddresses[0].ServiceAddress expected to be true, actual = %v", srvInts[0].IPAddresses[0].ServiceAddress) + t.Fatalf("srvInts[0].IPAddresses[0].ServiceAddress expected to be true, actual = %v", srvInts[0].IPAddresses[0].ServiceAddress) } } From 87d61c86f9b767a6b24b981594d0e6344b0b55de Mon Sep 17 00:00:00 2001 From: mattjackson220 Date: Mon, 15 Jun 2020 10:22:47 -0600 Subject: [PATCH 9/9] minor update to fix miss in rebase --- traffic_ops/traffic_ops_golang/deliveryservice/eligible.go | 2 +- .../traffic_ops_golang/deliveryservice/servers/servers.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go b/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go index 6a031c6eff..f99a42c244 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/eligible.go @@ -111,7 +111,7 @@ SELECT ( json_build_object ( SELECT ( json_build_object ( 'address', ip_address.address, 'gateway', ip_address.gateway, -'service_address', ip_address.service_address +'serviceAddress', ip_address.service_address )) FROM ip_address WHERE ip_address.interface = interface.name diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go index a10dd8a954..69fb684af0 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go @@ -640,7 +640,7 @@ SELECT ( json_build_object ( SELECT ( json_build_object ( 'address', ip_address.address, 'gateway', ip_address.gateway, -'service_address', ip_address.service_address +'serviceAddress', ip_address.service_address )) FROM ip_address WHERE ip_address.interface = interface.name