forked from cloudflare/cloudflare-go
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Deprecate virtualdns.go in favor of dns_firewall.go
This adds new types and functions for the DNS Firewall and DNS Firewall Analytics API to `dns_firewall.go`, deprecating `virtual_dns.go` For compatibility, the functions in `virtual_dns.go` are now wrappers around the functions in `dns_firewall.go`. This means that we now always use the new routes, even when one of the deprecated functions is called. In addition to replacing "Virtual DNS" with "DNS Firewall", a few minor changes were also made to names and function signatures. Finally, the new DNS Firewall equivalents of the following functions are no longer exported: - VirtualDNSResponse - VirtualDNSListResponse - VirtualDNSAnalyticsResponse
- Loading branch information
1 parent
ae366e9
commit a7a3235
Showing
5 changed files
with
360 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
package cloudflare | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"net/url" | ||
"strings" | ||
"time" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
// DNSFirewallCluster represents a DNS Firewall configuration. | ||
type DNSFirewallCluster struct { | ||
ID string `json:"id,omitempty"` | ||
Name string `json:"name"` | ||
OriginIPs []string `json:"origin_ips"` | ||
DNSFirewallIPs []string `json:"dns_firewall_ips,omitempty"` | ||
MinimumCacheTTL uint `json:"minimum_cache_ttl,omitempty"` | ||
MaximumCacheTTL uint `json:"maximum_cache_ttl,omitempty"` | ||
DeprecateAnyRequests bool `json:"deprecate_any_requests"` | ||
ModifiedOn string `json:"modified_on,omitempty"` | ||
} | ||
|
||
// DNSFirewallAnalyticsMetrics represents a group of aggregated DNS Firewall metrics. | ||
type DNSFirewallAnalyticsMetrics struct { | ||
QueryCount *int64 `json:"queryCount"` | ||
UncachedCount *int64 `json:"uncachedCount"` | ||
StaleCount *int64 `json:"staleCount"` | ||
ResponseTimeAvg *float64 `json:"responseTimeAvg"` | ||
ResponseTimeMedian *float64 `json:"responseTimeMedian"` | ||
ResponseTime90th *float64 `json:"responseTime90th"` | ||
ResponseTime99th *float64 `json:"responseTime99th"` | ||
} | ||
|
||
// DNSFirewallAnalytics represents a set of aggregated DNS Firewall metrics. | ||
// TODO: Add the queried data and not only the aggregated values. | ||
type DNSFirewallAnalytics struct { | ||
Totals DNSFirewallAnalyticsMetrics `json:"totals"` | ||
Min DNSFirewallAnalyticsMetrics `json:"min"` | ||
Max DNSFirewallAnalyticsMetrics `json:"max"` | ||
} | ||
|
||
// DNSFirewallUserAnalyticsOptions represents range and dimension selection on analytics endpoint | ||
type DNSFirewallUserAnalyticsOptions struct { | ||
Metrics []string | ||
Since *time.Time | ||
Until *time.Time | ||
} | ||
|
||
// dnsFirewallResponse represents a DNS Firewall response. | ||
type dnsFirewallResponse struct { | ||
Response | ||
Result *DNSFirewallCluster `json:"result"` | ||
} | ||
|
||
// dnsFirewallListResponse represents an array of DNS Firewall responses. | ||
type dnsFirewallListResponse struct { | ||
Response | ||
Result []*DNSFirewallCluster `json:"result"` | ||
} | ||
|
||
// dnsFirewallAnalyticsResponse represents a DNS Firewall analytics response. | ||
type dnsFirewallAnalyticsResponse struct { | ||
Response | ||
Result DNSFirewallAnalytics `json:"result"` | ||
} | ||
|
||
// CreateDNSFirewallCluster creates a new DNS Firewall cluster. | ||
// | ||
// API reference: https://api.cloudflare.com/#dns-firewall-create-dns-firewall-cluster | ||
func (api *API) CreateDNSFirewallCluster(ctx context.Context, v DNSFirewallCluster) (*DNSFirewallCluster, error) { | ||
uri := fmt.Sprintf("%s/dns_firewall", api.userBaseURL("/user")) | ||
res, err := api.makeRequestContext(ctx, http.MethodPost, uri, v) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
response := &dnsFirewallResponse{} | ||
err = json.Unmarshal(res, &response) | ||
if err != nil { | ||
return nil, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return response.Result, nil | ||
} | ||
|
||
// DNSFirewallCluster fetches a single DNS Firewall cluster. | ||
// | ||
// API reference: https://api.cloudflare.com/#dns-firewall-dns-firewall-cluster-details | ||
func (api *API) DNSFirewallCluster(ctx context.Context, clusterID string) (*DNSFirewallCluster, error) { | ||
uri := fmt.Sprintf("%s/dns_firewall/%s", api.userBaseURL("/user"), clusterID) | ||
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
response := &dnsFirewallResponse{} | ||
err = json.Unmarshal(res, &response) | ||
if err != nil { | ||
return nil, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return response.Result, nil | ||
} | ||
|
||
// ListDNSFirewallClusters lists the DNS Firewall clusters associated with an account. | ||
// | ||
// API reference: https://api.cloudflare.com/#dns-firewall-list-dns-firewall-clusters | ||
func (api *API) ListDNSFirewallClusters(ctx context.Context) ([]*DNSFirewallCluster, error) { | ||
uri := fmt.Sprintf("%s/dns_firewall", api.userBaseURL("/user")) | ||
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
response := &dnsFirewallListResponse{} | ||
err = json.Unmarshal(res, &response) | ||
if err != nil { | ||
return nil, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return response.Result, nil | ||
} | ||
|
||
// UpdateDNSFirewallCluster updates a DNS Firewall cluster. | ||
// | ||
// API reference: https://api.cloudflare.com/#dns-firewall-update-dns-firewall-cluster | ||
func (api *API) UpdateDNSFirewallCluster(ctx context.Context, clusterID string, vv DNSFirewallCluster) error { | ||
uri := fmt.Sprintf("%s/dns_firewall/%s", api.userBaseURL("/user"), clusterID) | ||
res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, vv) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
response := &dnsFirewallResponse{} | ||
err = json.Unmarshal(res, &response) | ||
if err != nil { | ||
return errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// DeleteDNSFirewallCluster deletes a DNS Firewall cluster. Note that this cannot be | ||
// undone, and will stop all traffic to that cluster. | ||
// | ||
// API reference: https://api.cloudflare.com/#dns-firewall-delete-dns-firewall-cluster | ||
func (api *API) DeleteDNSFirewallCluster(ctx context.Context, clusterID string) error { | ||
uri := fmt.Sprintf("%s/dns_firewall/%s", api.userBaseURL("/user"), clusterID) | ||
res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
response := &dnsFirewallResponse{} | ||
err = json.Unmarshal(res, &response) | ||
if err != nil { | ||
return errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// encode encodes non-nil fields into URL encoded form. | ||
func (o DNSFirewallUserAnalyticsOptions) encode() string { | ||
v := url.Values{} | ||
if o.Since != nil { | ||
v.Set("since", (*o.Since).UTC().Format(time.RFC3339)) | ||
} | ||
if o.Until != nil { | ||
v.Set("until", (*o.Until).UTC().Format(time.RFC3339)) | ||
} | ||
if o.Metrics != nil { | ||
v.Set("metrics", strings.Join(o.Metrics, ",")) | ||
} | ||
return v.Encode() | ||
} | ||
|
||
// DNSFirewallUserAnalytics retrieves analytics report for a specified dimension and time range | ||
func (api *API) DNSFirewallUserAnalytics(ctx context.Context, clusterID string, o DNSFirewallUserAnalyticsOptions) (DNSFirewallAnalytics, error) { | ||
uri := fmt.Sprintf("%s/dns_firewall/%s/dns_analytics/report?%s", api.userBaseURL("/user"), clusterID, o.encode()) | ||
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) | ||
if err != nil { | ||
return DNSFirewallAnalytics{}, err | ||
} | ||
|
||
response := dnsFirewallAnalyticsResponse{} | ||
err = json.Unmarshal(res, &response) | ||
if err != nil { | ||
return DNSFirewallAnalytics{}, errors.Wrap(err, errUnmarshalError) | ||
} | ||
|
||
return response.Result, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package cloudflare | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func float64Ptr(v float64) *float64 { | ||
return &v | ||
} | ||
|
||
func int64Ptr(v int64) *int64 { | ||
return &v | ||
} | ||
|
||
func TestDNSFirewallUserAnalytics(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
now := time.Now().UTC() | ||
since := now.Add(-1 * time.Hour) | ||
until := now | ||
|
||
handler := func(w http.ResponseWriter, r *http.Request) { | ||
expectedMetrics := "queryCount,uncachedCount,staleCount,responseTimeAvg,responseTimeMedia,responseTime90th,responseTime99th" | ||
|
||
assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET'") | ||
assert.Equal(t, expectedMetrics, r.URL.Query().Get("metrics"), "Expected many metrics in URL parameter") | ||
assert.Equal(t, since.Format(time.RFC3339), r.URL.Query().Get("since"), "Expected since parameter in URL") | ||
assert.Equal(t, until.Format(time.RFC3339), r.URL.Query().Get("until"), "Expected until parameter in URL") | ||
|
||
w.Header().Set("content-type", "application/json") | ||
fmt.Fprint(w, `{ | ||
"result": { | ||
"totals":{ | ||
"queryCount": 5, | ||
"uncachedCount":6, | ||
"staleCount":7, | ||
"responseTimeAvg":1.0, | ||
"responseTimeMedian":2.0, | ||
"responseTime90th":3.0, | ||
"responseTime99th":4.0 | ||
} | ||
}, | ||
"success": true, | ||
"errors": null, | ||
"messages": null | ||
}`) | ||
} | ||
|
||
mux.HandleFunc("/user/dns_firewall/12345/dns_analytics/report", handler) | ||
want := DNSFirewallAnalytics{ | ||
Totals: DNSFirewallAnalyticsMetrics{ | ||
QueryCount: int64Ptr(5), | ||
UncachedCount: int64Ptr(6), | ||
StaleCount: int64Ptr(7), | ||
ResponseTimeAvg: float64Ptr(1.0), | ||
ResponseTimeMedian: float64Ptr(2.0), | ||
ResponseTime90th: float64Ptr(3.0), | ||
ResponseTime99th: float64Ptr(4.0), | ||
}, | ||
} | ||
|
||
params := DNSFirewallUserAnalyticsOptions{ | ||
Metrics: []string{ | ||
"queryCount", | ||
"uncachedCount", | ||
"staleCount", | ||
"responseTimeAvg", | ||
"responseTimeMedia", | ||
"responseTime90th", | ||
"responseTime99th", | ||
}, | ||
Since: &since, | ||
Until: &until, | ||
} | ||
actual, err := client.DNSFirewallUserAnalytics(context.Background(), "12345", params) | ||
if assert.NoError(t, err) { | ||
assert.Equal(t, want, actual) | ||
} | ||
} |
Oops, something went wrong.