This is an automated email from the ASF dual-hosted git repository.
ocket8888 pushed a commit to branch 5.0.x
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git
The following commit(s) were added to refs/heads/5.0.x by this push:
new 4b80904 Validate the assignment of ORG servers to topology-based DSes
(#5260) (#5271)
4b80904 is described below
commit 4b809049075a523e9e234ec464128ad74eaeab06
Author: ocket8888 <[email protected]>
AuthorDate: Wed Nov 11 10:20:51 2020 -0700
Validate the assignment of ORG servers to topology-based DSes (#5260)
(#5271)
* Validate the assignment of ORG servers to topology-based DSes
The ORG server cachegroups must belong to the DS's topology.
* Address review comments
(cherry picked from commit b938e6755865d08fd64f3ae6bcef65321fac6bb1)
Co-authored-by: Rawlin Peters <[email protected]>
---
CHANGELOG.md | 1 +
lib/go-tc/servers.go | 11 +-
.../testing/api/v3/deliveryserviceservers_test.go | 134 +++++++++++++----
.../servers_to_deliveryservice_assignment_test.go | 85 ++++++++++-
.../traffic_ops_golang/dbhelpers/db_helpers.go | 126 ++++++++--------
.../deliveryservice/servers/servers.go | 159 ++++++++++++---------
.../deliveryservice/servers/servers_test.go | 11 +-
.../server/servers_assignment.go | 45 ++++++
8 files changed, 389 insertions(+), 183 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d4b73b..c883cff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -65,6 +65,7 @@ The format is based on [Keep a
Changelog](http://keepachangelog.com/en/1.0.0/).
- Added `--traffic_ops_insecure=<0|1>` optional option to traffic_ops_ort.pl
- Added User-Agent string to Traffic Router log output.
- Added default sort logic to GET API calls using Read()
+- Traffic Ops: added validation for assigning ORG servers to topology-based
delivery services
### Fixed
- Fixed #5188 - DSR (delivery service request) incorrectly marked as complete
and error message not displaying when DSR fulfilled and DS update fails in
Traffic Portal. [Related Github
issue](https://github.com/apache/trafficcontrol/issues/5188)
diff --git a/lib/go-tc/servers.go b/lib/go-tc/servers.go
index 975e016..051fc72 100644
--- a/lib/go-tc/servers.go
+++ b/lib/go-tc/servers.go
@@ -739,11 +739,12 @@ type ServerPutStatus struct {
}
type ServerInfo struct {
- CachegroupID int `json:"cachegroupId" db:"cachegroup_id"`
- CDNID int `json:"cdnId" db:"cdn_id"`
- DomainName string `json:"domainName" db:"domain_name"`
- HostName string `json:"hostName" db:"host_name"`
- Type string `json:"type" db:"server_type"`
+ Cachegroup string
+ CachegroupID int
+ CDNID int
+ DomainName string
+ HostName string
+ Type string
}
type ServerDetail struct {
diff --git a/traffic_ops/testing/api/v3/deliveryserviceservers_test.go
b/traffic_ops/testing/api/v3/deliveryserviceservers_test.go
index 69324c1..836f199 100644
--- a/traffic_ops/testing/api/v3/deliveryserviceservers_test.go
+++ b/traffic_ops/testing/api/v3/deliveryserviceservers_test.go
@@ -31,6 +31,7 @@ func TestDeliveryServiceServers(t *testing.T) {
WithObjs(t, []TCObj{CDNs, Types, Tenants, Parameters, Profiles,
Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies,
DeliveryServices}, func() {
DeleteTestDeliveryServiceServers(t)
AssignServersToTopologyBasedDeliveryService(t)
+ AssignOriginsToTopologyBasedDeliveryServices(t)
AssignServersToNonTopologyBasedDeliveryServiceThatUsesMidTier(t)
})
}
@@ -55,10 +56,10 @@ func AssignServersToTopologyBasedDeliveryService(t
*testing.T) {
if ds[0].Topology == nil {
t.Fatal("expected delivery service: 'ds-top' to have a non-nil
Topology, actual: nil")
}
- serversResp, _, err := TOSession.GetServers(nil)
- servers := []tc.Server{}
- for _, s := range serversResp {
- if s.CDNID == *ds[0].CDNID && s.Type ==
tc.CacheTypeEdge.String() {
+ serversResp, _, err := TOSession.GetServersWithHdr(nil, nil)
+ servers := []tc.ServerV30{}
+ for _, s := range serversResp.Response {
+ if s.CDNID != nil && *s.CDNID == *ds[0].CDNID && s.Type ==
tc.CacheTypeEdge.String() {
servers = append(servers, s)
}
}
@@ -67,8 +68,8 @@ func AssignServersToTopologyBasedDeliveryService(t
*testing.T) {
}
serverNames := []string{}
for _, s := range servers {
- if s.CDNID == *ds[0].CDNID && s.Type ==
tc.CacheTypeEdge.String() {
- serverNames = append(serverNames, s.HostName)
+ if s.CDNID != nil && *s.CDNID == *ds[0].CDNID && s.Type ==
tc.CacheTypeEdge.String() {
+ serverNames = append(serverNames, *s.HostName)
} else {
t.Fatalf("expected only EDGE servers in cdn '%s',
actual: %v", *ds[0].CDNName, servers)
}
@@ -81,7 +82,7 @@ func AssignServersToTopologyBasedDeliveryService(t
*testing.T) {
t.Fatalf("assigning servers to topology-based delivery service
- expected: 400-level status code, actual: %d", reqInf.StatusCode)
}
- _, reqInf, err = TOSession.CreateDeliveryServiceServers(*ds[0].ID,
[]int{servers[0].ID}, false)
+ _, reqInf, err = TOSession.CreateDeliveryServiceServers(*ds[0].ID,
[]int{*servers[0].ID}, false)
if err == nil {
t.Fatal("creating deliveryserviceserver assignment for
topology-based delivery service - expected: error, actual: nil error")
}
@@ -89,6 +90,75 @@ func AssignServersToTopologyBasedDeliveryService(t
*testing.T) {
t.Fatalf("creating deliveryserviceserver assignment for
topology-based delivery service - expected: 400-level status code, actual: %d",
reqInf.StatusCode)
}
}
+
+func AssignOriginsToTopologyBasedDeliveryServices(t *testing.T) {
+ // attempt to assign ORG server to a topology-based DS while the ORG
server's cachegroup doesn't belong to the topology
+ params := url.Values{}
+ params.Add("hostName", "denver-mso-org-01")
+ resp, _, err := TOSession.GetServersWithHdr(¶ms, nil)
+ if err != nil {
+ t.Fatalf("unable to GET server: %v", err)
+ }
+ if len(resp.Response) != 1 {
+ t.Fatalf("GET server expected length: 1, actual: %d",
len(resp.Response))
+ }
+ orgServer := resp.Response[0]
+ _, reqInf, err :=
TOSession.AssignServersToDeliveryService([]string{*orgServer.HostName},
"ds-top-req-cap")
+ if err == nil {
+ t.Fatal("assigning ORG server to topology-based delivery
service while the ORG server's cachegroup does not belong to the topology -
expected: error, actual: nil error")
+ }
+ if reqInf.StatusCode < http.StatusBadRequest || reqInf.StatusCode >=
http.StatusInternalServerError {
+ t.Fatalf("assigning ORG server to topology-based delivery
service while the ORG server's cachegroup does not belong to the topology -
expected: 400-level status code, actual: %d", reqInf.StatusCode)
+ }
+ params = url.Values{}
+ params.Set("xmlId", "ds-top-req-cap")
+ ds, _, err := TOSession.GetDeliveryServicesV30WithHdr(nil, params)
+ if err != nil {
+ t.Fatalf("cannot GET delivery service 'ds-top-req-cap': %s",
err.Error())
+ }
+ if len(ds) != 1 {
+ t.Fatalf("expected one delivery service: 'ds-top-req-cap',
actual: %v", len(ds))
+ }
+ if ds[0].Topology == nil {
+ t.Fatal("expected delivery service: 'ds-top-req-cap' to have a
non-nil Topology, actual: nil")
+ }
+ _, reqInf, err = TOSession.CreateDeliveryServiceServers(*ds[0].ID,
[]int{*orgServer.ID}, false)
+ if err == nil {
+ t.Fatal("creating deliveryserviceserver assignment for ORG
server to topology-based delivery service while the ORG server's cachegroup
does not belong to the topology - expected: error, actual: nil error")
+ }
+ if reqInf.StatusCode < http.StatusBadRequest || reqInf.StatusCode >=
http.StatusInternalServerError {
+ t.Fatalf("creating deliveryserviceserver assignment for ORG
server to topology-based delivery service while the ORG server's cachegroup
does not belong to the topology - expected: 400-level status code, actual: %d",
reqInf.StatusCode)
+ }
+
+ // attempt to assign ORG server to a topology-based DS while the ORG
server's cachegroup belongs to the topology
+ _, reqInf, err =
TOSession.AssignServersToDeliveryService([]string{*orgServer.HostName},
"ds-top")
+ if err != nil {
+ t.Fatalf("assigning ORG server to topology-based delivery
service while the ORG server's cachegroup belongs to the topology - expected:
no error, actual: %v", err)
+ }
+ if reqInf.StatusCode < http.StatusOK || reqInf.StatusCode >=
http.StatusMultipleChoices {
+ t.Fatalf("assigning ORG server to topology-based delivery
service while the ORG server's cachegroup belongs to the topology - expected:
200-level status code, actual: %d", reqInf.StatusCode)
+ }
+ params = url.Values{}
+ params.Set("xmlId", "ds-top")
+ ds, _, err = TOSession.GetDeliveryServicesV30WithHdr(nil, params)
+ if err != nil {
+ t.Fatalf("cannot GET delivery service 'ds-top': %s",
err.Error())
+ }
+ if len(ds) != 1 {
+ t.Fatalf("expected one delivery service: 'ds-top', actual: %v",
len(ds))
+ }
+ if ds[0].Topology == nil {
+ t.Fatal("expected delivery service: 'ds-top' to have a non-nil
Topology, actual: nil")
+ }
+ _, reqInf, err = TOSession.CreateDeliveryServiceServers(*ds[0].ID,
[]int{*orgServer.ID}, true)
+ if err != nil {
+ t.Fatalf("creating deliveryserviceserver assignment for ORG
server to topology-based delivery service while the ORG server's cachegroup
belongs to the topology - expected: no error, actual: %v", err)
+ }
+ if reqInf.StatusCode < http.StatusOK || reqInf.StatusCode >=
http.StatusMultipleChoices {
+ t.Fatalf("creating deliveryserviceserver assignment for ORG
server to topology-based delivery service while the ORG server's cachegroup
belongs to the topology - expected: 200-level status code, actual: %d",
reqInf.StatusCode)
+ }
+}
+
func AssignServersToNonTopologyBasedDeliveryServiceThatUsesMidTier(t
*testing.T) {
params := url.Values{}
params.Set("xmlId", "ds1")
@@ -178,24 +248,28 @@ func
CreateTestDeliveryServiceServersWithRequiredCapabilities(t *testing.T) {
t.Run(ctc.description, func(t *testing.T) {
params := url.Values{}
params.Add("hostName", ctc.serverName)
- resp, _, err := TOSession.GetServers(¶ms)
+ resp, _, err := TOSession.GetServersWithHdr(¶ms,
nil)
if err != nil {
t.Fatalf("cannot GET Server by hostname: %v",
err)
}
- server := resp[0]
+ servers := resp.Response
+ server := servers[0]
+ if server.ID == nil {
+ t.Fatalf("server %s had nil ID", ctc.serverName)
+ }
_, _, err =
TOSession.CreateDeliveryServicesRequiredCapability(ctc.capability)
if err != nil {
t.Fatalf("*POST delivery service required
capability: %v", err)
}
- ctc.ssc.ServerID = &server.ID
+ ctc.ssc.ServerID = server.ID
_, _, err =
TOSession.CreateServerServerCapability(ctc.ssc)
if err != nil {
t.Fatalf("could not POST the server capability
%v to server %v: %v", *ctc.ssc.ServerCapability, *ctc.ssc.Server, err)
}
- _, _, got :=
TOSession.CreateDeliveryServiceServers(*ctc.capability.DeliveryServiceID,
[]int{server.ID}, true)
+ _, _, got :=
TOSession.CreateDeliveryServiceServers(*ctc.capability.DeliveryServiceID,
[]int{*server.ID}, true)
if (ctc.err == nil && got != nil) || (ctc.err != nil &&
!strings.Contains(got.Error(), ctc.err.Error())) {
t.Fatalf("expected ctc.err to contain %v, got
%v", ctc.err, got)
}
@@ -209,7 +283,7 @@ func
CreateTestDeliveryServiceServersWithRequiredCapabilities(t *testing.T) {
}
func CreateTestMSODSServerWithReqCap(t *testing.T) {
- dsReqCap, _, err :=
TOSession.GetDeliveryServicesRequiredCapabilities(nil, util.StrPtr("msods1"),
nil)
+ dsReqCap, _, err :=
TOSession.GetDeliveryServicesRequiredCapabilitiesWithHdr(nil,
util.StrPtr("msods1"), nil, nil)
if err != nil {
t.Fatalf("GET delivery service required capabilites: %v", err)
}
@@ -222,19 +296,22 @@ func CreateTestMSODSServerWithReqCap(t *testing.T) {
// TODO: DON'T hard-code server hostnames!
params := url.Values{}
params.Add("hostName", "denver-mso-org-01")
- resp, _, err := TOSession.GetServers(¶ms)
+ resp, _, err := TOSession.GetServersWithHdr(¶ms, nil)
if err != nil {
t.Fatalf("GET server denver-mso-org-01: %v", err)
}
- servers := resp
+ servers := resp.Response
if len(servers) != 1 {
t.Fatal("expected 1 server with hostname denver-mso-org-01")
}
s := servers[0]
+ if s.ID == nil {
+ t.Fatal("server 'denver-mso-org-01' had nil ID")
+ }
// Make sure server has no caps to ensure test correctness
- sccs, _, err := TOSession.GetServerServerCapabilities(&s.ID, nil, nil)
+ sccs, _, err := TOSession.GetServerServerCapabilitiesWithHdr(s.ID, nil,
nil, nil)
if err != nil {
t.Fatalf("GET server server capabilities for denver-mso-org-01:
%v", err)
}
@@ -243,7 +320,7 @@ func CreateTestMSODSServerWithReqCap(t *testing.T) {
}
// Is origin included in eligible servers even though it doesnt have
required capability
- eServers, _, err :=
TOSession.GetDeliveryServicesEligible(*dsReqCap[0].DeliveryServiceID)
+ eServers, _, err :=
TOSession.GetDeliveryServicesEligibleWithHdr(*dsReqCap[0].DeliveryServiceID,
nil)
if err != nil {
t.Fatalf("GET delivery service msods1 eligible servers: %v",
err)
}
@@ -258,7 +335,7 @@ func CreateTestMSODSServerWithReqCap(t *testing.T) {
t.Fatal("expected to find origin server denver-mso-org-01 to be
in eligible server return even though it is missing a required capability")
}
- if _, _, err =
TOSession.CreateDeliveryServiceServers(*dsReqCap[0].DeliveryServiceID,
[]int{s.ID}, true); err != nil {
+ if _, _, err =
TOSession.CreateDeliveryServiceServers(*dsReqCap[0].DeliveryServiceID,
[]int{*s.ID}, true); err != nil {
t.Fatalf("POST delivery service origin servers without
capabilities: %v", err)
}
@@ -300,7 +377,7 @@ func DeleteTestDeliveryServiceServers(t *testing.T) {
t.Errorf("POST delivery service servers: %v", err)
}
- dsServers, _, err := TOSession.GetDeliveryServiceServers()
+ dsServers, _, err := TOSession.GetDeliveryServiceServersWithHdr(nil)
if err != nil {
t.Errorf("GET delivery service servers: %v", err)
}
@@ -320,7 +397,7 @@ func DeleteTestDeliveryServiceServers(t *testing.T) {
t.Errorf("DELETE delivery service server: %v", err)
}
- dsServers, _, err = TOSession.GetDeliveryServiceServers()
+ dsServers, _, err = TOSession.GetDeliveryServiceServersWithHdr(nil)
if err != nil {
t.Errorf("GET delivery service servers: %v", err)
}
@@ -337,8 +414,8 @@ func DeleteTestDeliveryServiceServers(t *testing.T) {
}
}
-func getServerAndDSofSameCDN(t *testing.T) (tc.DeliveryServiceNullable,
tc.ServerV30) {
- dses, _, err := TOSession.GetDeliveryServicesNullable()
+func getServerAndDSofSameCDN(t *testing.T) (tc.DeliveryServiceNullableV30,
tc.ServerV30) {
+ dses, _, err := TOSession.GetDeliveryServicesV30WithHdr(nil, nil)
if err != nil {
t.Fatalf("cannot GET DeliveryServices: %v", err)
}
@@ -346,28 +423,23 @@ func getServerAndDSofSameCDN(t *testing.T)
(tc.DeliveryServiceNullable, tc.Serve
t.Fatal("GET DeliveryServices returned no dses, must have at
least 1 to test ds-servers")
}
- resp, _, err := TOSession.GetServers(nil)
+ resp, _, err := TOSession.GetServersWithHdr(nil, nil)
if err != nil {
t.Fatalf("cannot GET Servers: %v", err)
}
- servers := resp
+ servers := resp.Response
if len(servers) < 1 {
t.Fatal("GET Servers returned no dses, must have at least 1 to
test ds-servers")
}
for _, ds := range dses {
for _, s := range servers {
- if ds.CDNName != nil && *ds.CDNName == s.CDNName {
- upgraded, err := s.ToNullable().Upgrade()
- if err != nil {
- t.Errorf("upgrading server: %v", err)
- continue
- }
- return ds, upgraded
+ if ds.CDNName != nil && s.CDNName != nil && *ds.CDNName
== *s.CDNName {
+ return ds, s
}
}
}
t.Fatal("expected at least one delivery service and server in the same
CDN")
- return tc.DeliveryServiceNullable{}, tc.ServerV30{}
+ return tc.DeliveryServiceNullableV30{}, tc.ServerV30{}
}
diff --git
a/traffic_ops/testing/api/v3/servers_to_deliveryservice_assignment_test.go
b/traffic_ops/testing/api/v3/servers_to_deliveryservice_assignment_test.go
index 74f2fe3..5004293 100644
--- a/traffic_ops/testing/api/v3/servers_to_deliveryservice_assignment_test.go
+++ b/traffic_ops/testing/api/v3/servers_to_deliveryservice_assignment_test.go
@@ -29,6 +29,7 @@ func TestAssignments(t *testing.T) {
AssignTestDeliveryService(t)
AssignIncorrectTestDeliveryService(t)
AssignTopologyBasedDeliveryService(t)
+ OriginAssignTopologyBasedDeliveryService(t)
})
}
@@ -56,7 +57,7 @@ func AssignTestDeliveryService(t *testing.T) {
t.Fatalf("Server '%s' had nil ID", *server.HostName)
}
- rd, _, err :=
TOSession.GetDeliveryServiceByXMLIDNullable(*testData.DeliveryServices[0].XMLID)
+ rd, _, err :=
TOSession.GetDeliveryServiceByXMLIDNullableWithHdr(*testData.DeliveryServices[0].XMLID,
nil)
if err != nil {
t.Fatalf("Failed to fetch DS information: %v", err)
} else if len(rd) == 0 {
@@ -73,7 +74,7 @@ func AssignTestDeliveryService(t *testing.T) {
}
t.Logf("alerts: %+v", alerts)
- response, _, err :=
TOSession.GetServerIDDeliveryServices(*firstServer.ID)
+ response, _, err :=
TOSession.GetServerIDDeliveryServicesWithHdr(*firstServer.ID, nil)
t.Logf("response: %+v", response)
if err != nil {
t.Fatalf("Couldn't get Delivery Services assigned to Server
'%+v': %v", firstServer, err)
@@ -131,7 +132,7 @@ func AssignIncorrectTestDeliveryService(t *testing.T) {
t.Fatalf("Server '%s' has nil ID", hostname)
}
- rd, _, err :=
TOSession.GetDeliveryServiceByXMLIDNullable(*testData.DeliveryServices[0].XMLID)
+ rd, _, err :=
TOSession.GetDeliveryServiceByXMLIDNullableWithHdr(*testData.DeliveryServices[0].XMLID,
nil)
if err != nil {
t.Fatalf("Failed to fetch DS information: %v", err)
} else if len(rd) == 0 {
@@ -147,7 +148,7 @@ func AssignIncorrectTestDeliveryService(t *testing.T) {
t.Errorf("Expected bad assignment to fail, but it didn't!
(alerts: %v)", alerts)
}
- response, _, err := TOSession.GetServerIDDeliveryServices(*server.ID)
+ response, _, err :=
TOSession.GetServerIDDeliveryServicesWithHdr(*server.ID, nil)
t.Logf("response: %+v", response)
if err != nil {
t.Fatalf("Couldn't get Delivery Services assigned to Server
'%+v': %v", *server, err)
@@ -192,7 +193,7 @@ func AssignTopologyBasedDeliveryService(t *testing.T) {
t.Fatal("Server had nil ID")
}
- rd, _, err := TOSession.GetDeliveryServiceByXMLIDNullable("ds-top")
+ rd, _, err :=
TOSession.GetDeliveryServiceByXMLIDNullableWithHdr("ds-top", nil)
if err != nil {
t.Fatalf("Failed to fetch DS information: %v", err)
} else if len(rd) == 0 {
@@ -211,7 +212,7 @@ func AssignTopologyBasedDeliveryService(t *testing.T) {
t.Fatalf("assigning Topology-based delivery service to server -
expected: non-error status code, actual: %d", reqInf.StatusCode)
}
- response, _, err := TOSession.GetServerIDDeliveryServices(*server.ID)
+ response, _, err :=
TOSession.GetServerIDDeliveryServicesWithHdr(*server.ID, nil)
t.Logf("response: %+v", response)
if err != nil {
t.Fatalf("Couldn't get Delivery Services assigned to Server
'%+v': %v", *server, err)
@@ -230,3 +231,75 @@ func AssignTopologyBasedDeliveryService(t *testing.T) {
t.Errorf(`Valid Server/DS assignment was not created!`)
}
}
+
+func OriginAssignTopologyBasedDeliveryService(t *testing.T) {
+ params := url.Values{}
+ params.Add("hostName", "denver-mso-org-01")
+ rs, _, err := TOSession.GetServersWithHdr(¶ms, nil)
+ if err != nil {
+ t.Fatalf("Failed to fetch server information: %v", err)
+ } else if len(rs.Response) == 0 {
+ t.Fatalf("Failed to fetch server information: No results
returned!")
+ }
+ origin := &rs.Response[0]
+ if origin.ID == nil {
+ t.Fatal("Server had nil ID")
+ }
+
+ rd, _, err :=
TOSession.GetDeliveryServiceByXMLIDNullableWithHdr("ds-top-req-cap", nil)
+ if err != nil {
+ t.Fatalf("Failed to fetch DS information: %v", err)
+ } else if len(rd) == 0 {
+ t.Fatalf("Failed to fetch DS information: No results returned!")
+ }
+ firstDS := rd[0]
+ if firstDS.ID == nil {
+ t.Fatal("Fetch DS information returned unknown ID")
+ }
+
+ // invalid assignment: ORG server cachegroup does not belong to the
topology
+ alerts, reqInf, err :=
TOSession.AssignDeliveryServiceIDsToServerID(*origin.ID, []int{*firstDS.ID},
true)
+ if err == nil {
+ t.Errorf("Expected assigning ORG server to topology-based
delivery service where the ORG server does not belong to the topology to fail,
but it didn't! (alerts: %v)", alerts)
+ }
+ if reqInf.StatusCode < http.StatusBadRequest || reqInf.StatusCode >=
http.StatusInternalServerError {
+ t.Fatalf("assigning Topology-based delivery service to ORG
server that does not belong to the topology - expected: 400-level status code,
actual: %d", reqInf.StatusCode)
+ }
+
+ // valid assignment ORG server cachegroup belongs to the topology
+ rd, _, err =
TOSession.GetDeliveryServiceByXMLIDNullableWithHdr("ds-top", nil)
+ if err != nil {
+ t.Fatalf("Failed to fetch DS information: %v", err)
+ } else if len(rd) == 0 {
+ t.Fatalf("Failed to fetch DS information: No results returned!")
+ }
+ firstDS = rd[0]
+ if firstDS.ID == nil {
+ t.Fatal("Fetch DS information returned unknown ID")
+ }
+
+ alerts, reqInf, err =
TOSession.AssignDeliveryServiceIDsToServerID(*origin.ID, []int{*firstDS.ID},
true)
+ if err != nil {
+ t.Errorf("Expected assigning ORG server to topology-based
delivery service where the ORG server belongs to the topology to succeed, but
it didn't! (alerts: %v, err: %v)", alerts, err)
+ }
+ if reqInf.StatusCode < http.StatusOK || reqInf.StatusCode >=
http.StatusMultipleChoices {
+ t.Fatalf("assigning Topology-based delivery service to ORG
server that belongs to the topology - expected: 200-level status code, actual:
%d", reqInf.StatusCode)
+ }
+
+ response, _, err :=
TOSession.GetServerIDDeliveryServicesWithHdr(*origin.ID, nil)
+ if err != nil {
+ t.Fatalf("Couldn't get Delivery Services assigned to Server
'%+v': %v", *origin, err)
+ }
+ var found bool
+ for _, ds := range response {
+
+ if ds.ID != nil && *ds.ID == *firstDS.ID {
+ found = true
+ break
+ }
+ }
+
+ if !found {
+ t.Errorf(`Valid Server/DS assignment was not created!`)
+ }
+}
diff --git a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
index ae239f1..03ac0a8 100644
--- a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
+++ b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
@@ -527,36 +527,6 @@ func GetCDNDomainFromName(tx *sql.Tx, cdnName tc.CDNName)
(string, bool, error)
return domain, true, nil
}
-// GetServerInfo returns a ServerInfo struct, whether the server exists, and
an error (if one occurs).
-func GetServerInfo(serverID int, tx *sql.Tx) (tc.ServerInfo, bool, error) {
- q := `
-SELECT
- s.cachegroup as cachegroup_id,
- s.cdn_id as cdn_id,
- s.domain_name as domain_name,
- s.host_name as host_name,
- t.name as server_type
-FROM
- server s
-JOIN type t ON s.type = t.id
-WHERE s.id = $1
-`
- row := tc.ServerInfo{}
- if err := tx.QueryRow(q, serverID).Scan(
- &row.CachegroupID,
- &row.CDNID,
- &row.DomainName,
- &row.HostName,
- &row.Type,
- ); err != nil {
- if err == sql.ErrNoRows {
- return row, false, nil
- }
- return row, false, fmt.Errorf("querying server id %d: %v",
serverID, err.Error())
- }
- return row, true, nil
-}
-
// GetServerInterfaces, given the IDs of one or more servers, returns all of
their network
// interfaces mapped by their ids, or an error if one occurs during retrieval.
func GetServersInterfaces(ids []int, tx *sql.Tx)
(map[int]map[string]tc.ServerInterfaceInfo, error) {
@@ -708,70 +678,72 @@ func GetServerNameFromID(tx *sql.Tx, id int) (string,
bool, error) {
return name, true, nil
}
-type ServerHostNameCDNIDAndType struct {
- HostName string
- CDNID int
- Type string
-}
-
-// GetServerHostNamesAndTypesFromIDs returns the server's hostname, cdn ID and
associated type name
-func GetServerHostNamesAndTypesFromIDs(tx *sql.Tx, ids []int)
([]ServerHostNameCDNIDAndType, error) {
- qry := `
+// language=sql
+const getServerInfoBaseQuery = `
SELECT
+ s.cachegroup,
+ c.name,
s.host_name,
+ s.domain_name,
s.cdn_id,
t.name
FROM
server s JOIN type t ON s.type = t.id
-WHERE
- s.id = ANY($1)
+ JOIN cachegroup c on s.cachegroup = c.id
+`
+
+// GetServerInfosFromIDs returns the ServerInfo structs of the given server
IDs or an error if any occur.
+func GetServerInfosFromIDs(tx *sql.Tx, ids []int) ([]tc.ServerInfo, error) {
+ qry := getServerInfoBaseQuery + `
+WHERE s.id = ANY($1)
`
rows, err := tx.Query(qry, pq.Array(ids))
if err != nil {
- return nil, errors.New("querying server host names and types: "
+ err.Error())
- }
- defer log.Close(rows, "error closing rows")
-
- servers := []ServerHostNameCDNIDAndType{}
- for rows.Next() {
- s := ServerHostNameCDNIDAndType{}
- if err := rows.Scan(&s.HostName, &s.CDNID, &s.Type); err != nil
{
- return nil, errors.New("scanning server host name and
type: " + err.Error())
- }
- servers = append(servers, s)
+ return nil, errors.New("querying server info: " + err.Error())
}
- return servers, nil
+ return scanServerInfoRows(rows)
}
-// GetServerTypesCdnIdFromHostNames returns the host names, server cdn and
types of the given server host names or an error if any occur.
-func GetServerTypesCdnIdFromHostNames(tx *sql.Tx, hostNames []string)
([]ServerHostNameCDNIDAndType, error) {
- qry := `
-SELECT
- s.host_name,
- s.cdn_id,
- t.name
-FROM
- server s JOIN type t ON s.type = t.id
-WHERE
- s.host_name = ANY($1)
+// GetServerInfosFromHostNames returns the ServerInfo structs of the given
server host names or an error if any occur.
+func GetServerInfosFromHostNames(tx *sql.Tx, hostNames []string)
([]tc.ServerInfo, error) {
+ qry := getServerInfoBaseQuery + `
+WHERE s.host_name = ANY($1)
`
rows, err := tx.Query(qry, pq.Array(hostNames))
if err != nil {
- return nil, errors.New("querying server host names and types: "
+ err.Error())
+ return nil, errors.New("querying server info: " + err.Error())
}
- defer log.Close(rows, "error closing rows")
+ return scanServerInfoRows(rows)
+}
- servers := []ServerHostNameCDNIDAndType{}
+func scanServerInfoRows(rows *sql.Rows) ([]tc.ServerInfo, error) {
+ defer log.Close(rows, "error closing rows")
+ servers := []tc.ServerInfo{}
for rows.Next() {
- s := ServerHostNameCDNIDAndType{}
- if err := rows.Scan(&s.HostName, &s.CDNID, &s.Type); err != nil
{
- return nil, errors.New("scanning server host name and
type: " + err.Error())
+ s := tc.ServerInfo{}
+ if err := rows.Scan(&s.CachegroupID, &s.Cachegroup,
&s.HostName, &s.DomainName, &s.CDNID, &s.Type); err != nil {
+ return nil, errors.New("scanning server info: " +
err.Error())
}
servers = append(servers, s)
}
return servers, nil
}
+// GetServerInfo returns a ServerInfo struct, whether the server exists, and
an error (if one occurs).
+func GetServerInfo(serverID int, tx *sql.Tx) (tc.ServerInfo, bool, error) {
+ servers, err := GetServerInfosFromIDs(tx, []int{serverID})
+ if err != nil {
+ return tc.ServerInfo{}, false, fmt.Errorf("getting server info:
%v", err)
+ }
+ if len(servers) == 0 {
+ return tc.ServerInfo{}, false, nil
+ }
+ if len(servers) != 1 {
+ return tc.ServerInfo{}, false, fmt.Errorf("getting server info
- expected row count: 1, actual: %d", len(servers))
+ }
+ return servers[0], true, nil
+}
+
func GetCDNDSes(tx *sql.Tx, cdn tc.CDNName)
(map[tc.DeliveryServiceName]struct{}, error) {
dses := map[tc.DeliveryServiceName]struct{}{}
qry := `SELECT xml_id from deliveryservice where cdn_id = (select id
from cdn where name = $1)`
@@ -867,6 +839,20 @@ func TopologyExists(tx *sql.Tx, name string) (bool, error)
{
return count > 0, err
}
+// GetTopologyCachegroups returns the set of cachegroup names for the given
topology.
+func GetTopologyCachegroups(tx *sql.Tx, name string) ([]string, error) {
+ q := `
+ SELECT ARRAY_AGG(tc.cachegroup)
+ FROM topology_cachegroup tc
+ WHERE tc.topology = $1
+ `
+ cachegroups := []string{}
+ if err := tx.QueryRow(q, name).Scan(pq.Array(&cachegroups)); err != nil
{
+ return nil, fmt.Errorf("querying topology '%s' cachegroups:
%s", name, err)
+ }
+ return cachegroups, nil
+}
+
// GetDeliveryServicesWithTopologies returns a list containing the delivery
services in the given dsIDs
// list that have a topology assigned. An error indicates unexpected errors
that occurred when querying.
func GetDeliveryServicesWithTopologies(tx *sql.Tx, dsIDs []int) ([]int, error)
{
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
index 4cc0b79..d099a3f 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
@@ -368,7 +368,7 @@ func GetReplaceHandler(w http.ResponseWriter, r
*http.Request) {
ds, ok, err := GetDSInfo(inf.Tx.Tx, *dsId)
if err != nil {
- api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError,
nil, errors.New("deliveryserviceserver getting XMLID: "+err.Error()))
+ api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError,
nil, fmt.Errorf("deliveryserviceserver getting delivery service info for ID %d:
%v", *dsId, err))
return
}
if !ok {
@@ -379,20 +379,15 @@ func GetReplaceHandler(w http.ResponseWriter, r
*http.Request) {
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
return
}
- serverNamesCdnIdAndTypes, err :=
dbhelpers.GetServerHostNamesAndTypesFromIDs(inf.Tx.Tx, servers)
+ serverInfos, err := dbhelpers.GetServerInfosFromIDs(inf.Tx.Tx, servers)
if err != nil {
- api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError,
err, nil)
- return
- }
- userErr = ValidateDSSAssignments(ds, serverNamesCdnIdAndTypes)
- if userErr != nil {
- api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, userErr,
nil)
+ api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError,
nil, err)
return
}
- usrErr, sysErr, status := ValidateServerCapabilities(ds.ID,
serverNamesCdnIdAndTypes, inf.Tx.Tx)
- if usrErr != nil || sysErr != nil {
- api.HandleErr(w, r, inf.Tx.Tx, status, usrErr, sysErr)
+ userErr, sysErr, status := validateDSSAssignments(inf.Tx.Tx, ds,
serverInfos)
+ if userErr != nil || sysErr != nil {
+ api.HandleErr(w, r, inf.Tx.Tx, status, userErr, sysErr)
return
}
@@ -421,7 +416,7 @@ func GetReplaceHandler(w http.ResponseWriter, r
*http.Request) {
return
}
api.CreateChangeLogRawTx(api.ApiChange, "DS: "+ds.Name+", ID:
"+strconv.Itoa(*dsId)+", ACTION: Replace existing servers assigned to delivery
service", inf.User, inf.Tx.Tx)
- api.WriteRespAlertObj(w, r, tc.SuccessLevel, "server assignements
complete", tc.DSSMapResponse{*dsId, *payload.Replace, respServers})
+ api.WriteRespAlertObj(w, r, tc.SuccessLevel, "server assignments
complete", tc.DSSMapResponse{*dsId, *payload.Replace, respServers})
}
type TODeliveryServiceServers tc.DeliveryServiceServers
@@ -444,7 +439,7 @@ func GetCreateHandler(w http.ResponseWriter, r
*http.Request) {
ds, ok, err := GetDSInfoByName(inf.Tx.Tx, dsName)
if err != nil {
- api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError,
nil, errors.New("ds servers create scanning: "+err.Error()))
+ api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError,
nil, fmt.Errorf("ds servers getting delivery service info for xmlID %s: %v",
dsName, err))
return
} else if !ok {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, nil,
errors.New("delivery service not found"))
@@ -460,21 +455,15 @@ func GetCreateHandler(w http.ResponseWriter, r
*http.Request) {
payload.XmlId = dsName
serverNames := payload.ServerNames
- serverNamesCdnIdAndTypes, err :=
dbhelpers.GetServerTypesCdnIdFromHostNames(inf.Tx.Tx, serverNames)
+ serverInfos, err := dbhelpers.GetServerInfosFromHostNames(inf.Tx.Tx,
serverNames)
if err != nil {
- api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError,
err, nil)
- return
- }
-
- userErr = ValidateDSSAssignments(ds, serverNamesCdnIdAndTypes)
- if userErr != nil {
- api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, userErr,
nil)
+ api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError,
nil, err)
return
}
- usrErr, sysErr, status := ValidateServerCapabilities(ds.ID,
serverNamesCdnIdAndTypes, inf.Tx.Tx)
- if usrErr != nil || sysErr != nil {
- api.HandleErr(w, r, inf.Tx.Tx, status, usrErr, sysErr)
+ userErr, sysErr, status := validateDSSAssignments(inf.Tx.Tx, ds,
serverInfos)
+ if userErr != nil || sysErr != nil {
+ api.HandleErr(w, r, inf.Tx.Tx, status, userErr, sysErr)
return
}
@@ -503,26 +492,67 @@ func GetCreateHandler(w http.ResponseWriter, r
*http.Request) {
api.WriteResp(w, r, tc.DeliveryServiceServers{payload.ServerNames,
payload.XmlId})
}
-// ValidateDSSAssignments returns an error if the given servers cannot be
assigned to the given delivery service.
-func ValidateDSSAssignments(ds DSInfo, servers
[]dbhelpers.ServerHostNameCDNIDAndType) error {
+// validateDSSAssignments returns an error if the given servers cannot be
assigned to the given delivery service.
+func validateDSSAssignments(tx *sql.Tx, ds DSInfo, serverInfos
[]tc.ServerInfo) (error, error, int) {
+ userErr, sysErr, status := validateDSS(tx, ds, serverInfos)
+ if userErr != nil || sysErr != nil {
+ return userErr, sysErr, status
+ }
+
+ userErr, sysErr, status = ValidateServerCapabilities(tx, ds.ID,
serverInfos)
+ if userErr != nil || sysErr != nil {
+ return userErr, sysErr, status
+ }
+ return nil, nil, http.StatusOK
+}
+
+func validateDSS(tx *sql.Tx, ds DSInfo, servers []tc.ServerInfo) (error,
error, int) {
if ds.Topology == nil {
for _, s := range servers {
if ds.CDNID != nil && s.CDNID != *ds.CDNID {
- return errors.New("server and delivery service
CDNs do not match")
+ return errors.New("server and delivery service
CDNs do not match"), nil, http.StatusBadRequest
}
}
- return nil
+ return nil, nil, http.StatusOK
}
for _, s := range servers {
if s.Type != tc.OriginTypeName {
- return errors.New("only servers of type ORG may be
assigned to topology-based delivery services")
+ return fmt.Errorf("only servers of type %s may be
assigned to topology-based delivery services", tc.OriginTypeName), nil,
http.StatusBadRequest
}
}
+
+ cachegroups, sysErr := dbhelpers.GetTopologyCachegroups(tx,
*ds.Topology)
+ if sysErr != nil {
+ return nil, fmt.Errorf("validating %s servers in topology %s:
%v", tc.OriginTypeName, *ds.Topology, sysErr), http.StatusInternalServerError
+ }
+ userErr := CheckServersInCachegroups(servers, cachegroups)
+ if userErr != nil {
+ return fmt.Errorf("validating %s servers in topology %s: %v",
tc.OriginTypeName, *ds.Topology, userErr), nil, http.StatusBadRequest
+ }
+ return nil, nil, http.StatusOK
+}
+
+// CheckServersInCachegroups checks whether or not all the given server
cachegroups belong to the topology
+// and returns a user error (if any).
+func CheckServersInCachegroups(servers []tc.ServerInfo, cachegroups []string)
error {
+ cgSet := make(map[string]struct{}, len(cachegroups))
+ for _, c := range cachegroups {
+ cgSet[c] = struct{}{}
+ }
+ invalid := []string{}
+ for _, s := range servers {
+ if _, ok := cgSet[s.Cachegroup]; !ok {
+ invalid = append(invalid, s.HostName+"
("+s.Cachegroup+")")
+ }
+ }
+ if len(invalid) > 0 {
+ return fmt.Errorf("the following servers are not in any of the
given cachegroups (%s): %s", strings.Join(cachegroups, ", "),
strings.Join(invalid, ", "))
+ }
return nil
}
// ValidateServerCapabilities checks that the delivery service's requirements
are met by each server to be assigned.
-func ValidateServerCapabilities(dsID int, serverNamesAndTypes
[]dbhelpers.ServerHostNameCDNIDAndType, tx *sql.Tx) (error, error, int) {
+func ValidateServerCapabilities(tx *sql.Tx, dsID int, serverNamesAndTypes
[]tc.ServerInfo) (error, error, int) {
nonOriginServerNames := []string{}
for _, s := range serverNamesAndTypes {
if strings.HasPrefix(s.Type, tc.EdgeTypePrefix) {
@@ -840,10 +870,10 @@ type DSInfo struct {
CDNID *int
}
-// GetDSInfo loads the DeliveryService fields needed by Delivery Service
Servers from the database, from the ID. Returns the data, whether the delivery
service was found, and any error.
-func GetDSInfo(tx *sql.Tx, id int) (DSInfo, bool, error) {
- qry := `
+// language=sql
+const getDSInfoBaseQuery = `
SELECT
+ ds.id,
ds.xml_id,
tp.name as type,
ds.edge_header_rewrite,
@@ -857,47 +887,46 @@ SELECT
FROM
deliveryservice ds
JOIN type tp ON ds.type = tp.id
-WHERE
- ds.id = $1
`
- di := DSInfo{ID: id}
- if err := tx.QueryRow(qry, id).Scan(&di.Name, &di.Type,
&di.EdgeHeaderRewrite, &di.MidHeaderRewrite, &di.RegexRemap,
&di.SigningAlgorithm, &di.CacheURL, &di.MaxOriginConnections, &di.Topology,
&di.CDNID); err != nil {
+
+func scanDSInfoRow(row *sql.Row) (DSInfo, bool, error) {
+ di := DSInfo{}
+ if err := row.Scan(
+ &di.ID,
+ &di.Name,
+ &di.Type,
+ &di.EdgeHeaderRewrite,
+ &di.MidHeaderRewrite,
+ &di.RegexRemap,
+ &di.SigningAlgorithm,
+ &di.CacheURL,
+ &di.MaxOriginConnections,
+ &di.Topology,
+ &di.CDNID,
+ ); err != nil {
if err == sql.ErrNoRows {
return DSInfo{}, false, nil
}
- return DSInfo{}, false, fmt.Errorf("querying delivery service
server ds info '%v': %v", id, err)
+ return DSInfo{}, false, fmt.Errorf("querying delivery service
server ds info: %v", err)
}
di.Type = tc.DSTypeFromString(string(di.Type))
return di, true, nil
}
-// GetDSInfoByName loads the DeliveryService fields needed by Delivery Service
Servers from the database, from the ID. Returns the data, whether the delivery
service was found, and any error.
+// GetDSInfo loads the DeliveryService fields needed by Delivery Service
Servers from the database, from the ID. Returns the data, whether the delivery
service was found, and any error.
+func GetDSInfo(tx *sql.Tx, id int) (DSInfo, bool, error) {
+ qry := getDSInfoBaseQuery + `
+WHERE ds.id = $1
+`
+ row := tx.QueryRow(qry, id)
+ return scanDSInfoRow(row)
+}
+
+// GetDSInfoByName loads the DeliveryService fields needed by Delivery Service
Servers from the database, from the name (xml_id). Returns the data, whether
the delivery service was found, and any error.
func GetDSInfoByName(tx *sql.Tx, dsName string) (DSInfo, bool, error) {
- qry := `
-SELECT
- ds.id,
- tp.name as type,
- ds.edge_header_rewrite,
- ds.mid_header_rewrite,
- ds.regex_remap,
- ds.signing_algorithm,
- ds.cacheurl,
- ds.max_origin_connections,
- ds.topology,
- ds.cdn_id
-FROM
- deliveryservice ds
- JOIN type tp ON ds.type = tp.id
-WHERE
- ds.xml_id = $1
+ qry := getDSInfoBaseQuery + `
+WHERE ds.xml_id = $1
`
- di := DSInfo{Name: dsName}
- if err := tx.QueryRow(qry, dsName).Scan(&di.ID, &di.Type,
&di.EdgeHeaderRewrite, &di.MidHeaderRewrite, &di.RegexRemap,
&di.SigningAlgorithm, &di.CacheURL, &di.MaxOriginConnections, &di.Topology,
&di.CDNID); err != nil {
- if err == sql.ErrNoRows {
- return DSInfo{}, false, nil
- }
- return DSInfo{}, false, fmt.Errorf("querying delivery service
server ds info by name '%v': %v", dsName, err)
- }
- di.Type = tc.DSTypeFromString(string(di.Type))
- return di, true, nil
+ row := tx.QueryRow(qry, dsName)
+ return scanDSInfoRow(row)
}
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 41382c1..2f2be31 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go
@@ -26,9 +26,8 @@ import (
"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"
+ "github.com/jmoiron/sqlx"
"gopkg.in/DATA-DOG/go-sqlmock.v1"
)
@@ -39,14 +38,14 @@ func TestValidateDSSAssignments(t *testing.T) {
ID: 0,
CDNID: &cdnID,
}
- var servers []dbhelpers.ServerHostNameCDNIDAndType
- server := dbhelpers.ServerHostNameCDNIDAndType{
+ var servers []tc.ServerInfo
+ server := tc.ServerInfo{
HostName: "serverHost",
CDNID: 0,
Type: "",
}
servers = append(servers, server)
- userErr := ValidateDSSAssignments(ds, servers)
+ userErr, _, _ := validateDSS(nil, ds, servers)
if userErr == nil {
t.Fatalf("Expected user error with mismatching ds and server
CDN IDs, got no error instead")
}
@@ -54,7 +53,7 @@ func TestValidateDSSAssignments(t *testing.T) {
t.Errorf("Expected error details %v, got %v", expected,
userErr.Error())
}
servers[0].CDNID = 1
- userErr = ValidateDSSAssignments(ds, servers)
+ userErr, _, _ = validateDSS(nil, ds, servers)
if userErr != nil {
t.Fatalf("Expected no user error, got %v", userErr.Error())
}
diff --git a/traffic_ops/traffic_ops_golang/server/servers_assignment.go
b/traffic_ops/traffic_ops_golang/server/servers_assignment.go
index ef1d83d..d9c4fd9 100644
--- a/traffic_ops/traffic_ops_golang/server/servers_assignment.go
+++ b/traffic_ops/traffic_ops_golang/server/servers_assignment.go
@@ -112,6 +112,12 @@ func AssignDeliveryServicesToServerHandler(w
http.ResponseWriter, r *http.Reques
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
return
}
+ if strings.HasPrefix(serverInfo.Type, tc.OriginTypeName) {
+ if userErr, sysErr, status :=
checkOriginInTopologies(inf.Tx.Tx, serverInfo.Cachegroup, dsList); userErr !=
nil || sysErr != nil {
+ api.HandleErr(w, r, inf.Tx.Tx, status, userErr,
sysErr)
+ return
+ }
+ }
}
assignedDSes, err := assignDeliveryServicesToServer(server, dsList,
replace, inf.Tx.Tx)
@@ -126,6 +132,45 @@ func AssignDeliveryServicesToServerHandler(w
http.ResponseWriter, r *http.Reques
api.WriteRespAlertObj(w, r, tc.SuccessLevel, "successfully assigned
dses to server", tc.AssignedDsResponse{server, assignedDSes, replace})
}
+// checkOriginInTopologies checks to make sure the given ORG server's
cachegroup belongs
+// to the topologies of the given delivery services.
+func checkOriginInTopologies(tx *sql.Tx, originCachegroup string, dsList
[]int) (error, error, int) {
+ // get the delivery services that don't have originCachegroup in their
topology
+ q := `
+SELECT
+ ds.xml_id,
+ tc.topology,
+ ARRAY_AGG(tc.cachegroup)
+FROM
+ deliveryservice ds
+ JOIN topology_cachegroup tc ON tc.topology = ds.topology
+WHERE
+ ds.id = ANY($1::BIGINT[])
+GROUP BY ds.xml_id, tc.topology
+HAVING NOT ($2 = ANY(ARRAY_AGG(tc.cachegroup)))
+`
+ rows, err := tx.Query(q, pq.Array(dsList), originCachegroup)
+ if err != nil {
+ return nil, errors.New("querying deliveryservice topologies: "
+ err.Error()), http.StatusInternalServerError
+ }
+ defer log.Close(rows, "error closing rows")
+
+ invalid := []string{}
+ for rows.Next() {
+ xmlID := ""
+ topology := ""
+ cachegroups := []string{}
+ if err := rows.Scan(&xmlID, &topology, pq.Array(&cachegroups));
err != nil {
+ return nil, errors.New("scanning deliveryservice
topologies: " + err.Error()), http.StatusInternalServerError
+ }
+ invalid = append(invalid, fmt.Sprintf("%s (%s)", topology,
xmlID))
+ }
+ if len(invalid) > 0 {
+ return fmt.Errorf("%s server cachegroup (%s) not found in the
following topologies: %s", tc.OriginTypeName, originCachegroup,
strings.Join(invalid, ", ")), nil, http.StatusBadRequest
+ }
+ return nil, nil, http.StatusOK
+}
+
func checkTenancyAndCDN(tx *sql.Tx, serverCDN string, server int, serverInfo
tc.ServerInfo, dsList []int, user *auth.CurrentUser) (int, error, error) {
rows, err := tx.Query(needsCheckInfoQuery, pq.Array(dsList))
if err != nil {