ocket8888 commented on a change in pull request #4700:
URL: https://github.com/apache/trafficcontrol/pull/4700#discussion_r428240582
##########
File path: lib/go-tc/servers.go
##########
@@ -49,6 +64,157 @@ type ServersV1DetailResponse struct {
Alerts
}
+// ServerIpAddress is the data associated with a server's interface's IP
address.
+type ServerIpAddress struct {
+ Address string `json:"address" db:"address"`
+ Gateway *string `json:"gateway" db:"gateway"`
+ ServiceAddress bool `json:"serviceAddress" db:"service_address"`
+}
+
+// ServerInterfaceInfo is the data associated with a server's interface.
+type ServerInterfaceInfo struct {
+ IPAddresses []ServerIpAddress `json:"ipAddresses" db:"ip_addresses"`
+ MaxBandwidth *uint64 `json:"maxBandwidth" db:"max_bandwidth"`
+ Monitor bool `json:"monitor" db:"monitor"`
+ MTU *uint64 `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)
+}
+
+// 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"`
+}
+
+// ToInterfaces converts a LegacyInterfaceDetails to a slice of
+// ServerInterfaceInfo structures. No interfaces will be marked for monitoring,
+// and it will generate service addresses according to the passed indicators
+// for each address family.
+func (lid *LegacyInterfaceDetails) ToInterfaces(ipv4IsService, ipv6IsService
bool) ([]ServerInterfaceInfo, error) {
+ var iface ServerInterfaceInfo
+ if lid.InterfaceMtu == nil {
+ return nil, errors.New("interfaceMtu is null")
+ }
+ mtu := uint64(*lid.InterfaceMtu)
+ iface.MTU = &mtu
+
+ if lid.InterfaceName == nil {
+ return nil, errors.New("interfaceName is null")
+ }
+ iface.Name = *lid.InterfaceName
+
+ var ips []ServerIpAddress
+ if lid.IPAddress != nil && *lid.IPAddress != "" {
+ if lid.IPGateway != nil && *lid.IPGateway == "" {
+ lid.IPGateway = nil
+ }
+
+ ipStr := *lid.IPAddress
+ if lid.IPNetmask != nil && *lid.IPNetmask != "" {
+ mask := net.ParseIP(*lid.IPNetmask).To4()
+ if mask == nil {
+ return nil, fmt.Errorf("Failed to parse netmask
'%s'", *lid.IPNetmask)
+ }
+ cidr, _ := net.IPv4Mask(mask[0], mask[1], mask[2],
mask[3]).Size()
+ ipStr = fmt.Sprintf("%s/%d", ipStr, cidr)
+ }
+
+ ips = append(ips, ServerIpAddress{
+ Address: ipStr,
+ Gateway: lid.IPGateway,
+ ServiceAddress: ipv4IsService,
+ })
+ }
+
+ if lid.IP6Address != nil && *lid.IP6Address != "" {
+ if lid.IP6Gateway != nil && *lid.IP6Gateway == "" {
+ lid.IP6Gateway = nil
+ }
+ ips = append(ips, ServerIpAddress{
+ Address: *lid.IP6Address,
+ Gateway: lid.IP6Gateway,
+ ServiceAddress: ipv6IsService,
+ })
+ }
+
+ iface.IPAddresses = ips
+ return []ServerInterfaceInfo{iface}, nil
+}
+
+// InterfaceInfoToLegacyInterfaces converts a ServerInterfaceInfo to an
+// equivalent LegacyInterfaceDetails structure. It does this by creating the
+// IP address fields using the "service" interface's IP addresses. All others
+// are discarded, as the legacy format is incapable of representing them.
+func InterfaceInfoToLegacyInterfaces(serverInterfaces []ServerInterfaceInfo)
(LegacyInterfaceDetails, error) {
+ var legacyDetails LegacyInterfaceDetails
+
+ for _, intFace := range serverInterfaces {
+
+ for _, addr := range intFace.IPAddresses {
+ if !addr.ServiceAddress {
+ continue
+ }
+
+ address := addr.Address
+ gateway := addr.Gateway
+
+ var parsedIp net.IP
+ var mask *net.IPNet
+ var err error
+ parsedIp, mask, err = net.ParseCIDR(address)
+ if err != nil {
+ parsedIp = net.ParseIP(address)
+ if parsedIp == nil {
+ return legacyDetails,
fmt.Errorf("Failed to parse '%s' as network or CIDR string: %v", address, err)
+ }
+ }
+
+ if parsedIp.To4() == nil {
+ legacyDetails.IP6Address = &address
+ legacyDetails.IP6Gateway = gateway
+ } else if mask != nil {
+ legacyDetails.IPAddress =
util.StrPtr(parsedIp.String())
+ legacyDetails.IPGateway = gateway
+ legacyDetails.IPNetmask =
util.StrPtr(fmt.Sprintf("%d.%d.%d.%d", mask.Mask[0], mask.Mask[1],
mask.Mask[2], mask.Mask[3]))
Review comment:
This shouldn't be an issue for well-formed `ServerInterfaceInfo`s
because they can only legally contain one IPv4 service address, but that's
probably still a good idea.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]