This is an automated email from the ASF dual-hosted git repository.
shamrick 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 c1f82c4000 Api v5 should return rfc3339 timestamps for static dns
entries (#7740)
c1f82c4000 is described below
commit c1f82c4000e28a101756e80a260bac85ca7a93c8
Author: Srijeet Chatterjee <[email protected]>
AuthorDate: Thu Aug 24 12:16:32 2023 -0600
Api v5 should return rfc3339 timestamps for static dns entries (#7740)
* wip
* tests passing
* Adding changelog and docs
* cleanup
* remove unneeded commit
---
CHANGELOG.md | 2 +-
docs/source/api/v5/staticdnsentries.rst | 12 +-
lib/go-tc/staticdnsentry.go | 70 ++++
traffic_ops/testing/api/v5/cdn_locks_test.go | 8 +-
.../testing/api/v5/staticdnsentries_test.go | 117 +++----
traffic_ops/testing/api/v5/traffic_control_test.go | 2 +-
traffic_ops/traffic_ops_golang/routing/routes.go | 8 +-
.../staticdnsentry/staticdnsentry.go | 382 +++++++++++++++++++++
traffic_ops/v5-client/staticdnsentry.go | 42 +--
9 files changed, 550 insertions(+), 93 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1a46e6c808..783e8a05e0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -157,7 +157,7 @@ The format is based on [Keep a
Changelog](http://keepachangelog.com/en/1.0.0/).
- [#7698](https://github.com/apache/trafficcontrol/pull/7698) *Traffic Ops*
Fixes `region` v5 apis to respond with `RFC3339` date/time Format.
- [#7686](https://github.com/apache/trafficcontrol/pull/7686) *Traffic Ops*
Fixes secured parameters being visible when role has proper permissions.
- [#7697](https://github.com/apache/trafficcontrol/pull/7697) *Traffic Ops*
Fixes `iloPassword` and `xmppPassword` checking for priv-level instead of using
permissions.
-
+- [#7740](https://github.com/apache/trafficcontrol/pull/7740) *Traffic Ops*
Fixes `staticDNSEntries` v5 apis to respond with `RFC3339` date/time Format.
### Removed
- [#7271](https://github.com/apache/trafficcontrol/pull/7271) Remove
components in `infrastructre/docker/`, not in use as cdn-in-a-box performs the
same functionality.
- [#7271](https://github.com/apache/trafficcontrol/pull/7271)
Remove`misc/jira_github_issue_import.py`, the project does not use JIRA.
diff --git a/docs/source/api/v5/staticdnsentries.rst
b/docs/source/api/v5/staticdnsentries.rst
index fb92ee4687..346e183017 100644
--- a/docs/source/api/v5/staticdnsentries.rst
+++ b/docs/source/api/v5/staticdnsentries.rst
@@ -89,7 +89,7 @@ Response Structure
:deliveryserviceId: The integral, unique identifier of a :term:`Delivery
Service` under the domain of which this static DNS entry shall be active
:host: If ``typeId`` identifies a ``CNAME`` type record, this is
an alias for the CNAME of the server, otherwise it is the Fully Qualified
Domain Name (FQDN) which shall resolve to ``address``
:id: An integral, unique identifier for this static DNS entry
-:lastUpdated: The date and time at which this static DNS entry was last
updated
+:lastUpdated: The date and time at which this static DNS entry was last
updated, in :rfc:`3339` format
:ttl: The :abbr:`TTL (Time To Live)` of this static DNS entry in
seconds
:type: The name of the type of this static DNS entry
:typeId: The integral, unique identifier of the :term:`Type` of
this static DNS entry
@@ -118,7 +118,7 @@ Response Structure
"deliveryserviceId": 1,
"host": "test",
"id": 2,
- "lastUpdated": "2018-12-10 19:59:56+00",
+ "lastUpdated": "2018-12-10T19:59:56-06:00",
"ttl": 300,
"type": "CNAME_RECORD",
"typeId": 41
@@ -180,7 +180,7 @@ Response Structure
:deliveryserviceId: The integral, unique identifier of a :term:`Delivery
Service` under the domain of which this static DNS entry shall be active
:host: If ``typeId`` identifies a ``CNAME`` type record, this is
an alias for the CNAME of the server, otherwise it is the Fully Qualified
Domain Name (FQDN) which shall resolve to ``address``
:id: An integral, unique identifier for this static DNS entry
-:lastUpdated: The date and time at which this static DNS entry was last
updated
+:lastUpdated: The date and time at which this static DNS entry was last
updated, in :rfc:`3339` format
:ttl: The :abbr:`TTL (Time To Live)` of this static DNS entry in
seconds
:type: The name of the :term:`Type` of this static DNS entry
:typeId: The integral, unique identifier of the :term:`Type` of
this static DNS entry
@@ -214,7 +214,7 @@ Response Structure
"deliveryserviceId": 1,
"host": "test",
"id": 2,
- "lastUpdated": "2018-12-10 19:54:19+00",
+ "lastUpdated": "2018-12-10T19:54:19-06:00",
"ttl": 300,
"type": "CNAME_RECORD",
"typeId": 41
@@ -283,7 +283,7 @@ Response Structure
:deliveryserviceId: The integral, unique identifier of a :term:`Delivery
Service` under the domain of which this static DNS entry shall be active
:host: If ``typeId`` identifies a ``CNAME`` type record, this is
an alias for the CNAME of the server, otherwise it is the :abbr:`FQDN (Fully
Qualified Domain Name)` which shall resolve to ``address``
:id: An integral, unique identifier for this static DNS entry
-:lastUpdated: The date and time at which this static DNS entry was last
updated
+:lastUpdated: The date and time at which this static DNS entry was last
updated, in :rfc:`3339` format
:ttl: The :abbr:`TTL (Time To Live)` of this static DNS entry in
seconds
:type: The name of the :term:`Type` of this static DNS entry
:typeId: The integral, unique identifier of the :term:`Type` of
this static DNS entry
@@ -317,7 +317,7 @@ Response Structure
"deliveryserviceId": 1,
"host": "test",
"id": 2,
- "lastUpdated": "2018-12-10 19:59:56+00",
+ "lastUpdated": "2018-12-10T19:59:56-06:00",
"ttl": 300,
"type": "CNAME_RECORD",
"typeId": 41
diff --git a/lib/go-tc/staticdnsentry.go b/lib/go-tc/staticdnsentry.go
index c867a89d77..a7d9ca6c61 100644
--- a/lib/go-tc/staticdnsentry.go
+++ b/lib/go-tc/staticdnsentry.go
@@ -1,5 +1,7 @@
package tc
+import "time"
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -25,6 +27,74 @@ type StaticDNSEntriesResponse struct {
Alerts
}
+// StaticDNSEntriesResponseV5 is a list of StaticDNSEntry as a response, for
api version 5.0., for the latest
+// minor version of 5.x.
+type StaticDNSEntriesResponseV5 = StaticDNSEntriesResponseV50
+
+// StaticDNSEntriesResponseV50 is a list of StaticDNSEntry as a response, for
api version 5.0.
+type StaticDNSEntriesResponseV50 struct {
+ Response []StaticDNSEntryV5 `json:"response"`
+ Alerts
+}
+
+// StaticDNSEntryV5 holds information about a static DNS entry, for the latest
minor version of 5.x.
+type StaticDNSEntryV5 = StaticDNSEntryV50
+
+// StaticDNSEntryV50 holds information about a static DNS entry, for api
version 5.0.
+type StaticDNSEntryV50 struct {
+
+ // The static IP Address or fqdn of the static dns entry
+ //
+ // required: true
+ Address *string `json:"address" db:"address"`
+
+ // The Cachegroup Name associated
+ //
+ CacheGroupName *string `json:"cachegroup" db:"cachegroup"`
+
+ // The Cachegroup ID associated
+ //
+ CacheGroupID *int `json:"cachegroupId" db:"cachegroup_id"`
+
+ // The DeliveryService associated
+ //
+ DeliveryService *string `json:"deliveryservice" db:"dsname"`
+
+ // The DeliveryService associated
+ //
+ // required: true
+ DeliveryServiceID *int `json:"deliveryserviceId"
db:"deliveryservice_id"`
+
+ // The host of the static dns entry
+ //
+ // required: true
+ Host *string `json:"host" db:"host"`
+
+ // ID of the StaticDNSEntry
+ //
+ // required: true
+ ID *int `json:"id" db:"id"`
+
+ // LastUpdated
+ //
+ LastUpdated *time.Time `json:"lastUpdated" db:"last_updated"`
+
+ // The Time To Live for the static dns entry
+ //
+ // required: true
+ TTL *int64 `json:"ttl" db:"ttl"`
+
+ // The type of the static DNS entry
+ //
+ // enum: ["A_RECORD", "AAAA_RECORD", "CNAME_RECORD"]
+ Type *string `json:"type"`
+
+ // The type id of the static DNS entry
+ //
+ // required: true
+ TypeID *int `json:"typeId" db:"type_id"`
+}
+
// StaticDNSEntry holds information about a static DNS entry.
type StaticDNSEntry struct {
diff --git a/traffic_ops/testing/api/v5/cdn_locks_test.go
b/traffic_ops/testing/api/v5/cdn_locks_test.go
index 04e36a2293..c3a2708448 100644
--- a/traffic_ops/testing/api/v5/cdn_locks_test.go
+++ b/traffic_ops/testing/api/v5/cdn_locks_test.go
@@ -463,6 +463,7 @@ func TestCDNLocks(t *testing.T) {
"deliveryservice":
"basic-ds-in-cdn2",
"host": "host2",
"type": "A_RECORD",
+ "ttl": int64(0),
},
Expectations:
utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
},
@@ -475,6 +476,7 @@ func TestCDNLocks(t *testing.T) {
"deliveryservice":
"basic-ds-in-cdn2",
"host": "host2",
"type": "A_RECORD",
+ "ttl": int64(0),
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusForbidden)),
},
@@ -680,18 +682,20 @@ func TestCDNLocks(t *testing.T) {
}
},
"STATIC DNS ENTRIES POST":
func(t *testing.T) {
- staticDNSEntry :=
tc.StaticDNSEntry{}
+ staticDNSEntry :=
tc.StaticDNSEntryV5{}
err =
json.Unmarshal(dat, &staticDNSEntry)
assert.NoError(t, err,
"Error occurred when unmarshalling request body: %v", err)
+ staticDNSEntry.TTL =
util.Ptr(int64(0))
alerts, reqInf, err :=
testCase.ClientSession.CreateStaticDNSEntry(staticDNSEntry,
testCase.RequestOpts)
for _, check := range
testCase.Expectations {
check(t,
reqInf, nil, alerts, err)
}
},
"STATIC DNS ENTRIES PUT":
func(t *testing.T) {
- staticDNSEntry :=
tc.StaticDNSEntry{}
+ staticDNSEntry :=
tc.StaticDNSEntryV5{}
err =
json.Unmarshal(dat, &staticDNSEntry)
assert.NoError(t, err,
"Error occurred when unmarshalling request body: %v", err)
+ staticDNSEntry.TTL =
util.Ptr(int64(0))
alerts, reqInf, err :=
testCase.ClientSession.UpdateStaticDNSEntry(testCase.EndpointID(),
staticDNSEntry, testCase.RequestOpts)
for _, check := range
testCase.Expectations {
check(t,
reqInf, nil, alerts, err)
diff --git a/traffic_ops/testing/api/v5/staticdnsentries_test.go
b/traffic_ops/testing/api/v5/staticdnsentries_test.go
index 3a57e58baa..975b1b2f1d 100644
--- a/traffic_ops/testing/api/v5/staticdnsentries_test.go
+++ b/traffic_ops/testing/api/v5/staticdnsentries_test.go
@@ -24,6 +24,7 @@ import (
"github.com/apache/trafficcontrol/lib/go-rfc"
"github.com/apache/trafficcontrol/lib/go-tc"
+ "github.com/apache/trafficcontrol/lib/go-util"
"github.com/apache/trafficcontrol/lib/go-util/assert"
"github.com/apache/trafficcontrol/traffic_ops/testing/api/utils"
"github.com/apache/trafficcontrol/traffic_ops/toclientlib"
@@ -37,7 +38,7 @@ func TestStaticDNSEntries(t *testing.T) {
currentTimeRFC := currentTime.Format(time.RFC1123)
tomorrow := currentTime.AddDate(0, 0, 1).Format(time.RFC1123)
- methodTests := utils.TestCase[client.Session,
client.RequestOptions, tc.StaticDNSEntry]{
+ methodTests := utils.TestCase[client.Session,
client.RequestOptions, tc.StaticDNSEntryV5]{
"GET": {
"NOT MODIFIED when NO CHANGES made": {
ClientSession: TOSession,
@@ -60,13 +61,13 @@ func TestStaticDNSEntries(t *testing.T) {
"OK when VALID request": {
EndpointID: GetStaticDNSEntryID(t,
"host2"),
ClientSession: TOSession,
- RequestBody: tc.StaticDNSEntry{
- Address: "192.168.0.2",
- CacheGroupName: "cachegroup2",
- DeliveryService: "ds2",
- Host: "host2",
- Type: "A_RECORD",
- TTL: 10,
+ RequestBody: tc.StaticDNSEntryV5{
+ Address:
util.Ptr("192.168.0.2"),
+ CacheGroupName:
util.Ptr("cachegroup2"),
+ DeliveryService:
util.Ptr("ds2"),
+ Host:
util.Ptr("host2"),
+ Type:
util.Ptr("A_RECORD"),
+ TTL:
util.Ptr(int64(10)),
},
Expectations:
utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK),
validateStaticDNSEntriesUpdateCreateFields("host2",
map[string]interface{}{"Address": "192.168.0.2"})),
@@ -74,52 +75,52 @@ func TestStaticDNSEntries(t *testing.T) {
"BAD REQUEST when INVALID IPV4 ADDRESS for
A_RECORD": {
EndpointID: GetStaticDNSEntryID(t,
"host2"),
ClientSession: TOSession,
- RequestBody: tc.StaticDNSEntry{
- Address:
"test.testdomain.net.",
- CacheGroupName: "cachegroup2",
- DeliveryService: "ds2",
- Host: "host2",
- Type: "A_RECORD",
- TTL: 10,
+ RequestBody: tc.StaticDNSEntryV5{
+ Address:
util.Ptr("test.testdomain.net."),
+ CacheGroupName:
util.Ptr("cachegroup2"),
+ DeliveryService:
util.Ptr("ds2"),
+ Host:
util.Ptr("host2"),
+ Type:
util.Ptr("A_RECORD"),
+ TTL:
util.Ptr(int64(10)),
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when INVALID DNS for
CNAME_RECORD": {
EndpointID: GetStaticDNSEntryID(t,
"host1"),
ClientSession: TOSession,
- RequestBody: tc.StaticDNSEntry{
- Address:
"2001:0db8:85a3:0000:0000:8a2e:0370:7334",
- CacheGroupName: "cachegroup1",
- DeliveryService: "ds1",
- Host: "host1",
- Type: "CNAME_RECORD",
- TTL: 0,
+ RequestBody: tc.StaticDNSEntryV5{
+ Address:
util.Ptr("2001:0db8:85a3:0000:0000:8a2e:0370:7334"),
+ CacheGroupName:
util.Ptr("cachegroup1"),
+ DeliveryService:
util.Ptr("ds1"),
+ Host:
util.Ptr("host1"),
+ Type:
util.Ptr("CNAME_RECORD"),
+ TTL:
util.Ptr(int64(0)),
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when MISSING TRAILING PERIOD for
CNAME_RECORD": {
EndpointID: GetStaticDNSEntryID(t,
"host1"),
ClientSession: TOSession,
- RequestBody: tc.StaticDNSEntry{
- Address: "cdn.test.com",
- CacheGroupName: "cachegroup1",
- DeliveryService: "ds1",
- Host: "host1",
- Type: "CNAME_RECORD",
- TTL: 0,
+ RequestBody: tc.StaticDNSEntryV5{
+ Address:
util.Ptr("cdn.test.com"),
+ CacheGroupName:
util.Ptr("cachegroup1"),
+ DeliveryService:
util.Ptr("ds1"),
+ Host:
util.Ptr("host1"),
+ Type:
util.Ptr("CNAME_RECORD"),
+ TTL:
util.Ptr(int64(0)),
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
"BAD REQUEST when INVALID IPV6 ADDRESS for
AAAA_RECORD": {
EndpointID: GetStaticDNSEntryID(t,
"host3"),
ClientSession: TOSession,
- RequestBody: tc.StaticDNSEntry{
- Address: "192.168.0.1",
- CacheGroupName: "cachegroup2",
- DeliveryService: "ds1",
- Host: "host3",
- TTL: 10,
- Type: "AAAA_RECORD",
+ RequestBody: tc.StaticDNSEntryV5{
+ Address:
util.Ptr("192.168.0.1"),
+ CacheGroupName:
util.Ptr("cachegroup2"),
+ DeliveryService:
util.Ptr("ds1"),
+ Host:
util.Ptr("host3"),
+ TTL:
util.Ptr(int64(10)),
+ Type:
util.Ptr("AAAA_RECORD"),
},
Expectations:
utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
},
@@ -127,26 +128,26 @@ func TestStaticDNSEntries(t *testing.T) {
EndpointID: GetStaticDNSEntryID(t,
"host3"),
ClientSession: TOSession,
RequestOpts:
client.RequestOptions{Header: http.Header{rfc.IfUnmodifiedSince:
{currentTimeRFC}}},
- RequestBody: tc.StaticDNSEntry{
- Address:
"2001:0db8:85a3:0000:0000:8a2e:0370:7334",
- CacheGroupName: "cachegroup2",
- DeliveryService: "ds1",
- Host: "host3",
- TTL: 10,
- Type: "AAAA_RECORD",
+ RequestBody: tc.StaticDNSEntryV5{
+ Address:
util.Ptr("2001:0db8:85a3:0000:0000:8a2e:0370:7334"),
+ CacheGroupName:
util.Ptr("cachegroup2"),
+ DeliveryService:
util.Ptr("ds1"),
+ Host:
util.Ptr("host3"),
+ TTL:
util.Ptr(int64(10)),
+ Type:
util.Ptr("AAAA_RECORD"),
},
Expectations:
utils.CkRequest(utils.HasError(),
utils.HasStatus(http.StatusPreconditionFailed)),
},
"PRECONDITION FAILED when updating with IFMATCH
ETAG Header": {
EndpointID: GetStaticDNSEntryID(t,
"host3"),
ClientSession: TOSession,
- RequestBody: tc.StaticDNSEntry{
- Address:
"2001:0db8:85a3:0000:0000:8a2e:0370:7334",
- CacheGroupName: "cachegroup2",
- DeliveryService: "ds1",
- Host: "host3",
- TTL: 10,
- Type: "AAAA_RECORD",
+ RequestBody: tc.StaticDNSEntryV5{
+ Address:
util.Ptr("2001:0db8:85a3:0000:0000:8a2e:0370:7334"),
+ CacheGroupName:
util.Ptr("cachegroup2"),
+ DeliveryService:
util.Ptr("ds1"),
+ Host:
util.Ptr("host3"),
+ TTL:
util.Ptr(int64(10)),
+ Type:
util.Ptr("AAAA_RECORD"),
},
RequestOpts:
client.RequestOptions{Header: http.Header{rfc.IfMatch:
{rfc.ETag(currentTime)}}},
Expectations:
utils.CkRequest(utils.HasError(),
utils.HasStatus(http.StatusPreconditionFailed)),
@@ -196,14 +197,14 @@ func TestStaticDNSEntries(t *testing.T) {
func validateStaticDNSEntriesFields(expectedResp map[string]interface{})
utils.CkReqFunc {
return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _
tc.Alerts, _ error) {
assert.RequireNotNil(t, resp, "Expected Static DNS Entries
response to not be nil.")
- staticDNSEntriesResp := resp.([]tc.StaticDNSEntry)
+ staticDNSEntriesResp := resp.([]tc.StaticDNSEntryV5)
for field, expected := range expectedResp {
for _, staticDNSEntry := range staticDNSEntriesResp {
switch field {
case "Address":
- assert.Equal(t, expected,
staticDNSEntry.Address, "Expected Address to be %v, but got %s", expected,
staticDNSEntry.Address)
+ assert.Equal(t, expected,
*staticDNSEntry.Address, "Expected Address to be %v, but got %s", expected,
*staticDNSEntry.Address)
case "Host":
- assert.Equal(t, expected,
staticDNSEntry.Host, "Expected Host to be %v, but got %s", expected,
staticDNSEntry.Host)
+ assert.Equal(t, expected,
*staticDNSEntry.Host, "Expected Host to be %v, but got %s", expected,
*staticDNSEntry.Host)
default:
t.Errorf("Expected field: %v, does not
exist in response", field)
}
@@ -227,9 +228,9 @@ func validateStaticDNSEntriesSort() utils.CkReqFunc {
return func(t *testing.T, _ toclientlib.ReqInf, resp interface{},
alerts tc.Alerts, _ error) {
assert.RequireNotNil(t, resp, "Expected Static DNS Entries
response to not be nil.")
var staticDNSEntryHosts []string
- staticDNSEntryResp := resp.([]tc.StaticDNSEntry)
+ staticDNSEntryResp := resp.([]tc.StaticDNSEntryV5)
for _, staticDNSEntry := range staticDNSEntryResp {
- staticDNSEntryHosts = append(staticDNSEntryHosts,
staticDNSEntry.Host)
+ staticDNSEntryHosts = append(staticDNSEntryHosts,
*staticDNSEntry.Host)
}
assert.Equal(t, true,
sort.StringsAreSorted(staticDNSEntryHosts), "List is not sorted by their hosts:
%v", staticDNSEntryHosts)
}
@@ -242,7 +243,7 @@ func GetStaticDNSEntryID(t *testing.T, host string) func()
int {
staticDNSEntries, _, err := TOSession.GetStaticDNSEntries(opts)
assert.RequireNoError(t, err, "Get Static DNS Entries Request
failed with error:", err)
assert.RequireEqual(t, 1, len(staticDNSEntries.Response),
"Expected response object length 1, but got %d", len(staticDNSEntries.Response))
- return staticDNSEntries.Response[0].ID
+ return *staticDNSEntries.Response[0].ID
}
}
@@ -258,11 +259,11 @@ func DeleteTestStaticDNSEntries(t *testing.T) {
assert.NoError(t, err, "Cannot get Static DNS Entries: %v - alerts:
%+v", err, staticDNSEntries.Alerts)
for _, staticDNSEntry := range staticDNSEntries.Response {
- alerts, _, err :=
TOSession.DeleteStaticDNSEntry(staticDNSEntry.ID, client.RequestOptions{})
+ alerts, _, err :=
TOSession.DeleteStaticDNSEntry(*staticDNSEntry.ID, client.RequestOptions{})
assert.NoError(t, err, "Unexpected error deleting Static DNS
Entry '%s' (#%d): %v - alerts: %+v", staticDNSEntry.Host, staticDNSEntry.ID,
err, alerts.Alerts)
// Retrieve the Static DNS Entry to see if it got deleted
opts := client.NewRequestOptions()
- opts.QueryParameters.Set("host", staticDNSEntry.Host)
+ opts.QueryParameters.Set("host", *staticDNSEntry.Host)
getStaticDNSEntry, _, err := TOSession.GetStaticDNSEntries(opts)
assert.NoError(t, err, "Error getting Static DNS Entry '%s'
after deletion: %v - alerts: %+v", staticDNSEntry.Host, err,
getStaticDNSEntry.Alerts)
assert.Equal(t, 0, len(getStaticDNSEntry.Response), "Expected
Static DNS Entry '%s' to be deleted, but it was found in Traffic Ops",
staticDNSEntry.Host)
diff --git a/traffic_ops/testing/api/v5/traffic_control_test.go
b/traffic_ops/testing/api/v5/traffic_control_test.go
index 6fa619b368..6112ea16ac 100644
--- a/traffic_ops/testing/api/v5/traffic_control_test.go
+++ b/traffic_ops/testing/api/v5/traffic_control_test.go
@@ -50,7 +50,7 @@ type TrafficControl struct {
ServerCapabilities
[]tc.ServerCapabilityV5 `json:"serverCapabilities"`
ServiceCategories
[]tc.ServiceCategoryV5 `json:"serviceCategories"`
Statuses []tc.StatusV5
`json:"statuses"`
- StaticDNSEntries []tc.StaticDNSEntry
`json:"staticdnsentries"`
+ StaticDNSEntries []tc.StaticDNSEntryV5
`json:"staticdnsentries"`
StatsSummaries []tc.StatsSummaryV5
`json:"statsSummaries"`
Tenants []tc.Tenant
`json:"tenants"`
ServerCheckExtensions
[]tc.ServerCheckExtensionNullable `json:"servercheck_extensions"`
diff --git a/traffic_ops/traffic_ops_golang/routing/routes.go
b/traffic_ops/traffic_ops_golang/routing/routes.go
index 8412bf74f7..7f2c8ecbbd 100644
--- a/traffic_ops/traffic_ops_golang/routing/routes.go
+++ b/traffic_ops/traffic_ops_golang/routing/routes.go
@@ -428,10 +428,10 @@ func Routes(d ServerData) ([]Route, http.Handler, error) {
{Version: api.Version{Major: 5, Minor: 0}, Method:
http.MethodDelete, Path: `service_categories/{name}$`, Handler:
servicecategory.DeleteServiceCategory, RequiredPrivLevel:
auth.PrivLevelOperations, RequiredPermissions:
[]string{"SERVICE-CATEGORY:DELETE", "SERVICE-CATEGORY:READ"}, Authenticated:
Authenticated, Middlewares: nil, ID: 43253822381},
//StaticDNSEntries
- {Version: api.Version{Major: 5, Minor: 0}, Method:
http.MethodGet, Path: `staticdnsentries/?$`, Handler:
api.ReadHandler(&staticdnsentry.TOStaticDNSEntry{}), RequiredPrivLevel:
auth.PrivLevelReadOnly, RequiredPermissions: []string{"STATIC-DN:READ",
"CACHE-GROUP:READ", "DELIVERY-SERVICE:READ"}, Authenticated: Authenticated,
Middlewares: nil, ID: 42893947731},
- {Version: api.Version{Major: 5, Minor: 0}, Method:
http.MethodPut, Path: `staticdnsentries/?$`, Handler:
api.UpdateHandler(&staticdnsentry.TOStaticDNSEntry{}), RequiredPrivLevel:
auth.PrivLevelOperations, RequiredPermissions: []string{"STATIC-DN:UPDATE",
"STATIC-DN:READ", "CACHE-GROUP:READ", "DELIVERY-SERVICE:READ"}, Authenticated:
Authenticated, Middlewares: nil, ID: 44245711131},
- {Version: api.Version{Major: 5, Minor: 0}, Method:
http.MethodPost, Path: `staticdnsentries/?$`, Handler:
api.CreateHandler(&staticdnsentry.TOStaticDNSEntry{}), RequiredPrivLevel:
auth.PrivLevelOperations, RequiredPermissions: []string{"STATIC-DN:CREATE",
"STATIC-DN:READ", "CACHE-GROUP:READ", "DELIVERY-SERVICE:READ"}, Authenticated:
Authenticated, Middlewares: nil, ID: 462914823831},
- {Version: api.Version{Major: 5, Minor: 0}, Method:
http.MethodDelete, Path: `staticdnsentries/?$`, Handler:
api.DeleteHandler(&staticdnsentry.TOStaticDNSEntry{}), RequiredPrivLevel:
auth.PrivLevelOperations, RequiredPermissions: []string{"STATIC-DN:DELETE",
"STATIC-DN:READ", "DELIVERY-SERVICE:READ", "CACHE-GROUP:READ"}, Authenticated:
Authenticated, Middlewares: nil, ID: 484603113231},
+ {Version: api.Version{Major: 5, Minor: 0}, Method:
http.MethodGet, Path: `staticdnsentries/?$`, Handler: staticdnsentry.Get,
RequiredPrivLevel: auth.PrivLevelReadOnly, RequiredPermissions:
[]string{"STATIC-DN:READ", "CACHE-GROUP:READ", "DELIVERY-SERVICE:READ"},
Authenticated: Authenticated, Middlewares: nil, ID: 42893947731},
+ {Version: api.Version{Major: 5, Minor: 0}, Method:
http.MethodPut, Path: `staticdnsentries/?$`, Handler: staticdnsentry.Update,
RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions:
[]string{"STATIC-DN:UPDATE", "STATIC-DN:READ", "CACHE-GROUP:READ",
"DELIVERY-SERVICE:READ"}, Authenticated: Authenticated, Middlewares: nil, ID:
44245711131},
+ {Version: api.Version{Major: 5, Minor: 0}, Method:
http.MethodPost, Path: `staticdnsentries/?$`, Handler: staticdnsentry.Create,
RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions:
[]string{"STATIC-DN:CREATE", "STATIC-DN:READ", "CACHE-GROUP:READ",
"DELIVERY-SERVICE:READ"}, Authenticated: Authenticated, Middlewares: nil, ID:
462914823831},
+ {Version: api.Version{Major: 5, Minor: 0}, Method:
http.MethodDelete, Path: `staticdnsentries/?$`, Handler: staticdnsentry.Delete,
RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions:
[]string{"STATIC-DN:DELETE", "STATIC-DN:READ", "DELIVERY-SERVICE:READ",
"CACHE-GROUP:READ"}, Authenticated: Authenticated, Middlewares: nil, ID:
484603113231},
//ProfileParameters
{Version: api.Version{Major: 5, Minor: 0}, Method:
http.MethodGet, Path: `profiles/{id}/parameters/?$`, Handler:
profileparameter.GetProfileID, RequiredPrivLevel: auth.PrivLevelReadOnly,
RequiredPermissions: []string{"PROFILE:READ", "PARAMETER:READ"}, Authenticated:
Authenticated, Middlewares: nil, ID: 47646497531},
diff --git a/traffic_ops/traffic_ops_golang/staticdnsentry/staticdnsentry.go
b/traffic_ops/traffic_ops_golang/staticdnsentry/staticdnsentry.go
index 71459e3272..3db3282393 100644
--- a/traffic_ops/traffic_ops_golang/staticdnsentry/staticdnsentry.go
+++ b/traffic_ops/traffic_ops_golang/staticdnsentry/staticdnsentry.go
@@ -20,17 +20,22 @@ package staticdnsentry
*/
import (
+ "database/sql"
+ "encoding/json"
"errors"
"fmt"
"net/http"
"strconv"
"time"
+ "github.com/apache/trafficcontrol/lib/go-log"
"github.com/apache/trafficcontrol/lib/go-tc"
"github.com/apache/trafficcontrol/lib/go-tc/tovalidate"
"github.com/apache/trafficcontrol/lib/go-util"
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
+
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/util/ims"
+
validation "github.com/go-ozzo/ozzo-validation"
"github.com/go-ozzo/ozzo-validation/is"
)
@@ -260,3 +265,380 @@ func deleteQuery() string {
WHERE id=:id`
return query
}
+
+// Validate validates a statisDNSEntry entity and makes sure that all the
supplied fields are valid.
+func Validate(staticDNSEntry tc.StaticDNSEntryV5, tx *sql.Tx) (error, error) {
+ typeStr, err := tc.ValidateTypeID(tx, staticDNSEntry.TypeID,
"staticdnsentry")
+ if err != nil {
+ return err, nil
+ }
+
+ var addressErr, ttlErr error
+ switch typeStr {
+ case "A_RECORD":
+ addressErr = validation.Validate(staticDNSEntry.Address,
validation.Required, is.IPv4)
+ case "AAAA_RECORD":
+ addressErr = validation.Validate(staticDNSEntry.Address,
validation.Required, is.IPv6)
+ case "CNAME_RECORD":
+ addressErr = validation.Validate(staticDNSEntry.Address,
validation.Required, is.DNSName)
+ address := *staticDNSEntry.Address
+ if addressErr == nil {
+ lastChar := address[len(address)-1:]
+ if lastChar != "." {
+ addressErr = fmt.Errorf("for type: CNAME_RECORD
must have a trailing period")
+ }
+ }
+ default:
+ addressErr = validation.Validate(staticDNSEntry.Address,
validation.Required)
+ }
+
+ if staticDNSEntry.TTL != nil {
+ if *staticDNSEntry.TTL == 0 {
+ ttlErr = validation.Validate(staticDNSEntry.TTL,
is.Digit)
+ }
+ } else {
+ ttlErr = validation.Validate(staticDNSEntry.TTL,
validation.Required)
+ }
+
+ errs := validation.Errors{
+ "host": validation.Validate(staticDNSEntry.Host,
validation.Required, is.DNSName),
+ "address": addressErr,
+ "deliveryserviceId":
validation.Validate(staticDNSEntry.DeliveryServiceID, validation.Required),
+ "ttl": ttlErr,
+ "typeId": validation.Validate(staticDNSEntry.TypeID,
validation.Required),
+ }
+ return util.JoinErrs(tovalidate.ToErrors(errs)), nil
+}
+
+// Update will modify an existing StaticDNSEntry entity in the database, for
api v5.0.
+func Update(w http.ResponseWriter, r *http.Request) {
+ inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+ if userErr != nil || sysErr != nil {
+ api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+ return
+ }
+ defer inf.Close()
+
+ tx := inf.Tx.Tx
+
+ defer r.Body.Close()
+ var staticDNSEntry tc.StaticDNSEntryV5
+
+ if err := json.NewDecoder(r.Body).Decode(&staticDNSEntry); err != nil {
+ api.HandleErr(w, r, nil, http.StatusInternalServerError, nil,
err)
+ return
+ }
+
+ userErr, sysErr = Validate(staticDNSEntry, tx)
+ if userErr != nil || sysErr != nil {
+ code := http.StatusBadRequest
+ if sysErr != nil {
+ code = http.StatusInternalServerError
+ }
+ api.HandleErr(w, r, tx, code, userErr, sysErr)
+ return
+ }
+
+ var cdnName tc.CDNName
+ if id, ok := inf.Params["id"]; !ok {
+ api.HandleErr(w, r, tx, http.StatusBadRequest,
errors.New("missing key: id"), nil)
+ return
+ } else {
+ idNum, err := strconv.Atoi(id)
+ if err != nil {
+ api.HandleErr(w, r, tx, http.StatusBadRequest,
errors.New("couldn't convert ID into a numeric value: "+err.Error()), nil)
+ return
+ }
+ staticDNSEntry.ID = &idNum
+ if staticDNSEntry.DeliveryServiceID != nil {
+ _, cdnName, _, err =
dbhelpers.GetDSNameAndCDNFromID(tx, *staticDNSEntry.DeliveryServiceID)
+ if err != nil {
+ api.HandleErr(w, r, tx,
http.StatusInternalServerError, nil, err)
+ return
+ }
+ userErr, sysErr, errCode :=
dbhelpers.CheckIfCurrentUserCanModifyCDN(tx, string(cdnName), inf.User.UserName)
+ if userErr != nil || sysErr != nil {
+ api.HandleErr(w, r, inf.Tx.Tx, errCode,
userErr, sysErr)
+ return
+ }
+ }
+
+ existingLastUpdated, found, err := api.GetLastUpdated(inf.Tx,
idNum, "staticdnsentry")
+ if err == nil && found == false {
+ api.HandleErr(w, r, tx, http.StatusNotFound,
errors.New("no staticDNSEntry found with this id"), nil)
+ return
+ }
+ if err != nil {
+ api.HandleErr(w, r, tx, http.StatusNotFound, nil, err)
+ return
+ }
+ if !api.IsUnmodified(r.Header, *existingLastUpdated) {
+ api.HandleErr(w, r, tx, http.StatusPreconditionFailed,
api.ResourceModifiedError, nil)
+ return
+ }
+
+ rows, err := inf.Tx.NamedQuery(updateQuery(), staticDNSEntry)
+ if err != nil {
+ userErr, sysErr, errCode = api.ParseDBError(err)
+ api.HandleErr(w, r, tx, errCode, userErr, sysErr)
+ return
+ }
+ defer rows.Close()
+
+ if !rows.Next() {
+ api.HandleErr(w, r, tx, http.StatusNotFound,
errors.New("no staticDNSEntry found with this id"), nil)
+ return
+ }
+ lastUpdated := time.Time{}
+ if err := rows.Scan(&lastUpdated); err != nil {
+ api.HandleErr(w, r, tx, http.StatusInternalServerError,
nil, errors.New("scanning lastUpdated from staticDNSEntry insert:
"+err.Error()))
+ return
+ }
+ staticDNSEntry.LastUpdated = &lastUpdated
+ if rows.Next() {
+ api.HandleErr(w, r, tx, http.StatusInternalServerError,
nil, errors.New("staticDNSEntry update affected too many rows: >1"))
+ return
+ }
+
+ alerts := tc.CreateAlerts(tc.SuccessLevel, "staticDNSEntry was
updated.")
+ api.WriteAlertsObj(w, r, http.StatusOK, alerts, staticDNSEntry)
+ changeLogMsg := fmt.Sprintf("STATICDNSENTRY: %s, ID: %d,
ACTION: Updated staticDNSEntry", *staticDNSEntry.Host, *staticDNSEntry.ID)
+ api.CreateChangeLogRawTx(api.ApiChange, changeLogMsg, inf.User,
tx)
+ return
+ }
+}
+
+// Create will add a new StaticDNSEntry entity into the database, for api v5.0.
+func Create(w http.ResponseWriter, r *http.Request) {
+ inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+ if userErr != nil || sysErr != nil {
+ api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+ return
+ }
+ defer inf.Close()
+
+ tx := inf.Tx.Tx
+
+ defer r.Body.Close()
+ var staticDNSEntry tc.StaticDNSEntryV5
+
+ if err := json.NewDecoder(r.Body).Decode(&staticDNSEntry); err != nil {
+ api.HandleErr(w, r, nil, http.StatusInternalServerError, nil,
err)
+ return
+ }
+
+ userErr, sysErr = Validate(staticDNSEntry, tx)
+ if userErr != nil || sysErr != nil {
+ code := http.StatusBadRequest
+ if sysErr != nil {
+ code = http.StatusInternalServerError
+ }
+ api.HandleErr(w, r, tx, code, userErr, sysErr)
+ return
+ }
+
+ var cdnName tc.CDNName
+ var err error
+ if staticDNSEntry.DeliveryServiceID != nil {
+ _, cdnName, _, err = dbhelpers.GetDSNameAndCDNFromID(tx,
*staticDNSEntry.DeliveryServiceID)
+ if err != nil {
+ api.HandleErr(w, r, tx, http.StatusInternalServerError,
nil, err)
+ return
+ }
+ userErr, sysErr, errCode :=
dbhelpers.CheckIfCurrentUserCanModifyCDN(tx, string(cdnName), inf.User.UserName)
+ if userErr != nil || sysErr != nil {
+ api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+ return
+ }
+ }
+
+ resultRows, err := inf.Tx.NamedQuery(insertQuery(), staticDNSEntry)
+ if err != nil {
+ userErr, sysErr, errCode = api.ParseDBError(err)
+ api.HandleErr(w, r, tx, errCode, userErr, sysErr)
+ return
+ }
+ defer resultRows.Close()
+
+ var id int
+ lastUpdated := time.Time{}
+ rowsAffected := 0
+ for resultRows.Next() {
+ rowsAffected++
+ if err := resultRows.Scan(&id, &lastUpdated); err != nil {
+ api.HandleErr(w, r, tx, http.StatusInternalServerError,
nil, errors.New("staticDNSEntry create scanning: "+err.Error()))
+ return
+ }
+ }
+
+ if rowsAffected == 0 {
+ api.HandleErr(w, r, tx, http.StatusInternalServerError, nil,
errors.New("staticDNSEntry create: no staticDNSEntry was inserted, no id was
returned"))
+ return
+ } else if rowsAffected > 1 {
+ api.HandleErr(w, r, tx, http.StatusInternalServerError, nil,
errors.New("too many ids returned from staticDNSEntry insert"))
+ return
+ }
+ staticDNSEntry.ID = &id
+ staticDNSEntry.LastUpdated = &lastUpdated
+
+ alerts := tc.CreateAlerts(tc.SuccessLevel, "staticDNSEntry was
created.")
+ api.WriteAlertsObj(w, r, http.StatusOK, alerts, staticDNSEntry)
+ changeLogMsg := fmt.Sprintf("STATICDNSENTRY: %s, ID: %d, ACTION:
Created staticDNSEntry", *staticDNSEntry.Host, *staticDNSEntry.ID)
+ api.CreateChangeLogRawTx(api.ApiChange, changeLogMsg, inf.User, tx)
+ return
+}
+
+// Delete removes a staticDNSEntry from the database, for api v5.0.
+func Delete(w http.ResponseWriter, r *http.Request) {
+ inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+ if userErr != nil || sysErr != nil {
+ api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+ return
+ }
+ defer inf.Close()
+
+ tx := inf.Tx.Tx
+ if id, ok := inf.Params["id"]; !ok {
+ api.HandleErr(w, r, tx, http.StatusBadRequest,
errors.New("missing key: id"), nil)
+ return
+ } else {
+ idNum, err := strconv.Atoi(id)
+ if err != nil {
+ api.HandleErr(w, r, tx, http.StatusBadRequest,
errors.New("couldn't convert ID into a numeric value: "+err.Error()), nil)
+ return
+ }
+ staticDNSEntry := tc.StaticDNSEntryV5{
+ ID: &idNum,
+ }
+ var cdnName tc.CDNName
+ var dsID int
+ if staticDNSEntry.DeliveryServiceID != nil {
+ dsID = *staticDNSEntry.DeliveryServiceID
+ } else if staticDNSEntry.ID != nil {
+ dsID, err = dbhelpers.GetDSIDFromStaticDNSEntry(tx,
*staticDNSEntry.ID)
+ if err != nil {
+ api.HandleErr(w, r, tx,
http.StatusInternalServerError, nil, errors.New("couldn't get DS ID from static
dns entry ID: "+err.Error()))
+ return
+ }
+ }
+ _, cdnName, _, err = dbhelpers.GetDSNameAndCDNFromID(tx, dsID)
+ if err != nil {
+ api.HandleErr(w, r, tx, http.StatusInternalServerError,
nil, err)
+ return
+ }
+ userErr, sysErr, errCode :=
dbhelpers.CheckIfCurrentUserCanModifyCDN(tx, string(cdnName), inf.User.UserName)
+ if userErr != nil || sysErr != nil {
+ api.HandleErr(w, r, tx, errCode, userErr, sysErr)
+ return
+ }
+ result, err := inf.Tx.NamedExec(deleteQuery(), staticDNSEntry)
+ if err != nil {
+ userErr, sysErr, errCode = api.ParseDBError(err)
+ api.HandleErr(w, r, tx, errCode, userErr, sysErr)
+ return
+ }
+
+ if rowsAffected, err := result.RowsAffected(); err != nil {
+ api.HandleErr(w, r, tx, http.StatusInternalServerError,
nil, errors.New("deleting staticDNSEntry: getting rows affected: "+err.Error()))
+ return
+ } else if rowsAffected < 1 {
+ api.HandleErr(w, r, tx, http.StatusBadRequest,
errors.New("no staticDNSEntry with that key found"), nil)
+ return
+ } else if rowsAffected > 1 {
+ api.HandleErr(w, r, tx, http.StatusInternalServerError,
nil, fmt.Errorf("staticDNSEntry delete affected too many rows: %d",
rowsAffected))
+ return
+ }
+ log.Debugf("changelog for delete on staticDNSEntry")
+
+ alerts := tc.CreateAlerts(tc.SuccessLevel, "staticDNSEntry was
deleted.")
+ api.WriteAlerts(w, r, http.StatusOK, alerts)
+ changeLogMsg := fmt.Sprintf("STATICDNSENTRY: %d, ID: %d,
ACTION: Deleted staticDNSEntry", *staticDNSEntry.ID, *staticDNSEntry.ID)
+ api.CreateChangeLogRawTx(api.ApiChange, changeLogMsg, inf.User,
tx)
+ return
+ }
+}
+
+// Get : function to read the staticDNSEntries, for api version 5.0.
+func Get(w http.ResponseWriter, r *http.Request) {
+ inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+ if userErr != nil || sysErr != nil {
+ api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+ return
+ }
+ defer inf.Close()
+
+ api.DefaultSort(inf, "host")
+ useIMS := false
+ config, e := api.GetConfig(r.Context())
+ if e == nil && config != nil {
+ useIMS = config.UseIMS
+ } else {
+ log.Warnf("Couldn't get config %v", e)
+ }
+
+ var maxTime time.Time
+ var runSecond bool
+
+ scList := make([]tc.StaticDNSEntryV5, 0)
+
+ tx := inf.Tx
+
+ where, orderBy, pagination, queryValues, errs :=
dbhelpers.BuildWhereAndOrderByAndPagination(inf.Params,
map[string]dbhelpers.WhereColumnInfo{
+ "address": dbhelpers.WhereColumnInfo{Column:
"sde.address"},
+ "cachegroup": dbhelpers.WhereColumnInfo{Column:
"cg.name"},
+ "cachegroupId": dbhelpers.WhereColumnInfo{Column: "cg.id"},
+ "deliveryservice": dbhelpers.WhereColumnInfo{Column:
"ds.xml_id"},
+ "deliveryserviceId": dbhelpers.WhereColumnInfo{Column:
"sde.deliveryservice"},
+ "host": dbhelpers.WhereColumnInfo{Column:
"sde.host"},
+ "id": dbhelpers.WhereColumnInfo{Column:
"sde.id"},
+ "ttl": dbhelpers.WhereColumnInfo{Column:
"sde.ttl"},
+ "type": dbhelpers.WhereColumnInfo{Column:
"tp.name"},
+ "typeId": dbhelpers.WhereColumnInfo{Column: "tp.id"},
+ })
+ if len(errs) > 0 {
+ api.HandleErr(w, r, tx.Tx, http.StatusBadRequest, nil,
util.JoinErrs(errs))
+ return
+ }
+ if useIMS {
+ runSecond, maxTime = ims.TryIfModifiedSinceQuery(inf.Tx,
r.Header, queryValues, selectMaxLastUpdatedQuery(where))
+ if !runSecond {
+ log.Debugln("IMS HIT")
+ api.AddLastModifiedHdr(w, maxTime)
+ w.WriteHeader(http.StatusNotModified)
+ return
+ }
+ log.Debugln("IMS MISS")
+ } else {
+ log.Debugln("Non IMS request")
+ }
+
+ // Case where we need to run the second query
+ query := selectQuery() + where + orderBy + pagination
+ rows, err := tx.NamedQuery(query, queryValues)
+ if err != nil {
+ api.HandleErr(w, r, tx.Tx, http.StatusInternalServerError, nil,
errors.New("querying static DNS entries: "+err.Error()))
+ return
+ }
+ defer rows.Close()
+
+ for rows.Next() {
+ v := tc.StaticDNSEntryV5{}
+ if err = rows.StructScan(&v); err != nil {
+ api.HandleErr(w, r, tx.Tx,
http.StatusInternalServerError, nil, errors.New("scanning static DNS entries:
"+err.Error()))
+ return
+ }
+ scList = append(scList, v)
+ }
+
+ api.WriteResp(w, r, scList)
+}
+
+func selectMaxLastUpdatedQuery(where string) string {
+ return `SELECT max(t) from (
+ SELECT max(sde.last_updated) as t FROM staticdnsentry as sde
+JOIN type as tp on sde.type = tp.id
+LEFT JOIN cachegroup as cg ON sde.cachegroup = cg.id
+JOIN deliveryservice as ds on sde.deliveryservice = ds.id ` + where +
+ ` UNION ALL
+ select max(last_updated) as t from last_deleted l where
l.table_name='staticdnsentry') as res`
+}
diff --git a/traffic_ops/v5-client/staticdnsentry.go
b/traffic_ops/v5-client/staticdnsentry.go
index dee4fe520d..63397884a4 100644
--- a/traffic_ops/v5-client/staticdnsentry.go
+++ b/traffic_ops/v5-client/staticdnsentry.go
@@ -28,63 +28,63 @@ import (
// endpoint.
const apiStaticDNSEntries = "/staticdnsentries"
-func staticDNSEntryIDs(to *Session, sdns *tc.StaticDNSEntry) error {
+func staticDNSEntryIDsV5(to *Session, sdns *tc.StaticDNSEntryV5) error {
if sdns == nil {
return errors.New("cannot resolve names to IDs for nil
StaticDNSEntry")
}
- if sdns.CacheGroupID == 0 && sdns.CacheGroupName != "" {
+ if (sdns.CacheGroupID == nil || *sdns.CacheGroupID == 0) &&
(sdns.CacheGroupName != nil && *sdns.CacheGroupName != "") {
opts := NewRequestOptions()
- opts.QueryParameters.Set("name", sdns.CacheGroupName)
+ opts.QueryParameters.Set("name", *sdns.CacheGroupName)
p, _, err := to.GetCacheGroups(opts)
if err != nil {
return err
}
if len(p.Response) == 0 {
- return errors.New("no CacheGroup named " +
sdns.CacheGroupName)
+ return errors.New("no CacheGroup named " +
*sdns.CacheGroupName)
}
if p.Response[0].ID == nil {
- return errors.New("CacheGroup named " +
sdns.CacheGroupName + " has a nil ID")
+ return errors.New("CacheGroup named " +
*sdns.CacheGroupName + " has a nil ID")
}
- sdns.CacheGroupID = *p.Response[0].ID
+ sdns.CacheGroupID = p.Response[0].ID
}
- if sdns.DeliveryServiceID == 0 && sdns.DeliveryService != "" {
+ if (sdns.DeliveryServiceID == nil || *sdns.DeliveryServiceID == 0) &&
(sdns.DeliveryService != nil && *sdns.DeliveryService != "") {
opts := NewRequestOptions()
- opts.QueryParameters.Set("xmlId", sdns.DeliveryService)
+ opts.QueryParameters.Set("xmlId", *sdns.DeliveryService)
dses, _, err := to.GetDeliveryServices(opts)
if err != nil {
return err
}
if len(dses.Response) == 0 {
- return errors.New("no deliveryservice with name " +
sdns.DeliveryService)
+ return errors.New("no deliveryservice with name " +
*sdns.DeliveryService)
}
if dses.Response[0].ID == nil {
- return errors.New("Deliveryservice with name " +
sdns.DeliveryService + " has a nil ID")
+ return errors.New("Deliveryservice with name " +
*sdns.DeliveryService + " has a nil ID")
}
- sdns.DeliveryServiceID = *dses.Response[0].ID
+ sdns.DeliveryServiceID = dses.Response[0].ID
}
- if sdns.TypeID == 0 && sdns.Type != "" {
+ if (sdns.TypeID == nil || *sdns.TypeID == 0) && (sdns.Type != nil &&
*sdns.Type != "") {
opts := NewRequestOptions()
- opts.QueryParameters.Set("name", sdns.Type)
+ opts.QueryParameters.Set("name", *sdns.Type)
types, _, err := to.GetTypes(opts)
if err != nil {
return err
}
if len(types.Response) == 0 {
- return errors.New("no type with name " + sdns.Type)
+ return errors.New("no type with name " + *sdns.Type)
}
- sdns.TypeID = types.Response[0].ID
+ sdns.TypeID = &types.Response[0].ID
}
return nil
}
// CreateStaticDNSEntry creates the given Static DNS Entry.
-func (to *Session) CreateStaticDNSEntry(sdns tc.StaticDNSEntry, opts
RequestOptions) (tc.Alerts, toclientlib.ReqInf, error) {
+func (to *Session) CreateStaticDNSEntry(sdns tc.StaticDNSEntryV5, opts
RequestOptions) (tc.Alerts, toclientlib.ReqInf, error) {
// fill in missing IDs from names
var alerts tc.Alerts
- err := staticDNSEntryIDs(to, &sdns)
+ err := staticDNSEntryIDsV5(to, &sdns)
if err != nil {
return alerts, toclientlib.ReqInf{CacheHitStatus:
toclientlib.CacheHitStatusMiss}, err
}
@@ -94,10 +94,10 @@ func (to *Session) CreateStaticDNSEntry(sdns
tc.StaticDNSEntry, opts RequestOpti
// UpdateStaticDNSEntry replaces the Static DNS Entry identified by 'id' with
// the one provided.
-func (to *Session) UpdateStaticDNSEntry(id int, sdns tc.StaticDNSEntry, opts
RequestOptions) (tc.Alerts, toclientlib.ReqInf, error) {
+func (to *Session) UpdateStaticDNSEntry(id int, sdns tc.StaticDNSEntryV5, opts
RequestOptions) (tc.Alerts, toclientlib.ReqInf, error) {
// fill in missing IDs from names
var alerts tc.Alerts
- err := staticDNSEntryIDs(to, &sdns)
+ err := staticDNSEntryIDsV5(to, &sdns)
if err != nil {
return alerts, toclientlib.ReqInf{CacheHitStatus:
toclientlib.CacheHitStatusMiss}, err
}
@@ -110,8 +110,8 @@ func (to *Session) UpdateStaticDNSEntry(id int, sdns
tc.StaticDNSEntry, opts Req
}
// GetStaticDNSEntries retrieves all Static DNS Entries stored in Traffic Ops.
-func (to *Session) GetStaticDNSEntries(opts RequestOptions)
(tc.StaticDNSEntriesResponse, toclientlib.ReqInf, error) {
- var data tc.StaticDNSEntriesResponse
+func (to *Session) GetStaticDNSEntries(opts RequestOptions)
(tc.StaticDNSEntriesResponseV5, toclientlib.ReqInf, error) {
+ var data tc.StaticDNSEntriesResponseV5
reqInf, err := to.get(apiStaticDNSEntries, opts, &data)
return data, reqInf, err
}