You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by oc...@apache.org on 2022/05/13 01:34:52 UTC
[trafficcontrol] branch master updated: Prevent modifying and/or deleting reserved statuses (#6817)
This is an automated email from the ASF dual-hosted git repository.
ocket8888 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 aa24989fa3 Prevent modifying and/or deleting reserved statuses (#6817)
aa24989fa3 is described below
commit aa24989fa31c633df28d6b8c10a4fb86b03fbc48
Author: Srijeet Chatterjee <30...@users.noreply.github.com>
AuthorDate: Thu May 12 19:34:46 2022 -0600
Prevent modifying and/or deleting reserved statuses (#6817)
* prevent modifying and/or deleting reserved statuses
* fix tests
* cleanup
* code review fixes
* fix test
* code review round 2
* remove unused file
---
CHANGELOG.md | 1 +
.../testing/ort-tests/t3c-apply-diff_test.go | 2 +-
.../ort-tests/t3c-apply-unset-update_test.go | 2 +-
.../ort-tests/t3c-apply-wait-for-parents_test.go | 6 +-
.../ort-tests/t3c-create-empty-file_test.go | 2 +-
.../testing/ort-tests/t3c-dns-local-bind_test.go | 2 +-
.../testing/ort-tests/t3c-fail-log_test.go | 2 +-
cache-config/testing/ort-tests/t3c-git_test.go | 2 +-
cache-config/testing/ort-tests/t3c-ims_test.go | 2 +-
cache-config/testing/ort-tests/t3c-jobs_test.go | 2 +-
.../testing/ort-tests/t3c-lockfile_test.go | 2 +-
.../ort-tests/t3c-no-outgoing-ip-flag_test.go | 2 +-
.../ort-tests/t3c-os-hostname-short_test.go | 2 +-
cache-config/testing/ort-tests/t3c-reload_test.go | 2 +-
cache-config/testing/ort-tests/t3c_mode_test.go | 2 +-
.../testing/ort-tests/t3c_update_to_flags_test.go | 2 +-
cache-config/testing/ort-tests/tc-fixtures.json | 29 -----
cache-config/testing/ort-tests/tcdata/statuses.go | 62 ----------
cache-config/testing/ort-tests/tcdata/todb.go | 2 +-
cache-config/testing/ort-tests/tcdata/withobjs.go | 2 -
.../testing/ort-tests/to_requester_test.go | 2 +-
cache-config/testing/ort-tests/to_updater_test.go | 2 +-
lib/go-tc/enum.go | 3 +
lib/go-tc/statuses.go | 18 +++
.../testing/tests/health-client-startup_test.go | 2 +-
...2022050916074300_add_reserved_statuses.down.sql | 17 +++
.../2022050916074300_add_reserved_statuses.up.sql | 23 ++++
traffic_ops/testing/api/v2/statuses_test.go | 77 ++++++------
traffic_ops/testing/api/v2/tc-fixtures.json | 20 ---
traffic_ops/testing/api/v2/todb_test.go | 2 +-
traffic_ops/testing/api/v3/statuses_test.go | 115 +++++++++---------
traffic_ops/testing/api/v3/tc-fixtures.json | 20 ---
traffic_ops/testing/api/v3/todb_test.go | 2 +-
traffic_ops/testing/api/v4/statuses_test.go | 134 +++++++++++----------
traffic_ops/testing/api/v4/tc-fixtures.json | 20 ---
traffic_ops/testing/api/v4/todb_test.go | 2 +-
traffic_ops/traffic_ops_golang/status/statuses.go | 26 +++-
37 files changed, 282 insertions(+), 333 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 341ce78450..db7aa0e5de 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,6 +25,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- Added layered profile feature to 4.0 for `GET` /deliveryservices/{id}/servers/ and /deliveryservices/{id}/servers/eligible.
### Fixed
+- [#6291](https://github.com/apache/trafficcontrol/issues/6291) Prevent Traffic Ops from modifying and/or deleting reserved statuses.
- Update traffic\_portal dependencies to mitigate `npm audit` issues.
- Fixed a cdn-in-a-box build issue when using `RHEL_VERSION=7`
- `dequeueing` server updates should not require checking for cdn locks.
diff --git a/cache-config/testing/ort-tests/t3c-apply-diff_test.go b/cache-config/testing/ort-tests/t3c-apply-diff_test.go
index b35e3da372..f7613bc68e 100644
--- a/cache-config/testing/ort-tests/t3c-apply-diff_test.go
+++ b/cache-config/testing/ort-tests/t3c-apply-diff_test.go
@@ -28,7 +28,7 @@ import (
func TestApplyDiff(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
diff --git a/cache-config/testing/ort-tests/t3c-apply-unset-update_test.go b/cache-config/testing/ort-tests/t3c-apply-unset-update_test.go
index 0d3ae688f0..55b95c36f4 100644
--- a/cache-config/testing/ort-tests/t3c-apply-unset-update_test.go
+++ b/cache-config/testing/ort-tests/t3c-apply-unset-update_test.go
@@ -73,7 +73,7 @@ func verifyUpdateStatusIsTrue() error {
func TestT3cUnsetsUpdateFlag(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
diff --git a/cache-config/testing/ort-tests/t3c-apply-wait-for-parents_test.go b/cache-config/testing/ort-tests/t3c-apply-wait-for-parents_test.go
index 94df96e26a..4b86042d4d 100644
--- a/cache-config/testing/ort-tests/t3c-apply-wait-for-parents_test.go
+++ b/cache-config/testing/ort-tests/t3c-apply-wait-for-parents_test.go
@@ -36,7 +36,7 @@ const childCacheHostName = DefaultCacheHostName
func TestWaitForParentsTrue(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
@@ -147,7 +147,7 @@ func TestWaitForParentsTrue(t *testing.T) {
func TestWaitForParentsDefaultReval(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
@@ -216,7 +216,7 @@ func TestWaitForParentsDefaultReval(t *testing.T) {
func TestWaitForParentsFalse(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
diff --git a/cache-config/testing/ort-tests/t3c-create-empty-file_test.go b/cache-config/testing/ort-tests/t3c-create-empty-file_test.go
index 9389597c79..48781faf4b 100644
--- a/cache-config/testing/ort-tests/t3c-create-empty-file_test.go
+++ b/cache-config/testing/ort-tests/t3c-create-empty-file_test.go
@@ -31,7 +31,7 @@ func TestT3cCreateEmptyFile(t *testing.T) {
// t3c must create semantically blank files. Failing to do so will cause other config files that reference them to fail.
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
diff --git a/cache-config/testing/ort-tests/t3c-dns-local-bind_test.go b/cache-config/testing/ort-tests/t3c-dns-local-bind_test.go
index 247fc53391..be158d885e 100644
--- a/cache-config/testing/ort-tests/t3c-dns-local-bind_test.go
+++ b/cache-config/testing/ort-tests/t3c-dns-local-bind_test.go
@@ -29,7 +29,7 @@ import (
func TestT3CDNSLocalBind(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
diff --git a/cache-config/testing/ort-tests/t3c-fail-log_test.go b/cache-config/testing/ort-tests/t3c-fail-log_test.go
index 98e310412e..47a6a3014c 100644
--- a/cache-config/testing/ort-tests/t3c-fail-log_test.go
+++ b/cache-config/testing/ort-tests/t3c-fail-log_test.go
@@ -24,7 +24,7 @@ import (
func TestT3cApplyFailMsg(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
diff --git a/cache-config/testing/ort-tests/t3c-git_test.go b/cache-config/testing/ort-tests/t3c-git_test.go
index 2250595d83..7f58773dc5 100644
--- a/cache-config/testing/ort-tests/t3c-git_test.go
+++ b/cache-config/testing/ort-tests/t3c-git_test.go
@@ -31,7 +31,7 @@ import (
func TestT3cGit(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
diff --git a/cache-config/testing/ort-tests/t3c-ims_test.go b/cache-config/testing/ort-tests/t3c-ims_test.go
index 7772a539ab..50e27c119a 100644
--- a/cache-config/testing/ort-tests/t3c-ims_test.go
+++ b/cache-config/testing/ort-tests/t3c-ims_test.go
@@ -34,7 +34,7 @@ import (
func TestIMS(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
diff --git a/cache-config/testing/ort-tests/t3c-jobs_test.go b/cache-config/testing/ort-tests/t3c-jobs_test.go
index e3fff5905b..980ee67ce3 100644
--- a/cache-config/testing/ort-tests/t3c-jobs_test.go
+++ b/cache-config/testing/ort-tests/t3c-jobs_test.go
@@ -29,7 +29,7 @@ import (
func TestT3CJobs(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
diff --git a/cache-config/testing/ort-tests/t3c-lockfile_test.go b/cache-config/testing/ort-tests/t3c-lockfile_test.go
index 677d5b2900..6f06a8ff2b 100644
--- a/cache-config/testing/ort-tests/t3c-lockfile_test.go
+++ b/cache-config/testing/ort-tests/t3c-lockfile_test.go
@@ -27,7 +27,7 @@ import (
func TestLockfile(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
diff --git a/cache-config/testing/ort-tests/t3c-no-outgoing-ip-flag_test.go b/cache-config/testing/ort-tests/t3c-no-outgoing-ip-flag_test.go
index 2c74bb92c6..8e14dc8068 100644
--- a/cache-config/testing/ort-tests/t3c-no-outgoing-ip-flag_test.go
+++ b/cache-config/testing/ort-tests/t3c-no-outgoing-ip-flag_test.go
@@ -55,7 +55,7 @@ func testNoOutgoingIPAfterUpdate(t *testing.T, noOutgoingIP *bool) {
func TestT3CNoOutgoingIP(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
diff --git a/cache-config/testing/ort-tests/t3c-os-hostname-short_test.go b/cache-config/testing/ort-tests/t3c-os-hostname-short_test.go
index 49d42136f8..5eaace94dc 100644
--- a/cache-config/testing/ort-tests/t3c-os-hostname-short_test.go
+++ b/cache-config/testing/ort-tests/t3c-os-hostname-short_test.go
@@ -25,7 +25,7 @@ import (
func TestT3cApplyOSHostnameShort(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
diff --git a/cache-config/testing/ort-tests/t3c-reload_test.go b/cache-config/testing/ort-tests/t3c-reload_test.go
index a9705b66c7..5dd390d5a5 100644
--- a/cache-config/testing/ort-tests/t3c-reload_test.go
+++ b/cache-config/testing/ort-tests/t3c-reload_test.go
@@ -28,7 +28,7 @@ import (
func TestT3cReload(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices, tcdata.InvalidationJobs}, func() {
diff --git a/cache-config/testing/ort-tests/t3c_mode_test.go b/cache-config/testing/ort-tests/t3c_mode_test.go
index 12cb8d667c..702e14e8e9 100644
--- a/cache-config/testing/ort-tests/t3c_mode_test.go
+++ b/cache-config/testing/ort-tests/t3c_mode_test.go
@@ -106,7 +106,7 @@ func checkDiff(fName, atsUid, atsGid string, t *testing.T) {
func TestT3cBadassAndSyncDs(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
diff --git a/cache-config/testing/ort-tests/t3c_update_to_flags_test.go b/cache-config/testing/ort-tests/t3c_update_to_flags_test.go
index 35ae74f980..39c9dec0ce 100644
--- a/cache-config/testing/ort-tests/t3c_update_to_flags_test.go
+++ b/cache-config/testing/ort-tests/t3c_update_to_flags_test.go
@@ -25,7 +25,7 @@ import (
func TestT3cTOUpdates(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices, tcdata.InvalidationJobs}, func() {
diff --git a/cache-config/testing/ort-tests/tc-fixtures.json b/cache-config/testing/ort-tests/tc-fixtures.json
index 4f7098aeb0..54a3677132 100644
--- a/cache-config/testing/ort-tests/tc-fixtures.json
+++ b/cache-config/testing/ort-tests/tc-fixtures.json
@@ -4535,35 +4535,6 @@
"type": "AAAA_RECORD"
}
],
- "statuses": [
- {
- "description": "Edge: Puts server in CCR config file in this state, but CCR will never route traffic to it. Mid: Server will not be included in parent.config files for its edge caches",
- "name": "OFFLINE"
- },
- {
- "description": "Edge: Puts server in CCR config file in this state, and CCR will always route traffic to it. Mid: Server will be included in parent.config files for its edges",
- "name": "ONLINE"
- },
- {
- "description": "Edge: Puts server in CCR config file in this state, and CCR will adhere to the health protocol. Mid: N/A for now",
- "name": "REPORTED"
- },
- {
- "description": "Temporary down. Edge: XMPP client will send status OFFLINE to CCR, otherwise similar to REPORTED. Mid: Server will not be included in parent.config files for its edge caches",
- "name": "ADMIN_DOWN"
- },
- {
- "description": "Edge: 12M will not include caches in this state in CCR config files. Mid: N/A for now",
- "name": "CCR_IGNORE"
- },
- {
- "description": "Pre Production. Not active in any configuration.",
- "name": "PRE_PROD"
- },
- {
- "name": "TEST_NULL_DESCRIPTION"
- }
- ],
"tenants": [
{
"active": true,
diff --git a/cache-config/testing/ort-tests/tcdata/statuses.go b/cache-config/testing/ort-tests/tcdata/statuses.go
deleted file mode 100644
index 81d82b288b..0000000000
--- a/cache-config/testing/ort-tests/tcdata/statuses.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package tcdata
-
-/*
-
- 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 (
- "testing"
-)
-
-func (r *TCData) CreateTestStatuses(t *testing.T) {
-
- for _, status := range r.TestData.Statuses {
- resp, _, err := TOSession.CreateStatusNullable(status)
- t.Log("Response: ", resp)
- if err != nil {
- t.Errorf("could not CREATE types: %v", err)
- }
- }
-
-}
-
-func (r *TCData) DeleteTestStatuses(t *testing.T) {
-
- for _, status := range r.TestData.Statuses {
- if status.Name == nil {
- t.Fatal("cannot get ftest statuses: test data statuses must have names")
- }
-
- // Retrieve the Status by name so we can get the id for the Update
- resp, _, err := TOSession.GetStatusByName(*status.Name)
- if err != nil {
- t.Errorf("cannot GET Status by name: %s - %v", *status.Name, err)
- }
- respStatus := resp[0]
-
- delResp, _, err := TOSession.DeleteStatusByID(respStatus.ID)
- if err != nil {
- t.Errorf("cannot DELETE Status by name: %v - %v", err, delResp)
- }
-
- // Retrieve the Status to see if it got deleted
- types, _, err := TOSession.GetStatusByName(*status.Name)
- if err != nil {
- t.Errorf("error deleting Status name: %v", err)
- }
- if len(types) > 0 {
- t.Errorf("expected Status name: %s to be deleted", *status.Name)
- }
- }
-}
diff --git a/cache-config/testing/ort-tests/tcdata/todb.go b/cache-config/testing/ort-tests/tcdata/todb.go
index d1df501774..0bbb27b76c 100644
--- a/cache-config/testing/ort-tests/tcdata/todb.go
+++ b/cache-config/testing/ort-tests/tcdata/todb.go
@@ -279,7 +279,7 @@ func (r *TCData) Teardown(db *sql.DB) error {
DELETE FROM cachegroup;
DELETE FROM coordinate;
DELETE FROM type;
- DELETE FROM status;
+ DELETE FROM status s WHERE s.name NOT IN ('OFFLINE', 'ONLINE', 'PRE_PROD', 'ADMIN_DOWN', 'REPORTED');
DELETE FROM snapshot;
DELETE FROM cdn;
DELETE FROM service_category;
diff --git a/cache-config/testing/ort-tests/tcdata/withobjs.go b/cache-config/testing/ort-tests/tcdata/withobjs.go
index b3bf3337d1..d2460bea3e 100644
--- a/cache-config/testing/ort-tests/tcdata/withobjs.go
+++ b/cache-config/testing/ort-tests/tcdata/withobjs.go
@@ -49,7 +49,6 @@ const (
ServerServerCapabilities
Servers
ServiceCategories
- Statuses
StaticDNSEntries
SteeringTargets
Tenants
@@ -99,7 +98,6 @@ func (r *TCData) WithObjs(t *testing.T, objs []TCObj, f func()) {
ServerServerCapabilities: {r.CreateTestServerServerCapabilities, r.DeleteTestServerServerCapabilities},
Servers: {r.CreateTestServers, r.DeleteTestServers},
ServiceCategories: {r.CreateTestServiceCategories, r.DeleteTestServiceCategories},
- Statuses: {r.CreateTestStatuses, r.DeleteTestStatuses},
StaticDNSEntries: {r.CreateTestStaticDNSEntries, r.DeleteTestStaticDNSEntries},
SteeringTargets: {r.SetupSteeringTargets, r.DeleteTestSteeringTargets},
Tenants: {r.CreateTestTenants, r.DeleteTestTenants},
diff --git a/cache-config/testing/ort-tests/to_requester_test.go b/cache-config/testing/ort-tests/to_requester_test.go
index cbc1e521f1..982ba47923 100644
--- a/cache-config/testing/ort-tests/to_requester_test.go
+++ b/cache-config/testing/ort-tests/to_requester_test.go
@@ -35,7 +35,7 @@ type Package struct {
func TestTORequester(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices}, func() {
diff --git a/cache-config/testing/ort-tests/to_updater_test.go b/cache-config/testing/ort-tests/to_updater_test.go
index 5384818e86..efc97cab4e 100644
--- a/cache-config/testing/ort-tests/to_updater_test.go
+++ b/cache-config/testing/ort-tests/to_updater_test.go
@@ -31,7 +31,7 @@ import (
func TestTOUpdater(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
tcdata.DeliveryServices, tcdata.InvalidationJobs}, func() {
diff --git a/lib/go-tc/enum.go b/lib/go-tc/enum.go
index 014a624485..8d100fa683 100644
--- a/lib/go-tc/enum.go
+++ b/lib/go-tc/enum.go
@@ -374,6 +374,9 @@ const (
// by Traffic Monitor. The vast majority of cache servers should have this
// Status.
CacheStatusReported = CacheStatus("REPORTED")
+ // CacheStatusPreProd represents a cache server that is not deployed to "production",
+ // but is ready for it.
+ CacheStatusPreProd = CacheStatus("PRE_PROD")
// CacheStatusInvalid represents an unrecognized Status value. Note that
// this is not actually "invalid", because Statuses may have any unique
// name, not just those captured as CacheStatus values in this package.
diff --git a/lib/go-tc/statuses.go b/lib/go-tc/statuses.go
index eafaf1a4e5..74c847b4a3 100644
--- a/lib/go-tc/statuses.go
+++ b/lib/go-tc/statuses.go
@@ -70,3 +70,21 @@ type StatusNullable struct {
LastUpdated *TimeNoMod `json:"lastUpdated" db:"last_updated"`
Name *string `json:"name" db:"name"`
}
+
+// IsReservedStatus returns true if the passed in status name is reserved, and false if it isn't.
+// Currently, the reserved statuses are OFFLINE, ONLINE, REPORTED, PRE_PROD and ADMIN_DOWN.
+func IsReservedStatus(status string) bool {
+ switch CacheStatus(status) {
+ case CacheStatusOffline:
+ fallthrough
+ case CacheStatusReported:
+ fallthrough
+ case CacheStatusOnline:
+ fallthrough
+ case CacheStatusPreProd:
+ fallthrough
+ case CacheStatusAdminDown:
+ return true
+ }
+ return false
+}
diff --git a/tc-health-client/testing/tests/health-client-startup_test.go b/tc-health-client/testing/tests/health-client-startup_test.go
index 60c198bbe8..6d03fa45f3 100644
--- a/tc-health-client/testing/tests/health-client-startup_test.go
+++ b/tc-health-client/testing/tests/health-client-startup_test.go
@@ -39,7 +39,7 @@ func startHealthClient() {
func TestHealthClientStartup(t *testing.T) {
tcd.WithObjs(t, []tcdata.TCObj{
tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
- tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Profiles, tcdata.ProfileParameters,
tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
}, func() {
diff --git a/traffic_ops/app/db/migrations/2022050916074300_add_reserved_statuses.down.sql b/traffic_ops/app/db/migrations/2022050916074300_add_reserved_statuses.down.sql
new file mode 100644
index 0000000000..6b6a6e9174
--- /dev/null
+++ b/traffic_ops/app/db/migrations/2022050916074300_add_reserved_statuses.down.sql
@@ -0,0 +1,17 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
diff --git a/traffic_ops/app/db/migrations/2022050916074300_add_reserved_statuses.up.sql b/traffic_ops/app/db/migrations/2022050916074300_add_reserved_statuses.up.sql
new file mode 100644
index 0000000000..ddd9a128d3
--- /dev/null
+++ b/traffic_ops/app/db/migrations/2022050916074300_add_reserved_statuses.up.sql
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+INSERT INTO public.status ("name", description) VALUES ('ONLINE', 'Server is online.') ON CONFLICT ("name") DO NOTHING;
+INSERT INTO public.status ("name", description) VALUES ('OFFLINE', 'Server is Offline. Not active in any configuration.') ON CONFLICT ("name") DO NOTHING;
+INSERT INTO public.status ("name", description) VALUES ('REPORTED', 'Server is online and reported in the health protocol.') ON CONFLICT ("name") DO NOTHING;
+INSERT INTO public.status ("name", description) VALUES ('ADMIN_DOWN', 'Sever is administrative down and does not receive traffic.') ON CONFLICT ("name") DO NOTHING;
+INSERT INTO public.status ("name", description) VALUES ('PRE_PROD', 'Pre Production. Not active in any configuration.') ON CONFLICT ("name") DO NOTHING;
+
diff --git a/traffic_ops/testing/api/v2/statuses_test.go b/traffic_ops/testing/api/v2/statuses_test.go
index 9a15714723..9a11866f20 100644
--- a/traffic_ops/testing/api/v2/statuses_test.go
+++ b/traffic_ops/testing/api/v2/statuses_test.go
@@ -29,48 +29,55 @@ func TestStatuses(t *testing.T) {
}
func CreateTestStatuses(t *testing.T) {
-
for _, status := range testData.Statuses {
resp, _, err := TOSession.CreateStatusNullable(status)
t.Log("Response: ", resp)
if err != nil {
- t.Errorf("could not CREATE types: %v", err)
+ t.Errorf("could not CREATE status: %v", err)
}
}
-
}
func UpdateTestStatuses(t *testing.T) {
- firstStatus := testData.Statuses[0]
- if firstStatus.Name == nil {
- t.Fatal("cannot update test statuses: first test data status must have a name")
- }
-
- // Retrieve the Status by name so we can get the id for the Update
- resp, _, err := TOSession.GetStatusByName(*firstStatus.Name)
- if err != nil {
- t.Errorf("cannot GET Status by name: %v - %v", firstStatus.Name, err)
+ if len(testData.Statuses) < 1 {
+ t.Fatal("Need at least one Status to test updating a Status")
}
- remoteStatus := resp[0]
- expectedStatusDesc := "new description"
- remoteStatus.Description = expectedStatusDesc
- var alert tc.Alerts
- alert, _, err = TOSession.UpdateStatusByID(remoteStatus.ID, remoteStatus)
- if err != nil {
- t.Errorf("cannot UPDATE Status by id: %v - %v", err, alert)
- }
-
- // Retrieve the Status to check Status name got updated
- resp, _, err = TOSession.GetStatusByID(remoteStatus.ID)
- if err != nil {
- t.Errorf("cannot GET Status by ID: %v - %v", firstStatus.Description, err)
- }
- respStatus := resp[0]
- if respStatus.Description != expectedStatusDesc {
- t.Errorf("results do not match actual: %s, expected: %s", respStatus.Name, expectedStatusDesc)
+ for _, status := range testData.Statuses {
+ if status.Name == nil {
+ t.Fatal("cannot update test statuses: test data status must have a name")
+ }
+ // Retrieve the Status by name so we can get the id for the Update
+ resp, _, err := TOSession.GetStatusByName(*status.Name)
+ if err != nil {
+ t.Errorf("cannot GET Status by name: %s - %v", *status.Name, err)
+ }
+ remoteStatus := resp[0]
+ expectedStatusDesc := "new description"
+ remoteStatus.Description = expectedStatusDesc
+ var alert tc.Alerts
+ alert, _, err = TOSession.UpdateStatusByID(remoteStatus.ID, remoteStatus)
+
+ if tc.IsReservedStatus(*status.Name) {
+ if err == nil {
+ t.Errorf("expected an error about while updating a reserved status, but got nothing")
+ }
+ } else {
+ if err != nil {
+ t.Errorf("cannot UPDATE Status by id: %d, err: %v - %v", remoteStatus.ID, err, alert)
+ }
+
+ // Retrieve the Status to check Status name got updated
+ resp, _, err = TOSession.GetStatusByID(remoteStatus.ID)
+ if err != nil {
+ t.Errorf("cannot GET Status by ID: %d - %v", remoteStatus.ID, err)
+ }
+ respStatus := resp[0]
+ if respStatus.Description != expectedStatusDesc {
+ t.Errorf("results do not match actual: %s, expected: %s", respStatus.Name, expectedStatusDesc)
+ }
+ }
}
-
}
func GetTestStatuses(t *testing.T) {
@@ -97,7 +104,7 @@ func DeleteTestStatuses(t *testing.T) {
// Retrieve the Status by name so we can get the id for the Update
resp, _, err := TOSession.GetStatusByName(*status.Name)
if err != nil {
- t.Errorf("cannot GET Status by name: %v - %v", status.Name, err)
+ t.Errorf("cannot GET Status by name: %s - %v", *status.Name, err)
}
if len(resp) != 1 {
t.Errorf("Expected exactly one Status to exist with name '%s', found: %d", *status.Name, len(resp))
@@ -107,15 +114,15 @@ func DeleteTestStatuses(t *testing.T) {
delResp, _, err := TOSession.DeleteStatusByID(respStatus.ID)
if err != nil {
- t.Errorf("cannot DELETE Status by name: %v - %v", err, delResp)
+ t.Errorf("cannot DELETE Status by ID: %v - %v", err, delResp)
}
// Retrieve the Status to see if it got deleted
- types, _, err := TOSession.GetStatusByName(*status.Name)
+ statuses, _, err := TOSession.GetStatusByName(*status.Name)
if err != nil {
- t.Errorf("error deleting Status name: %s", err.Error())
+ t.Errorf("error getting status by name: %s, err: %v", *status.Name, err)
}
- if len(types) > 0 {
+ if len(statuses) > 0 {
t.Errorf("expected Status name: %s to be deleted", *status.Name)
}
}
diff --git a/traffic_ops/testing/api/v2/tc-fixtures.json b/traffic_ops/testing/api/v2/tc-fixtures.json
index cdb6a0cad1..77467ff78c 100644
--- a/traffic_ops/testing/api/v2/tc-fixtures.json
+++ b/traffic_ops/testing/api/v2/tc-fixtures.json
@@ -2224,30 +2224,10 @@
}
],
"statuses": [
- {
- "description": "Edge: Puts server in CCR config file in this state, but CCR will never route traffic to it. Mid: Server will not be included in parent.config files for its edge caches",
- "name": "OFFLINE"
- },
- {
- "description": "Edge: Puts server in CCR config file in this state, and CCR will always route traffic to it. Mid: Server will be included in parent.config files for its edges",
- "name": "ONLINE"
- },
- {
- "description": "Edge: Puts server in CCR config file in this state, and CCR will adhere to the health protocol. Mid: N/A for now",
- "name": "REPORTED"
- },
- {
- "description": "Temporary down. Edge: XMPP client will send status OFFLINE to CCR, otherwise similar to REPORTED. Mid: Server will not be included in parent.config files for its edge caches",
- "name": "ADMIN_DOWN"
- },
{
"description": "Edge: 12M will not include caches in this state in CCR config files. Mid: N/A for now",
"name": "CCR_IGNORE"
},
- {
- "description": "Pre Production. Not active in any configuration.",
- "name": "PRE_PROD"
- },
{
"name": "TEST_NULL_DESCRIPTION"
}
diff --git a/traffic_ops/testing/api/v2/todb_test.go b/traffic_ops/testing/api/v2/todb_test.go
index d8ea4870b0..887bbcdb78 100644
--- a/traffic_ops/testing/api/v2/todb_test.go
+++ b/traffic_ops/testing/api/v2/todb_test.go
@@ -283,7 +283,7 @@ func Teardown(db *sql.DB) error {
DELETE FROM cachegroup;
DELETE FROM coordinate;
DELETE FROM type;
- DELETE FROM status;
+ DELETE FROM status s WHERE s.name NOT IN ('OFFLINE', 'ONLINE', 'PRE_PROD', 'ADMIN_DOWN', 'REPORTED');
DELETE FROM snapshot;
DELETE FROM cdn;
DELETE FROM service_category;
diff --git a/traffic_ops/testing/api/v3/statuses_test.go b/traffic_ops/testing/api/v3/statuses_test.go
index db095c6c83..b5ed2b1c7d 100644
--- a/traffic_ops/testing/api/v3/statuses_test.go
+++ b/traffic_ops/testing/api/v3/statuses_test.go
@@ -47,27 +47,31 @@ func TestStatuses(t *testing.T) {
}
func UpdateTestStatusesWithHeaders(t *testing.T, header http.Header) {
- if len(testData.Statuses) > 0 {
- firstStatus := testData.Statuses[0]
- if firstStatus.Name == nil {
- t.Fatal("cannot update test statuses: first test data status must have a name")
- }
+ if len(testData.Statuses) < 1 {
+ t.Fatal("Need at least one Status to test updating a status with an HTTP header")
+ }
- // Retrieve the Status by name so we can get the id for the Update
- resp, _, err := TOSession.GetStatusByNameWithHdr(*firstStatus.Name, header)
- if err != nil {
- t.Errorf("cannot GET Status by name: %v - %v", firstStatus.Name, err)
+ for _, status := range testData.Statuses {
+ if status.Name == nil {
+ t.Fatal("cannot update test statuses: test data status must have a name")
}
- if len(resp) > 0 {
- remoteStatus := resp[0]
- expectedStatusDesc := "new description"
- remoteStatus.Description = expectedStatusDesc
- _, reqInf, err := TOSession.UpdateStatusByIDWithHdr(remoteStatus.ID, remoteStatus, header)
- if err == nil {
- t.Errorf("Expected error about precondition failed, but got none")
+ if !tc.IsReservedStatus(*status.Name) {
+ // Retrieve the Status by name so we can get the id for the Update
+ resp, _, err := TOSession.GetStatusByNameWithHdr(*status.Name, header)
+ if err != nil {
+ t.Errorf("cannot GET Status by name: %s - %v", *status.Name, err)
}
- if reqInf.StatusCode != http.StatusPreconditionFailed {
- t.Errorf("Expected status code 412, got %v", reqInf.StatusCode)
+ if len(resp) > 0 {
+ remoteStatus := resp[0]
+ expectedStatusDesc := "new description"
+ remoteStatus.Description = expectedStatusDesc
+ _, reqInf, err := TOSession.UpdateStatusByIDWithHdr(remoteStatus.ID, remoteStatus, header)
+ if err == nil {
+ t.Errorf("Expected error about precondition failed, but got none")
+ }
+ if reqInf.StatusCode != http.StatusPreconditionFailed {
+ t.Errorf("Expected status code 412, got %v", reqInf.StatusCode)
+ }
}
}
}
@@ -125,15 +129,13 @@ func GetTestStatusesIMS(t *testing.T) {
}
func CreateTestStatuses(t *testing.T) {
-
for _, status := range testData.Statuses {
resp, _, err := TOSession.CreateStatusNullable(status)
t.Log("Response: ", resp)
if err != nil {
- t.Errorf("could not CREATE types: %v", err)
+ t.Errorf("could not CREATE status: %v", err)
}
}
-
}
func SortTestStatuses(t *testing.T) {
@@ -156,36 +158,41 @@ func SortTestStatuses(t *testing.T) {
}
func UpdateTestStatuses(t *testing.T) {
+ for _, status := range testData.Statuses {
+ if status.Name == nil {
+ t.Fatal("cannot update test statuses: test data status must have a name")
+ }
+ // Retrieve the Status by name so we can get the id for the Update
+ resp, _, err := TOSession.GetStatusByName(*status.Name)
+ if err != nil {
+ t.Errorf("cannot GET Status by name: %s - %v", *status.Name, err)
+ }
+ remoteStatus := resp[0]
+ expectedStatusDesc := "new description"
+ remoteStatus.Description = expectedStatusDesc
+ var alert tc.Alerts
+ alert, _, err = TOSession.UpdateStatusByID(remoteStatus.ID, remoteStatus)
- firstStatus := testData.Statuses[0]
- if firstStatus.Name == nil {
- t.Fatal("cannot update test statuses: first test data status must have a name")
- }
-
- // Retrieve the Status by name so we can get the id for the Update
- resp, _, err := TOSession.GetStatusByName(*firstStatus.Name)
- if err != nil {
- t.Errorf("cannot GET Status by name: %v - %v", firstStatus.Name, err)
- }
- remoteStatus := resp[0]
- expectedStatusDesc := "new description"
- remoteStatus.Description = expectedStatusDesc
- var alert tc.Alerts
- alert, _, err = TOSession.UpdateStatusByID(remoteStatus.ID, remoteStatus)
- if err != nil {
- t.Errorf("cannot UPDATE Status by id: %v - %v", err, alert)
- }
+ if tc.IsReservedStatus(*status.Name) {
+ if err == nil {
+ t.Errorf("expected an error about while updating a reserved status, but got nothing")
+ }
+ } else {
+ if err != nil {
+ t.Errorf("cannot UPDATE Status by id: %d, err: %v - %v", remoteStatus.ID, err, alert)
+ }
- // Retrieve the Status to check Status name got updated
- resp, _, err = TOSession.GetStatusByID(remoteStatus.ID)
- if err != nil {
- t.Errorf("cannot GET Status by ID: %v - %v", firstStatus.Description, err)
- }
- respStatus := resp[0]
- if respStatus.Description != expectedStatusDesc {
- t.Errorf("results do not match actual: %s, expected: %s", respStatus.Name, expectedStatusDesc)
+ // Retrieve the Status to check Status name got updated
+ resp, _, err = TOSession.GetStatusByID(remoteStatus.ID)
+ if err != nil {
+ t.Errorf("cannot GET Status by ID: %d - %v", remoteStatus.ID, err)
+ }
+ respStatus := resp[0]
+ if respStatus.Description != expectedStatusDesc {
+ t.Errorf("results do not match actual: %s, expected: %s", respStatus.Name, expectedStatusDesc)
+ }
+ }
}
-
}
func GetTestStatuses(t *testing.T) {
@@ -205,27 +212,27 @@ func DeleteTestStatuses(t *testing.T) {
for _, status := range testData.Statuses {
if status.Name == nil {
- t.Fatal("cannot get ftest statuses: test data statuses must have names")
+ t.Fatal("cannot get test statuses: test data statuses must have names")
}
// Retrieve the Status by name so we can get the id for the Update
resp, _, err := TOSession.GetStatusByName(*status.Name)
if err != nil {
- t.Errorf("cannot GET Status by name: %v - %v", status.Name, err)
+ t.Errorf("cannot GET Status by name: %s - %v", *status.Name, err)
}
respStatus := resp[0]
delResp, _, err := TOSession.DeleteStatusByID(respStatus.ID)
if err != nil {
- t.Errorf("cannot DELETE Status by name: %v - %v", err, delResp)
+ t.Errorf("cannot DELETE Status by ID: %v - %v", err, delResp)
}
// Retrieve the Status to see if it got deleted
- types, _, err := TOSession.GetStatusByName(*status.Name)
+ statuses, _, err := TOSession.GetStatusByName(*status.Name)
if err != nil {
- t.Errorf("error deleting Status name: %s", err.Error())
+ t.Errorf("error getting status by name: %s, err: %v", *status.Name, err)
}
- if len(types) > 0 {
+ if len(statuses) > 0 {
t.Errorf("expected Status name: %s to be deleted", *status.Name)
}
}
diff --git a/traffic_ops/testing/api/v3/tc-fixtures.json b/traffic_ops/testing/api/v3/tc-fixtures.json
index d9b962a512..39671def48 100644
--- a/traffic_ops/testing/api/v3/tc-fixtures.json
+++ b/traffic_ops/testing/api/v3/tc-fixtures.json
@@ -4785,30 +4785,10 @@
}
],
"statuses": [
- {
- "description": "Edge: Puts server in CCR config file in this state, but CCR will never route traffic to it. Mid: Server will not be included in parent.config files for its edge caches",
- "name": "OFFLINE"
- },
- {
- "description": "Edge: Puts server in CCR config file in this state, and CCR will always route traffic to it. Mid: Server will be included in parent.config files for its edges",
- "name": "ONLINE"
- },
- {
- "description": "Edge: Puts server in CCR config file in this state, and CCR will adhere to the health protocol. Mid: N/A for now",
- "name": "REPORTED"
- },
- {
- "description": "Temporary down. Edge: XMPP client will send status OFFLINE to CCR, otherwise similar to REPORTED. Mid: Server will not be included in parent.config files for its edge caches",
- "name": "ADMIN_DOWN"
- },
{
"description": "Edge: 12M will not include caches in this state in CCR config files. Mid: N/A for now",
"name": "CCR_IGNORE"
},
- {
- "description": "Pre Production. Not active in any configuration.",
- "name": "PRE_PROD"
- },
{
"name": "TEST_NULL_DESCRIPTION"
}
diff --git a/traffic_ops/testing/api/v3/todb_test.go b/traffic_ops/testing/api/v3/todb_test.go
index 26a7539cc4..f42ae00ad4 100644
--- a/traffic_ops/testing/api/v3/todb_test.go
+++ b/traffic_ops/testing/api/v3/todb_test.go
@@ -285,7 +285,7 @@ func Teardown(db *sql.DB) error {
DELETE FROM cachegroup;
DELETE FROM coordinate;
DELETE FROM type;
- DELETE FROM status;
+ DELETE FROM status s WHERE s.name NOT IN ('OFFLINE', 'ONLINE', 'PRE_PROD', 'ADMIN_DOWN', 'REPORTED');
DELETE FROM snapshot;
DELETE FROM cdn;
DELETE FROM service_category;
diff --git a/traffic_ops/testing/api/v4/statuses_test.go b/traffic_ops/testing/api/v4/statuses_test.go
index 106d5ca112..90958e94e5 100644
--- a/traffic_ops/testing/api/v4/statuses_test.go
+++ b/traffic_ops/testing/api/v4/statuses_test.go
@@ -23,6 +23,7 @@ import (
"time"
"github.com/apache/trafficcontrol/lib/go-rfc"
+ "github.com/apache/trafficcontrol/lib/go-tc"
client "github.com/apache/trafficcontrol/traffic_ops/v4-client"
)
@@ -52,31 +53,33 @@ func UpdateTestStatusesWithHeaders(t *testing.T, header http.Header) {
t.Fatal("Need at least one Status to test updating a status with an HTTP header")
}
- firstStatus := testData.Statuses[0]
- if firstStatus.Name == nil {
- t.Fatal("cannot update test statuses: first test data status must have a name")
- }
-
- // Retrieve the Status by name so we can get the id for the Update
- opts := client.NewRequestOptions()
- opts.Header = header
- opts.QueryParameters.Set("name", *firstStatus.Name)
- resp, _, err := TOSession.GetStatuses(opts)
- if err != nil {
- t.Errorf("cannot get Status by name '%s': %v - alerts %+v", *firstStatus.Name, err, resp.Alerts)
- }
- if len(resp.Response) > 0 {
- remoteStatus := resp.Response[0]
- expectedStatusDesc := "new description"
- remoteStatus.Description = expectedStatusDesc
-
- opts.QueryParameters.Del("name")
- _, reqInf, err := TOSession.UpdateStatus(remoteStatus.ID, remoteStatus, opts)
- if err == nil {
- t.Errorf("Expected error about precondition failed, but got none")
+ for _, status := range testData.Statuses {
+ if status.Name == nil {
+ t.Fatal("cannot update test statuses: test data status must have a name")
}
- if reqInf.StatusCode != http.StatusPreconditionFailed {
- t.Errorf("Expected status code 412, got %d", reqInf.StatusCode)
+ if !tc.IsReservedStatus(*status.Name) {
+ // Retrieve the Status by name so we can get the id for the Update
+ opts := client.NewRequestOptions()
+ opts.Header = header
+ opts.QueryParameters.Set("name", *status.Name)
+ resp, _, err := TOSession.GetStatuses(opts)
+ if err != nil {
+ t.Errorf("cannot get Status by name '%s': %v - alerts %+v", *status.Name, err, resp.Alerts)
+ }
+ if len(resp.Response) > 0 {
+ remoteStatus := resp.Response[0]
+ expectedStatusDesc := "new description"
+ remoteStatus.Description = expectedStatusDesc
+
+ opts.QueryParameters.Del("name")
+ _, reqInf, err := TOSession.UpdateStatus(remoteStatus.ID, remoteStatus, opts)
+ if err == nil {
+ t.Errorf("Expected error about precondition failed, but got none")
+ }
+ if reqInf.StatusCode != http.StatusPreconditionFailed {
+ t.Errorf("Expected status code 412, got %d", reqInf.StatusCode)
+ }
+ }
}
}
}
@@ -148,7 +151,6 @@ func CreateTestStatuses(t *testing.T) {
t.Errorf("could not create Status: %v - alerts: %+v", err, resp.Alerts)
}
}
-
}
func SortTestStatuses(t *testing.T) {
@@ -171,45 +173,50 @@ func UpdateTestStatuses(t *testing.T) {
if len(testData.Statuses) < 1 {
t.Fatal("Need at least one Status to test updating a Status")
}
- firstStatus := testData.Statuses[0]
- if firstStatus.Name == nil {
- t.Fatal("cannot update test statuses: first test data status must have a name")
- }
-
- // Retrieve the Status by name so we can get the id for the Update
- opts := client.NewRequestOptions()
- opts.QueryParameters.Set("name", *firstStatus.Name)
- resp, _, err := TOSession.GetStatuses(opts)
- if err != nil {
- t.Errorf("cannot get Status by name '%s': %v - alerts: %+v", *firstStatus.Name, err, resp.Alerts)
- }
- if len(resp.Response) != 1 {
- t.Fatalf("Expected exactly one Status to exist with name '%s', found: %d", *firstStatus.Name, len(resp.Response))
- }
- remoteStatus := resp.Response[0]
- expectedStatusDesc := "new description"
- remoteStatus.Description = expectedStatusDesc
-
- alert, _, err := TOSession.UpdateStatus(remoteStatus.ID, remoteStatus, client.RequestOptions{})
- if err != nil {
- t.Errorf("cannot update Status: %v - alerts: %+v", err, alert.Alerts)
- }
-
- // Retrieve the Status to check Status name got updated
- opts.QueryParameters.Del("name")
- opts.QueryParameters.Set("id", strconv.Itoa(remoteStatus.ID))
- resp, _, err = TOSession.GetStatuses(opts)
- if err != nil {
- t.Errorf("cannot get Status '%s' by ID %d: %v - alerts: %+v", *firstStatus.Name, remoteStatus.ID, err, resp.Alerts)
- }
- if len(resp.Response) != 1 {
- t.Fatalf("Expected exactly one Status to exist with ID %d, found: %d", remoteStatus.ID, len(resp.Response))
- }
- respStatus := resp.Response[0]
- if respStatus.Description != expectedStatusDesc {
- t.Errorf("results do not match actual: %s, expected: %s", respStatus.Name, expectedStatusDesc)
+ for _, status := range testData.Statuses {
+ if status.Name == nil {
+ t.Fatal("cannot update test statuses: test data status must have a name")
+ }
+ // Retrieve the Status by name so we can get the id for the Update
+ opts := client.NewRequestOptions()
+ opts.QueryParameters.Set("name", *status.Name)
+ resp, _, err := TOSession.GetStatuses(opts)
+ if err != nil {
+ t.Errorf("cannot get Status by name '%s': %v - alerts: %+v", *status.Name, err, resp.Alerts)
+ }
+ if len(resp.Response) != 1 {
+ t.Fatalf("Expected exactly one Status to exist with name '%s', found: %d", *status.Name, len(resp.Response))
+ }
+ remoteStatus := resp.Response[0]
+ expectedStatusDesc := "new description"
+ remoteStatus.Description = expectedStatusDesc
+ alert, _, err := TOSession.UpdateStatus(remoteStatus.ID, remoteStatus, client.RequestOptions{})
+
+ if tc.IsReservedStatus(*status.Name) {
+ if err == nil {
+ t.Errorf("expected an error about while updating a reserved status, but got nothing")
+ }
+ } else {
+ if err != nil {
+ t.Errorf("cannot update Status: %v - alerts: %+v", err, alert.Alerts)
+ }
+
+ // Retrieve the Status to check Status name got updated
+ opts.QueryParameters.Del("name")
+ opts.QueryParameters.Set("id", strconv.Itoa(remoteStatus.ID))
+ resp, _, err = TOSession.GetStatuses(opts)
+ if err != nil {
+ t.Errorf("cannot get Status '%s' by ID %d: %v - alerts: %+v", *status.Name, remoteStatus.ID, err, resp.Alerts)
+ }
+ if len(resp.Response) != 1 {
+ t.Fatalf("Expected exactly one Status to exist with ID %d, found: %d", remoteStatus.ID, len(resp.Response))
+ }
+ respStatus := resp.Response[0]
+ if respStatus.Description != expectedStatusDesc {
+ t.Errorf("results do not match actual: %s, expected: %s", respStatus.Name, expectedStatusDesc)
+ }
+ }
}
-
}
func GetTestStatuses(t *testing.T) {
@@ -232,7 +239,6 @@ func DeleteTestStatuses(t *testing.T) {
if status.Name == nil {
t.Fatal("cannot get test statuses: test data statuses must have names")
}
-
// Retrieve the Status by name so we can get the id for the Update
opts.QueryParameters.Set("name", *status.Name)
resp, _, err := TOSession.GetStatuses(opts)
diff --git a/traffic_ops/testing/api/v4/tc-fixtures.json b/traffic_ops/testing/api/v4/tc-fixtures.json
index 632153f725..2956a60cf1 100644
--- a/traffic_ops/testing/api/v4/tc-fixtures.json
+++ b/traffic_ops/testing/api/v4/tc-fixtures.json
@@ -5437,30 +5437,10 @@
}
],
"statuses": [
- {
- "description": "Edge: Puts server in CCR config file in this state, but CCR will never route traffic to it. Mid: Server will not be included in parent.config files for its edge caches",
- "name": "OFFLINE"
- },
- {
- "description": "Edge: Puts server in CCR config file in this state, and CCR will always route traffic to it. Mid: Server will be included in parent.config files for its edges",
- "name": "ONLINE"
- },
- {
- "description": "Edge: Puts server in CCR config file in this state, and CCR will adhere to the health protocol. Mid: N/A for now",
- "name": "REPORTED"
- },
- {
- "description": "Temporary down. Edge: XMPP client will send status OFFLINE to CCR, otherwise similar to REPORTED. Mid: Server will not be included in parent.config files for its edge caches",
- "name": "ADMIN_DOWN"
- },
{
"description": "Edge: 12M will not include caches in this state in CCR config files. Mid: N/A for now",
"name": "CCR_IGNORE"
},
- {
- "description": "Pre Production. Not active in any configuration.",
- "name": "PRE_PROD"
- },
{
"name": "TEST_NULL_DESCRIPTION"
}
diff --git a/traffic_ops/testing/api/v4/todb_test.go b/traffic_ops/testing/api/v4/todb_test.go
index 697f35df36..7f9104a8a3 100644
--- a/traffic_ops/testing/api/v4/todb_test.go
+++ b/traffic_ops/testing/api/v4/todb_test.go
@@ -417,7 +417,7 @@ func Teardown(db *sql.DB) error {
DELETE FROM cachegroup;
DELETE FROM coordinate;
DELETE FROM type;
- DELETE FROM status;
+ DELETE FROM status s WHERE s.name NOT IN ('OFFLINE', 'ONLINE', 'PRE_PROD', 'ADMIN_DOWN', 'REPORTED');
DELETE FROM snapshot;
DELETE FROM cdn;
DELETE FROM service_category;
diff --git a/traffic_ops/traffic_ops_golang/status/statuses.go b/traffic_ops/traffic_ops_golang/status/statuses.go
index f5f75d5940..875edce434 100644
--- a/traffic_ops/traffic_ops_golang/status/statuses.go
+++ b/traffic_ops/traffic_ops_golang/status/statuses.go
@@ -119,9 +119,29 @@ func (st *TOStatus) Read(h http.Header, useIMS bool) ([]interface{}, error, erro
return readVals, nil, nil, errCode, maxTime
}
-func (st *TOStatus) Update(h http.Header) (error, error, int) { return api.GenericUpdate(h, st) }
-func (st *TOStatus) Create() (error, error, int) { return api.GenericCreate(st) }
-func (st *TOStatus) Delete() (error, error, int) { return api.GenericDelete(st) }
+func (st *TOStatus) Update(h http.Header) (error, error, int) {
+ var statusName string
+ err := st.APIInfo().Tx.QueryRow(`SELECT name from status WHERE id = $1`, *st.ID).Scan(&statusName)
+ if err != nil {
+ return nil, fmt.Errorf("error querying status name from ID: %w", err), http.StatusInternalServerError
+ }
+ if tc.IsReservedStatus(statusName) {
+ return fmt.Errorf("cannot modify %s status", statusName), nil, http.StatusForbidden
+ }
+ return api.GenericUpdate(h, st)
+}
+func (st *TOStatus) Create() (error, error, int) { return api.GenericCreate(st) }
+func (st *TOStatus) Delete() (error, error, int) {
+ var statusName string
+ err := st.APIInfo().Tx.QueryRow(`SELECT name from status WHERE id = $1`, *st.ID).Scan(&statusName)
+ if err != nil {
+ return nil, fmt.Errorf("error querying status name from ID: %w", err), http.StatusInternalServerError
+ }
+ if tc.IsReservedStatus(statusName) {
+ return fmt.Errorf("cannot delete %s status", statusName), nil, http.StatusForbidden
+ }
+ return api.GenericDelete(st)
+}
func selectQuery() string {
return `