0568e81701
This adds an implementation of node discovery via DNS TXT records to the go-ethereum library. The implementation doesn't match EIP-1459 exactly, the main difference being that this implementation uses separate merkle trees for tree links and ENRs. The EIP will be updated to match p2p/dnsdisc. To maintain DNS trees, cmd/devp2p provides a frontend for the p2p/dnsdisc library. The new 'dns' subcommands can be used to create, sign and deploy DNS discovery trees.
298 lines
9.8 KiB
Go
298 lines
9.8 KiB
Go
package cloudflare
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/url"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// Railgun represents a Railgun's properties.
|
|
type Railgun struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Status string `json:"status"`
|
|
Enabled bool `json:"enabled"`
|
|
ZonesConnected int `json:"zones_connected"`
|
|
Build string `json:"build"`
|
|
Version string `json:"version"`
|
|
Revision string `json:"revision"`
|
|
ActivationKey string `json:"activation_key"`
|
|
ActivatedOn time.Time `json:"activated_on"`
|
|
CreatedOn time.Time `json:"created_on"`
|
|
ModifiedOn time.Time `json:"modified_on"`
|
|
UpgradeInfo struct {
|
|
LatestVersion string `json:"latest_version"`
|
|
DownloadLink string `json:"download_link"`
|
|
} `json:"upgrade_info"`
|
|
}
|
|
|
|
// RailgunListOptions represents the parameters used to list railguns.
|
|
type RailgunListOptions struct {
|
|
Direction string
|
|
}
|
|
|
|
// railgunResponse represents the response from the Create Railgun and the Railgun Details endpoints.
|
|
type railgunResponse struct {
|
|
Response
|
|
Result Railgun `json:"result"`
|
|
}
|
|
|
|
// railgunsResponse represents the response from the List Railguns endpoint.
|
|
type railgunsResponse struct {
|
|
Response
|
|
Result []Railgun `json:"result"`
|
|
}
|
|
|
|
// CreateRailgun creates a new Railgun.
|
|
//
|
|
// API reference: https://api.cloudflare.com/#railgun-create-railgun
|
|
func (api *API) CreateRailgun(name string) (Railgun, error) {
|
|
uri := api.userBaseURL("") + "/railguns"
|
|
params := struct {
|
|
Name string `json:"name"`
|
|
}{
|
|
Name: name,
|
|
}
|
|
res, err := api.makeRequest("POST", uri, params)
|
|
if err != nil {
|
|
return Railgun{}, errors.Wrap(err, errMakeRequestError)
|
|
}
|
|
var r railgunResponse
|
|
if err := json.Unmarshal(res, &r); err != nil {
|
|
return Railgun{}, errors.Wrap(err, errUnmarshalError)
|
|
}
|
|
return r.Result, nil
|
|
}
|
|
|
|
// ListRailguns lists Railguns connected to an account.
|
|
//
|
|
// API reference: https://api.cloudflare.com/#railgun-list-railguns
|
|
func (api *API) ListRailguns(options RailgunListOptions) ([]Railgun, error) {
|
|
v := url.Values{}
|
|
if options.Direction != "" {
|
|
v.Set("direction", options.Direction)
|
|
}
|
|
uri := api.userBaseURL("") + "/railguns" + "?" + v.Encode()
|
|
res, err := api.makeRequest("GET", uri, nil)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, errMakeRequestError)
|
|
}
|
|
var r railgunsResponse
|
|
if err := json.Unmarshal(res, &r); err != nil {
|
|
return nil, errors.Wrap(err, errUnmarshalError)
|
|
}
|
|
return r.Result, nil
|
|
}
|
|
|
|
// RailgunDetails returns the details for a Railgun.
|
|
//
|
|
// API reference: https://api.cloudflare.com/#railgun-railgun-details
|
|
func (api *API) RailgunDetails(railgunID string) (Railgun, error) {
|
|
uri := api.userBaseURL("") + "/railguns/" + railgunID
|
|
res, err := api.makeRequest("GET", uri, nil)
|
|
if err != nil {
|
|
return Railgun{}, errors.Wrap(err, errMakeRequestError)
|
|
}
|
|
var r railgunResponse
|
|
if err := json.Unmarshal(res, &r); err != nil {
|
|
return Railgun{}, errors.Wrap(err, errUnmarshalError)
|
|
}
|
|
return r.Result, nil
|
|
}
|
|
|
|
// RailgunZones returns the zones that are currently using a Railgun.
|
|
//
|
|
// API reference: https://api.cloudflare.com/#railgun-get-zones-connected-to-a-railgun
|
|
func (api *API) RailgunZones(railgunID string) ([]Zone, error) {
|
|
uri := api.userBaseURL("") + "/railguns/" + railgunID + "/zones"
|
|
res, err := api.makeRequest("GET", uri, nil)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, errMakeRequestError)
|
|
}
|
|
var r ZonesResponse
|
|
if err := json.Unmarshal(res, &r); err != nil {
|
|
return nil, errors.Wrap(err, errUnmarshalError)
|
|
}
|
|
return r.Result, nil
|
|
}
|
|
|
|
// enableRailgun enables (true) or disables (false) a Railgun for all zones connected to it.
|
|
//
|
|
// API reference: https://api.cloudflare.com/#railgun-enable-or-disable-a-railgun
|
|
func (api *API) enableRailgun(railgunID string, enable bool) (Railgun, error) {
|
|
uri := api.userBaseURL("") + "/railguns/" + railgunID
|
|
params := struct {
|
|
Enabled bool `json:"enabled"`
|
|
}{
|
|
Enabled: enable,
|
|
}
|
|
res, err := api.makeRequest("PATCH", uri, params)
|
|
if err != nil {
|
|
return Railgun{}, errors.Wrap(err, errMakeRequestError)
|
|
}
|
|
var r railgunResponse
|
|
if err := json.Unmarshal(res, &r); err != nil {
|
|
return Railgun{}, errors.Wrap(err, errUnmarshalError)
|
|
}
|
|
return r.Result, nil
|
|
}
|
|
|
|
// EnableRailgun enables a Railgun for all zones connected to it.
|
|
//
|
|
// API reference: https://api.cloudflare.com/#railgun-enable-or-disable-a-railgun
|
|
func (api *API) EnableRailgun(railgunID string) (Railgun, error) {
|
|
return api.enableRailgun(railgunID, true)
|
|
}
|
|
|
|
// DisableRailgun enables a Railgun for all zones connected to it.
|
|
//
|
|
// API reference: https://api.cloudflare.com/#railgun-enable-or-disable-a-railgun
|
|
func (api *API) DisableRailgun(railgunID string) (Railgun, error) {
|
|
return api.enableRailgun(railgunID, false)
|
|
}
|
|
|
|
// DeleteRailgun disables and deletes a Railgun.
|
|
//
|
|
// API reference: https://api.cloudflare.com/#railgun-delete-railgun
|
|
func (api *API) DeleteRailgun(railgunID string) error {
|
|
uri := api.userBaseURL("") + "/railguns/" + railgunID
|
|
if _, err := api.makeRequest("DELETE", uri, nil); err != nil {
|
|
return errors.Wrap(err, errMakeRequestError)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ZoneRailgun represents the status of a Railgun on a zone.
|
|
type ZoneRailgun struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Enabled bool `json:"enabled"`
|
|
Connected bool `json:"connected"`
|
|
}
|
|
|
|
// zoneRailgunResponse represents the response from the Zone Railgun Details endpoint.
|
|
type zoneRailgunResponse struct {
|
|
Response
|
|
Result ZoneRailgun `json:"result"`
|
|
}
|
|
|
|
// zoneRailgunsResponse represents the response from the Zone Railgun endpoint.
|
|
type zoneRailgunsResponse struct {
|
|
Response
|
|
Result []ZoneRailgun `json:"result"`
|
|
}
|
|
|
|
// RailgunDiagnosis represents the test results from testing railgun connections
|
|
// to a zone.
|
|
type RailgunDiagnosis struct {
|
|
Method string `json:"method"`
|
|
HostName string `json:"host_name"`
|
|
HTTPStatus int `json:"http_status"`
|
|
Railgun string `json:"railgun"`
|
|
URL string `json:"url"`
|
|
ResponseStatus string `json:"response_status"`
|
|
Protocol string `json:"protocol"`
|
|
ElapsedTime string `json:"elapsed_time"`
|
|
BodySize string `json:"body_size"`
|
|
BodyHash string `json:"body_hash"`
|
|
MissingHeaders string `json:"missing_headers"`
|
|
ConnectionClose bool `json:"connection_close"`
|
|
Cloudflare string `json:"cloudflare"`
|
|
CFRay string `json:"cf-ray"`
|
|
// NOTE: Cloudflare's online API documentation does not yet have definitions
|
|
// for the following fields. See: https://api.cloudflare.com/#railgun-connections-for-a-zone-test-railgun-connection/
|
|
CFWANError string `json:"cf-wan-error"`
|
|
CFCacheStatus string `json:"cf-cache-status"`
|
|
}
|
|
|
|
// railgunDiagnosisResponse represents the response from the Test Railgun Connection enpoint.
|
|
type railgunDiagnosisResponse struct {
|
|
Response
|
|
Result RailgunDiagnosis `json:"result"`
|
|
}
|
|
|
|
// ZoneRailguns returns the available Railguns for a zone.
|
|
//
|
|
// API reference: https://api.cloudflare.com/#railguns-for-a-zone-get-available-railguns
|
|
func (api *API) ZoneRailguns(zoneID string) ([]ZoneRailgun, error) {
|
|
uri := "/zones/" + zoneID + "/railguns"
|
|
res, err := api.makeRequest("GET", uri, nil)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, errMakeRequestError)
|
|
}
|
|
var r zoneRailgunsResponse
|
|
if err := json.Unmarshal(res, &r); err != nil {
|
|
return nil, errors.Wrap(err, errUnmarshalError)
|
|
}
|
|
return r.Result, nil
|
|
}
|
|
|
|
// ZoneRailgunDetails returns the configuration for a given Railgun.
|
|
//
|
|
// API reference: https://api.cloudflare.com/#railguns-for-a-zone-get-railgun-details
|
|
func (api *API) ZoneRailgunDetails(zoneID, railgunID string) (ZoneRailgun, error) {
|
|
uri := "/zones/" + zoneID + "/railguns/" + railgunID
|
|
res, err := api.makeRequest("GET", uri, nil)
|
|
if err != nil {
|
|
return ZoneRailgun{}, errors.Wrap(err, errMakeRequestError)
|
|
}
|
|
var r zoneRailgunResponse
|
|
if err := json.Unmarshal(res, &r); err != nil {
|
|
return ZoneRailgun{}, errors.Wrap(err, errUnmarshalError)
|
|
}
|
|
return r.Result, nil
|
|
}
|
|
|
|
// TestRailgunConnection tests a Railgun connection for a given zone.
|
|
//
|
|
// API reference: https://api.cloudflare.com/#railgun-connections-for-a-zone-test-railgun-connection
|
|
func (api *API) TestRailgunConnection(zoneID, railgunID string) (RailgunDiagnosis, error) {
|
|
uri := "/zones/" + zoneID + "/railguns/" + railgunID + "/diagnose"
|
|
res, err := api.makeRequest("GET", uri, nil)
|
|
if err != nil {
|
|
return RailgunDiagnosis{}, errors.Wrap(err, errMakeRequestError)
|
|
}
|
|
var r railgunDiagnosisResponse
|
|
if err := json.Unmarshal(res, &r); err != nil {
|
|
return RailgunDiagnosis{}, errors.Wrap(err, errUnmarshalError)
|
|
}
|
|
return r.Result, nil
|
|
}
|
|
|
|
// connectZoneRailgun connects (true) or disconnects (false) a Railgun for a given zone.
|
|
//
|
|
// API reference: https://api.cloudflare.com/#railguns-for-a-zone-connect-or-disconnect-a-railgun
|
|
func (api *API) connectZoneRailgun(zoneID, railgunID string, connect bool) (ZoneRailgun, error) {
|
|
uri := "/zones/" + zoneID + "/railguns/" + railgunID
|
|
params := struct {
|
|
Connected bool `json:"connected"`
|
|
}{
|
|
Connected: connect,
|
|
}
|
|
res, err := api.makeRequest("PATCH", uri, params)
|
|
if err != nil {
|
|
return ZoneRailgun{}, errors.Wrap(err, errMakeRequestError)
|
|
}
|
|
var r zoneRailgunResponse
|
|
if err := json.Unmarshal(res, &r); err != nil {
|
|
return ZoneRailgun{}, errors.Wrap(err, errUnmarshalError)
|
|
}
|
|
return r.Result, nil
|
|
}
|
|
|
|
// ConnectZoneRailgun connects a Railgun for a given zone.
|
|
//
|
|
// API reference: https://api.cloudflare.com/#railguns-for-a-zone-connect-or-disconnect-a-railgun
|
|
func (api *API) ConnectZoneRailgun(zoneID, railgunID string) (ZoneRailgun, error) {
|
|
return api.connectZoneRailgun(zoneID, railgunID, true)
|
|
}
|
|
|
|
// DisconnectZoneRailgun disconnects a Railgun for a given zone.
|
|
//
|
|
// API reference: https://api.cloudflare.com/#railguns-for-a-zone-connect-or-disconnect-a-railgun
|
|
func (api *API) DisconnectZoneRailgun(zoneID, railgunID string) (ZoneRailgun, error) {
|
|
return api.connectZoneRailgun(zoneID, railgunID, false)
|
|
}
|