blob: 9c04a80ff3cf206538a4bc75806750d155c56bdf [file] [log] [blame]
package servers
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 (
"fmt"
"strconv"
"strings"
"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/jmoiron/sqlx"
"gopkg.in/DATA-DOG/go-sqlmock.v1"
)
func TestValidateDSSAssignments(t *testing.T) {
expected := `server and delivery service CDNs do not match`
cdnID := 1
ds := DSInfo{
ID: 0,
CDNID: &cdnID,
}
var servers []tc.ServerInfo
server := tc.ServerInfo{
HostName: "serverHost",
CDNID: 0,
Type: "",
}
servers = append(servers, server)
userErr, _, _ := validateDSS(nil, ds, servers)
if userErr == nil {
t.Fatalf("Expected user error with mismatching ds and server CDN IDs, got no error instead")
}
if userErr.Error() != expected {
t.Errorf("Expected error details %v, got %v", expected, userErr.Error())
}
servers[0].CDNID = 1
userErr, _, _ = validateDSS(nil, ds, servers)
if userErr != nil {
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()
dsID := 1
mock.ExpectBegin()
idRows := sqlmock.NewRows([]string{"id"})
for _, s := range testServers {
idRows = idRows.AddRow(*s.ID)
}
mock.ExpectQuery("SELECT s.id FROM server s (.+)").WithArgs(dsID).WillReturnRows(idRows)
for _, s := range testServers {
testInterfaces := createServerIntefaces(*s.ID)
mockServerInterfaces(mock, *s.ID, testInterfaces)
}
cols := []string{
"id",
"cachegroup",
"cachegroup_id",
"cdn_id",
"cdn_name",
"domain_name",
"guid",
"host_name",
"https_port",
"ilo_ip_address",
"ilo_ip_gateway",
"ilo_ip_netmask",
"ilo_password",
"ilo_username",
"last_updated",
"mgmt_ip_address",
"mgmt_ip_gateway",
"mgmt_ip_netmask",
"offline_reason",
"phys_location",
"phys_location_id",
"profile_name",
"rack",
"status",
"status_id",
"tcp_port",
"server_type",
"server_type_id",
"upd_pending"}
rows := sqlmock.NewRows(cols)
for _, s := range testServers {
rows = rows.AddRow(
s.ID,
s.Cachegroup,
s.CachegroupID,
s.CDNID,
s.CDNName,
s.DomainName,
s.GUID,
s.HostName,
s.HTTPSPort,
s.ILOIPAddress,
s.ILOIPGateway,
s.ILOIPNetmask,
s.ILOPassword,
s.ILOUsername,
s.LastUpdated,
s.MgmtIPAddress,
s.MgmtIPGateway,
s.MgmtIPNetmask,
s.OfflineReason,
s.PhysLocation,
s.PhysLocationID,
fmt.Sprintf("{%s}", strings.Join(s.ProfileNames, ",")),
s.Rack,
s.Status,
s.StatusID,
s.TCPPort,
s.Type,
s.TypeID,
s.UpdPending,
)
}
mock.ExpectQuery("SELECT").WillReturnRows(rows)
mock.ExpectCommit()
actualSrvs, err := read(db.MustBegin(), dsID, &auth.CurrentUser{PrivLevel: 30})
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) != 2 {
t.Fatalf("servers.read expected len(srvInts) == 2, actual = %v", len(srvInts))
}
for _, interf := range srvInts {
if interf.RouterHostName != "router1" && interf.RouterHostName != "router2" {
t.Errorf("RouterHostName %s does't match router1 or router2", interf.RouterHostName)
}
if interf.RouterPortName != "9090" && interf.RouterPortName != "9091" {
t.Errorf("RouterPortName %s does't match 9090 or 9091", interf.RouterPortName)
}
if len(interf.IPAddresses) != 4 {
t.Fatalf("servers.read expected len(interf.IPAddresses) == 4, actual = %v", len(interf.IPAddresses))
}
}
}
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
}
srvsExpected := []tc.DSServerV4{srv}
return srvsExpected
}
func createServerIntefaces(cacheID int) []tc.ServerInterfaceInfoV40 {
return []tc.ServerInterfaceInfoV40{
{
ServerInterfaceInfo: tc.ServerInterfaceInfo{
IPAddresses: []tc.ServerIPAddress{
{
Address: "5.6.7.8",
Gateway: util.StrPtr("5.6.7.0/24"),
ServiceAddress: true,
},
{
Address: "2020::4",
Gateway: util.StrPtr("fd53::9"),
ServiceAddress: true,
},
{
Address: "5.6.7.9",
Gateway: util.StrPtr("5.6.7.0/24"),
ServiceAddress: false,
},
{
Address: "2021::4",
Gateway: util.StrPtr("fd53::9"),
ServiceAddress: false,
},
},
MaxBandwidth: util.Uint64Ptr(2500),
Monitor: true,
MTU: util.Uint64Ptr(1500),
Name: "interfaceName" + strconv.Itoa(cacheID),
},
RouterHostName: "router1",
RouterPortName: "9090",
},
{
ServerInterfaceInfo: tc.ServerInterfaceInfo{
IPAddresses: []tc.ServerIPAddress{
{
Address: "6.7.8.9",
Gateway: util.StrPtr("6.7.8.0/24"),
ServiceAddress: true,
},
{
Address: "2021::4",
Gateway: util.StrPtr("fd54::9"),
ServiceAddress: true,
},
{
Address: "6.6.7.9",
Gateway: util.StrPtr("6.6.7.0/24"),
ServiceAddress: false,
},
{
Address: "2022::4",
Gateway: util.StrPtr("fd53::9"),
ServiceAddress: false,
},
},
MaxBandwidth: util.Uint64Ptr(1500),
Monitor: false,
MTU: util.Uint64Ptr(1500),
Name: "interfaceName2" + strconv.Itoa(cacheID),
},
RouterHostName: "router2",
RouterPortName: "9091",
},
}
}
func mockServerInterfaces(mock sqlmock.Sqlmock, cacheID int, serverInterfaces []tc.ServerInterfaceInfoV40) {
interfaceRows := sqlmock.NewRows([]string{"max_bandwidth", "monitor", "mtu", "name", "server", "router_host_name", "router_port_name"})
ipAddressRows := sqlmock.NewRows([]string{"address", "gateway", "service_address", "interface", "server"})
for _, interf := range serverInterfaces {
interfaceRows = interfaceRows.AddRow(*interf.MaxBandwidth, interf.Monitor, *interf.MTU, interf.Name, cacheID, interf.RouterHostName, interf.RouterPortName)
for _, ip := range interf.IPAddresses {
ipAddressRows = ipAddressRows.AddRow(ip.Address, *ip.Gateway, ip.ServiceAddress, interf.Name, cacheID)
}
}
mock.ExpectQuery("SELECT (.+) FROM interface").WillReturnRows(interfaceRows)
mock.ExpectQuery("SELECT (.+) FROM ip_address").WillReturnRows(ipAddressRows)
}