blob: fcc6a5744514bee2216feee02a22bdd7531c0a0d [file] [log] [blame]
package v4
/*
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 (
"encoding/json"
"net/http"
"testing"
"time"
"github.com/apache/trafficcontrol/lib/go-rfc"
"github.com/apache/trafficcontrol/lib/go-tc"
"github.com/apache/trafficcontrol/lib/go-util"
"github.com/apache/trafficcontrol/traffic_ops/testing/api/assert"
"github.com/apache/trafficcontrol/traffic_ops/testing/api/utils"
"github.com/apache/trafficcontrol/traffic_ops/toclientlib"
client "github.com/apache/trafficcontrol/traffic_ops/v4-client"
)
func TestSteeringTargets(t *testing.T) {
WithObjs(t, []TCObj{CDNs, Types, Tenants, Parameters, Profiles, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices, Users, SteeringTargets}, func() {
steeringUserSession := utils.CreateV4Session(t, Config.TrafficOps.URL, "steering", "pa$$word", Config.Default.Session.TimeoutInSecs)
currentTime := time.Now().UTC().Add(-15 * time.Second)
currentTimeRFC := currentTime.Format(time.RFC1123)
tomorrow := currentTime.AddDate(0, 0, 1).Format(time.RFC1123)
methodTests := utils.V4TestCase{
"GET": {
"NOT MODIFIED when NO CHANGES made": {
EndpointId: GetDeliveryServiceId(t, "ds1"),
ClientSession: steeringUserSession,
RequestOpts: client.RequestOptions{Header: http.Header{rfc.IfModifiedSince: {tomorrow}}},
Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
},
"OK when VALID request": {
EndpointId: GetDeliveryServiceId(t, "ds1"),
ClientSession: steeringUserSession,
Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(1),
validateSteeringTargetFields(map[string]interface{}{"DeliveryService": "ds1", "DeliveryServiceID": uint64(GetDeliveryServiceId(t, "ds1")()),
"Target": "ds2", "TargetID": uint64(GetDeliveryServiceId(t, "ds2")()), "Type": "STEERING_WEIGHT", "TypeID": GetTypeID(t, "STEERING_WEIGHT")(), "Value": util.JSONIntStr(42)})),
},
},
"PUT": {
"OK when VALID request": {
ClientSession: steeringUserSession,
RequestBody: map[string]interface{}{
"deliveryServiceId": GetDeliveryServiceId(t, "ds3")(),
"targetId": GetDeliveryServiceId(t, "ds4")(),
"value": -12345,
"typeId": GetTypeID(t, "STEERING_WEIGHT")(),
},
Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
validateSteeringTargetUpdateCreateFields(GetDeliveryServiceId(t, "ds3")(),
map[string]interface{}{"DeliveryService": "ds3", "DeliveryServiceID": uint64(GetDeliveryServiceId(t, "ds3")()),
"Target": "ds4", "TargetID": uint64(GetDeliveryServiceId(t, "ds4")()), "Type": "STEERING_WEIGHT",
"TypeID": GetTypeID(t, "STEERING_WEIGHT")(), "Value": util.JSONIntStr(-12345)})),
},
"PRECONDITION FAILED when updating with IMS & IUS Headers": {
ClientSession: steeringUserSession,
RequestOpts: client.RequestOptions{Header: http.Header{rfc.IfUnmodifiedSince: {currentTimeRFC}}},
RequestBody: map[string]interface{}{
"deliveryServiceId": GetDeliveryServiceId(t, "ds3")(),
"targetId": GetDeliveryServiceId(t, "ds4")(),
"value": -12345,
"type": "STEERING_WEIGHT",
"typeId": GetTypeID(t, "STEERING_WEIGHT")(),
},
Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusPreconditionFailed)),
},
"PRECONDITION FAILED when updating with IFMATCH ETAG Header": {
ClientSession: steeringUserSession,
RequestOpts: client.RequestOptions{Header: http.Header{rfc.IfMatch: {rfc.ETag(currentTime)}}},
RequestBody: map[string]interface{}{
"deliveryServiceId": GetDeliveryServiceId(t, "ds3")(),
"targetId": GetDeliveryServiceId(t, "ds4")(),
"value": -12345,
"type": "STEERING_WEIGHT",
"typeId": GetTypeID(t, "STEERING_WEIGHT")(),
},
Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusPreconditionFailed)),
},
},
"GET AFTER CHANGES": {
"OK when CHANGES made": {
EndpointId: GetDeliveryServiceId(t, "ds1"),
ClientSession: steeringUserSession,
RequestOpts: client.RequestOptions{Header: http.Header{rfc.IfModifiedSince: {currentTimeRFC}}},
Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
},
},
}
for method, testCases := range methodTests {
t.Run(method, func(t *testing.T) {
for name, testCase := range testCases {
steeringTarget := tc.SteeringTargetNullable{}
if testCase.RequestBody != nil {
dat, err := json.Marshal(testCase.RequestBody)
assert.NoError(t, err, "Error occurred when marshalling request body: %v", err)
err = json.Unmarshal(dat, &steeringTarget)
assert.NoError(t, err, "Error occurred when unmarshalling request body: %v", err)
}
switch method {
case "GET", "GET AFTER CHANGES":
t.Run(name, func(t *testing.T) {
resp, reqInf, err := testCase.ClientSession.GetSteeringTargets(testCase.EndpointId(), testCase.RequestOpts)
for _, check := range testCase.Expectations {
check(t, reqInf, resp.Response, resp.Alerts, err)
}
})
case "POST":
t.Run(name, func(t *testing.T) {
alerts, reqInf, err := testCase.ClientSession.CreateSteeringTarget(steeringTarget, testCase.RequestOpts)
for _, check := range testCase.Expectations {
check(t, reqInf, nil, alerts, err)
}
})
case "PUT":
t.Run(name, func(t *testing.T) {
alerts, reqInf, err := testCase.ClientSession.UpdateSteeringTarget(steeringTarget, testCase.RequestOpts)
for _, check := range testCase.Expectations {
check(t, reqInf, nil, alerts, err)
}
})
case "DELETE":
t.Run(name, func(t *testing.T) {
var targetID int
if testCase.RequestBody != nil {
if val, ok := testCase.RequestBody["targetID"]; ok {
targetID = val.(int)
}
}
alerts, reqInf, err := testCase.ClientSession.DeleteSteeringTarget(testCase.EndpointId(), targetID, testCase.RequestOpts)
for _, check := range testCase.Expectations {
check(t, reqInf, nil, alerts, err)
}
})
}
}
})
}
})
}
func validateSteeringTargetFields(expectedResp map[string]interface{}) utils.CkReqFunc {
return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _ tc.Alerts, _ error) {
assert.RequireNotNil(t, resp, "Expected Steering Targets response to not be nil.")
steeringTargetsResp := resp.([]tc.SteeringTargetNullable)
for field, expected := range expectedResp {
for _, steeringTarget := range steeringTargetsResp {
switch field {
case "DeliveryService":
assert.RequireNotNil(t, steeringTarget.DeliveryService, "Expected DeliveryService to not be nil.")
assert.Equal(t, expected, string(*steeringTarget.DeliveryService), "Expected DeliveryService to be %v, but got %s", expected, *steeringTarget.DeliveryService)
case "DeliveryServiceID":
assert.RequireNotNil(t, steeringTarget.DeliveryServiceID, "Expected DeliveryServiceID to not be nil.")
assert.Equal(t, expected, *steeringTarget.DeliveryServiceID, "Expected DeliveryServiceID to be %v, but got %s", expected, *steeringTarget.DeliveryServiceID)
case "Target":
assert.RequireNotNil(t, steeringTarget.Target, "Expected Target to not be nil.")
assert.Equal(t, expected, string(*steeringTarget.Target), "Expected Target to be %v, but got %s", expected, *steeringTarget.Target)
case "TargetID":
assert.RequireNotNil(t, steeringTarget.TargetID, "Expected TargetID to not be nil.")
assert.Equal(t, expected, *steeringTarget.TargetID, "Expected TargetID to be %v, but got %s", expected, *steeringTarget.TargetID)
case "Type":
assert.RequireNotNil(t, steeringTarget.Type, "Expected Type to not be nil.")
assert.Equal(t, expected, *steeringTarget.Type, "Expected Type to be %v, but got %s", expected, *steeringTarget.Type)
case "TypeID":
assert.RequireNotNil(t, steeringTarget.Type, "Expected TypeID to not be nil.")
assert.Equal(t, expected, *steeringTarget.TypeID, "Expected TypeID to be %v, but got %s", expected, *steeringTarget.TypeID)
case "Value":
assert.RequireNotNil(t, steeringTarget.Value, "Expected Value to not be nil.")
assert.Equal(t, expected, *steeringTarget.Value, "Expected Value to be %v, but got %s", expected, *steeringTarget.Value)
default:
t.Errorf("Expected field: %v, does not exist in response", field)
}
}
}
}
}
func validateSteeringTargetUpdateCreateFields(dsId int, expectedResp map[string]interface{}) utils.CkReqFunc {
return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _ tc.Alerts, _ error) {
steeringTargets, _, err := TOSession.GetSteeringTargets(dsId, client.RequestOptions{})
assert.RequireNoError(t, err, "Error getting Steering Targets: %v - alerts: %+v", err, steeringTargets.Alerts)
assert.RequireEqual(t, 1, len(steeringTargets.Response), "Expected one Steering Target returned Got: %d", len(steeringTargets.Response))
validateSteeringTargetFields(expectedResp)(t, toclientlib.ReqInf{}, steeringTargets.Response, tc.Alerts{}, nil)
}
}
func CreateTestSteeringTargets(t *testing.T) {
steeringUserSession := utils.CreateV4Session(t, Config.TrafficOps.URL, "steering", "pa$$word", Config.Default.Session.TimeoutInSecs)
for _, st := range testData.SteeringTargets {
st.TypeID = util.IntPtr(GetTypeID(t, *st.Type)())
st.DeliveryServiceID = util.UInt64Ptr(uint64(GetDeliveryServiceId(t, string(*st.DeliveryService))()))
st.TargetID = util.UInt64Ptr(uint64(GetDeliveryServiceId(t, string(*st.Target))()))
resp, _, err := steeringUserSession.CreateSteeringTarget(st, client.RequestOptions{})
assert.RequireNoError(t, err, "Creating steering target: %v - alerts: %+v", err, resp.Alerts)
}
}
func DeleteTestSteeringTargets(t *testing.T) {
steeringUserSession := utils.CreateV4Session(t, Config.TrafficOps.URL, "steering", "pa$$word", Config.Default.Session.TimeoutInSecs)
dsIDs := []uint64{}
for _, st := range testData.SteeringTargets {
opts := client.NewRequestOptions()
opts.QueryParameters.Set("xmlId", string(*st.DeliveryService))
respDS, _, err := steeringUserSession.GetDeliveryServices(opts)
assert.RequireNoError(t, err, "Deleting steering target: getting ds: %v - alerts: %+v", err, respDS.Alerts)
assert.RequireEqual(t, 1, len(respDS.Response), "Deleting steering target: getting ds: expected 1 delivery service")
assert.RequireNotNil(t, respDS.Response[0].ID, "Deleting steering target: getting ds: nil ID returned")
dsID := uint64(*respDS.Response[0].ID)
st.DeliveryServiceID = &dsID
dsIDs = append(dsIDs, dsID)
opts.QueryParameters.Set("xmlId", string(*st.Target))
respTarget, _, err := steeringUserSession.GetDeliveryServices(opts)
assert.RequireNoError(t, err, "Deleting steering target: getting target ds: %v - alerts: %+v", err, respTarget.Alerts)
assert.RequireEqual(t, 1, len(respTarget.Response), "Deleting steering target: getting target ds: expected 1 delivery service")
assert.RequireNotNil(t, respTarget.Response[0].ID, "Deleting steering target: getting target ds: not found")
targetID := uint64(*respTarget.Response[0].ID)
st.TargetID = &targetID
resp, _, err := steeringUserSession.DeleteSteeringTarget(int(*st.DeliveryServiceID), int(*st.TargetID), client.RequestOptions{})
assert.NoError(t, err, "Deleting steering target: deleting: %v - alerts: %+v", err, resp.Alerts)
}
for _, dsID := range dsIDs {
sts, _, err := steeringUserSession.GetSteeringTargets(int(dsID), client.RequestOptions{})
assert.NoError(t, err, "deleting steering targets: getting steering target: %v - alerts: %+v", err, sts.Alerts)
assert.Equal(t, 0, len(sts.Response), "Deleting steering targets: after delete, getting steering target: expected 0 actual %d", len(sts.Response))
}
}