Skip to content
This repository was archived by the owner on Nov 24, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- Traffic Ops: Added an API 3.0 endpoint, /api/3.0/topologies, to create, read, update and delete flexible topologies.
- Traffic Ops: Added new `topology` field to the /api/3.0/deliveryservices APIs
- Traffic Ops: Added support for `topology` query parameter to `GET /api/3.0/cachegroups` to return all cachegroups used in the given topology.
- Traffic Ops: Added validation to prohibit assigning caches to topology-based delivery services
- Traffic Portal: Added the ability to create, read, update and delete flexible topologies.
- Traffic Portal: Added the ability to assign topologies to delivery services
- Updated /servers/details to use multiple interfaces in API v3
Expand Down
4 changes: 2 additions & 2 deletions lib/go-tc/deliveryservices.go
Original file line number Diff line number Diff line change
Expand Up @@ -614,13 +614,13 @@ type DSServerIDs struct {
}

type CachegroupPostDSReq struct {
DeliveryServices []int64 `json:"deliveryServices"`
DeliveryServices []int `json:"deliveryServices"`
}

type CacheGroupPostDSResp struct {
ID util.JSONIntStr `json:"id"`
ServerNames []CacheName `json:"serverNames"`
DeliveryServices []int64 `json:"deliveryServices"`
DeliveryServices []int `json:"deliveryServices"`
}

type CacheGroupPostDSRespResponse struct {
Expand Down
25 changes: 25 additions & 0 deletions traffic_ops/client/cachegroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"net"
"net/http"
"net/url"
"strconv"

"github.com/apache/trafficcontrol/lib/go-log"
"github.com/apache/trafficcontrol/lib/go-tc"
Expand Down Expand Up @@ -212,3 +213,27 @@ func (to *Session) GetCacheGroupsByQueryParams(qparams url.Values) ([]tc.CacheGr

return data.Response, reqInf, nil
}

func (to *Session) SetCachegroupDeliveryServices(cgID int, dsIDs []int) (tc.CacheGroupPostDSRespResponse, ReqInf, error) {
uri := apiBase + `/cachegroups/` + strconv.Itoa(cgID) + `/deliveryservices`
req := tc.CachegroupPostDSReq{DeliveryServices: dsIDs}
reqBody, err := json.Marshal(req)
if err != nil {
return tc.CacheGroupPostDSRespResponse{}, ReqInf{}, err
}
reqResp, remoteAddr, err := to.request(http.MethodPost, uri, reqBody)
reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
if reqResp != nil {
reqInf.StatusCode = reqResp.StatusCode
}
if err != nil {
return tc.CacheGroupPostDSRespResponse{}, reqInf, errors.New("requesting from Traffic Ops: " + err.Error())
}
defer log.Close(reqResp.Body, "unable to close response body")

resp := tc.CacheGroupPostDSRespResponse{}
if err := json.NewDecoder(reqResp.Body).Decode(&resp); err != nil {
return tc.CacheGroupPostDSRespResponse{}, reqInf, errors.New("decoding response: " + err.Error())
}
return resp, reqInf, nil
}
23 changes: 0 additions & 23 deletions traffic_ops/client/coordinate.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@ package client

import (
"encoding/json"
"errors"
"fmt"
"net"
"net/http"
"strconv"

"github.com/apache/trafficcontrol/lib/go-tc"
)
Expand Down Expand Up @@ -132,24 +130,3 @@ func (to *Session) DeleteCoordinateByID(id int) (tc.Alerts, ReqInf, error) {
err = json.NewDecoder(resp.Body).Decode(&alerts)
return alerts, reqInf, nil
}

func (to *Session) SetCachegroupDeliveryServices(cgID int, dsIDs []int64) (tc.CacheGroupPostDSRespResponse, ReqInf, error) {
uri := apiBase + `/cachegroups/` + strconv.Itoa(cgID) + `/deliveryservices`
req := tc.CachegroupPostDSReq{DeliveryServices: dsIDs}
reqBody, err := json.Marshal(req)
reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss}
if err != nil {
return tc.CacheGroupPostDSRespResponse{}, reqInf, err
}
reqResp, _, err := to.request(http.MethodPost, uri, reqBody)
if err != nil {
return tc.CacheGroupPostDSRespResponse{}, reqInf, errors.New("requesting from Traffic Ops: " + err.Error())
}
defer reqResp.Body.Close()

resp := tc.CacheGroupPostDSRespResponse{}
if err := json.NewDecoder(reqResp.Body).Decode(&resp); err != nil {
return tc.CacheGroupPostDSRespResponse{}, reqInf, errors.New("decoding response: " + err.Error())
}
return resp, reqInf, nil
}
5 changes: 5 additions & 0 deletions traffic_ops/client/deliveryservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ const (
// to the associations between Delivery Services and their assigned Server(s).
// See Also: https://traffic-control-cdn.readthedocs.io/en/latest/api/v3/deliveryserviceserver.html
API_DELIVERY_SERVICE_SERVER = apiBase + "/deliveryserviceserver"

// API_DELIVERY_SERVICES_SERVERS is the API path on which Traffic Ops serves functionality related
// to the associations between a Delivery Service and its assigned Server(s).
// See Also: https://traffic-control-cdn.readthedocs.io/en/latest/api/v3/deliveryservices_xmlid_servers.html
API_DELIVERY_SERVICES_SERVERS = apiBase + "/deliveryservices/%s/servers"
)

// GetDeliveryServicesByServer returns all of the (tenant-visible) Delivery Services assigned to
Expand Down
34 changes: 29 additions & 5 deletions traffic_ops/client/deliveryserviceserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@ package client
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"

"github.com/apache/trafficcontrol/lib/go-log"
"github.com/apache/trafficcontrol/lib/go-tc"
"github.com/apache/trafficcontrol/lib/go-util"
)

// CreateDeliveryServiceServers associates the given servers with the given delivery services. If replace is true, it deletes any existing associations for the given delivery service.
func (to *Session) CreateDeliveryServiceServers(dsID int, serverIDs []int, replace bool) (*tc.DSServerIDs, error) {
func (to *Session) CreateDeliveryServiceServers(dsID int, serverIDs []int, replace bool) (*tc.DSServerIDs, ReqInf, error) {
path := apiBase + `/deliveryserviceserver`
req := tc.DSServerIDs{
DeliveryServiceID: util.IntPtr(dsID),
Expand All @@ -37,15 +39,16 @@ func (to *Session) CreateDeliveryServiceServers(dsID int, serverIDs []int, repla
}
jsonReq, err := json.Marshal(&req)
if err != nil {
return nil, err
return nil, ReqInf{}, err
}
resp := struct {
Response tc.DSServerIDs `json:"response"`
}{}
if _, err := post(to, path, jsonReq, &resp); err != nil {
return nil, err
reqInf, err := post(to, path, jsonReq, &resp)
if err != nil {
return nil, reqInf, err
}
return &resp.Response, nil
return &resp.Response, reqInf, nil
}

func (to *Session) DeleteDeliveryServiceServer(dsID int, serverID int) (tc.Alerts, ReqInf, error) {
Expand All @@ -63,6 +66,27 @@ func (to *Session) DeleteDeliveryServiceServer(dsID int, serverID int) (tc.Alert
return resp, reqInf, nil
}

// AssignServersToDeliveryService assigns the given list of servers to the delivery service with the given xmlId.
func (to *Session) AssignServersToDeliveryService(servers []string, xmlId string) (tc.Alerts, ReqInf, error) {
route := fmt.Sprintf(API_DELIVERY_SERVICES_SERVERS, xmlId)
dss := tc.DeliveryServiceServers{ServerNames: servers, XmlId: xmlId}
reqBody, err := json.Marshal(&dss)
reqResp, remoteAddr, err := to.request(http.MethodPost, route, reqBody)
reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
if reqResp != nil {
reqInf.StatusCode = reqResp.StatusCode
}
if err != nil {
return tc.Alerts{}, reqInf, errors.New("requesting from Traffic Ops: " + err.Error())
}
defer log.Close(reqResp.Body, "unable to close response body")
resp := tc.Alerts{}
if err = json.NewDecoder(reqResp.Body).Decode(&resp); err != nil {
return tc.Alerts{}, reqInf, errors.New("decoding response: " + err.Error())
}
return resp, reqInf, nil
}

// GetDeliveryServiceServers gets all delivery service servers, with the default API limit.
func (to *Session) GetDeliveryServiceServers() (tc.DeliveryServiceServerResponse, ReqInf, error) {
return to.getDeliveryServiceServers(url.Values{})
Expand Down
6 changes: 5 additions & 1 deletion traffic_ops/client/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"net/url"
"strings"

"github.com/apache/trafficcontrol/lib/go-log"
"github.com/apache/trafficcontrol/lib/go-tc"
)

Expand Down Expand Up @@ -301,10 +302,13 @@ func (to *Session) AssignDeliveryServiceIDsToServerID(server int, dsIDs []int, r
}

resp, remoteAddr, err := to.request(http.MethodPost, endpoint, reqBody)
if resp != nil {
reqInf.StatusCode = resp.StatusCode
}
if err != nil {
return tc.Alerts{}, reqInf, err
}
defer resp.Body.Close()
defer log.Close(resp.Body, "unable to close response body")
reqInf.RemoteAddr = remoteAddr
var alerts tc.Alerts
err = json.NewDecoder(resp.Body).Decode(&alerts)
Expand Down
7 changes: 6 additions & 1 deletion traffic_ops/client/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
"encoding/json"
"errors"
"io/ioutil"

"github.com/apache/trafficcontrol/lib/go-log"
)

func get(to *Session, endpoint string, respStruct interface{}) (ReqInf, error) {
Expand All @@ -40,10 +42,13 @@ func del(to *Session, endpoint string, respStruct interface{}) (ReqInf, error) {
func makeReq(to *Session, method, endpoint string, body []byte, respStruct interface{}) (ReqInf, error) {
resp, remoteAddr, err := to.request(method, endpoint, body) // TODO change to getBytesWithTTL
reqInf := ReqInf{RemoteAddr: remoteAddr, CacheHitStatus: CacheHitStatusMiss}
if resp != nil {
reqInf.StatusCode = resp.StatusCode
}
if err != nil {
return reqInf, err
}
defer resp.Body.Close()
defer log.Close(resp.Body, "unable to close response body")

bts, err := ioutil.ReadAll(resp.Body)
if err != nil {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ func CreateTestCachegroupsDeliveryServices(t *testing.T) {
}
cgID := *clientCG.ID

dsIDs := []int64{}
dsIDs := []int{}
for _, ds := range dses {
if ds.CDNName == "cdn1" {
dsIDs = append(dsIDs, int64(ds.ID))
dsIDs = append(dsIDs, ds.ID)
}
}
if len(dsIDs) < 1 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ func CreateTestCachegroupsDeliveryServices(t *testing.T) {
}
cgID := *clientCG.ID

dsIDs := []int64{}
dsIDs := []int{}
for _, ds := range dses {
if *ds.CDNName == "cdn1" {
dsIDs = append(dsIDs, int64(*ds.ID))
dsIDs = append(dsIDs, *ds.ID)
}
}
if len(dsIDs) < 1 {
Expand Down
22 changes: 19 additions & 3 deletions traffic_ops/testing/api/v3/cachegroupsdeliveryservices_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package v3
*/

import (
"net/http"
"testing"
)

Expand Down Expand Up @@ -58,16 +59,31 @@ func CreateTestCachegroupsDeliveryServices(t *testing.T) {
}
cgID := *clientCG.ID

dsIDs := []int64{}
dsIDs := []int{}
topologyDsIDs := []int{}
for _, ds := range dses {
if *ds.CDNName == "cdn1" {
dsIDs = append(dsIDs, int64(*ds.ID))
if *ds.CDNName == "cdn1" && ds.Topology == nil {
dsIDs = append(dsIDs, *ds.ID)
} else if *ds.CDNName == "cdn1" && ds.Topology != nil {
topologyDsIDs = append(topologyDsIDs, *ds.ID)
}
}
if len(dsIDs) < 1 {
t.Fatal("No Delivery Services found in CDN 'cdn1', cannot continue.")
}

if len(topologyDsIDs) < 1 {
t.Fatal("No Topology-based Delivery Services found in CDN 'cdn1', cannot continue.")
}

_, reqInf, err := TOSession.SetCachegroupDeliveryServices(cgID, topologyDsIDs)
if err == nil {
t.Fatal("assigning Topology-based delivery service to cachegroup - expected: error, actual: nil")
}
if reqInf.StatusCode < http.StatusBadRequest || reqInf.StatusCode >= http.StatusInternalServerError {
t.Fatalf("assigning Topology-based delivery service to cachegroup - expected: 400-level status code, actual: %d", reqInf.StatusCode)
}

resp, _, err := TOSession.SetCachegroupDeliveryServices(cgID, dsIDs)
if err != nil {
t.Fatalf("setting cachegroup delivery services returned error: %v", err)
Expand Down
2 changes: 1 addition & 1 deletion traffic_ops/testing/api/v3/crconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func UpdateTestCRConfigSnapshot(t *testing.T) {
t.Error("GetDeliveryServiceByXMLIDNullable got unknown delivery service id")
}
anymapDSID := *res[0].ID
_, err = TOSession.CreateDeliveryServiceServers(anymapDSID, []int{serverID}, true)
_, _, err = TOSession.CreateDeliveryServiceServers(anymapDSID, []int{serverID}, true)
if err != nil {
t.Errorf("POST delivery service servers: %v", err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ func InvalidDeliveryServicesRequiredCapabilityAddition(t *testing.T) {
}

// Assign server to ds
_, err = TOSession.CreateDeliveryServiceServers(*dsID, []int{sID}, false)
_, _, err = TOSession.CreateDeliveryServiceServers(*dsID, []int{sID}, false)
if err != nil {
t.Fatalf("cannot CREATE server delivery service assignement: %v", err)
}
Expand Down
Loading