You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by sr...@apache.org on 2022/11/02 18:09:28 UTC
[trafficcontrol] branch master updated: Refactor Snapshot Tests (#7114)
This is an automated email from the ASF dual-hosted git repository.
srijeet0406 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git
The following commit(s) were added to refs/heads/master by this push:
new a32a37fc01 Refactor Snapshot Tests (#7114)
a32a37fc01 is described below
commit a32a37fc012efdf9075f7e81d8a9571470325e03
Author: Eric Holguin <14...@users.noreply.github.com>
AuthorDate: Wed Nov 2 12:09:22 2022 -0600
Refactor Snapshot Tests (#7114)
* initial refactor
* Initial refactor
* snapshot tests refactor
* crconfig v3 tests refactor
* crconfig v5 tests refactor
* clean up
* remove unsued type
* Use edge not being used by server id ds test
---
traffic_ops/testing/api/utils/utils.go | 3 +
.../api/v3/cdns_name_configs_monitoring_test.go | 103 ++++++
.../testing/api/v3/cdns_name_snapshot_new_test.go | 122 +++++++
.../testing/api/v3/cdns_name_snapshot_test.go | 60 ++++
traffic_ops/testing/api/v3/crconfig_test.go | 279 ----------------
traffic_ops/testing/api/v3/snapshot_test.go | 141 ++++++++
traffic_ops/testing/api/v3/tc-fixtures.json | 10 +
.../api/v4/cdns_name_configs_monitoring_test.go | 104 ++++++
.../testing/api/v4/cdns_name_snapshot_new_test.go | 121 +++++++
.../testing/api/v4/cdns_name_snapshot_test.go | 60 ++++
traffic_ops/testing/api/v4/crconfig_test.go | 356 ---------------------
traffic_ops/testing/api/v4/snapshot_test.go | 126 ++++++++
traffic_ops/testing/api/v4/tc-fixtures.json | 11 +-
.../api/v5/cdns_name_configs_monitoring_test.go | 104 ++++++
.../testing/api/v5/cdns_name_snapshot_new_test.go | 121 +++++++
.../testing/api/v5/cdns_name_snapshot_test.go | 60 ++++
traffic_ops/testing/api/v5/crconfig_test.go | 356 ---------------------
traffic_ops/testing/api/v5/snapshot_test.go | 126 ++++++++
traffic_ops/testing/api/v5/tc-fixtures.json | 11 +-
19 files changed, 1281 insertions(+), 993 deletions(-)
diff --git a/traffic_ops/testing/api/utils/utils.go b/traffic_ops/testing/api/utils/utils.go
index 6b72505675..6315d5af66 100644
--- a/traffic_ops/testing/api/utils/utils.go
+++ b/traffic_ops/testing/api/utils/utils.go
@@ -113,6 +113,7 @@ type V3TestData struct {
RequestParams url.Values
RequestHeaders http.Header
RequestBody map[string]interface{}
+ PreReqFuncs []func()
Expectations []CkReqFunc
}
@@ -132,6 +133,7 @@ type V4TestData struct {
ClientSession *v4client.Session
RequestOpts v4client.RequestOptions
RequestBody map[string]interface{}
+ PreReqFuncs []func()
Expectations []CkReqFunc
}
@@ -141,6 +143,7 @@ type V5TestData struct {
ClientSession *v5client.Session
RequestOpts v5client.RequestOptions
RequestBody map[string]interface{}
+ PreReqFuncs []func()
Expectations []CkReqFunc
}
diff --git a/traffic_ops/testing/api/v3/cdns_name_configs_monitoring_test.go b/traffic_ops/testing/api/v3/cdns_name_configs_monitoring_test.go
new file mode 100644
index 0000000000..dd3d2686d3
--- /dev/null
+++ b/traffic_ops/testing/api/v3/cdns_name_configs_monitoring_test.go
@@ -0,0 +1,103 @@
+package v3
+
+/*
+
+ 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 (
+ "net/http"
+ "net/url"
+ "strings"
+ "testing"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "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"
+)
+
+func TestCDNNameConfigsMonitoring(t *testing.T) {
+ WithObjs(t, []TCObj{CDNs, Types, Tenants, Parameters, Profiles, ProfileParameters, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices}, func() {
+
+ methodTests := utils.V3TestCase{
+ "GET": {
+ "OK when VALID request": {
+ ClientSession: TOSession,
+ RequestParams: url.Values{"cdn": {"cdn1"}},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
+ validateHealthThresholdParameters("EDGE1", map[string]string{"loadavg": "25.0", "availableBandwidthInKbps": ">1750000", "queryTime": "1000"})),
+ },
+ },
+ }
+
+ for method, testCases := range methodTests {
+ t.Run(method, func(t *testing.T) {
+ for name, testCase := range testCases {
+ switch method {
+ case "GET":
+ t.Run(name, func(t *testing.T) {
+ var cdn string
+ if val, ok := testCase.RequestParams["cdn"]; ok {
+ cdn = val[0]
+ }
+ resp, reqInf, err := testCase.ClientSession.GetTrafficMonitorConfig(cdn)
+ for _, check := range testCase.Expectations {
+ check(t, reqInf, resp, tc.Alerts{}, err)
+ }
+ })
+ }
+ }
+ })
+ }
+ })
+}
+
+func validateHealthThresholdParameters(profileName string, healthThresholdParams map[string]string) utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _ tc.Alerts, _ error) {
+ assert.RequireNotNil(t, resp, "Expected Traffic Monitor Config response to not be nil.")
+ tmConfig := resp.(*tc.TrafficMonitorConfig)
+ parameterMap := map[string]tc.HealthThreshold{}
+ parameterFound := map[string]bool{}
+ for parameter, parameterValue := range healthThresholdParams {
+ threshold, err := tc.StrToThreshold(parameterValue)
+ parameterMap[parameter] = threshold
+ assert.RequireNoError(t, err, "Error: converting string '%s' to HealthThreshold: %v", parameterValue, err)
+ parameterFound[parameter] = false
+ }
+
+ profileFound := false
+ var profile tc.TMProfile
+ for _, profile = range tmConfig.Profiles {
+ if profile.Name == profileName {
+ profileFound = true
+ break
+ }
+ }
+ assert.RequireEqual(t, true, profileFound, "Traffic Monitor Config contained no Profile named '%s", profileName)
+
+ for parameterName, value := range profile.Parameters.Thresholds {
+ _, ok := parameterFound[parameterName]
+ assert.Equal(t, true, ok, "Unexpected Threshold Parameter name '%s' found in Profile '%s' in Traffic Monitor Config", parameterName, profileName)
+ parameterFound[parameterName] = true
+ assert.Equal(t, parameterMap[parameterName].String(), value.String(), "Expected '%s' but received '%s' for Threshold Parameter '%s' in Profile '%s' in Traffic Monitor Config", parameterMap[parameterName].String(), value.String(), parameterName, profileName)
+ }
+ missingParameters := []string{}
+ for parameterName, found := range parameterFound {
+ if !found {
+ missingParameters = append(missingParameters, parameterName)
+ }
+ }
+ assert.Equal(t, 0, len(missingParameters), "Threshold parameters defined for Profile '%s' but missing for Profile '%s' in Traffic Monitor Config: %s", profileName, profileName, strings.Join(missingParameters, ", "))
+ }
+}
diff --git a/traffic_ops/testing/api/v3/cdns_name_snapshot_new_test.go b/traffic_ops/testing/api/v3/cdns_name_snapshot_new_test.go
new file mode 100644
index 0000000000..eff9af5e75
--- /dev/null
+++ b/traffic_ops/testing/api/v3/cdns_name_snapshot_new_test.go
@@ -0,0 +1,122 @@
+package v3
+
+/*
+
+ 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"
+ "net/url"
+ "testing"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "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"
+)
+
+var baselineCRConfig tc.CRConfig
+
+func TestCDNNameSnapshotNew(t *testing.T) {
+ WithObjs(t, []TCObj{CDNs, Types, Tenants, Parameters, Profiles, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices}, func() {
+
+ methodTests := utils.V3TestCase{
+ "GET": {
+ "VERIFY SNAPSHOT UPDATE CAPTURED CORRECTLY": {
+ ClientSession: TOSession,
+ RequestParams: url.Values{"cdn": {"cdn1"}},
+ PreReqFuncs: []func(){getBaselineCRConfig(t, "cdn1"), deleteParameter(t, "tm.url")},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
+ validateCRConfigNewFields("cdn1", map[string]interface{}{"TMHost": ""}), validateDeliveryServicesUnchanged()),
+ },
+ },
+ }
+
+ for method, testCases := range methodTests {
+ t.Run(method, func(t *testing.T) {
+ for name, testCase := range testCases {
+ switch method {
+ case "GET":
+ t.Run(name, func(t *testing.T) {
+ var cdn string
+ if val, ok := testCase.RequestParams["cdn"]; ok {
+ cdn = val[0]
+ }
+ for _, prerequisite := range testCase.PreReqFuncs {
+ prerequisite()
+ }
+ resp, reqInf, err := testCase.ClientSession.GetCRConfigNew(cdn)
+ for _, check := range testCase.Expectations {
+ check(t, reqInf, resp, tc.Alerts{}, err)
+ }
+ })
+ }
+ }
+ })
+ }
+ })
+}
+
+func validateCRConfigNewFields(cdn string, expectedResp map[string]interface{}) utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _ tc.Alerts, _ error) {
+ assert.RequireNotNil(t, resp, "Expected CRConfigNew response to not be nil.")
+ var newCRConfig tc.CRConfig
+ err := json.Unmarshal(resp.([]byte), &newCRConfig)
+ assert.NoError(t, err, "Error occurred when unmarshalling request body: %v", err)
+
+ for field, expected := range expectedResp {
+ switch field {
+ case "TMPath":
+ assert.RequireNotNil(t, newCRConfig.Stats.TMPath, "Expected Stats TM Path to not be nil.")
+ case "TMHost":
+ assert.RequireNotNil(t, newCRConfig.Stats.TMHost, "Expected Stats TM Host to not be nil.")
+ assert.Equal(t, expected, *newCRConfig.Stats.TMHost, "Expected Stats TM Host to be %v, but got %s", expected, *newCRConfig.Stats.TMHost)
+ default:
+ t.Errorf("Expected field: %v, does not exist in response", field)
+ }
+ }
+ }
+}
+
+func validateDeliveryServicesUnchanged() utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _ tc.Alerts, _ error) {
+ assert.RequireNotNil(t, resp, "Expected new snapshot response to not be nil.")
+ var newCRConfig tc.CRConfig
+ err := json.Unmarshal(resp.([]byte), &newCRConfig)
+ assert.NoError(t, err, "Error occurred when unmarshalling request body: %v", err)
+ assert.Exactly(t, newCRConfig.DeliveryServices, baselineCRConfig.DeliveryServices, "Expected Delivery Services to be unchanged.")
+ }
+}
+
+func getBaselineCRConfig(t *testing.T, cdn string) func() {
+ return func() {
+ _, err := TOSession.SnapshotCRConfigWithHdr(cdn, nil)
+ assert.RequireNoError(t, err, "Unexpected error taking Snapshot of CDN '%s': %v", cdn, err)
+ getCRConfig, _, err := TOSession.GetCRConfig(cdn)
+ assert.RequireNoError(t, err, "Unexpected error retrieving Snapshot of CDN '%s': %v", cdn, err)
+ err = json.Unmarshal(getCRConfig, &baselineCRConfig)
+ assert.NoError(t, err, "Error occurred when unmarshalling request body: %v", err)
+ }
+}
+
+func deleteParameter(t *testing.T, paramName string) func() {
+ return func() {
+ paramResp, _, err := TOSession.GetParameterByNameWithHdr(paramName, nil)
+ assert.RequireNoError(t, err, "Cannot get Parameter by name '%s': %v", paramName, err)
+ assert.RequireGreaterOrEqual(t, len(paramResp), 1, "Expected at least one parameter to be returned.")
+ delResp, _, err := TOSession.DeleteParameterByID(paramResp[0].ID)
+ assert.RequireNoError(t, err, "Cannot DELETE Parameter by name: %v - %v", err, delResp)
+ }
+}
diff --git a/traffic_ops/testing/api/v3/cdns_name_snapshot_test.go b/traffic_ops/testing/api/v3/cdns_name_snapshot_test.go
new file mode 100644
index 0000000000..eb1fde46a6
--- /dev/null
+++ b/traffic_ops/testing/api/v3/cdns_name_snapshot_test.go
@@ -0,0 +1,60 @@
+package v3
+
+/*
+
+ 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 (
+ "net/http"
+ "net/url"
+ "testing"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "github.com/apache/trafficcontrol/traffic_ops/testing/api/utils"
+)
+
+func TestCDNNameSnapshot(t *testing.T) {
+ WithObjs(t, []TCObj{CDNs, Types, Tenants, Parameters, Profiles, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices}, func() {
+
+ methodTests := utils.V3TestCase{
+ "GET": {
+ "OK when VALID request": {
+ ClientSession: TOSession,
+ RequestParams: url.Values{"cdn": {"cdn1"}},
+ 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 {
+ switch method {
+ case "GET":
+ t.Run(name, func(t *testing.T) {
+ var cdn string
+ if val, ok := testCase.RequestParams["cdn"]; ok {
+ cdn = val[0]
+ }
+ resp, reqInf, err := testCase.ClientSession.GetCRConfig(cdn)
+ for _, check := range testCase.Expectations {
+ check(t, reqInf, resp, tc.Alerts{}, err)
+ }
+ })
+ }
+ }
+ })
+ }
+ })
+}
diff --git a/traffic_ops/testing/api/v3/crconfig_test.go b/traffic_ops/testing/api/v3/crconfig_test.go
deleted file mode 100644
index c293d95d0b..0000000000
--- a/traffic_ops/testing/api/v3/crconfig_test.go
+++ /dev/null
@@ -1,279 +0,0 @@
-package v3
-
-/*
-
- 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"
- "strings"
- "testing"
-
- "github.com/apache/trafficcontrol/lib/go-tc"
-)
-
-func TestCRConfig(t *testing.T) {
- WithObjs(t, []TCObj{CDNs, Types, Tenants, Parameters, Profiles, ProfileParameters, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, DeliveryServices}, func() {
- UpdateTestCRConfigSnapshot(t)
- MonitoringConfig(t)
- SnapshotTestCDNbyName(t)
- SnapshotTestCDNbyInvalidName(t)
- SnapshotTestCDNbyID(t)
- SnapshotTestCDNbyInvalidID(t)
- })
-}
-
-func UpdateTestCRConfigSnapshot(t *testing.T) {
- if len(testData.CDNs) < 1 {
- t.Error("no cdn test data")
- }
- cdn := testData.CDNs[0].Name
-
- tmURLParamName := "tm.url"
- tmURLExpected := "crconfig.tm.url.test.invalid"
- _, _, err := TOSession.CreateParameter(tc.Parameter{
- ConfigFile: "global",
- Name: tmURLParamName,
- Value: "https://crconfig.tm.url.test.invalid",
- })
- if err != nil {
- t.Fatalf("GetCRConfig CreateParameter error expected: nil, actual: " + err.Error())
- }
-
- // create an ANY_MAP DS assignment to verify that it doesn't show up in the CRConfig
- resp, _, err := TOSession.GetServers(nil)
- if err != nil {
- t.Fatalf("GetServers err expected nil, actual %+v", err)
- }
- servers := resp
- serverID := 0
- for _, server := range servers {
- if server.Type == "EDGE" && server.CDNName == "cdn1" {
- serverID = server.ID
- break
- }
- }
- if serverID == 0 {
- t.Errorf("GetServers expected EDGE server in cdn1, actual: %+v", servers)
- }
- res, _, err := TOSession.GetDeliveryServiceByXMLIDNullable("anymap-ds")
- if err != nil {
- t.Errorf("GetDeliveryServiceByXMLIDNullable err expected nil, actual %+v", err)
- }
- if len(res) != 1 {
- t.Error("GetDeliveryServiceByXMLIDNullable expected 1 DS, actual 0")
- }
- if res[0].ID == nil {
- t.Error("GetDeliveryServiceByXMLIDNullable got unknown delivery service id")
- }
- anymapDSID := *res[0].ID
- _, _, err = TOSession.CreateDeliveryServiceServers(anymapDSID, []int{serverID}, true)
- if err != nil {
- t.Errorf("POST delivery service servers: %v", err)
- }
-
- _, err = TOSession.SnapshotCRConfig(cdn)
- if err != nil {
- t.Errorf("SnapshotCRConfig err expected nil, actual %+v", err)
- }
- crcBts, _, err := TOSession.GetCRConfig(cdn)
- if err != nil {
- t.Errorf("GetCRConfig err expected nil, actual %+v", err)
- }
- crc := tc.CRConfig{}
- if err := json.Unmarshal(crcBts, &crc); err != nil {
- t.Errorf("GetCRConfig bytes expected: valid tc.CRConfig, actual JSON unmarshal err: %+v", err)
- }
-
- if len(crc.DeliveryServices) == 0 {
- t.Error("GetCRConfig len(crc.DeliveryServices) expected: >0, actual: 0")
- }
-
- // verify no ANY_MAP delivery services are in the CRConfig
- for ds := range crc.DeliveryServices {
- if ds == "anymap-ds" {
- t.Error("found ANY_MAP delivery service in CRConfig deliveryServices")
- }
- }
- for server := range crc.ContentServers {
- for ds := range crc.ContentServers[server].DeliveryServices {
- if ds == "anymap-ds" {
- t.Error("found ANY_MAP delivery service in contentServers deliveryServices mapping")
- }
- }
- }
-
- if crc.Stats.TMPath == nil {
- t.Error("GetCRConfig crc.Stats.Path expected: some non-null string (but we don't check contents because it's deprecated), actual: null")
- }
-
- if crc.Stats.TMHost == nil {
- t.Errorf("GetCRConfig crc.Stats.Path expected: '"+tmURLExpected+"', actual: %+v", crc.Stats.TMHost)
- } else if *crc.Stats.TMHost != tmURLExpected {
- t.Errorf("GetCRConfig crc.Stats.Path expected: '"+tmURLExpected+"', actual: %+v", *crc.Stats.TMHost)
- }
-
- paramResp, _, err := TOSession.GetParameterByName(tmURLParamName)
- if err != nil {
- t.Fatalf("cannot GET Parameter by name: %v - %v", tmURLParamName, err)
- }
- if len(paramResp) == 0 {
- t.Fatal("CRConfig create tm.url parameter was successful, but GET returned no parameters")
- }
- tmURLParam := paramResp[0]
-
- delResp, _, err := TOSession.DeleteParameterByID(tmURLParam.ID)
- if err != nil {
- t.Fatalf("cannot DELETE Parameter by name: %v - %v", err, delResp)
- }
-
- crcBtsNew, _, err := TOSession.GetCRConfigNew(cdn)
- if err != nil {
- t.Errorf("GetCRConfig err expected nil, actual %+v", err)
- }
- crcNew := tc.CRConfig{}
- if err := json.Unmarshal(crcBtsNew, &crcNew); err != nil {
- t.Errorf("GetCRConfig bytes expected: valid tc.CRConfig, actual JSON unmarshal err: %+v", err)
- }
-
- if len(crcNew.DeliveryServices) != len(crc.DeliveryServices) {
- t.Errorf("/new endpoint returned a different snapshot. DeliveryServices length expected %v, was %v", len(crc.DeliveryServices), len(crcNew.DeliveryServices))
- }
-
- if *crcNew.Stats.TMHost != "" {
- t.Errorf("update to snapshot not captured in /new endpoint")
- }
-}
-
-func MonitoringConfig(t *testing.T) {
- if len(testData.CDNs) < 1 {
- t.Fatalf("no cdn test data")
- }
- const cdnName = "cdn1"
- const profileName = "EDGE1"
- cdns, _, err := TOSession.GetCDNByNameWithHdr(cdnName, nil)
- if err != nil {
- t.Fatalf("getting CDNs with name '%s': %s", cdnName, err.Error())
- }
- if len(cdns) < 1 {
- t.Fatalf("expected to find a CDN named %s", cdnName)
- }
- if len(cdns) > 1 {
- t.Fatalf("expected exactly 1 CDN named %s but found %d CDNs", cdnName, len(cdns))
- }
- profiles, _, err := TOSession.GetProfileByNameWithHdr(profileName, nil)
- if err != nil {
- t.Fatalf("getting Profiles with name '%s': %s", profileName, err.Error())
- }
- if len(profiles) != 1 {
- t.Fatalf("expected exactly 1 Profiles named %s but found %d Profiles", profileName, len(profiles))
- }
- parameters, _, err := TOSession.GetParametersByProfileNameWithHdr(profileName, nil)
- if err != nil {
- t.Fatalf("getting Parameters by Profile name '%s': %s", profileName, err.Error())
- }
- parameterMap := map[string]tc.HealthThreshold{}
- parameterFound := map[string]bool{}
- const thresholdPrefixLength = len(tc.ThresholdPrefix)
- for _, parameter := range parameters {
- if !strings.HasPrefix(parameter.Name, tc.ThresholdPrefix) {
- continue
- }
- parameterName := parameter.Name[thresholdPrefixLength:]
- parameterMap[parameterName], err = tc.StrToThreshold(parameter.Value)
- if err != nil {
- t.Fatalf("converting string '%s' to HealthThreshold: %s", parameter.Value, err.Error())
- }
- parameterFound[parameterName] = false
- }
- const expectedThresholdParameters = 3
- if len(parameterMap) != expectedThresholdParameters {
- t.Fatalf("expected Profile '%s' to contain %d Parameters with names starting with '%s' but %d such Parameters were found", profileName, expectedThresholdParameters, tc.ThresholdPrefix, len(parameterMap))
- }
- tmConfig, _, err := TOSession.GetTrafficMonitorConfig(cdnName)
- if err != nil {
- t.Fatalf("getting Traffic Monitor Config: %s", err.Error())
- }
- profileFound := false
- var profile tc.TMProfile
- for _, profile = range tmConfig.Profiles {
- if profile.Name == profileName {
- profileFound = true
- break
- }
- }
- if !profileFound {
- t.Fatalf("Traffic Monitor Config contained no Profile named '%s", profileName)
- }
- for parameterName, value := range profile.Parameters.Thresholds {
- if _, ok := parameterFound[parameterName]; !ok {
- t.Fatalf("unexpected Threshold Parameter name '%s' found in Profile '%s' in Traffic Monitor Config", parameterName, profileName)
- }
- parameterFound[parameterName] = true
- if parameterMap[parameterName].String() != value.String() {
- t.Fatalf("expected '%s' but received '%s' for Threshold Parameter '%s' in Profile '%s' in Traffic Monitor Config", parameterMap[parameterName].String(), value.String(), parameterName, profileName)
- }
- }
- missingParameters := []string{}
- for parameterName, found := range parameterFound {
- if !found {
- missingParameters = append(missingParameters, parameterName)
- }
- }
- if len(missingParameters) != 0 {
- t.Fatalf("Threshold parameters defined for Profile '%s' but missing for Profile '%s' in Traffic Monitor Config: %s", profileName, profileName, strings.Join(missingParameters, ", "))
- }
-}
-
-func SnapshotTestCDNbyName(t *testing.T) {
-
- firstCDN := testData.CDNs[0]
- _, err := TOSession.SnapshotCRConfig(firstCDN.Name)
- if err != nil {
- t.Errorf("failed to snapshot CDN by name: %v", err)
- }
-}
-
-func SnapshotTestCDNbyInvalidName(t *testing.T) {
-
- invalidCDNName := "cdn-invalid"
- _, err := TOSession.SnapshotCRConfig(invalidCDNName)
- if err == nil {
- t.Errorf("snapshot occurred on invalid cdn name: %v - %v", invalidCDNName, err)
- }
-}
-
-func SnapshotTestCDNbyID(t *testing.T) {
-
- firstCDN := testData.CDNs[0]
- // Retrieve the CDN by name so we can get the id for the snapshot
- resp, _, err := TOSession.GetCDNByName(firstCDN.Name)
- if err != nil {
- t.Errorf("cannot GET CDN by name: '%s', %v", firstCDN.Name, err)
- }
- remoteCDN := resp[0]
- alert, _, err := TOSession.SnapshotCRConfigByID(remoteCDN.ID)
- if err != nil {
- t.Errorf("failed to snapshot CDN by id: %v - %v", err, alert)
- }
-}
-
-func SnapshotTestCDNbyInvalidID(t *testing.T) {
-
- invalidCDNID := 999999
- alert, _, err := TOSession.SnapshotCRConfigByID(invalidCDNID)
- if err == nil {
- t.Errorf("snapshot occurred on invalid cdn id: %v - %v - %v", invalidCDNID, err, alert)
- }
-}
diff --git a/traffic_ops/testing/api/v3/snapshot_test.go b/traffic_ops/testing/api/v3/snapshot_test.go
new file mode 100644
index 0000000000..ab37ccab4a
--- /dev/null
+++ b/traffic_ops/testing/api/v3/snapshot_test.go
@@ -0,0 +1,141 @@
+package v3
+
+/*
+
+ 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"
+ "net/url"
+ "strconv"
+ "testing"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "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"
+)
+
+func TestSnapshot(t *testing.T) {
+ WithObjs(t, []TCObj{CDNs, Types, Tenants, Users, Parameters, Profiles, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices, DeliveryServiceServerAssignments}, func() {
+
+ methodTests := utils.V3TestCase{
+ "PUT": {
+ "VERIFY ANYMAP DELIVERY SERVICE is NOT in CRCONFIG": {
+ ClientSession: TOSession,
+ RequestParams: url.Values{"cdn": {"cdn1"}},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
+ validateDeliveryServiceNotInCRConfig("cdn1", "anymap-ds"),
+ validateCRConfigFields("cdn1", map[string]interface{}{"TMPath": "", "TMHost": "crconfig.tm.url.test.invalid"})),
+ },
+ "OK when VALID CDN parameter": {
+ ClientSession: TOSession,
+ RequestParams: url.Values{"cdn": {"cdn1"}},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+ },
+ "OK when VALID CDNID parameter": {
+ ClientSession: TOSession,
+ RequestParams: url.Values{"cdnID": {strconv.Itoa(GetCDNID(t, "cdn1")())}},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+ },
+ "NOT FOUND when NON-EXISTENT CDN": {
+ ClientSession: TOSession,
+ RequestParams: url.Values{"cdn": {"cdn-invalid"}},
+ Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusNotFound)),
+ },
+ "NOT FOUND when NON-EXISTENT CDNID": {
+ ClientSession: TOSession,
+ RequestParams: url.Values{"cdnID": {"999999"}},
+ Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusNotFound)),
+ },
+ },
+ }
+
+ for method, testCases := range methodTests {
+ t.Run(method, func(t *testing.T) {
+ for name, testCase := range testCases {
+ switch method {
+ case "PUT":
+ t.Run(name, func(t *testing.T) {
+ if name == "OK when VALID CDNID parameter" {
+ var cdnID int
+ var err error
+ if val, ok := testCase.RequestParams["cdnID"]; ok {
+ cdnID, err = strconv.Atoi(val[0])
+ assert.NoError(t, err, "Error converting string to integer: %v", err)
+ }
+ resp, reqInf, err := testCase.ClientSession.SnapshotCRConfigByID(cdnID)
+ for _, check := range testCase.Expectations {
+ check(t, reqInf, resp, tc.Alerts{}, err)
+ }
+ } else {
+ var cdn string
+ if val, ok := testCase.RequestParams["cdn"]; ok {
+ cdn = val[0]
+ }
+ reqInf, err := testCase.ClientSession.SnapshotCRConfigWithHdr(cdn, testCase.RequestHeaders)
+ for _, check := range testCase.Expectations {
+ check(t, reqInf, nil, tc.Alerts{}, err)
+ }
+ }
+ })
+ }
+ }
+ })
+ }
+ })
+}
+
+func validateCRConfigFields(cdn string, expectedResp map[string]interface{}) utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, _ interface{}, _ tc.Alerts, _ error) {
+ var crconfig tc.CRConfig
+ snapshotResp, _, err := TOSession.GetCRConfig(cdn)
+ assert.RequireNoError(t, err, "Unexpected error retrieving Snapshot of CDN '%s': %v", cdn, err)
+ err = json.Unmarshal(snapshotResp, &crconfig)
+ assert.NoError(t, err, "Error occurred when unmarshalling request body: %v", err)
+
+ for field, expected := range expectedResp {
+ switch field {
+ case "TMPath":
+ assert.RequireNotNil(t, crconfig.Stats.TMPath, "Expected Stats TM Path to not be nil.")
+ case "TMHost":
+ assert.RequireNotNil(t, crconfig.Stats.TMHost, "Expected Stats TM Host to not be nil.")
+ assert.Equal(t, expected, *crconfig.Stats.TMHost, "Expected Stats TM Host to be %v, but got %s", expected, *crconfig.Stats.TMHost)
+ default:
+ t.Errorf("Expected field: %v, does not exist in response", field)
+ }
+ }
+ }
+}
+
+func validateDeliveryServiceNotInCRConfig(cdn string, deliveryService string) utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, _ interface{}, _ tc.Alerts, _ error) {
+ var crconfig tc.CRConfig
+ snapshotResp, _, err := TOSession.GetCRConfig(cdn)
+ assert.RequireNoError(t, err, "Unexpected error retrieving Snapshot of CDN '%s': %v", cdn, err)
+ err = json.Unmarshal(snapshotResp, &crconfig)
+ assert.NoError(t, err, "Error occurred when unmarshalling request body: %v", err)
+
+ for ds := range crconfig.DeliveryServices {
+ assert.NotEqual(t, ds, deliveryService, "Found unexpected delivery service: %s in CRConfig Delivery Services.", deliveryService)
+ }
+
+ for _, server := range crconfig.ContentServers {
+ for ds := range server.DeliveryServices {
+ assert.NotEqual(t, ds, deliveryService, "Found unexpected delivery service: %s in CRConfig Content Servers Delivery Services.", deliveryService)
+ }
+ }
+ }
+}
diff --git a/traffic_ops/testing/api/v3/tc-fixtures.json b/traffic_ops/testing/api/v3/tc-fixtures.json
index 5240c8e0ad..f153e2cbef 100644
--- a/traffic_ops/testing/api/v3/tc-fixtures.json
+++ b/traffic_ops/testing/api/v3/tc-fixtures.json
@@ -1580,6 +1580,10 @@
{
"xmlId": "ds2",
"serverNames": ["atlanta-org-2"]
+ },
+ {
+ "xmlId": "anymap-ds",
+ "serverNames": ["atlanta-edge-15"]
}
],
"topologyBasedDeliveryServicesRequiredCapabilities": [
@@ -1845,6 +1849,12 @@
"name": "location",
"secure": false,
"value": "/remap/config/location/parameter/"
+ },
+ {
+ "configFile": "global",
+ "name": "tm.url",
+ "secure": false,
+ "value": "https://crconfig.tm.url.test.invalid"
}
],
"physLocations": [
diff --git a/traffic_ops/testing/api/v4/cdns_name_configs_monitoring_test.go b/traffic_ops/testing/api/v4/cdns_name_configs_monitoring_test.go
new file mode 100644
index 0000000000..bb6860f66a
--- /dev/null
+++ b/traffic_ops/testing/api/v4/cdns_name_configs_monitoring_test.go
@@ -0,0 +1,104 @@
+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 (
+ "net/http"
+ "net/url"
+ "strings"
+ "testing"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "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 TestCDNNameConfigsMonitoring(t *testing.T) {
+ WithObjs(t, []TCObj{CDNs, Types, Tenants, Parameters, Profiles, ProfileParameters, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices}, func() {
+
+ methodTests := utils.V4TestCase{
+ "GET": {
+ "OK when VALID request": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdn": {"cdn1"}}},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
+ validateHealthThresholdParameters("EDGE1", map[string]string{"loadavg": "25.0", "availableBandwidthInKbps": ">1750000", "queryTime": "1000"})),
+ },
+ },
+ }
+
+ for method, testCases := range methodTests {
+ t.Run(method, func(t *testing.T) {
+ for name, testCase := range testCases {
+ switch method {
+ case "GET":
+ t.Run(name, func(t *testing.T) {
+ var cdn string
+ if val, ok := testCase.RequestOpts.QueryParameters["cdn"]; ok {
+ cdn = val[0]
+ }
+ resp, reqInf, err := testCase.ClientSession.GetTrafficMonitorConfig(cdn, testCase.RequestOpts)
+ for _, check := range testCase.Expectations {
+ check(t, reqInf, resp.Response, resp.Alerts, err)
+ }
+ })
+ }
+ }
+ })
+ }
+ })
+}
+
+func validateHealthThresholdParameters(profileName string, healthThresholdParams map[string]string) utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _ tc.Alerts, _ error) {
+ assert.RequireNotNil(t, resp, "Expected Traffic Monitor Config response to not be nil.")
+ tmConfig := resp.(tc.TrafficMonitorConfig)
+ parameterMap := map[string]tc.HealthThreshold{}
+ parameterFound := map[string]bool{}
+ for parameter, parameterValue := range healthThresholdParams {
+ threshold, err := tc.StrToThreshold(parameterValue)
+ parameterMap[parameter] = threshold
+ assert.RequireNoError(t, err, "Error: converting string '%s' to HealthThreshold: %v", parameterValue, err)
+ parameterFound[parameter] = false
+ }
+
+ profileFound := false
+ var profile tc.TMProfile
+ for _, profile = range tmConfig.Profiles {
+ if profile.Name == profileName {
+ profileFound = true
+ break
+ }
+ }
+ assert.RequireEqual(t, true, profileFound, "Traffic Monitor Config contained no Profile named '%s", profileName)
+
+ for parameterName, value := range profile.Parameters.Thresholds {
+ _, ok := parameterFound[parameterName]
+ assert.Equal(t, true, ok, "Unexpected Threshold Parameter name '%s' found in Profile '%s' in Traffic Monitor Config", parameterName, profileName)
+ parameterFound[parameterName] = true
+ assert.Equal(t, parameterMap[parameterName].String(), value.String(), "Expected '%s' but received '%s' for Threshold Parameter '%s' in Profile '%s' in Traffic Monitor Config", parameterMap[parameterName].String(), value.String(), parameterName, profileName)
+ }
+ missingParameters := []string{}
+ for parameterName, found := range parameterFound {
+ if !found {
+ missingParameters = append(missingParameters, parameterName)
+ }
+ }
+ assert.Equal(t, 0, len(missingParameters), "Threshold parameters defined for Profile '%s' but missing for Profile '%s' in Traffic Monitor Config: %s", profileName, profileName, strings.Join(missingParameters, ", "))
+ }
+}
diff --git a/traffic_ops/testing/api/v4/cdns_name_snapshot_new_test.go b/traffic_ops/testing/api/v4/cdns_name_snapshot_new_test.go
new file mode 100644
index 0000000000..b702a1d385
--- /dev/null
+++ b/traffic_ops/testing/api/v4/cdns_name_snapshot_new_test.go
@@ -0,0 +1,121 @@
+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 (
+ "net/http"
+ "net/url"
+ "testing"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "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"
+)
+
+var baselineCRConfig tc.CRConfig
+
+func TestCDNNameSnapshotNew(t *testing.T) {
+ WithObjs(t, []TCObj{CDNs, Types, Tenants, Parameters, Profiles, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices}, func() {
+
+ methodTests := utils.V4TestCase{
+ "GET": {
+ "VERIFY SNAPSHOT UPDATE CAPTURED CORRECTLY": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdn": {"cdn1"}}},
+ PreReqFuncs: []func(){getBaselineCRConfig(t, "cdn1"), deleteParameter(t, "tm.url")},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
+ validateCRConfigNewFields("cdn1", map[string]interface{}{"TMHost": ""}), validateDeliveryServicesUnchanged()),
+ },
+ },
+ }
+
+ for method, testCases := range methodTests {
+ t.Run(method, func(t *testing.T) {
+ for name, testCase := range testCases {
+ switch method {
+ case "GET":
+ t.Run(name, func(t *testing.T) {
+ var cdn string
+ if val, ok := testCase.RequestOpts.QueryParameters["cdn"]; ok {
+ cdn = val[0]
+ }
+ for _, prerequisite := range testCase.PreReqFuncs {
+ prerequisite()
+ }
+ resp, reqInf, err := testCase.ClientSession.GetCRConfigNew(cdn, testCase.RequestOpts)
+ for _, check := range testCase.Expectations {
+ check(t, reqInf, resp.Response, resp.Alerts, err)
+ }
+ })
+ }
+ }
+ })
+ }
+ })
+}
+
+func validateCRConfigNewFields(cdn string, expectedResp map[string]interface{}) utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _ tc.Alerts, _ error) {
+ assert.RequireNotNil(t, resp, "Expected CRConfigNew response to not be nil.")
+ crconfig := resp.(tc.CRConfig)
+
+ for field, expected := range expectedResp {
+ switch field {
+ case "TMPath":
+ assert.Equal(t, expected, crconfig.Stats.TMPath, "Expected no TMPath in APIv4, but it was: %s", *crconfig.Stats.TMPath)
+ case "TMHost":
+ assert.RequireNotNil(t, crconfig.Stats.TMHost, "Expected Stats TM Host to not be nil.")
+ assert.Equal(t, expected, *crconfig.Stats.TMHost, "Expected Stats TM Host to be %v, but got %s", expected, *crconfig.Stats.TMHost)
+ default:
+ t.Errorf("Expected field: %v, does not exist in response", field)
+ }
+ }
+ }
+}
+
+func validateDeliveryServicesUnchanged() utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _ tc.Alerts, _ error) {
+ assert.RequireNotNil(t, resp, "Expected new snapshot response to not be nil.")
+ newSnapshot := resp.(tc.CRConfig)
+ assert.Exactly(t, newSnapshot.DeliveryServices, baselineCRConfig.DeliveryServices, "Expected Delivery Services to be unchanged.")
+ }
+}
+
+func getBaselineCRConfig(t *testing.T, cdn string) func() {
+ return func() {
+ opts := client.NewRequestOptions()
+ opts.QueryParameters.Set("cdn", cdn)
+ snapshotResp, _, err := TOSession.SnapshotCRConfig(opts)
+ assert.RequireNoError(t, err, "Unexpected error taking Snapshot of CDN '%s': %v - alerts: %+v", cdn, err, snapshotResp.Alerts)
+ getCRConfig, _, err := TOSession.GetCRConfig(cdn, client.RequestOptions{})
+ assert.RequireNoError(t, err, "Unexpected error retrieving Snapshot of CDN '%s': %v - alerts: %+v", cdn, err, snapshotResp.Alerts)
+ baselineCRConfig = getCRConfig.Response
+ }
+}
+
+func deleteParameter(t *testing.T, paramName string) func() {
+ return func() {
+ opts := client.NewRequestOptions()
+ opts.QueryParameters.Set("name", paramName)
+ paramResp, _, err := TOSession.GetParameters(opts)
+ assert.RequireNoError(t, err, "Cannot get Parameter by name '%s': %v - alerts: %+v", paramName, err, paramResp.Alerts)
+ assert.RequireGreaterOrEqual(t, len(paramResp.Response), 1, "Expected at least one parameter to be returned.")
+ delResp, _, err := TOSession.DeleteParameter(paramResp.Response[0].ID, client.RequestOptions{})
+ assert.RequireNoError(t, err, "Cannot DELETE Parameter by name: %v - %v", err, delResp)
+ }
+}
diff --git a/traffic_ops/testing/api/v4/cdns_name_snapshot_test.go b/traffic_ops/testing/api/v4/cdns_name_snapshot_test.go
new file mode 100644
index 0000000000..71e218aeb4
--- /dev/null
+++ b/traffic_ops/testing/api/v4/cdns_name_snapshot_test.go
@@ -0,0 +1,60 @@
+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 (
+ "net/http"
+ "net/url"
+ "testing"
+
+ "github.com/apache/trafficcontrol/traffic_ops/testing/api/utils"
+ client "github.com/apache/trafficcontrol/traffic_ops/v4-client"
+)
+
+func TestCDNNameSnapshot(t *testing.T) {
+ WithObjs(t, []TCObj{CDNs, Types, Tenants, Parameters, Profiles, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices}, func() {
+
+ methodTests := utils.V4TestCase{
+ "GET": {
+ "OK when VALID request": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdn": {"cdn1"}}},
+ 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 {
+ switch method {
+ case "GET":
+ t.Run(name, func(t *testing.T) {
+ var cdn string
+ if val, ok := testCase.RequestOpts.QueryParameters["cdn"]; ok {
+ cdn = val[0]
+ }
+ resp, reqInf, err := testCase.ClientSession.GetCRConfig(cdn, testCase.RequestOpts)
+ for _, check := range testCase.Expectations {
+ check(t, reqInf, resp.Response, resp.Alerts, err)
+ }
+ })
+ }
+ }
+ })
+ }
+ })
+}
diff --git a/traffic_ops/testing/api/v4/crconfig_test.go b/traffic_ops/testing/api/v4/crconfig_test.go
deleted file mode 100644
index 4574cfb16b..0000000000
--- a/traffic_ops/testing/api/v4/crconfig_test.go
+++ /dev/null
@@ -1,356 +0,0 @@
-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 (
- "net/http"
- "strconv"
- "strings"
- "testing"
- "time"
-
- "github.com/apache/trafficcontrol/lib/go-tc"
- "github.com/apache/trafficcontrol/lib/go-util"
- client "github.com/apache/trafficcontrol/traffic_ops/v4-client"
- toclient "github.com/apache/trafficcontrol/traffic_ops/v4-client"
-)
-
-func TestCRConfig(t *testing.T) {
- WithObjs(t, []TCObj{CDNs, Types, Tenants, Parameters, Profiles, ProfileParameters, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices}, func() {
- UpdateTestCRConfigSnapshot(t)
- MonitoringConfig(t)
- SnapshotTestCDNbyName(t)
- SnapshotTestCDNbyInvalidName(t)
- SnapshotTestCDNbyID(t)
- SnapshotTestCDNbyInvalidID(t)
- SnapshotWithReadOnlyUser(t)
- })
-}
-
-func SnapshotWithReadOnlyUser(t *testing.T) {
- if len(testData.CDNs) == 0 {
- t.Fatalf("expected one or more valid CDNs, but got none")
- }
-
- tenantOpts := client.NewRequestOptions()
- tenantOpts.QueryParameters.Set("name", "root")
- resp, _, err := TOSession.GetTenants(tenantOpts)
- if err != nil {
- t.Fatalf("couldn't get the root tenant ID: %v - alerts: %+v", err, resp.Alerts)
- }
- if len(resp.Response) != 1 {
- t.Fatalf("Expected exactly one Tenant to have the name 'root', found: %d", len(resp.Response))
- }
-
- toReqTimeout := time.Second * time.Duration(Config.Default.Session.TimeoutInSecs)
- user := tc.UserV4{
- Username: "test_user_tm",
- RegistrationSent: new(time.Time),
- LocalPassword: util.StrPtr("test_pa$$word"),
- Role: "read-only",
- }
- user.Email = util.StrPtr("email_tm@domain.com")
- user.TenantID = resp.Response[0].ID
- user.FullName = util.StrPtr("firstName LastName")
-
- u, _, err := TOSession.CreateUser(user, client.RequestOptions{})
- if err != nil {
- t.Fatalf("could not create read-only user: %v - alerts: %+v", err, u.Alerts)
- }
- client, _, err := toclient.LoginWithAgent(TOSession.URL, "test_user_tm", "test_pa$$word", true, "to-api-v4-client-tests/tenant4user", true, toReqTimeout)
- if err != nil {
- t.Fatalf("failed to log in with test_user: %v", err.Error())
- }
- opts := toclient.NewRequestOptions()
- opts.QueryParameters.Set("cdn", testData.CDNs[0].Name)
- _, reqInf, err := client.SnapshotCRConfig(opts)
- if err == nil {
- t.Errorf("expected to get an error about a read-only client trying to snap a CDN, but got none")
- }
- if reqInf.StatusCode != http.StatusForbidden {
- t.Errorf("expected a 403 forbidden status code, but got %d", reqInf.StatusCode)
- }
- ForceDeleteTestUsersByUsernames(t, []string{"test_user_tm"})
-}
-
-func UpdateTestCRConfigSnapshot(t *testing.T) {
- if len(testData.CDNs) < 1 {
- t.Error("no cdn test data")
- }
- cdn := testData.CDNs[0].Name
-
- tmURLParamName := "tm.url"
- tmURLExpected := "crconfig.tm.url.test.invalid"
- paramAlerts, _, err := TOSession.CreateParameter(tc.Parameter{
- ConfigFile: "global",
- Name: tmURLParamName,
- Value: "https://crconfig.tm.url.test.invalid",
- }, client.RequestOptions{})
- if err != nil {
- t.Fatalf("GetCRConfig CreateParameter error expected: nil, actual: %v - alerts: %+v", err, paramAlerts.Alerts)
- }
-
- // create an ANY_MAP DS assignment to verify that it doesn't show up in the CRConfig
- resp, _, err := TOSession.GetServers(client.RequestOptions{})
- if err != nil {
- t.Fatalf("GetServers err expected nil, actual: %v - alerts: %+v", err, resp.Alerts)
- }
- servers := resp.Response
- serverID := 0
- for _, server := range servers {
- if server.CDNName == nil || server.ID == nil {
- t.Error("Traffic Ops returned a representation for a servver with null or undefined ID and/or CDN name")
- continue
- }
- if server.Type == "EDGE" && *server.CDNName == "cdn1" {
- serverID = *server.ID
- break
- }
- }
- if serverID == 0 {
- t.Errorf("GetServers expected EDGE server in cdn1, actual: %+v", servers)
- }
- opts := client.NewRequestOptions()
- opts.QueryParameters.Set("xmlId", "anymap-ds")
- res, _, err := TOSession.GetDeliveryServices(opts)
- if err != nil {
- t.Errorf("Unexpected error getting Delivery Services filtered by XMLID 'anymap-ds': %v - alerts: %+v", err, res.Alerts)
- }
- if len(res.Response) != 1 {
- t.Fatalf("Expected exactly 1 Delivery Service to exist with XMLID 'anymap-ds', actual %d", len(res.Response))
- }
- if res.Response[0].ID == nil {
- t.Fatal("Traffic Ops returned a representation of Delivery Service 'anymap-ds' that had a null or undefined ID")
- }
- anymapDSID := *res.Response[0].ID
- alerts, _, err := TOSession.CreateDeliveryServiceServers(anymapDSID, []int{serverID}, true, client.RequestOptions{})
- if err != nil {
- t.Fatalf("Unexpected error assigning server #%d to Delivery Service #%d: %v - alerts: %+v", serverID, anymapDSID, err, alerts.Alerts)
- }
-
- opts = client.NewRequestOptions()
- opts.QueryParameters.Set("cdn", cdn)
- snapshotResp, _, err := TOSession.SnapshotCRConfig(opts)
- if err != nil {
- t.Errorf("Unexpected error taking Snapshot of CDN '%s': %v - alerts: %+v", cdn, err, snapshotResp.Alerts)
- }
- crcResp, _, err := TOSession.GetCRConfig(cdn, client.RequestOptions{})
- if err != nil {
- t.Errorf("Unexpected error retrieving Snapshot of CDN '%s': %v - alerts: %+v", cdn, err, crcResp.Alerts)
- }
- crc := crcResp.Response
-
- if len(crc.DeliveryServices) == 0 {
- t.Error("GetCRConfig len(crc.DeliveryServices) expected: >0, actual: 0")
- }
-
- // verify no ANY_MAP delivery services are in the CRConfig
- for ds := range crc.DeliveryServices {
- if ds == "anymap-ds" {
- t.Error("found ANY_MAP delivery service in CRConfig deliveryServices")
- }
- }
- for server := range crc.ContentServers {
- for ds := range crc.ContentServers[server].DeliveryServices {
- if ds == "anymap-ds" {
- t.Error("found ANY_MAP delivery service in contentServers deliveryServices mapping")
- }
- }
- }
-
- if crc.Stats.TMPath != nil {
- t.Errorf("Expected no TMPath in APIv4, but it was: %v", *crc.Stats.TMPath)
- }
-
- if crc.Stats.TMHost == nil {
- t.Errorf("GetCRConfig crc.Stats.Path expected: '"+tmURLExpected+"', actual: %+v", crc.Stats.TMHost)
- } else if *crc.Stats.TMHost != tmURLExpected {
- t.Errorf("GetCRConfig crc.Stats.Path expected: '"+tmURLExpected+"', actual: %+v", *crc.Stats.TMHost)
- }
-
- opts.QueryParameters.Del("cdn")
- opts.QueryParameters.Set("name", tmURLParamName)
- paramResp, _, err := TOSession.GetParameters(opts)
- if err != nil {
- t.Fatalf("cannot get Parameter by name '%s': %v - alerts: %+v", tmURLParamName, err, paramResp.Alerts)
- }
- if len(paramResp.Response) == 0 {
- t.Fatal("CRConfig create tm.url parameter was successful, but GET returned no parameters")
- }
- tmURLParam := paramResp.Response[0]
-
- delResp, _, err := TOSession.DeleteParameter(tmURLParam.ID, client.RequestOptions{})
- if err != nil {
- t.Fatalf("cannot DELETE Parameter by name: %v - %v", err, delResp)
- }
-
- crcResp, _, err = TOSession.GetCRConfigNew(cdn, client.RequestOptions{})
- if err != nil {
- t.Errorf("Unexpected error getting new Snapshot for CDN '%s': %v - alerts: %+v", cdn, err, crcResp.Alerts)
- }
- crcNew := crcResp.Response
-
- if len(crcNew.DeliveryServices) != len(crc.DeliveryServices) {
- t.Errorf("/new endpoint returned a different snapshot. DeliveryServices length expected %v, was %v", len(crc.DeliveryServices), len(crcNew.DeliveryServices))
- }
-
- if *crcNew.Stats.TMHost != "" {
- t.Errorf("update to snapshot not captured in /new endpoint")
- }
-}
-
-func MonitoringConfig(t *testing.T) {
- if len(testData.CDNs) < 1 {
- t.Fatalf("no cdn test data")
- }
- const cdnName = "cdn1"
- const profileName = "EDGE1"
- opts := client.NewRequestOptions()
- opts.QueryParameters.Set("name", cdnName)
- cdns, _, err := TOSession.GetCDNs(opts)
- if err != nil {
- t.Fatalf("getting CDNs with name '%s': %v - alerts: %+v", cdnName, err, cdns.Alerts)
- }
- if len(cdns.Response) != 1 {
- t.Fatalf("expected exactly 1 CDN named '%s' but found %d CDNs", cdnName, len(cdns.Response))
- }
- opts.QueryParameters.Set("name", profileName)
- profiles, _, err := TOSession.GetProfiles(opts)
- if err != nil {
- t.Fatalf("getting Profiles with name '%s': %v - alerts: %+v", profileName, err, profiles.Alerts)
- }
- if len(profiles.Response) != 1 {
- t.Fatalf("expected exactly 1 Profiles named %s but found %d Profiles", profileName, len(profiles.Response))
- }
- parameters, _, err := TOSession.GetParametersByProfileName(profileName, client.RequestOptions{})
- if err != nil {
- t.Fatalf("getting Parameters by Profile name '%s': %v - alerts: %+v", profileName, err, parameters.Alerts)
- }
- parameterMap := map[string]tc.HealthThreshold{}
- parameterFound := map[string]bool{}
- const thresholdPrefixLength = len(tc.ThresholdPrefix)
- for _, parameter := range parameters.Response {
- if !strings.HasPrefix(parameter.Name, tc.ThresholdPrefix) {
- continue
- }
- parameterName := parameter.Name[thresholdPrefixLength:]
- parameterMap[parameterName], err = tc.StrToThreshold(parameter.Value)
- if err != nil {
- t.Fatalf("converting string '%s' to HealthThreshold: %s", parameter.Value, err.Error())
- }
- parameterFound[parameterName] = false
- }
- const expectedThresholdParameters = 3
- if len(parameterMap) != expectedThresholdParameters {
- t.Fatalf("expected Profile '%s' to contain %d Parameters with names starting with '%s' but %d such Parameters were found", profileName, expectedThresholdParameters, tc.ThresholdPrefix, len(parameterMap))
- }
- tmConfig, _, err := TOSession.GetTrafficMonitorConfig(cdnName, client.RequestOptions{})
- if err != nil {
- t.Fatalf("getting Traffic Monitor Config: %v - alerts: %+v", err, tmConfig.Alerts)
- }
- profileFound := false
- var profile tc.TMProfile
- for _, profile = range tmConfig.Response.Profiles {
- if profile.Name == profileName {
- profileFound = true
- break
- }
- }
- if !profileFound {
- t.Fatalf("Traffic Monitor Config contained no Profile named '%s", profileName)
- }
- for parameterName, value := range profile.Parameters.Thresholds {
- if _, ok := parameterFound[parameterName]; !ok {
- t.Fatalf("unexpected Threshold Parameter name '%s' found in Profile '%s' in Traffic Monitor Config", parameterName, profileName)
- }
- parameterFound[parameterName] = true
- if parameterMap[parameterName].String() != value.String() {
- t.Fatalf("expected '%s' but received '%s' for Threshold Parameter '%s' in Profile '%s' in Traffic Monitor Config", parameterMap[parameterName].String(), value.String(), parameterName, profileName)
- }
- }
- missingParameters := []string{}
- for parameterName, found := range parameterFound {
- if !found {
- missingParameters = append(missingParameters, parameterName)
- }
- }
- if len(missingParameters) != 0 {
- t.Fatalf("Threshold parameters defined for Profile '%s' but missing for Profile '%s' in Traffic Monitor Config: %s", profileName, profileName, strings.Join(missingParameters, ", "))
- }
-}
-
-func SnapshotTestCDNbyName(t *testing.T) {
- if len(testData.CDNs) < 1 {
- t.Fatal("Need at least one CDN to test taking CDN Snapshot using CDN name")
- }
- firstCDN := testData.CDNs[0].Name
- opts := client.NewRequestOptions()
- opts.QueryParameters.Set("cdn", firstCDN)
- resp, _, err := TOSession.SnapshotCRConfig(opts)
- if err != nil {
- t.Errorf("failed to snapshot CDN '%s' by name: %v - alerts: %+v", firstCDN, err, resp.Alerts)
- }
-}
-
-// Note that this test will break if anyone adds a CDN to the fixture data with
-// the name "cdn-invalid".
-func SnapshotTestCDNbyInvalidName(t *testing.T) {
- invalidCDNName := "cdn-invalid"
- opts := client.NewRequestOptions()
- opts.QueryParameters.Set("cdn", invalidCDNName)
- _, _, err := TOSession.SnapshotCRConfig(opts)
- if err == nil {
- t.Errorf("snapshot occurred without error on (presumed) invalid CDN '%s'", invalidCDNName)
- }
-}
-
-func SnapshotTestCDNbyID(t *testing.T) {
- if len(testData.CDNs) < 1 {
- t.Fatal("Need at least one CDN to test Snapshotting CDNs")
- }
- firstCDNName := testData.CDNs[0].Name
- opts := client.NewRequestOptions()
- opts.QueryParameters.Set("name", firstCDNName)
- // Retrieve the CDN by name so we can get the id for the snapshot
- resp, _, err := TOSession.GetCDNs(opts)
- if err != nil {
- t.Errorf("cannot get CDN '%s': %v - alerts: %+v", firstCDNName, err, resp.Alerts)
- }
- if len(resp.Response) != 1 {
- t.Fatalf("Expected exactly one CDN to exist with name '%s', found: %d", firstCDNName, len(resp.Response))
- }
- remoteCDNID := resp.Response[0].ID
- opts.QueryParameters.Del("name")
- opts.QueryParameters.Set("cdnID", strconv.Itoa(remoteCDNID))
- alert, _, err := TOSession.SnapshotCRConfig(opts)
- if err != nil {
- t.Errorf("failed to snapshot CDN '%s' (#%d) by id: %v - alerts: %+v", firstCDNName, remoteCDNID, err, alert.Alerts)
- }
-}
-
-// Note that this test will break in the event that 1,000,000 CDNs are created
-// in the TO instance at any time (they don't need to exist concurrently, just
-// that many successful CDN creations have to happen, even if they are
-// all immediately deleted except the 999999th one).
-func SnapshotTestCDNbyInvalidID(t *testing.T) {
- opts := client.NewRequestOptions()
- invalidCDNID := 999999
- opts.QueryParameters.Set("cdnID", strconv.Itoa(invalidCDNID))
- alert, _, err := TOSession.SnapshotCRConfig(opts)
- if err == nil {
- t.Errorf("snapshot occurred on (presumed) invalid CDN #%d: %v - alerts: %+v", invalidCDNID, err, alert.Alerts)
- }
-}
diff --git a/traffic_ops/testing/api/v4/snapshot_test.go b/traffic_ops/testing/api/v4/snapshot_test.go
new file mode 100644
index 0000000000..17ff44a47d
--- /dev/null
+++ b/traffic_ops/testing/api/v4/snapshot_test.go
@@ -0,0 +1,126 @@
+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 (
+ "net/http"
+ "net/url"
+ "strconv"
+ "testing"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "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 TestSnapshot(t *testing.T) {
+ WithObjs(t, []TCObj{CDNs, Types, Tenants, Users, Parameters, Profiles, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices, DeliveryServiceServerAssignments}, func() {
+
+ readOnlyUserSession := utils.CreateV4Session(t, Config.TrafficOps.URL, "readonlyuser", "pa$$word", Config.Default.Session.TimeoutInSecs)
+
+ methodTests := utils.V4TestCase{
+ "PUT": {
+ "VERIFY ANYMAP DELIVERY SERVICE is NOT in CRCONFIG": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdn": {"cdn1"}}},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
+ validateDeliveryServiceNotInCRConfig("cdn1", "anymap-ds"),
+ validateCRConfigFields("cdn1", map[string]interface{}{"TMPath": (*string)(nil), "TMHost": "crconfig.tm.url.test.invalid"})),
+ },
+ "OK when VALID CDN parameter": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdn": {"cdn1"}}},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+ },
+ "OK when VALID CDNID parameter": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdnID": {strconv.Itoa(GetCDNID(t, "cdn1")())}}},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+ },
+ "NOT FOUND when NON-EXISTENT CDN": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdn": {"cdn-invalid"}}},
+ Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusNotFound)),
+ },
+ "NOT FOUND when NON-EXISTENT CDNID": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdnID": {"999999"}}},
+ Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusNotFound)),
+ },
+ "FORBIDDEN when READ-ONLY user": {
+ ClientSession: readOnlyUserSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdn": {"cdn1"}}},
+ Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusForbidden)),
+ },
+ },
+ }
+
+ for method, testCases := range methodTests {
+ t.Run(method, func(t *testing.T) {
+ for name, testCase := range testCases {
+ switch method {
+ case "PUT":
+ t.Run(name, func(t *testing.T) {
+ resp, reqInf, err := testCase.ClientSession.SnapshotCRConfig(testCase.RequestOpts)
+ for _, check := range testCase.Expectations {
+ check(t, reqInf, resp.Response, resp.Alerts, err)
+ }
+ })
+ }
+ }
+ })
+ }
+ })
+}
+
+func validateCRConfigFields(cdn string, expectedResp map[string]interface{}) utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, _ interface{}, _ tc.Alerts, _ error) {
+ snapshotResp, _, err := TOSession.GetCRConfig(cdn, client.RequestOptions{})
+ assert.RequireNoError(t, err, "Unexpected error retrieving Snapshot of CDN '%s': %v - alerts: %+v", cdn, err, snapshotResp.Alerts)
+ crconfig := snapshotResp.Response
+
+ for field, expected := range expectedResp {
+ switch field {
+ case "TMPath":
+ assert.Equal(t, expected, crconfig.Stats.TMPath, "Expected no TMPath in APIv4, but it was: %v", crconfig.Stats.TMPath)
+ case "TMHost":
+ assert.RequireNotNil(t, crconfig.Stats.TMHost, "Expected Stats TM Host to not be nil.")
+ assert.Equal(t, expected, *crconfig.Stats.TMHost, "Expected Stats TM Host to be %v, but got %s", expected, *crconfig.Stats.TMHost)
+ default:
+ t.Errorf("Expected field: %v, does not exist in response", field)
+ }
+ }
+ }
+}
+
+func validateDeliveryServiceNotInCRConfig(cdn string, deliveryService string) utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, _ interface{}, _ tc.Alerts, _ error) {
+ snapshotResp, _, err := TOSession.GetCRConfig(cdn, client.RequestOptions{})
+ assert.RequireNoError(t, err, "Unexpected error retrieving Snapshot of CDN '%s': %v - alerts: %+v", cdn, err, snapshotResp.Alerts)
+
+ for ds := range snapshotResp.Response.DeliveryServices {
+ assert.NotEqual(t, ds, deliveryService, "Found unexpected delivery service: %s in CRConfig Delivery Services.", deliveryService)
+ }
+
+ for _, server := range snapshotResp.Response.ContentServers {
+ for ds := range server.DeliveryServices {
+ assert.NotEqual(t, ds, deliveryService, "Found unexpected delivery service: %s in CRConfig Content Servers Delivery Services.", deliveryService)
+ }
+ }
+ }
+}
diff --git a/traffic_ops/testing/api/v4/tc-fixtures.json b/traffic_ops/testing/api/v4/tc-fixtures.json
index 49c23a60cb..86260687cc 100644
--- a/traffic_ops/testing/api/v4/tc-fixtures.json
+++ b/traffic_ops/testing/api/v4/tc-fixtures.json
@@ -1801,6 +1801,10 @@
{
"xmlId": "ds2",
"serverNames": ["atlanta-org-2"]
+ },
+ {
+ "xmlId": "anymap-ds",
+ "serverNames": ["atlanta-edge-15"]
}
],
"divisions": [
@@ -2024,8 +2028,13 @@
"name": "testSecure",
"secure": true,
"value": "hidden value"
+ },
+ {
+ "configFile": "global",
+ "name": "tm.url",
+ "secure": false,
+ "value": "https://crconfig.tm.url.test.invalid"
}
-
],
"physLocations": [
{
diff --git a/traffic_ops/testing/api/v5/cdns_name_configs_monitoring_test.go b/traffic_ops/testing/api/v5/cdns_name_configs_monitoring_test.go
new file mode 100644
index 0000000000..966f44a93c
--- /dev/null
+++ b/traffic_ops/testing/api/v5/cdns_name_configs_monitoring_test.go
@@ -0,0 +1,104 @@
+package v5
+
+/*
+
+ 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 (
+ "net/http"
+ "net/url"
+ "strings"
+ "testing"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "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/v5-client"
+)
+
+func TestCDNNameConfigsMonitoring(t *testing.T) {
+ WithObjs(t, []TCObj{CDNs, Types, Tenants, Parameters, Profiles, ProfileParameters, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices}, func() {
+
+ methodTests := utils.V5TestCase{
+ "GET": {
+ "OK when VALID request": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdn": {"cdn1"}}},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
+ validateHealthThresholdParameters("EDGE1", map[string]string{"loadavg": "25.0", "availableBandwidthInKbps": ">1750000", "queryTime": "1000"})),
+ },
+ },
+ }
+
+ for method, testCases := range methodTests {
+ t.Run(method, func(t *testing.T) {
+ for name, testCase := range testCases {
+ switch method {
+ case "GET":
+ t.Run(name, func(t *testing.T) {
+ var cdn string
+ if val, ok := testCase.RequestOpts.QueryParameters["cdn"]; ok {
+ cdn = val[0]
+ }
+ resp, reqInf, err := testCase.ClientSession.GetTrafficMonitorConfig(cdn, testCase.RequestOpts)
+ for _, check := range testCase.Expectations {
+ check(t, reqInf, resp.Response, resp.Alerts, err)
+ }
+ })
+ }
+ }
+ })
+ }
+ })
+}
+
+func validateHealthThresholdParameters(profileName string, healthThresholdParams map[string]string) utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _ tc.Alerts, _ error) {
+ assert.RequireNotNil(t, resp, "Expected Traffic Monitor Config response to not be nil.")
+ tmConfig := resp.(tc.TrafficMonitorConfig)
+ parameterMap := map[string]tc.HealthThreshold{}
+ parameterFound := map[string]bool{}
+ for parameter, parameterValue := range healthThresholdParams {
+ threshold, err := tc.StrToThreshold(parameterValue)
+ parameterMap[parameter] = threshold
+ assert.RequireNoError(t, err, "Error: converting string '%s' to HealthThreshold: %v", parameterValue, err)
+ parameterFound[parameter] = false
+ }
+
+ profileFound := false
+ var profile tc.TMProfile
+ for _, profile = range tmConfig.Profiles {
+ if profile.Name == profileName {
+ profileFound = true
+ break
+ }
+ }
+ assert.RequireEqual(t, true, profileFound, "Traffic Monitor Config contained no Profile named '%s", profileName)
+
+ for parameterName, value := range profile.Parameters.Thresholds {
+ _, ok := parameterFound[parameterName]
+ assert.Equal(t, true, ok, "Unexpected Threshold Parameter name '%s' found in Profile '%s' in Traffic Monitor Config", parameterName, profileName)
+ parameterFound[parameterName] = true
+ assert.Equal(t, parameterMap[parameterName].String(), value.String(), "Expected '%s' but received '%s' for Threshold Parameter '%s' in Profile '%s' in Traffic Monitor Config", parameterMap[parameterName].String(), value.String(), parameterName, profileName)
+ }
+ missingParameters := []string{}
+ for parameterName, found := range parameterFound {
+ if !found {
+ missingParameters = append(missingParameters, parameterName)
+ }
+ }
+ assert.Equal(t, 0, len(missingParameters), "Threshold parameters defined for Profile '%s' but missing for Profile '%s' in Traffic Monitor Config: %s", profileName, profileName, strings.Join(missingParameters, ", "))
+ }
+}
diff --git a/traffic_ops/testing/api/v5/cdns_name_snapshot_new_test.go b/traffic_ops/testing/api/v5/cdns_name_snapshot_new_test.go
new file mode 100644
index 0000000000..473e3e9c78
--- /dev/null
+++ b/traffic_ops/testing/api/v5/cdns_name_snapshot_new_test.go
@@ -0,0 +1,121 @@
+package v5
+
+/*
+
+ 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 (
+ "net/http"
+ "net/url"
+ "testing"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "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/v5-client"
+)
+
+var baselineCRConfig tc.CRConfig
+
+func TestCDNNameSnapshotNew(t *testing.T) {
+ WithObjs(t, []TCObj{CDNs, Types, Tenants, Parameters, Profiles, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices}, func() {
+
+ methodTests := utils.V5TestCase{
+ "GET": {
+ "VERIFY SNAPSHOT UPDATE CAPTURED CORRECTLY": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdn": {"cdn1"}}},
+ PreReqFuncs: []func(){getBaselineCRConfig(t, "cdn1"), deleteParameter(t, "tm.url")},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
+ validateCRConfigNewFields("cdn1", map[string]interface{}{"TMHost": ""}), validateDeliveryServicesUnchanged()),
+ },
+ },
+ }
+
+ for method, testCases := range methodTests {
+ t.Run(method, func(t *testing.T) {
+ for name, testCase := range testCases {
+ switch method {
+ case "GET":
+ t.Run(name, func(t *testing.T) {
+ var cdn string
+ if val, ok := testCase.RequestOpts.QueryParameters["cdn"]; ok {
+ cdn = val[0]
+ }
+ for _, prerequisite := range testCase.PreReqFuncs {
+ prerequisite()
+ }
+ resp, reqInf, err := testCase.ClientSession.GetCRConfigNew(cdn, testCase.RequestOpts)
+ for _, check := range testCase.Expectations {
+ check(t, reqInf, resp.Response, resp.Alerts, err)
+ }
+ })
+ }
+ }
+ })
+ }
+ })
+}
+
+func validateCRConfigNewFields(cdn string, expectedResp map[string]interface{}) utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _ tc.Alerts, _ error) {
+ assert.RequireNotNil(t, resp, "Expected CRConfigNew response to not be nil.")
+ crconfig := resp.(tc.CRConfig)
+
+ for field, expected := range expectedResp {
+ switch field {
+ case "TMPath":
+ assert.Equal(t, expected, crconfig.Stats.TMPath, "Expected no TMPath in APIv4, but it was: %s", *crconfig.Stats.TMPath)
+ case "TMHost":
+ assert.RequireNotNil(t, crconfig.Stats.TMHost, "Expected Stats TM Host to not be nil.")
+ assert.Equal(t, expected, *crconfig.Stats.TMHost, "Expected Stats TM Host to be %v, but got %s", expected, *crconfig.Stats.TMHost)
+ default:
+ t.Errorf("Expected field: %v, does not exist in response", field)
+ }
+ }
+ }
+}
+
+func validateDeliveryServicesUnchanged() utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _ tc.Alerts, _ error) {
+ assert.RequireNotNil(t, resp, "Expected new snapshot response to not be nil.")
+ newSnapshot := resp.(tc.CRConfig)
+ assert.Exactly(t, newSnapshot.DeliveryServices, baselineCRConfig.DeliveryServices, "Expected Delivery Services to be unchanged.")
+ }
+}
+
+func getBaselineCRConfig(t *testing.T, cdn string) func() {
+ return func() {
+ opts := client.NewRequestOptions()
+ opts.QueryParameters.Set("cdn", cdn)
+ snapshotResp, _, err := TOSession.SnapshotCRConfig(opts)
+ assert.RequireNoError(t, err, "Unexpected error taking Snapshot of CDN '%s': %v - alerts: %+v", cdn, err, snapshotResp.Alerts)
+ getCRConfig, _, err := TOSession.GetCRConfig(cdn, client.RequestOptions{})
+ assert.RequireNoError(t, err, "Unexpected error retrieving Snapshot of CDN '%s': %v - alerts: %+v", cdn, err, snapshotResp.Alerts)
+ baselineCRConfig = getCRConfig.Response
+ }
+}
+
+func deleteParameter(t *testing.T, paramName string) func() {
+ return func() {
+ opts := client.NewRequestOptions()
+ opts.QueryParameters.Set("name", paramName)
+ paramResp, _, err := TOSession.GetParameters(opts)
+ assert.RequireNoError(t, err, "Cannot get Parameter by name '%s': %v - alerts: %+v", paramName, err, paramResp.Alerts)
+ assert.RequireGreaterOrEqual(t, len(paramResp.Response), 1, "Expected at least one parameter to be returned.")
+ delResp, _, err := TOSession.DeleteParameter(paramResp.Response[0].ID, client.RequestOptions{})
+ assert.RequireNoError(t, err, "Cannot DELETE Parameter by name: %v - %v", err, delResp)
+ }
+}
diff --git a/traffic_ops/testing/api/v5/cdns_name_snapshot_test.go b/traffic_ops/testing/api/v5/cdns_name_snapshot_test.go
new file mode 100644
index 0000000000..3dba9ea686
--- /dev/null
+++ b/traffic_ops/testing/api/v5/cdns_name_snapshot_test.go
@@ -0,0 +1,60 @@
+package v5
+
+/*
+
+ 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 (
+ "net/http"
+ "net/url"
+ "testing"
+
+ "github.com/apache/trafficcontrol/traffic_ops/testing/api/utils"
+ client "github.com/apache/trafficcontrol/traffic_ops/v5-client"
+)
+
+func TestCDNNameSnapshot(t *testing.T) {
+ WithObjs(t, []TCObj{CDNs, Types, Tenants, Parameters, Profiles, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices}, func() {
+
+ methodTests := utils.V5TestCase{
+ "GET": {
+ "OK when VALID request": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdn": {"cdn1"}}},
+ 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 {
+ switch method {
+ case "GET":
+ t.Run(name, func(t *testing.T) {
+ var cdn string
+ if val, ok := testCase.RequestOpts.QueryParameters["cdn"]; ok {
+ cdn = val[0]
+ }
+ resp, reqInf, err := testCase.ClientSession.GetCRConfig(cdn, testCase.RequestOpts)
+ for _, check := range testCase.Expectations {
+ check(t, reqInf, resp.Response, resp.Alerts, err)
+ }
+ })
+ }
+ }
+ })
+ }
+ })
+}
diff --git a/traffic_ops/testing/api/v5/crconfig_test.go b/traffic_ops/testing/api/v5/crconfig_test.go
deleted file mode 100644
index 3e03bf3b16..0000000000
--- a/traffic_ops/testing/api/v5/crconfig_test.go
+++ /dev/null
@@ -1,356 +0,0 @@
-package v5
-
-/*
-
- 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 (
- "net/http"
- "strconv"
- "strings"
- "testing"
- "time"
-
- "github.com/apache/trafficcontrol/lib/go-tc"
- "github.com/apache/trafficcontrol/lib/go-util"
- client "github.com/apache/trafficcontrol/traffic_ops/v5-client"
- toclient "github.com/apache/trafficcontrol/traffic_ops/v5-client"
-)
-
-func TestCRConfig(t *testing.T) {
- WithObjs(t, []TCObj{CDNs, Types, Tenants, Parameters, Profiles, ProfileParameters, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices}, func() {
- UpdateTestCRConfigSnapshot(t)
- MonitoringConfig(t)
- SnapshotTestCDNbyName(t)
- SnapshotTestCDNbyInvalidName(t)
- SnapshotTestCDNbyID(t)
- SnapshotTestCDNbyInvalidID(t)
- SnapshotWithReadOnlyUser(t)
- })
-}
-
-func SnapshotWithReadOnlyUser(t *testing.T) {
- if len(testData.CDNs) == 0 {
- t.Fatalf("expected one or more valid CDNs, but got none")
- }
-
- tenantOpts := client.NewRequestOptions()
- tenantOpts.QueryParameters.Set("name", "root")
- resp, _, err := TOSession.GetTenants(tenantOpts)
- if err != nil {
- t.Fatalf("couldn't get the root tenant ID: %v - alerts: %+v", err, resp.Alerts)
- }
- if len(resp.Response) != 1 {
- t.Fatalf("Expected exactly one Tenant to have the name 'root', found: %d", len(resp.Response))
- }
-
- toReqTimeout := time.Second * time.Duration(Config.Default.Session.TimeoutInSecs)
- user := tc.UserV4{
- Username: "test_user_tm",
- RegistrationSent: new(time.Time),
- LocalPassword: util.StrPtr("test_pa$$word"),
- Role: "read-only",
- }
- user.Email = util.StrPtr("email_tm@domain.com")
- user.TenantID = resp.Response[0].ID
- user.FullName = util.StrPtr("firstName LastName")
-
- u, _, err := TOSession.CreateUser(user, client.RequestOptions{})
- if err != nil {
- t.Fatalf("could not create read-only user: %v - alerts: %+v", err, u.Alerts)
- }
- client, _, err := toclient.LoginWithAgent(TOSession.URL, "test_user_tm", "test_pa$$word", true, "to-api-v5-client-tests/tenant4user", true, toReqTimeout)
- if err != nil {
- t.Fatalf("failed to log in with test_user: %v", err.Error())
- }
- opts := toclient.NewRequestOptions()
- opts.QueryParameters.Set("cdn", testData.CDNs[0].Name)
- _, reqInf, err := client.SnapshotCRConfig(opts)
- if err == nil {
- t.Errorf("expected to get an error about a read-only client trying to snap a CDN, but got none")
- }
- if reqInf.StatusCode != http.StatusForbidden {
- t.Errorf("expected a 403 forbidden status code, but got %d", reqInf.StatusCode)
- }
- ForceDeleteTestUsersByUsernames(t, []string{"test_user_tm"})
-}
-
-func UpdateTestCRConfigSnapshot(t *testing.T) {
- if len(testData.CDNs) < 1 {
- t.Error("no cdn test data")
- }
- cdn := testData.CDNs[0].Name
-
- tmURLParamName := "tm.url"
- tmURLExpected := "crconfig.tm.url.test.invalid"
- paramAlerts, _, err := TOSession.CreateParameter(tc.Parameter{
- ConfigFile: "global",
- Name: tmURLParamName,
- Value: "https://crconfig.tm.url.test.invalid",
- }, client.RequestOptions{})
- if err != nil {
- t.Fatalf("GetCRConfig CreateParameter error expected: nil, actual: %v - alerts: %+v", err, paramAlerts.Alerts)
- }
-
- // create an ANY_MAP DS assignment to verify that it doesn't show up in the CRConfig
- resp, _, err := TOSession.GetServers(client.RequestOptions{})
- if err != nil {
- t.Fatalf("GetServers err expected nil, actual: %v - alerts: %+v", err, resp.Alerts)
- }
- servers := resp.Response
- serverID := 0
- for _, server := range servers {
- if server.CDNName == nil || server.ID == nil {
- t.Error("Traffic Ops returned a representation for a servver with null or undefined ID and/or CDN name")
- continue
- }
- if server.Type == "EDGE" && *server.CDNName == "cdn1" {
- serverID = *server.ID
- break
- }
- }
- if serverID == 0 {
- t.Errorf("GetServers expected EDGE server in cdn1, actual: %+v", servers)
- }
- opts := client.NewRequestOptions()
- opts.QueryParameters.Set("xmlId", "anymap-ds")
- res, _, err := TOSession.GetDeliveryServices(opts)
- if err != nil {
- t.Errorf("Unexpected error getting Delivery Services filtered by XMLID 'anymap-ds': %v - alerts: %+v", err, res.Alerts)
- }
- if len(res.Response) != 1 {
- t.Fatalf("Expected exactly 1 Delivery Service to exist with XMLID 'anymap-ds', actual %d", len(res.Response))
- }
- if res.Response[0].ID == nil {
- t.Fatal("Traffic Ops returned a representation of Delivery Service 'anymap-ds' that had a null or undefined ID")
- }
- anymapDSID := *res.Response[0].ID
- alerts, _, err := TOSession.CreateDeliveryServiceServers(anymapDSID, []int{serverID}, true, client.RequestOptions{})
- if err != nil {
- t.Fatalf("Unexpected error assigning server #%d to Delivery Service #%d: %v - alerts: %+v", serverID, anymapDSID, err, alerts.Alerts)
- }
-
- opts = client.NewRequestOptions()
- opts.QueryParameters.Set("cdn", cdn)
- snapshotResp, _, err := TOSession.SnapshotCRConfig(opts)
- if err != nil {
- t.Errorf("Unexpected error taking Snapshot of CDN '%s': %v - alerts: %+v", cdn, err, snapshotResp.Alerts)
- }
- crcResp, _, err := TOSession.GetCRConfig(cdn, client.RequestOptions{})
- if err != nil {
- t.Errorf("Unexpected error retrieving Snapshot of CDN '%s': %v - alerts: %+v", cdn, err, crcResp.Alerts)
- }
- crc := crcResp.Response
-
- if len(crc.DeliveryServices) == 0 {
- t.Error("GetCRConfig len(crc.DeliveryServices) expected: >0, actual: 0")
- }
-
- // verify no ANY_MAP delivery services are in the CRConfig
- for ds := range crc.DeliveryServices {
- if ds == "anymap-ds" {
- t.Error("found ANY_MAP delivery service in CRConfig deliveryServices")
- }
- }
- for server := range crc.ContentServers {
- for ds := range crc.ContentServers[server].DeliveryServices {
- if ds == "anymap-ds" {
- t.Error("found ANY_MAP delivery service in contentServers deliveryServices mapping")
- }
- }
- }
-
- if crc.Stats.TMPath != nil {
- t.Errorf("Expected no TMPath in APIv4, but it was: %v", *crc.Stats.TMPath)
- }
-
- if crc.Stats.TMHost == nil {
- t.Errorf("GetCRConfig crc.Stats.Path expected: '"+tmURLExpected+"', actual: %+v", crc.Stats.TMHost)
- } else if *crc.Stats.TMHost != tmURLExpected {
- t.Errorf("GetCRConfig crc.Stats.Path expected: '"+tmURLExpected+"', actual: %+v", *crc.Stats.TMHost)
- }
-
- opts.QueryParameters.Del("cdn")
- opts.QueryParameters.Set("name", tmURLParamName)
- paramResp, _, err := TOSession.GetParameters(opts)
- if err != nil {
- t.Fatalf("cannot get Parameter by name '%s': %v - alerts: %+v", tmURLParamName, err, paramResp.Alerts)
- }
- if len(paramResp.Response) == 0 {
- t.Fatal("CRConfig create tm.url parameter was successful, but GET returned no parameters")
- }
- tmURLParam := paramResp.Response[0]
-
- delResp, _, err := TOSession.DeleteParameter(tmURLParam.ID, client.RequestOptions{})
- if err != nil {
- t.Fatalf("cannot DELETE Parameter by name: %v - %v", err, delResp)
- }
-
- crcResp, _, err = TOSession.GetCRConfigNew(cdn, client.RequestOptions{})
- if err != nil {
- t.Errorf("Unexpected error getting new Snapshot for CDN '%s': %v - alerts: %+v", cdn, err, crcResp.Alerts)
- }
- crcNew := crcResp.Response
-
- if len(crcNew.DeliveryServices) != len(crc.DeliveryServices) {
- t.Errorf("/new endpoint returned a different snapshot. DeliveryServices length expected %v, was %v", len(crc.DeliveryServices), len(crcNew.DeliveryServices))
- }
-
- if *crcNew.Stats.TMHost != "" {
- t.Errorf("update to snapshot not captured in /new endpoint")
- }
-}
-
-func MonitoringConfig(t *testing.T) {
- if len(testData.CDNs) < 1 {
- t.Fatalf("no cdn test data")
- }
- const cdnName = "cdn1"
- const profileName = "EDGE1"
- opts := client.NewRequestOptions()
- opts.QueryParameters.Set("name", cdnName)
- cdns, _, err := TOSession.GetCDNs(opts)
- if err != nil {
- t.Fatalf("getting CDNs with name '%s': %v - alerts: %+v", cdnName, err, cdns.Alerts)
- }
- if len(cdns.Response) != 1 {
- t.Fatalf("expected exactly 1 CDN named '%s' but found %d CDNs", cdnName, len(cdns.Response))
- }
- opts.QueryParameters.Set("name", profileName)
- profiles, _, err := TOSession.GetProfiles(opts)
- if err != nil {
- t.Fatalf("getting Profiles with name '%s': %v - alerts: %+v", profileName, err, profiles.Alerts)
- }
- if len(profiles.Response) != 1 {
- t.Fatalf("expected exactly 1 Profiles named %s but found %d Profiles", profileName, len(profiles.Response))
- }
- parameters, _, err := TOSession.GetParametersByProfileName(profileName, client.RequestOptions{})
- if err != nil {
- t.Fatalf("getting Parameters by Profile name '%s': %v - alerts: %+v", profileName, err, parameters.Alerts)
- }
- parameterMap := map[string]tc.HealthThreshold{}
- parameterFound := map[string]bool{}
- const thresholdPrefixLength = len(tc.ThresholdPrefix)
- for _, parameter := range parameters.Response {
- if !strings.HasPrefix(parameter.Name, tc.ThresholdPrefix) {
- continue
- }
- parameterName := parameter.Name[thresholdPrefixLength:]
- parameterMap[parameterName], err = tc.StrToThreshold(parameter.Value)
- if err != nil {
- t.Fatalf("converting string '%s' to HealthThreshold: %s", parameter.Value, err.Error())
- }
- parameterFound[parameterName] = false
- }
- const expectedThresholdParameters = 3
- if len(parameterMap) != expectedThresholdParameters {
- t.Fatalf("expected Profile '%s' to contain %d Parameters with names starting with '%s' but %d such Parameters were found", profileName, expectedThresholdParameters, tc.ThresholdPrefix, len(parameterMap))
- }
- tmConfig, _, err := TOSession.GetTrafficMonitorConfig(cdnName, client.RequestOptions{})
- if err != nil {
- t.Fatalf("getting Traffic Monitor Config: %v - alerts: %+v", err, tmConfig.Alerts)
- }
- profileFound := false
- var profile tc.TMProfile
- for _, profile = range tmConfig.Response.Profiles {
- if profile.Name == profileName {
- profileFound = true
- break
- }
- }
- if !profileFound {
- t.Fatalf("Traffic Monitor Config contained no Profile named '%s", profileName)
- }
- for parameterName, value := range profile.Parameters.Thresholds {
- if _, ok := parameterFound[parameterName]; !ok {
- t.Fatalf("unexpected Threshold Parameter name '%s' found in Profile '%s' in Traffic Monitor Config", parameterName, profileName)
- }
- parameterFound[parameterName] = true
- if parameterMap[parameterName].String() != value.String() {
- t.Fatalf("expected '%s' but received '%s' for Threshold Parameter '%s' in Profile '%s' in Traffic Monitor Config", parameterMap[parameterName].String(), value.String(), parameterName, profileName)
- }
- }
- missingParameters := []string{}
- for parameterName, found := range parameterFound {
- if !found {
- missingParameters = append(missingParameters, parameterName)
- }
- }
- if len(missingParameters) != 0 {
- t.Fatalf("Threshold parameters defined for Profile '%s' but missing for Profile '%s' in Traffic Monitor Config: %s", profileName, profileName, strings.Join(missingParameters, ", "))
- }
-}
-
-func SnapshotTestCDNbyName(t *testing.T) {
- if len(testData.CDNs) < 1 {
- t.Fatal("Need at least one CDN to test taking CDN Snapshot using CDN name")
- }
- firstCDN := testData.CDNs[0].Name
- opts := client.NewRequestOptions()
- opts.QueryParameters.Set("cdn", firstCDN)
- resp, _, err := TOSession.SnapshotCRConfig(opts)
- if err != nil {
- t.Errorf("failed to snapshot CDN '%s' by name: %v - alerts: %+v", firstCDN, err, resp.Alerts)
- }
-}
-
-// Note that this test will break if anyone adds a CDN to the fixture data with
-// the name "cdn-invalid".
-func SnapshotTestCDNbyInvalidName(t *testing.T) {
- invalidCDNName := "cdn-invalid"
- opts := client.NewRequestOptions()
- opts.QueryParameters.Set("cdn", invalidCDNName)
- _, _, err := TOSession.SnapshotCRConfig(opts)
- if err == nil {
- t.Errorf("snapshot occurred without error on (presumed) invalid CDN '%s'", invalidCDNName)
- }
-}
-
-func SnapshotTestCDNbyID(t *testing.T) {
- if len(testData.CDNs) < 1 {
- t.Fatal("Need at least one CDN to test Snapshotting CDNs")
- }
- firstCDNName := testData.CDNs[0].Name
- opts := client.NewRequestOptions()
- opts.QueryParameters.Set("name", firstCDNName)
- // Retrieve the CDN by name so we can get the id for the snapshot
- resp, _, err := TOSession.GetCDNs(opts)
- if err != nil {
- t.Errorf("cannot get CDN '%s': %v - alerts: %+v", firstCDNName, err, resp.Alerts)
- }
- if len(resp.Response) != 1 {
- t.Fatalf("Expected exactly one CDN to exist with name '%s', found: %d", firstCDNName, len(resp.Response))
- }
- remoteCDNID := resp.Response[0].ID
- opts.QueryParameters.Del("name")
- opts.QueryParameters.Set("cdnID", strconv.Itoa(remoteCDNID))
- alert, _, err := TOSession.SnapshotCRConfig(opts)
- if err != nil {
- t.Errorf("failed to snapshot CDN '%s' (#%d) by id: %v - alerts: %+v", firstCDNName, remoteCDNID, err, alert.Alerts)
- }
-}
-
-// Note that this test will break in the event that 1,000,000 CDNs are created
-// in the TO instance at any time (they don't need to exist concurrently, just
-// that many successful CDN creations have to happen, even if they are
-// all immediately deleted except the 999999th one).
-func SnapshotTestCDNbyInvalidID(t *testing.T) {
- opts := client.NewRequestOptions()
- invalidCDNID := 999999
- opts.QueryParameters.Set("cdnID", strconv.Itoa(invalidCDNID))
- alert, _, err := TOSession.SnapshotCRConfig(opts)
- if err == nil {
- t.Errorf("snapshot occurred on (presumed) invalid CDN #%d: %v - alerts: %+v", invalidCDNID, err, alert.Alerts)
- }
-}
diff --git a/traffic_ops/testing/api/v5/snapshot_test.go b/traffic_ops/testing/api/v5/snapshot_test.go
new file mode 100644
index 0000000000..9da1fca93d
--- /dev/null
+++ b/traffic_ops/testing/api/v5/snapshot_test.go
@@ -0,0 +1,126 @@
+package v5
+
+/*
+
+ 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 (
+ "net/http"
+ "net/url"
+ "strconv"
+ "testing"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "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/v5-client"
+)
+
+func TestSnapshot(t *testing.T) {
+ WithObjs(t, []TCObj{CDNs, Types, Tenants, Users, Parameters, Profiles, Statuses, Divisions, Regions, PhysLocations, CacheGroups, Servers, Topologies, ServiceCategories, DeliveryServices, DeliveryServiceServerAssignments}, func() {
+
+ readOnlyUserSession := utils.CreateV5Session(t, Config.TrafficOps.URL, "readonlyuser", "pa$$word", Config.Default.Session.TimeoutInSecs)
+
+ methodTests := utils.V5TestCase{
+ "PUT": {
+ "VERIFY ANYMAP DELIVERY SERVICE is NOT in CRCONFIG": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdn": {"cdn1"}}},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
+ validateDeliveryServiceNotInCRConfig("cdn1", "anymap-ds"),
+ validateCRConfigFields("cdn1", map[string]interface{}{"TMPath": (*string)(nil), "TMHost": "crconfig.tm.url.test.invalid"})),
+ },
+ "OK when VALID CDN parameter": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdn": {"cdn1"}}},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+ },
+ "OK when VALID CDNID parameter": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdnID": {strconv.Itoa(GetCDNID(t, "cdn1")())}}},
+ Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+ },
+ "NOT FOUND when NON-EXISTENT CDN": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdn": {"cdn-invalid"}}},
+ Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusNotFound)),
+ },
+ "NOT FOUND when NON-EXISTENT CDNID": {
+ ClientSession: TOSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdnID": {"999999"}}},
+ Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusNotFound)),
+ },
+ "FORBIDDEN when READ-ONLY user": {
+ ClientSession: readOnlyUserSession,
+ RequestOpts: client.RequestOptions{QueryParameters: url.Values{"cdn": {"cdn1"}}},
+ Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusForbidden)),
+ },
+ },
+ }
+
+ for method, testCases := range methodTests {
+ t.Run(method, func(t *testing.T) {
+ for name, testCase := range testCases {
+ switch method {
+ case "PUT":
+ t.Run(name, func(t *testing.T) {
+ resp, reqInf, err := testCase.ClientSession.SnapshotCRConfig(testCase.RequestOpts)
+ for _, check := range testCase.Expectations {
+ check(t, reqInf, resp.Response, resp.Alerts, err)
+ }
+ })
+ }
+ }
+ })
+ }
+ })
+}
+
+func validateCRConfigFields(cdn string, expectedResp map[string]interface{}) utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, _ interface{}, _ tc.Alerts, _ error) {
+ snapshotResp, _, err := TOSession.GetCRConfig(cdn, client.RequestOptions{})
+ assert.RequireNoError(t, err, "Unexpected error retrieving Snapshot of CDN '%s': %v - alerts: %+v", cdn, err, snapshotResp.Alerts)
+ crconfig := snapshotResp.Response
+
+ for field, expected := range expectedResp {
+ switch field {
+ case "TMPath":
+ assert.Equal(t, expected, crconfig.Stats.TMPath, "Expected no TMPath in APIv4, but it was: %v", crconfig.Stats.TMPath)
+ case "TMHost":
+ assert.RequireNotNil(t, crconfig.Stats.TMHost, "Expected Stats TM Host to not be nil.")
+ assert.Equal(t, expected, *crconfig.Stats.TMHost, "Expected Stats TM Host to be %v, but got %s", expected, *crconfig.Stats.TMHost)
+ default:
+ t.Errorf("Expected field: %v, does not exist in response", field)
+ }
+ }
+ }
+}
+
+func validateDeliveryServiceNotInCRConfig(cdn string, deliveryService string) utils.CkReqFunc {
+ return func(t *testing.T, _ toclientlib.ReqInf, _ interface{}, _ tc.Alerts, _ error) {
+ snapshotResp, _, err := TOSession.GetCRConfig(cdn, client.RequestOptions{})
+ assert.RequireNoError(t, err, "Unexpected error retrieving Snapshot of CDN '%s': %v - alerts: %+v", cdn, err, snapshotResp.Alerts)
+
+ for ds := range snapshotResp.Response.DeliveryServices {
+ assert.NotEqual(t, ds, deliveryService, "Found unexpected delivery service: %s in CRConfig Delivery Services.", deliveryService)
+ }
+
+ for _, server := range snapshotResp.Response.ContentServers {
+ for ds := range server.DeliveryServices {
+ assert.NotEqual(t, ds, deliveryService, "Found unexpected delivery service: %s in CRConfig Content Servers Delivery Services.", deliveryService)
+ }
+ }
+ }
+}
diff --git a/traffic_ops/testing/api/v5/tc-fixtures.json b/traffic_ops/testing/api/v5/tc-fixtures.json
index c3d5a9803f..3258ce828f 100644
--- a/traffic_ops/testing/api/v5/tc-fixtures.json
+++ b/traffic_ops/testing/api/v5/tc-fixtures.json
@@ -1801,6 +1801,10 @@
{
"xmlId": "ds2",
"serverNames": ["atlanta-org-2"]
+ },
+ {
+ "xmlId": "anymap-ds",
+ "serverNames": ["atlanta-edge-15"]
}
],
"divisions": [
@@ -2024,8 +2028,13 @@
"name": "testSecure",
"secure": true,
"value": "hidden value"
+ },
+ {
+ "configFile": "global",
+ "name": "tm.url",
+ "secure": false,
+ "value": "https://crconfig.tm.url.test.invalid"
}
-
],
"physLocations": [
{