Merge pull request #7037 from hashicorp/b-cloudflare-lib-upgrade

provider/cloudflare: Upgrade library to github.com/cloudflare/cloudflare-go
This commit is contained in:
Clint 2016-06-06 15:29:39 -05:00
commit 3d4bc56d97
28 changed files with 1722 additions and 830 deletions

View File

@ -1,10 +1,10 @@
package cloudflare
import (
"fmt"
"log"
// NOTE: Temporary until they merge my PR:
"github.com/mitchellh/cloudflare-go"
"github.com/cloudflare/cloudflare-go"
)
type Config struct {
@ -14,7 +14,10 @@ type Config struct {
// Client() returns a new client for accessing cloudflare.
func (c *Config) Client() (*cloudflare.API, error) {
client := cloudflare.New(c.Token, c.Email)
client, err := cloudflare.New(c.Token, c.Email)
if err != nil {
return nil, fmt.Errorf("Error creating new CloudFlare client: %s", err)
}
log.Printf("[INFO] CloudFlare Client configured for user: %s", c.Email)
return client, nil
}

View File

@ -4,10 +4,8 @@ import (
"fmt"
"log"
"github.com/cloudflare/cloudflare-go"
"github.com/hashicorp/terraform/helper/schema"
// NOTE: Temporary until they merge my PR:
"github.com/mitchellh/cloudflare-go"
)
func resourceCloudFlareRecord() *schema.Resource {
@ -103,7 +101,13 @@ func resourceCloudFlareRecordCreate(d *schema.ResourceData, meta interface{}) er
return fmt.Errorf("Failed to create record: %s", err)
}
d.SetId(r.ID)
// In the Event that the API returns an empty DNS Record, we verify that the
// ID returned is not the default ""
if r.Result.ID == "" {
return fmt.Errorf("Failed to find record in Creat response; Record was empty")
}
d.SetId(r.Result.ID)
log.Printf("[INFO] CloudFlare Record ID: %s", d.Id())

View File

@ -5,11 +5,9 @@ import (
"os"
"testing"
"github.com/cloudflare/cloudflare-go"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
// NOTE: Temporary until they merge my PR:
"github.com/mitchellh/cloudflare-go"
)
func TestAccCloudFlareRecord_Basic(t *testing.T) {

96
vendor/github.com/cloudflare/cloudflare-go/README.md generated vendored Normal file
View File

@ -0,0 +1,96 @@
# cloudflare-go
[![GoDoc](https://img.shields.io/badge/godoc-reference-5673AF.svg?style=flat-square)](https://godoc.org/github.com/cloudflare/cloudflare-go)
[![Build Status](https://img.shields.io/travis/cloudflare/cloudflare-go/master.svg?style=flat-square)](https://travis-ci.org/cloudflare/cloudflare-go)
[![Go Report Card](https://goreportcard.com/badge/github.com/cloudflare/cloudflare-go?style=flat-square)](https://goreportcard.com/report/github.com/cloudflare/cloudflare-go)
> **Note**: This library is under active development as we expand it to cover our (expanding!) API.
Consider the public API of this package a little unstable as we work towards a v1.0.
A Go library for interacting with [CloudFlare's API v4](https://api.cloudflare.com/). This library
allows you to:
* Manage and automate changes to your DNS records within CloudFlare
* Manage and automate changes to your zones (domains) on CloudFlare, including adding new zones to
your account
* List and modify the status of WAF (Web Application Firewall) rules for your zones
* Fetch CloudFlare's IP ranges for automating your firewall whitelisting
A command-line client, [flarectl](cmd/flarectl), is also available as part of this project.
## Features
The current feature list includes:
- [x] DNS Records
- [x] Zones
- [x] Web Application Firewall (WAF)
- [x] CloudFlare IPs
- [x] User Administration (partial)
- [x] Virtual DNS Management
- [ ] Organization Administration
- [ ] [Railgun](https://www.cloudflare.com/railgun/) administration
- [ ] [Keyless SSL](https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/)
- [ ] [Origin CA](https://blog.cloudflare.com/universal-ssl-encryption-all-the-way-to-the-origin-for-free/)
Pull Requests are welcome, but please open an issue (or comment in an existing issue) to discuss any
non-trivial changes before submitting code.
## Installation
You need a working Go environment.
```
go get github.com/cloudflare/cloudflare-go
```
## Getting Started
```go
package main
import (
"fmt"
"log"
"os"
"github.com/cloudflare/cloudflare-go"
)
func main() {
// Construct a new API object
api, err := cloudflare.New(os.Getenv("CF_API_KEY"), os.Getenv("CF_API_EMAIL"))
if err != nil {
log.Fatal(err)
}
// Fetch user details on the account
u, err := api.UserDetails()
if err != nil {
log.Fatal(err)
}
// Print user details
fmt.Println(u)
// Fetch the zone ID
id, err := api.ZoneIDByName("example.com") // Assuming example.com exists in your CloudFlare account already
if err != nil {
log.Fatal(err)
}
// Fetch zone details
zone, err := api.ZoneDetails(id)
if err != nil {
log.Fatal(err)
}
// Print zone details
fmt.Println(zone)
}
```
Also refer to the [API documentation](https://godoc.org/github.com/cloudflare/cloudflare-go) for how
to use this package in-depth.
# License
BSD licensed. See the [LICENSE](LICENSE) file for details.

View File

@ -0,0 +1,317 @@
// Package cloudflare implements the CloudFlare v4 API.
package cloudflare
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"net/http"
"time"
"github.com/pkg/errors"
)
const apiURL = "https://api.cloudflare.com/client/v4"
// API holds the configuration for the current API client. A client should not
// be modified concurrently.
type API struct {
APIKey string
APIEmail string
BaseURL string
headers http.Header
httpClient *http.Client
}
// New creates a new CloudFlare v4 API client.
func New(key, email string, opts ...Option) (*API, error) {
if key == "" || email == "" {
return nil, errors.New(errEmptyCredentials)
}
api := &API{
APIKey: key,
APIEmail: email,
BaseURL: apiURL,
headers: make(http.Header),
}
err := api.parseOptions(opts...)
if err != nil {
return nil, errors.Wrap(err, "options parsing failed")
}
// Fall back to http.DefaultClient if the package user does not provide
// their own.
if api.httpClient == nil {
api.httpClient = http.DefaultClient
}
return api, nil
}
// ZoneIDByName retrieves a zone's ID from the name.
func (api *API) ZoneIDByName(zoneName string) (string, error) {
res, err := api.ListZones(zoneName)
if err != nil {
return "", errors.Wrap(err, "ListZones command failed")
}
for _, zone := range res {
if zone.Name == zoneName {
return zone.ID, nil
}
}
return "", errors.New("Zone could not be found")
}
// makeRequest makes a HTTP request and returns the body as a byte slice,
// closing it before returnng. params will be serialized to JSON.
func (api *API) makeRequest(method, uri string, params interface{}) ([]byte, error) {
// Replace nil with a JSON object if needed
var reqBody io.Reader
if params != nil {
json, err := json.Marshal(params)
if err != nil {
return nil, errors.Wrap(err, "error marshalling params to JSON")
}
reqBody = bytes.NewReader(json)
} else {
reqBody = nil
}
resp, err := api.request(method, uri, reqBody)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, errors.Wrap(err, "could not read response body")
}
switch resp.StatusCode {
case http.StatusOK:
break
case http.StatusUnauthorized:
return nil, errors.Errorf("HTTP status %d: invalid credentials", resp.StatusCode)
case http.StatusForbidden:
return nil, errors.Errorf("HTTP status %d: insufficient permissions", resp.StatusCode)
default:
var s string
if body != nil {
s = string(body)
}
return nil, errors.Errorf("HTTP status %d: content %q", resp.StatusCode, s)
}
return body, nil
}
// request makes a HTTP request to the given API endpoint, returning the raw
// *http.Response, or an error if one occurred. The caller is responsible for
// closing the response body.
func (api *API) request(method, uri string, reqBody io.Reader) (*http.Response, error) {
req, err := http.NewRequest(method, api.BaseURL+uri, reqBody)
if err != nil {
return nil, errors.Wrap(err, "HTTP request creation failed")
}
// Apply any user-defined headers first.
req.Header = api.headers
req.Header.Set("X-Auth-Key", api.APIKey)
req.Header.Set("X-Auth-Email", api.APIEmail)
resp, err := api.httpClient.Do(req)
if err != nil {
return nil, errors.Wrap(err, "HTTP request failed")
}
return resp, nil
}
// ResponseInfo contains a code and message returned by the API as errors or
// informational messages inside the response.
type ResponseInfo struct {
Code int `json:"code"`
Message string `json:"message"`
}
// Response is a template. There will also be a result struct. There will be a
// unique response type for each response, which will include this type.
type Response struct {
Success bool `json:"success"`
Errors []ResponseInfo `json:"errors"`
Messages []ResponseInfo `json:"messages"`
}
// ResultInfo contains metadata about the Response.
type ResultInfo struct {
Page int `json:"page"`
PerPage int `json:"per_page"`
Count int `json:"count"`
Total int `json:"total_count"`
}
// User describes a user account.
type User struct {
ID string `json:"id"`
Email string `json:"email"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Username string `json:"username"`
Telephone string `json:"telephone"`
Country string `json:"country"`
Zipcode string `json:"zipcode"`
CreatedOn time.Time `json:"created_on"`
ModifiedOn time.Time `json:"modified_on"`
APIKey string `json:"api_key"`
TwoFA bool `json:"two_factor_authentication_enabled"`
Betas []string `json:"betas"`
Organizations []Organization `json:"organizations"`
}
// UserResponse wraps a response containing User accounts.
type UserResponse struct {
Response
Result User `json:"result"`
}
// Owner describes the resource owner.
type Owner struct {
ID string `json:"id"`
Email string `json:"email"`
OwnerType string `json:"owner_type"`
}
// DNSRecord represents a DNS record in a zone.
type DNSRecord struct {
ID string `json:"id,omitempty"`
Type string `json:"type,omitempty"`
Name string `json:"name,omitempty"`
Content string `json:"content,omitempty"`
Proxiable bool `json:"proxiable,omitempty"`
Proxied bool `json:"proxied,omitempty"`
TTL int `json:"ttl,omitempty"`
Locked bool `json:"locked,omitempty"`
ZoneID string `json:"zone_id,omitempty"`
ZoneName string `json:"zone_name,omitempty"`
CreatedOn time.Time `json:"created_on,omitempty"`
ModifiedOn time.Time `json:"modified_on,omitempty"`
Data interface{} `json:"data,omitempty"` // data returned by: SRV, LOC
Meta interface{} `json:"meta,omitempty"`
Priority int `json:"priority,omitempty"`
}
// DNSRecordResponse represents the response from the DNS endpoint.
type DNSRecordResponse struct {
Response
Result DNSRecord `json:"result"`
}
// DNSListResponse represents the response from the list DNS records endpoint.
type DNSListResponse struct {
Response
Result []DNSRecord `json:"result"`
}
// KeylessSSL represents Keyless SSL configuration.
type KeylessSSL struct {
ID string `json:"id"`
Name string `json:"name"`
Host string `json:"host"`
Port int `json:"port"`
Status string `json:"success"`
Enabled bool `json:"enabled"`
Permissions []string `json:"permissions"`
CreatedOn time.Time `json:"created_on"`
ModifiedOn time.Time `json:"modifed_on"`
}
// KeylessSSLResponse represents the response from the Keyless SSL endpoint.
type KeylessSSLResponse struct {
Response
Result []KeylessSSL `json:"result"`
}
// CustomPage represents a custom page configuration.
type CustomPage struct {
CreatedOn string `json:"created_on"`
ModifiedOn time.Time `json:"modified_on"`
URL string `json:"url"`
State string `json:"state"`
RequiredTokens []string `json:"required_tokens"`
PreviewTarget string `json:"preview_target"`
Description string `json:"description"`
}
// CustomPageResponse represents the response from the custom pages endpoint.
type CustomPageResponse struct {
Response
Result []CustomPage `json:"result"`
}
// WAFPackage represents a WAF package configuration.
type WAFPackage struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
ZoneID string `json:"zone_id"`
DetectionMode string `json:"detection_mode"`
Sensitivity string `json:"sensitivity"`
ActionMode string `json:"action_mode"`
}
// WAFPackagesResponse represents the response from the WAF packages endpoint.
type WAFPackagesResponse struct {
Response
Result []WAFPackage `json:"result"`
ResultInfo ResultInfo `json:"result_info"`
}
// WAFRule represents a WAF rule.
type WAFRule struct {
ID string `json:"id"`
Description string `json:"description"`
Priority string `json:"priority"`
PackageID string `json:"package_id"`
Group struct {
ID string `json:"id"`
Name string `json:"name"`
} `json:"group"`
Mode string `json:"mode"`
DefaultMode string `json:"default_mode"`
AllowedModes []string `json:"allowed_modes"`
}
// WAFRulesResponse represents the response from the WAF rule endpoint.
type WAFRulesResponse struct {
Response
Result []WAFRule `json:"result"`
ResultInfo ResultInfo `json:"result_info"`
}
// PurgeCacheRequest represents the request format made to the purge endpoint.
type PurgeCacheRequest struct {
Everything bool `json:"purge_everything,omitempty"`
Files []string `json:"files,omitempty"`
Tags []string `json:"tags,omitempty"`
}
// PurgeCacheResponse represents the response from the purge endpoint.
type PurgeCacheResponse struct {
Response
}
// IPRanges contains lists of IPv4 and IPv6 CIDRs
type IPRanges struct {
IPv4CIDRs []string `json:"ipv4_cidrs"`
IPv6CIDRs []string `json:"ipv6_cidrs"`
}
// IPsResponse is the API response containing a list of IPs
type IPsResponse struct {
Response
Result IPRanges `json:"result"`
}

View File

@ -7,34 +7,30 @@ import (
"github.com/pkg/errors"
)
/*
Create a DNS record.
API reference:
https://api.cloudflare.com/#dns-records-for-a-zone-create-dns-record
POST /zones/:zone_identifier/dns_records
*/
func (api *API) CreateDNSRecord(zoneID string, rr DNSRecord) (DNSRecord, error) {
// CreateDNSRecord creates a DNS record for the zone identifier.
// API reference:
// https://api.cloudflare.com/#dns-records-for-a-zone-create-dns-record
// POST /zones/:zone_identifier/dns_records
func (api *API) CreateDNSRecord(zoneID string, rr DNSRecord) (*DNSRecordResponse, error) {
uri := "/zones/" + zoneID + "/dns_records"
res, err := api.makeRequest("POST", uri, rr)
if err != nil {
return DNSRecord{}, errors.Wrap(err, errMakeRequestError)
return nil, errors.Wrap(err, errMakeRequestError)
}
var r DNSRecordResponse
err = json.Unmarshal(res, &r)
var recordResp *DNSRecordResponse
err = json.Unmarshal(res, &recordResp)
if err != nil {
return DNSRecord{}, errors.Wrap(err, errUnmarshalError)
return nil, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
return recordResp, nil
}
/*
Fetches DNS records for a zone.
API reference:
https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records
GET /zones/:zone_identifier/dns_records
*/
// DNSRecords returns a slice of DNS records for the given zone identifier.
// API reference:
// https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records
// GET /zones/:zone_identifier/dns_records
func (api *API) DNSRecords(zoneID string, rr DNSRecord) ([]DNSRecord, error) {
// Construct a query string
v := url.Values{}
@ -64,13 +60,11 @@ func (api *API) DNSRecords(zoneID string, rr DNSRecord) ([]DNSRecord, error) {
return r.Result, nil
}
/*
Fetches a single DNS record.
API reference:
https://api.cloudflare.com/#dns-records-for-a-zone-dns-record-details
GET /zones/:zone_identifier/dns_records/:identifier
*/
// DNSRecord returns a single DNS record for the given zone & record
// identifiers.
// API reference:
// https://api.cloudflare.com/#dns-records-for-a-zone-dns-record-details
// GET /zones/:zone_identifier/dns_records/:identifier
func (api *API) DNSRecord(zoneID, recordID string) (DNSRecord, error) {
uri := "/zones/" + zoneID + "/dns_records/" + recordID
res, err := api.makeRequest("GET", uri, nil)
@ -85,13 +79,11 @@ func (api *API) DNSRecord(zoneID, recordID string) (DNSRecord, error) {
return r.Result, nil
}
/*
Change a DNS record.
API reference:
https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record
PUT /zones/:zone_identifier/dns_records/:identifier
*/
// UpdateDNSRecord updates a single DNS record for the given zone & record
// identifiers.
// API reference:
// https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record
// PUT /zones/:zone_identifier/dns_records/:identifier
func (api *API) UpdateDNSRecord(zoneID, recordID string, rr DNSRecord) error {
rec, err := api.DNSRecord(zoneID, recordID)
if err != nil {
@ -112,13 +104,11 @@ func (api *API) UpdateDNSRecord(zoneID, recordID string, rr DNSRecord) error {
return nil
}
/*
Delete a DNS record.
API reference:
https://api.cloudflare.com/#dns-records-for-a-zone-delete-dns-record
DELETE /zones/:zone_identifier/dns_records/:identifier
*/
// DeleteDNSRecord deletes a single DNS record for the given zone & record
// identifiers.
// API reference:
// https://api.cloudflare.com/#dns-records-for-a-zone-delete-dns-record
// DELETE /zones/:zone_identifier/dns_records/:identifier
func (api *API) DeleteDNSRecord(zoneID, recordID string) error {
uri := "/zones/" + zoneID + "/dns_records/" + recordID
res, err := api.makeRequest("DELETE", uri, nil)

47
vendor/github.com/cloudflare/cloudflare-go/errors.go generated vendored Normal file
View File

@ -0,0 +1,47 @@
package cloudflare
// Error messages
const (
errEmptyCredentials = "invalid credentials: key & email must not be empty"
errMakeRequestError = "error from makeRequest"
errUnmarshalError = "error unmarshalling the JSON response"
)
var _ Error = &UserError{}
// Error represents an error returned from this library.
type Error interface {
error
// Raised when user credentials or configuration is invalid.
User() bool
// Raised when a parsing error (e.g. JSON) occurs.
Parse() bool
// Raised when a network error occurs.
Network() bool
// Contains the most recent error.
}
// UserError represents a user-generated error.
type UserError struct {
Err error
}
// User is a user-caused error.
func (e *UserError) User() bool {
return true
}
// Network error.
func (e *UserError) Network() bool {
return false
}
// Parse error.
func (e *UserError) Parse() bool {
return true
}
// Error wraps the underlying error.
func (e *UserError) Error() string {
return e.Err.Error()
}

36
vendor/github.com/cloudflare/cloudflare-go/keyless.go generated vendored Normal file
View File

@ -0,0 +1,36 @@
package cloudflare
// CreateKeyless creates a new Keyless SSL configuration for the zone.
// API reference:
// https://api.cloudflare.com/#keyless-ssl-for-a-zone-create-a-keyless-ssl-configuration
// POST /zones/:zone_identifier/keyless_certificates
func (api *API) CreateKeyless() {
}
// ListKeyless lists Keyless SSL configurations for a zone.
// API reference:
// https://api.cloudflare.com/#keyless-ssl-for-a-zone-list-keyless-ssls
// GET /zones/:zone_identifier/keyless_certificates
func (api *API) ListKeyless() {
}
// Keyless provides the configuration for a given Keyless SSL identifier.
// API reference:
// https://api.cloudflare.com/#keyless-ssl-for-a-zone-keyless-ssl-details
// GET /zones/:zone_identifier/keyless_certificates/:identifier
func (api *API) Keyless() {
}
// UpdateKeyless updates an existing Keyless SSL configuration.
// API reference:
// https://api.cloudflare.com/#keyless-ssl-for-a-zone-update-keyless-configuration
// PATCH /zones/:zone_identifier/keyless_certificates/:identifier
func (api *API) UpdateKeyless() {
}
// DeleteKeyless deletes an existing Keyless SSL configuration.
// API reference:
// https://api.cloudflare.com/#keyless-ssl-for-a-zone-delete-keyless-configuration
// DELETE /zones/:zone_identifier/keyless_certificates/:identifier
func (api *API) DeleteKeyless() {
}

39
vendor/github.com/cloudflare/cloudflare-go/options.go generated vendored Normal file
View File

@ -0,0 +1,39 @@
package cloudflare
import "net/http"
// Option is a functional option for configuring the API client.
type Option func(*API) error
// HTTPClient accepts a custom *http.Client for making API calls.
func HTTPClient(client *http.Client) Option {
return func(api *API) error {
api.httpClient = client
return nil
}
}
// Headers allows you to set custom HTTP headers when making API calls (e.g. for
// satisfying HTTP proxies, or for debugging).
func Headers(headers http.Header) Option {
return func(api *API) error {
api.headers = headers
return nil
}
}
// parseOptions parses the supplied options functions and returns a configured
// *API instance.
func (api *API) parseOptions(opts ...Option) error {
// Range over each options function and apply it to our API type to
// configure it. Options functions are applied in order, with any
// conflicting options overriding earlier calls.
for _, option := range opts {
err := option(api)
if err != nil {
return err
}
}
return nil
}

View File

@ -0,0 +1,17 @@
package cloudflare
// Organization represents a multi-user organization.
type Organization struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Status string `json:"status,omitempty"`
Permissions []string `json:"permissions,omitempty"`
Roles []string `json:"roles,omitempty"`
}
// OrganizationResponse represents the response from the Organization endpoint.
type OrganizationResponse struct {
Response
Result []Organization `json:"result"`
ResultInfo ResultInfo `json:"result_info"`
}

View File

@ -2,6 +2,7 @@ package cloudflare
import (
"encoding/json"
"time"
"github.com/pkg/errors"
)
@ -32,13 +33,13 @@ Valid IDs are:
cache_level
disable_apps
disable_performance
disable_railgun
disable_security
edge_cache_ttl
email_obfuscation
forwarding_url
ip_geolocation
mirage
railgun
rocket_loader
security_level
server_side_exclude
@ -60,13 +61,13 @@ var PageRuleActions = map[string]string{
"cache_level": "Cache Level", // Value of type string
"disable_apps": "Disable Apps", // Value of type interface{}
"disable_performance": "Disable Performance", // Value of type interface{}
"disable_railgun": "Disable Railgun", // Value of type string
"disable_security": "Disable Security", // Value of type interface{}
"edge_cache_ttl": "Edge Cache TTL", // Value of type int
"email_obfuscation": "Email Obfuscation", // Value of type string
"forwarding_url": "Forwarding URL", // Value of type map[string]interface
"ip_geolocation": "IP Geolocation Header", // Value of type string
"mirage": "Mirage", // Value of type string
"railgun": "Railgun", // Value of type string
"rocket_loader": "Rocker Loader", // Value of type string
"security_level": "Security Level", // Value of type string
"server_side_exclude": "Server Side Excludes", // Value of type string
@ -82,8 +83,8 @@ type PageRule struct {
Actions []PageRuleAction `json:"actions"`
Priority int `json:"priority"`
Status string `json:"status"` // can be: active, paused
ModifiedOn string `json:"modified_on,omitempty"`
CreatedOn string `json:"created_on,omitempty"`
ModifiedOn time.Time `json:"modified_on,omitempty"`
CreatedOn time.Time `json:"created_on,omitempty"`
}
// PageRuleDetailResponse is the API response, containing a single PageRule.

311
vendor/github.com/cloudflare/cloudflare-go/railgun.go generated vendored Normal file
View File

@ -0,0 +1,311 @@
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
// POST /railguns
func (api *API) CreateRailgun(name string) (Railgun, error) {
uri := "/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
// GET /railguns
func (api *API) ListRailguns(options RailgunListOptions) ([]Railgun, error) {
v := url.Values{}
if options.Direction != "" {
v.Set("direction", options.Direction)
}
uri := "/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
// GET /railguns/:identifier
func (api *API) RailgunDetails(railgunID string) (Railgun, error) {
uri := "/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
// GET /railguns/:identifier/zones
func (api *API) RailgunZones(railgunID string) ([]Zone, error) {
uri := "/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
// PATCH /railguns/:identifier
func (api *API) enableRailgun(railgunID string, enable bool) (Railgun, error) {
uri := "/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
// PATCH /railguns/:identifier
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
// PATCH /railguns/:identifier
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
// DELETE /railguns/:identifier
func (api *API) DeleteRailgun(railgunID string) error {
uri := "/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
// GET /zones/:zone_identifier/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
}
// Railgun returns the configuration for a given Railgun.
// API reference:
// https://api.cloudflare.com/#railguns-for-a-zone-get-railgun-details
// GET /zones/:zone_identifier/railguns/:identifier
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
}
// TestRailgunResponse tests a Railgun connection for a given zone.
// API reference:
// https://api.cloudflare.com/#railgun-connections-for-a-zone-test-railgun-connection
// GET /zones/:zone_identifier/railguns/:identifier/diagnose
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
// PATCH /zones/:zone_identifier/railguns/:identifier
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
}
// ZoneRailgun connects a Railgun for a given zone.
// API reference:
// https://api.cloudflare.com/#railguns-for-a-zone-connect-or-disconnect-a-railgun
// PATCH /zones/:zone_identifier/railguns/:identifier
func (api *API) ConnectZoneRailgun(zoneID, railgunID string) (ZoneRailgun, error) {
return api.connectZoneRailgun(zoneID, railgunID, true)
}
// ZoneRailgun disconnects a Railgun for a given zone.
// API reference:
// https://api.cloudflare.com/#railguns-for-a-zone-connect-or-disconnect-a-railgun
// PATCH /zones/:zone_identifier/railguns/:identifier
func (api *API) DisconnectZoneRailgun(zoneID, railgunID string) (ZoneRailgun, error) {
return api.connectZoneRailgun(zoneID, railgunID, false)
}

154
vendor/github.com/cloudflare/cloudflare-go/ssl.go generated vendored Normal file
View File

@ -0,0 +1,154 @@
package cloudflare
import (
"encoding/json"
"time"
"github.com/pkg/errors"
)
// ZoneCustomSSL represents custom SSL certificate metadata.
type ZoneCustomSSL struct {
ID string `json:"id"`
Hosts []string `json:"hosts"`
Issuer string `json:"issuer"`
Signature string `json:"signature"`
Status string `json:"status"`
BundleMethod string `json:"bundle_method"`
ZoneID string `json:"zone_id"`
UploadedOn time.Time `json:"uploaded_on"`
ModifiedOn time.Time `json:"modified_on"`
ExpiresOn time.Time `json:"expires_on"`
Priority int `json:"priority"`
KeylessServer KeylessSSL `json:"keyless_server"`
}
// zoneCustomSSLResponse represents the response from the zone SSL details endpoint.
type zoneCustomSSLResponse struct {
Response
Result ZoneCustomSSL `json:"result"`
}
// zoneCustomSSLsResponse represents the response from the zone SSL list endpoint.
type zoneCustomSSLsResponse struct {
Response
Result []ZoneCustomSSL `json:"result"`
}
// ZoneCustomSSLOptions represents the parameters to create or update an existing
// custom SSL configuration.
type ZoneCustomSSLOptions struct {
Certificate string `json:"certificate"`
PrivateKey string `json:"private_key"`
BundleMethod string `json:"bundle_method,omitempty"`
}
// ZoneCustomSSLPriority represents a certificate's ID and priority. It is a
// subset of ZoneCustomSSL used for patch requests.
type ZoneCustomSSLPriority struct {
ID string `json:"ID"`
Priority int `json:"priority"`
}
// CreateSSL allows you to add a custom SSL certificate to the given zone.
// API reference:
// https://api.cloudflare.com/#custom-ssl-for-a-zone-create-ssl-configuration
// POST /zones/:zone_identifier/custom_certificates
func (api *API) CreateSSL(zoneID string, options ZoneCustomSSLOptions) (ZoneCustomSSL, error) {
uri := "/zones/" + zoneID + "/custom_certificates"
res, err := api.makeRequest("POST", uri, options)
if err != nil {
return ZoneCustomSSL{}, errors.Wrap(err, errMakeRequestError)
}
var r zoneCustomSSLResponse
if err := json.Unmarshal(res, &r); err != nil {
return ZoneCustomSSL{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
// ListSSL lists the custom certificates for the given zone.
// API reference:
// https://api.cloudflare.com/#custom-ssl-for-a-zone-list-ssl-configurations
// GET /zones/:zone_identifier/custom_certificates
func (api *API) ListSSL(zoneID string) ([]ZoneCustomSSL, error) {
uri := "/zones/" + zoneID + "/custom_certificates"
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return nil, errors.Wrap(err, errMakeRequestError)
}
var r zoneCustomSSLsResponse
if err := json.Unmarshal(res, &r); err != nil {
return nil, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
// SSLDetails returns the configuration details for a custom SSL certificate.
// API reference:
// https://api.cloudflare.com/#custom-ssl-for-a-zone-ssl-configuration-details
// GET /zones/:zone_identifier/custom_certificates/:identifier
func (api *API) SSLDetails(zoneID, certificateID string) (ZoneCustomSSL, error) {
uri := "/zones/" + zoneID + "/custom_certificates/" + certificateID
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return ZoneCustomSSL{}, errors.Wrap(err, errMakeRequestError)
}
var r zoneCustomSSLResponse
if err := json.Unmarshal(res, &r); err != nil {
return ZoneCustomSSL{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
// UpdateSSL updates (replaces) a custom SSL certificate.
// API reference:
// https://api.cloudflare.com/#custom-ssl-for-a-zone-update-ssl-configuration
// PATCH /zones/:zone_identifier/custom_certificates/:identifier
func (api *API) UpdateSSL(zoneID, certificateID string, options ZoneCustomSSLOptions) (ZoneCustomSSL, error) {
uri := "/zones/" + zoneID + "/custom_certificates/" + certificateID
res, err := api.makeRequest("PATCH", uri, options)
if err != nil {
return ZoneCustomSSL{}, errors.Wrap(err, errMakeRequestError)
}
var r zoneCustomSSLResponse
if err := json.Unmarshal(res, &r); err != nil {
return ZoneCustomSSL{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
// ReprioritizeSSL allows you to change the priority (which is served for a given
// request) of custom SSL certificates associated with the given zone.
// API reference:
// https://api.cloudflare.com/#custom-ssl-for-a-zone-re-prioritize-ssl-certificates
// PUT /zones/:zone_identifier/custom_certificates/prioritize
func (api *API) ReprioritizeSSL(zoneID string, p []ZoneCustomSSLPriority) ([]ZoneCustomSSL, error) {
uri := "/zones/" + zoneID + "/custom_certificates/prioritize"
params := struct {
Certificates []ZoneCustomSSLPriority `json:"certificates"`
}{
Certificates: p,
}
res, err := api.makeRequest("PUT", uri, params)
if err != nil {
return nil, errors.Wrap(err, errMakeRequestError)
}
var r zoneCustomSSLsResponse
if err := json.Unmarshal(res, &r); err != nil {
return nil, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
// DeleteSSL deletes a custom SSL certificate from the given zone.
// API reference:
// https://api.cloudflare.com/#custom-ssl-for-a-zone-delete-an-ssl-certificate
// DELETE /zones/:zone_identifier/custom_certificates/:identifier
func (api *API) DeleteSSL(zoneID, certificateID string) error {
uri := "/zones/" + zoneID + "/custom_certificates/" + certificateID
if _, err := api.makeRequest("DELETE", uri, nil); err != nil {
return errors.Wrap(err, errMakeRequestError)
}
return nil
}

View File

@ -6,30 +6,30 @@ import (
"github.com/pkg/errors"
)
/*
Information about the logged-in user.
API reference: https://api.cloudflare.com/#user-user-details
*/
func (api API) UserDetails() (User, error) {
// UserDetails provides information about the logged-in user.
// API reference:
// https://api.cloudflare.com/#user-user-details
// GET /user
func (api *API) UserDetails() (User, error) {
var r UserResponse
res, err := api.makeRequest("GET", "/user", nil)
if err != nil {
return User{}, errors.Wrap(err, errMakeRequestError)
}
err = json.Unmarshal(res, &r)
if err != nil {
return User{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
/*
Update user properties.
API reference: https://api.cloudflare.com/#user-update-user
*/
func (api API) UpdateUser() (User, error) {
// UpdateUser updates the properties of the given user.
// API reference:
// https://api.cloudflare.com/#user-update-user
// PATCH /user
func (api *API) UpdateUser() (User, error) {
// api.makeRequest("PATCH", "/user", user)
return User{}, nil
}

View File

@ -0,0 +1,130 @@
package cloudflare
import (
"encoding/json"
"github.com/pkg/errors"
)
// VirtualDNS represents a Virtual DNS configuration.
type VirtualDNS struct {
ID string `json:"id"`
Name string `json:"name"`
OriginIPs []string `json:"origin_ips"`
VirtualDNSIPs []string `json:"virtual_dns_ips"`
MinimumCacheTTL uint `json:"minimum_cache_ttl"`
MaximumCacheTTL uint `json:"maximum_cache_ttl"`
DeprecateAnyRequests bool `json:"deprecate_any_requests"`
ModifiedOn string `json:"modified_on"`
}
// VirtualDNSResponse represents a Virtual DNS response.
type VirtualDNSResponse struct {
Response
Result *VirtualDNS `json:"result"`
}
// VirtualDNSListResponse represents an array of Virtual DNS responses.
type VirtualDNSListResponse struct {
Response
Result []*VirtualDNS `json:"result"`
}
// CreateVirtualDNS creates a new Virtual DNS cluster.
// API reference:
// https://api.cloudflare.com/#virtual-dns-users--create-a-virtual-dns-cluster
// POST /user/virtual_dns
func (api *API) CreateVirtualDNS(v *VirtualDNS) (*VirtualDNS, error) {
res, err := api.makeRequest("POST", "/user/virtual_dns", v)
if err != nil {
return nil, errors.Wrap(err, errMakeRequestError)
}
response := &VirtualDNSResponse{}
err = json.Unmarshal(res, &response)
if err != nil {
return nil, errors.Wrap(err, errUnmarshalError)
}
return response.Result, nil
}
// VirtualDNS fetches a single virtual DNS cluster.
// API reference:
// https://api.cloudflare.com/#virtual-dns-users--get-a-virtual-dns-cluster
// GET /user/virtual_dns/:identifier
func (api *API) VirtualDNS(virtualDNSID string) (*VirtualDNS, error) {
uri := "/user/virtual_dns/" + virtualDNSID
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return nil, errors.Wrap(err, errMakeRequestError)
}
response := &VirtualDNSResponse{}
err = json.Unmarshal(res, &response)
if err != nil {
return nil, errors.Wrap(err, errUnmarshalError)
}
return response.Result, nil
}
// ListVirtualDNS lists the virtual DNS clusters associated with an account.
// API reference:
// https://api.cloudflare.com/#virtual-dns-users--get-virtual-dns-clusters
// GET /user/virtual_dns
func (api *API) ListVirtualDNS() ([]*VirtualDNS, error) {
res, err := api.makeRequest("GET", "/user/virtual_dns", nil)
if err != nil {
return nil, errors.Wrap(err, errMakeRequestError)
}
response := &VirtualDNSListResponse{}
err = json.Unmarshal(res, &response)
if err != nil {
return nil, errors.Wrap(err, errUnmarshalError)
}
return response.Result, nil
}
// UpdateVirtualDNS updates a Virtual DNS cluster.
// API reference:
// https://api.cloudflare.com/#virtual-dns-users--modify-a-virtual-dns-cluster
// PATCH /user/virtual_dns/:identifier
func (api *API) UpdateVirtualDNS(virtualDNSID string, vv VirtualDNS) error {
uri := "/user/virtual_dns/" + virtualDNSID
res, err := api.makeRequest("PUT", uri, vv)
if err != nil {
return errors.Wrap(err, errMakeRequestError)
}
response := &VirtualDNSResponse{}
err = json.Unmarshal(res, &response)
if err != nil {
return errors.Wrap(err, errUnmarshalError)
}
return nil
}
// DeleteVirtualDNS deletes a Virtual DNS cluster. Note that this cannot be
// undone, and will stop all traffic to that cluster.
// API reference:
// https://api.cloudflare.com/#virtual-dns-users--delete-a-virtual-dns-cluster
// DELETE /user/virtual_dns/:identifier
func (api *API) DeleteVirtualDNS(virtualDNSID string) error {
uri := "/user/virtual_dns/" + virtualDNSID
res, err := api.makeRequest("DELETE", uri, nil)
if err != nil {
return errors.Wrap(err, errMakeRequestError)
}
response := &VirtualDNSResponse{}
err = json.Unmarshal(res, &response)
if err != nil {
return errors.Wrap(err, errUnmarshalError)
}
return nil
}

View File

@ -6,6 +6,7 @@ import (
"github.com/pkg/errors"
)
// ListWAFPackages returns a slice of the WAF packages for the given zone.
func (api *API) ListWAFPackages(zoneID string) ([]WAFPackage, error) {
var p WAFPackagesResponse
var packages []WAFPackage
@ -24,12 +25,13 @@ func (api *API) ListWAFPackages(zoneID string) ([]WAFPackage, error) {
// TODO: Provide an actual error message instead of always returning nil
return []WAFPackage{}, err
}
for pi, _ := range p.Result {
for pi := range p.Result {
packages = append(packages, p.Result[pi])
}
return packages, nil
}
// ListWAFRules returns a slice of the WAF rules for the given WAF package.
func (api *API) ListWAFRules(zoneID, packageID string) ([]WAFRule, error) {
var r WAFRulesResponse
var rules []WAFRule
@ -48,7 +50,7 @@ func (api *API) ListWAFRules(zoneID, packageID string) ([]WAFRule, error) {
// TODO: Provide an actual error message instead of always returning nil
return []WAFRule{}, err
}
for ri, _ := range r.Result {
for ri := range r.Result {
rules = append(rules, r.Result[ri])
}
return rules, nil

502
vendor/github.com/cloudflare/cloudflare-go/zone.go generated vendored Normal file
View File

@ -0,0 +1,502 @@
package cloudflare
import (
"encoding/json"
"fmt"
"net/url"
"time"
"github.com/pkg/errors"
)
// Zone describes a CloudFlare zone.
type Zone struct {
ID string `json:"id"`
Name string `json:"name"`
DevMode int `json:"development_mode"`
OriginalNS []string `json:"original_name_servers"`
OriginalRegistrar string `json:"original_registrar"`
OriginalDNSHost string `json:"original_dnshost"`
CreatedOn string `json:"created_on"`
ModifiedOn string `json:"modified_on"`
NameServers []string `json:"name_servers"`
Owner Owner `json:"owner"`
Permissions []string `json:"permissions"`
Plan ZonePlan `json:"plan"`
PlanPending ZonePlan `json:"plan_pending,omitempty"`
Status string `json:"status"`
Paused bool `json:"paused"`
Type string `json:"type"`
Host struct {
Name string
Website string
} `json:"host"`
VanityNS []string `json:"vanity_name_servers"`
Betas []string `json:"betas"`
DeactReason string `json:"deactivation_reason"`
Meta ZoneMeta `json:"meta"`
}
// ZoneMeta metadata about a zone.
type ZoneMeta struct {
// custom_certificate_quota is broken - sometimes it's a string, sometimes a number!
// CustCertQuota int `json:"custom_certificate_quota"`
PageRuleQuota int `json:"page_rule_quota"`
WildcardProxiable bool `json:"wildcard_proxiable"`
PhishingDetected bool `json:"phishing_detected"`
}
// ZonePlan contains the plan information for a zone.
type ZonePlan struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
Price int `json:"price,omitempty"`
Currency string `json:"currency,omitempty"`
Frequency string `json:"frequency,omitempty"`
LegacyID string `json:"legacy_id,omitempty"`
IsSubscribed bool `json:"is_subscribed,omitempty"`
CanSubscribe bool `json:"can_subscribe,omitempty"`
}
// ZoneID contains only the zone ID.
type ZoneID struct {
ID string `json:"id"`
}
// ZoneResponse represents the response from the Zone endpoint containing a single zone.
type ZoneResponse struct {
Response
Result Zone `json:"result"`
}
// ZonesResponse represents the response from the Zone endpoint containing an array of zones.
type ZonesResponse struct {
Response
Result []Zone `json:"result"`
}
// ZoneIDResponse represents the response from the Zone endpoint, containing only a zone ID.
type ZoneIDResponse struct {
Response
Result ZoneID `json:"result"`
}
// AvailableZonePlansResponse represents the response from the Available Plans endpoint.
type AvailableZonePlansResponse struct {
Response
Result []ZonePlan `json:"result"`
ResultInfo
}
// ZonePlanResponse represents the response from the Plan Details endpoint.
type ZonePlanResponse struct {
Response
Result ZonePlan `json:"result"`
}
// ZoneSetting contains settings for a zone.
type ZoneSetting struct {
ID string `json:"id"`
Editable bool `json:"editable"`
ModifiedOn string `json:"modified_on"`
Value interface{} `json:"value"`
TimeRemaining int `json:"time_remaining"`
}
// ZoneSettingResponse represents the response from the Zone Setting endpoint.
type ZoneSettingResponse struct {
Response
Result []ZoneSetting `json:"result"`
}
// ZoneAnalyticsData contains totals and timeseries analytics data for a zone.
type ZoneAnalyticsData struct {
Totals ZoneAnalytics `json:"totals"`
Timeseries []ZoneAnalytics `json:"timeseries"`
}
// zoneAnalyticsDataResponse represents the response from the Zone Analytics Dashboard endpoint.
type zoneAnalyticsDataResponse struct {
Response
Result ZoneAnalyticsData `json:"result"`
}
// ZoneAnalyticsColocation contains analytics data by datacenter.
type ZoneAnalyticsColocation struct {
ColocationID string `json:"colo_id"`
Timeseries []ZoneAnalytics `json:"timeseries"`
}
// zoneAnalyticsColocationResponse represents the response from the Zone Analytics By Co-location endpoint.
type zoneAnalyticsColocationResponse struct {
Response
Result []ZoneAnalyticsColocation `json:"result"`
}
// ZoneAnalytics contains analytics data for a zone.
type ZoneAnalytics struct {
Since time.Time `json:"since"`
Until time.Time `json:"until"`
Requests struct {
All int `json:"all"`
Cached int `json:"cached"`
Uncached int `json:"uncached"`
ContentType map[string]int `json:"content_type"`
Country map[string]int `json:"country"`
SSL struct {
Encrypted int `json:"encrypted"`
Unencrypted int `json:"unencrypted"`
} `json:"ssl"`
HTTPStatus map[string]int `json:"http_status"`
} `json:"requests"`
Bandwidth struct {
All int `json:"all"`
Cached int `json:"cached"`
Uncached int `json:"uncached"`
ContentType map[string]int `json:"content_type"`
Country map[string]int `json:"country"`
SSL struct {
Encrypted int `json:"encrypted"`
Unencrypted int `json:"unencrypted"`
} `json:"ssl"`
} `json:"bandwidth"`
Threats struct {
All int `json:"all"`
Country map[string]int `json:"country"`
Type map[string]int `json:"type"`
} `json:"threats"`
Pageviews struct {
All int `json:"all"`
SearchEngines map[string]int `json:"search_engines"`
} `json:"pageviews"`
Uniques struct {
All int `json:"all"`
}
}
// ZoneAnalyticsOptions represents the optional parameters in Zone Analytics
// endpoint requests.
type ZoneAnalyticsOptions struct {
Since *time.Time
Until *time.Time
Continuous *bool
}
// newZone describes a new zone.
type newZone struct {
Name string `json:"name"`
JumpStart bool `json:"jump_start"`
// We use a pointer to get a nil type when the field is empty.
// This allows us to completely omit this with json.Marshal().
Organization *Organization `json:"organization,omitempty"`
}
// CreateZone creates a zone on an account.
//
// API reference: https://api.cloudflare.com/#zone-create-a-zone
func (api *API) CreateZone(name string, jumpstart bool, org Organization) (Zone, error) {
var newzone newZone
newzone.Name = name
newzone.JumpStart = jumpstart
if org.ID != "" {
newzone.Organization = &org
}
res, err := api.makeRequest("POST", "/zones", newzone)
if err != nil {
return Zone{}, errors.Wrap(err, errMakeRequestError)
}
var r ZoneResponse
err = json.Unmarshal(res, &r)
if err != nil {
return Zone{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
// ZoneActivationCheck initiates another zone activation check for newly-created zones.
//
// API reference: https://api.cloudflare.com/#zone-initiate-another-zone-activation-check
func (api *API) ZoneActivationCheck(zoneID string) (Response, error) {
res, err := api.makeRequest("PUT", "/zones/"+zoneID+"/activation_check", nil)
if err != nil {
return Response{}, errors.Wrap(err, errMakeRequestError)
}
var r Response
err = json.Unmarshal(res, &r)
if err != nil {
return Response{}, errors.Wrap(err, errUnmarshalError)
}
return r, nil
}
// ListZones lists zones on an account. Optionally takes a list of zone names
// to filter against.
//
// API reference: https://api.cloudflare.com/#zone-list-zones
func (api *API) ListZones(z ...string) ([]Zone, error) {
v := url.Values{}
var res []byte
var r ZonesResponse
var zones []Zone
var err error
if len(z) > 0 {
for _, zone := range z {
v.Set("name", zone)
res, err = api.makeRequest("GET", "/zones?"+v.Encode(), nil)
if err != nil {
return []Zone{}, errors.Wrap(err, errMakeRequestError)
}
err = json.Unmarshal(res, &r)
if err != nil {
return []Zone{}, errors.Wrap(err, errUnmarshalError)
}
if !r.Success {
// TODO: Provide an actual error message instead of always returning nil
return []Zone{}, err
}
for zi := range r.Result {
zones = append(zones, r.Result[zi])
}
}
} else {
// TODO: Paginate here. We only grab the first page of results.
// Could do this concurrently after the first request by creating a
// sync.WaitGroup or just a channel + workers.
res, err = api.makeRequest("GET", "/zones", nil)
if err != nil {
return []Zone{}, errors.Wrap(err, errMakeRequestError)
}
err = json.Unmarshal(res, &r)
if err != nil {
return []Zone{}, errors.Wrap(err, errUnmarshalError)
}
zones = r.Result
}
return zones, nil
}
// ZoneDetails fetches information about a zone.
//
// API reference: https://api.cloudflare.com/#zone-zone-details
func (api *API) ZoneDetails(zoneID string) (Zone, error) {
res, err := api.makeRequest("GET", "/zones"+zoneID, nil)
if err != nil {
return Zone{}, errors.Wrap(err, errMakeRequestError)
}
var r ZoneResponse
err = json.Unmarshal(res, &r)
if err != nil {
return Zone{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
// ZoneOptions is a subset of Zone, for editable options.
type ZoneOptions struct {
// FIXME(jamesog): Using omitempty here means we can't disable Paused.
// Currently unsure how to work around this.
Paused bool `json:"paused,omitempty"`
VanityNS []string `json:"vanity_name_servers,omitempty"`
Plan *ZonePlan `json:"plan,omitempty"`
}
// ZoneSetPaused pauses CloudFlare service for the entire zone, sending all
// traffic direct to the origin.
func (api *API) ZoneSetPaused(zoneID string, paused bool) (Zone, error) {
zoneopts := ZoneOptions{Paused: paused}
zone, err := api.EditZone(zoneID, zoneopts)
if err != nil {
return Zone{}, err
}
return zone, nil
}
// ZoneSetVanityNS sets custom nameservers for the zone.
// These names must be within the same zone.
func (api *API) ZoneSetVanityNS(zoneID string, ns []string) (Zone, error) {
zoneopts := ZoneOptions{VanityNS: ns}
zone, err := api.EditZone(zoneID, zoneopts)
if err != nil {
return Zone{}, err
}
return zone, nil
}
// ZoneSetPlan changes the zone plan.
func (api *API) ZoneSetPlan(zoneID string, plan ZonePlan) (Zone, error) {
zoneopts := ZoneOptions{Plan: &plan}
zone, err := api.EditZone(zoneID, zoneopts)
if err != nil {
return Zone{}, err
}
return zone, nil
}
// EditZone edits the given zone.
// This is usually called by ZoneSetPaused, ZoneSetVanityNS or ZoneSetPlan.
//
// API reference: https://api.cloudflare.com/#zone-edit-zone-properties
func (api *API) EditZone(zoneID string, zoneOpts ZoneOptions) (Zone, error) {
res, err := api.makeRequest("PATCH", "/zones/"+zoneID, zoneOpts)
if err != nil {
return Zone{}, errors.Wrap(err, errMakeRequestError)
}
var r ZoneResponse
err = json.Unmarshal(res, &r)
if err != nil {
return Zone{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
// PurgeEverything purges the cache for the given zone.
// Note: this will substantially increase load on the origin server for that
// zone if there is a high cached vs. uncached request ratio.
//
// API reference: https://api.cloudflare.com/#zone-purge-all-files
func (api *API) PurgeEverything(zoneID string) (PurgeCacheResponse, error) {
uri := "/zones/" + zoneID + "/purge_cache"
res, err := api.makeRequest("DELETE", uri, PurgeCacheRequest{true, nil, nil})
if err != nil {
return PurgeCacheResponse{}, errors.Wrap(err, errMakeRequestError)
}
var r PurgeCacheResponse
err = json.Unmarshal(res, &r)
if err != nil {
return PurgeCacheResponse{}, errors.Wrap(err, errUnmarshalError)
}
return r, nil
}
// PurgeCache purges the cache using the given PurgeCacheRequest (zone/url/tag).
//
// API reference: https://api.cloudflare.com/#zone-purge-individual-files-by-url-and-cache-tags
func (api *API) PurgeCache(zoneID string, pcr PurgeCacheRequest) (PurgeCacheResponse, error) {
uri := "/zones/" + zoneID + "/purge_cache"
res, err := api.makeRequest("DELETE", uri, pcr)
if err != nil {
return PurgeCacheResponse{}, errors.Wrap(err, errMakeRequestError)
}
var r PurgeCacheResponse
err = json.Unmarshal(res, &r)
if err != nil {
return PurgeCacheResponse{}, errors.Wrap(err, errUnmarshalError)
}
return r, nil
}
// DeleteZone deletes the given zone.
//
// API reference: https://api.cloudflare.com/#zone-delete-a-zone
func (api *API) DeleteZone(zoneID string) (ZoneID, error) {
res, err := api.makeRequest("DELETE", "/zones"+zoneID, nil)
if err != nil {
return ZoneID{}, errors.Wrap(err, errMakeRequestError)
}
var r ZoneIDResponse
err = json.Unmarshal(res, &r)
if err != nil {
return ZoneID{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
// AvailableZonePlans returns information about all plans available to the specified zone.
//
// API reference: https://api.cloudflare.com/#zone-plan-available-plans
func (api *API) AvailableZonePlans(zoneID string) ([]ZonePlan, error) {
uri := "/zones/" + zoneID + "/available_plans"
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return []ZonePlan{}, errors.Wrap(err, errMakeRequestError)
}
var r AvailableZonePlansResponse
err = json.Unmarshal(res, &r)
if err != nil {
return []ZonePlan{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
// ZonePlanDetails returns information about a zone plan.
//
// API reference: https://api.cloudflare.com/#zone-plan-plan-details
func (api *API) ZonePlanDetails(zoneID, planID string) (ZonePlan, error) {
uri := "/zones/" + zoneID + "/available_plans/" + planID
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return ZonePlan{}, errors.Wrap(err, errMakeRequestError)
}
var r ZonePlanResponse
err = json.Unmarshal(res, &r)
if err != nil {
return ZonePlan{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
// encode encodes non-nil fields into URL encoded form.
func (o ZoneAnalyticsOptions) encode() string {
v := url.Values{}
if o.Since != nil {
v.Set("since", (*o.Since).Format(time.RFC3339))
}
if o.Until != nil {
v.Set("until", (*o.Until).Format(time.RFC3339))
}
if o.Continuous != nil {
v.Set("continuous", fmt.Sprintf("%t", *o.Continuous))
}
return v.Encode()
}
// ZoneAnalyticsDashboard returns zone analytics information.
//
// API reference:
// https://api.cloudflare.com/#zone-analytics-dashboard
// GET /zones/:zone_identifier/analytics/dashboard
func (api *API) ZoneAnalyticsDashboard(zoneID string, options ZoneAnalyticsOptions) (ZoneAnalyticsData, error) {
uri := "/zones/" + zoneID + "/analytics/dashboard" + "?" + options.encode()
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return ZoneAnalyticsData{}, errors.Wrap(err, errMakeRequestError)
}
var r zoneAnalyticsDataResponse
err = json.Unmarshal(res, &r)
if err != nil {
return ZoneAnalyticsData{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
// ZoneAnalyticsByColocation returns zone analytics information by datacenter.
//
// API reference:
// https://api.cloudflare.com/#zone-analytics-analytics-by-co-locations
// GET /zones/:zone_identifier/analytics/colos
func (api *API) ZoneAnalyticsByColocation(zoneID string, options ZoneAnalyticsOptions) ([]ZoneAnalyticsColocation, error) {
uri := "/zones/" + zoneID + "/analytics/colos" + "?" + options.encode()
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return nil, errors.Wrap(err, errMakeRequestError)
}
var r zoneAnalyticsColocationResponse
err = json.Unmarshal(res, &r)
if err != nil {
return nil, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
// Zone Settings
// https://api.cloudflare.com/#zone-settings-for-a-zone-get-all-zone-settings
// e.g.
// https://api.cloudflare.com/#zone-settings-for-a-zone-get-always-online-setting
// https://api.cloudflare.com/#zone-settings-for-a-zone-change-always-online-setting

View File

@ -1,23 +0,0 @@
language: go
sudo: false
matrix:
include:
- go: 1.4
- go: 1.5
- go: 1.6
- go: tip
allow_failures:
- go: tip
script:
- go get -t -v $(go list ./... | grep -v '/vendor/')
- diff -u <(echo -n) <(gofmt -d .)
- go vet $(go list ./... | grep -v '/vendor/')
- go test -v -race ./...
notifications:
email:
recipients:
- jamesog@cloudflare.com
- msilverlock@cloudflare.com

View File

@ -1,44 +0,0 @@
[![GoDoc](https://godoc.org/github.com/cloudflare/cloudflare-go?status.svg)](https://godoc.org/github.com/cloudflare/cloudflare-go)
# cloudflare
A Go library for interacting with [CloudFlare's API v4](https://api.cloudflare.com/).
# Installation
You need a working Go environment.
```
go get github.com/cloudflare/cloudflare-go
```
# Getting Started
```
package main
import (
"fmt"
"github.com/cloudflare/cloudflare-go"
)
var api *cloudflare.API
func main() {
// Construct a new API object
api = cloudflare.New(os.Getenv("CF_API_KEY"), os.Getenv("CF_API_EMAIL"))
// Fetch the list of zones on the account
zones, err := api.ListZones()
if err != nil {
fmt.Println(err)
}
// Print the zone names
for _, z := range zones {
fmt.Println(z.Name)
}
}
```
An example application, [flarectl](cmd/flarectl), is in this repository.

View File

@ -1,451 +0,0 @@
/*
Package cloudflare implements the CloudFlare v4 API.
New API requests created like:
api := cloudflare.New(apikey, apiemail)
*/
package cloudflare
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"net/http"
"github.com/pkg/errors"
)
const apiURL = "https://api.cloudflare.com/client/v4"
// Error messages
const errMakeRequestError = "Error from makeRequest"
const errUnmarshalError = "Error unmarshalling JSON"
type API struct {
APIKey string
APIEmail string
}
// Initializes the API configuration.
func New(key, email string) *API {
return &API{key, email}
}
// Initializes a new zone.
func NewZone() *Zone {
return &Zone{}
}
// ZoneIDByName retrieves a zone's ID from the name.
func (api *API) ZoneIDByName(zoneName string) (string, error) {
res, err := api.ListZones(zoneName)
if err != nil {
return "", errors.Wrap(err, "ListZones command failed")
}
for _, zone := range res {
if zone.Name == zoneName {
return zone.ID, nil
}
}
return "", errors.New("Zone could not be found")
}
// Params can be turned into a URL query string or a body
// TODO: Give this func a better name
func (api *API) makeRequest(method, uri string, params interface{}) ([]byte, error) {
// Replace nil with a JSON object if needed
var reqBody io.Reader
if params != nil {
json, err := json.Marshal(params)
if err != nil {
return nil, errors.Wrap(err, "Error marshalling params to JSON")
}
reqBody = bytes.NewReader(json)
} else {
reqBody = nil
}
req, err := http.NewRequest(method, apiURL+uri, reqBody)
if err != nil {
return nil, errors.Wrap(err, "HTTP request creation failed")
}
req.Header.Add("X-Auth-Key", api.APIKey)
req.Header.Add("X-Auth-Email", api.APIEmail)
// Could be application/json or multipart/form-data
// req.Header.Add("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, errors.Wrap(err, "HTTP request failed")
}
defer resp.Body.Close()
resBody, err := ioutil.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
if err != nil {
return nil, errors.Wrap(err, "Error returned from API")
} else if resBody != nil {
return nil, errors.New(string(resBody))
} else {
return nil, errors.New(resp.Status)
}
}
return resBody, nil
}
// The Response struct is a template. There will also be a result struct.
// There will be a unique response type for each response, which will include
// this type.
type Response struct {
Success bool `json:"success"`
Errors []string `json:"errors"`
Messages []string `json:"messages"`
}
type ResultInfo struct {
Page int `json:"page"`
PerPage int `json:"per_page"`
Count int `json:"count"`
Total int `json:"total_count"`
}
// An Organization describes a multi-user organization. (Enterprise only.)
type Organization struct {
ID string
Name string
Status string
Permissions []string
Roles []string
}
// A User describes a user account.
type User struct {
ID string `json:"id"`
Email string `json:"email"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Username string `json:"username"`
Telephone string `json:"telephone"`
Country string `json:"country"`
Zipcode string `json:"zipcode"`
CreatedOn string `json:"created_on"` // Should this be a time.Date?
ModifiedOn string `json:"modified_on"`
APIKey string `json:"api_key"`
TwoFA bool `json:"two_factor_authentication_enabled"`
Betas []string `json:"betas"`
Organizations []Organization `json:"organizations"`
}
type UserResponse struct {
Success bool `json:"success"`
Errors []string `json:"errors"`
Messages []string `json:"messages"`
Result User `json:"result"`
}
type Owner struct {
ID string `json:"id"`
Email string `json:"email"`
OwnerType string `json:"owner_type"`
}
// A Zone describes a CloudFlare zone.
type Zone struct {
ID string `json:"id"`
Name string `json:"name"`
DevMode int `json:"development_mode"`
OriginalNS []string `json:"original_name_servers"`
OriginalRegistrar string `json:"original_registrar"`
OriginalDNSHost string `json:"original_dnshost"`
CreatedOn string `json:"created_on"`
ModifiedOn string `json:"modified_on"`
NameServers []string `json:"name_servers"`
Owner Owner `json:"owner"`
Permissions []string `json:"permissions"`
Plan ZonePlan `json:"plan"`
Status string `json:"status"`
Paused bool `json:"paused"`
Type string `json:"type"`
Host struct {
Name string
Website string
} `json:"host"`
VanityNS []string `json:"vanity_name_servers"`
Betas []string `json:"betas"`
DeactReason string `json:"deactivation_reason"`
Meta ZoneMeta `json:"meta"`
}
// Contains metadata about a zone.
type ZoneMeta struct {
// custom_certificate_quota is broken - sometimes it's a string, sometimes a number!
// CustCertQuota int `json:"custom_certificate_quota"`
PageRuleQuota int `json:"page_rule_quota"`
WildcardProxiable bool `json:"wildcard_proxiable"`
PhishingDetected bool `json:"phishing_detected"`
}
// Contains the plan information for a zone.
type ZonePlan struct {
ID string `json:"id"`
Name string `json:"name"`
Price int `json:"price"`
Currency string `json:"currency"`
Frequency string `json:"frequency"`
LegacyID string `json:"legacy_id"`
IsSubscribed bool `json:"is_subscribed"`
CanSubscribe bool `json:"can_subscribe"`
}
type ZoneResponse struct {
Success bool `json:"success"`
Errors []string `json:"errors"`
Messages []string `json:"messages"`
Result []Zone `json:"result"`
}
type ZonePlanResponse struct {
Success bool `json:"success"`
Errors []string `json:"errors"`
Messages []string `json:"messages"`
Result []ZonePlan `json:"result"`
}
// type zoneSetting struct {
// ID string `json:"id"`
// Editable bool `json:"editable"`
// ModifiedOn string `json:"modified_on"`
// }
// type zoneSettingStringVal struct {
// zoneSetting
// Value string `json:"value"`
// }
// type zoneSettingIntVal struct {
// zoneSetting
// Value int64 `json:"value"`
// }
type ZoneSetting struct {
ID string `json:"id"`
Editable bool `json:"editable"`
ModifiedOn string `json:"modified_on"`
Value interface{} `json:"value"`
TimeRemaining int `json:"time_remaining"`
}
type ZoneSettingResponse struct {
Success bool `json:"success"`
Errors []string `json:"errors"`
Messages []string `json:"messages"`
Result []ZoneSetting `json:"result"`
}
// Describes a DNS record for a zone.
type DNSRecord struct {
ID string `json:"id,omitempty"`
Type string `json:"type,omitempty"`
Name string `json:"name,omitempty"`
Content string `json:"content,omitempty"`
Proxiable bool `json:"proxiable,omitempty"`
Proxied bool `json:"proxied,omitempty"`
TTL int `json:"ttl,omitempty"`
Locked bool `json:"locked,omitempty"`
ZoneID string `json:"zone_id,omitempty"`
ZoneName string `json:"zone_name,omitempty"`
CreatedOn string `json:"created_on,omitempty"`
ModifiedOn string `json:"modified_on,omitempty"`
Data interface{} `json:"data,omitempty"` // data returned by: SRV, LOC
Meta interface{} `json:"meta,omitempty"`
Priority int `json:"priority,omitempty"`
}
// The response for creating or updating a DNS record.
type DNSRecordResponse struct {
Success bool `json:"success"`
Errors []interface{} `json:"errors"`
Messages []string `json:"messages"`
Result DNSRecord `json:"result"`
}
// The response for listing DNS records.
type DNSListResponse struct {
Success bool `json:"success"`
Errors []interface{} `json:"errors"`
Messages []string `json:"messages"`
Result []DNSRecord `json:"result"`
}
// Railgun status for a zone.
type ZoneRailgun struct {
ID string `json:"id"`
Name string `json:"string"`
Enabled bool `json:"enabled"`
Connected bool `json:"connected"`
}
type ZoneRailgunResponse struct {
Success bool `json:"success"`
Errors []string `json:"errors"`
Messages []string `json:"messages"`
Result []ZoneRailgun `json:"result"`
}
// Custom SSL certificates for a zone.
type ZoneCustomSSL struct {
ID string `json:"id"`
Hosts []string `json:"hosts"`
Issuer string `json:"issuer"`
Priority int `json:"priority"`
Status string `json:"success"`
BundleMethod string `json:"bundle_method"`
ZoneID string `json:"zone_id"`
Permissions []string `json:"permissions"`
UploadedOn string `json:"uploaded_on"`
ModifiedOn string `json:"modified_on"`
ExpiresOn string `json:"expires_on"`
KeylessServer KeylessSSL `json:"keyless_server"`
}
type ZoneCustomSSLResponse struct {
Success bool `json:"success"`
Errors []string `json:"errors"`
Messages []string `json:"messages"`
Result []ZoneCustomSSL `json:"result"`
}
type KeylessSSL struct {
ID string `json:"id"`
Name string `json:"name"`
Host string `json:"host"`
Port int `json:"port"`
Status string `json:"success"`
Enabled bool `json:"enabled"`
Permissions []string `json:"permissions"`
CreatedOn string `json:"created_on"`
ModifiedOn string `json:"modifed_on"`
}
type KeylessSSLResponse struct {
Success bool `json:"success"`
Errors []string `json:"errors"`
Messages []string `json:"messages"`
Result []KeylessSSL `json:"result"`
}
type Railgun struct {
ID string `json:"id"`
Name string `json:"name"`
Status string `json:"success"`
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 string `json:"activated_on"`
CreatedOn string `json:"created_on"`
ModifiedOn string `json:"modified_on"`
// XXX: UpgradeInfo struct {
// version string
// url string
// } `json:"upgrade_info"`
}
type RailgunResponse struct {
Success bool `json:"success"`
Errors []string `json:"errors"`
Messages []string `json:"messages"`
Result []Railgun `json:"result"`
}
// Custom error pages.
type CustomPage struct {
CreatedOn string `json:"created_on"`
ModifiedOn string `json:"modified_on"`
URL string `json:"url"`
State string `json:"state"`
RequiredTokens []string `json:"required_tokens"`
PreviewTarget string `json:"preview_target"`
Description string `json:"description"`
}
type CustomPageResponse struct {
Success bool `json:"success"`
Errors []string `json:"errors"`
Messages []string `json:"messages"`
Result []CustomPage `json:"result"`
}
// WAF packages
type WAFPackage struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
ZoneID string `json:"zone_id"`
DetectionMode string `json:"detection_mode"`
Sensitivity string `json:"sensitivity"`
ActionMode string `json:"action_mode"`
}
type WAFPackagesResponse struct {
Result []WAFPackage `json:"result"`
Success bool `json:"success"`
ResultInfo struct {
Page uint `json:"page"`
PerPage uint `json:"per_page"`
Count uint `json:"count"`
TotalCount uint `json:"total_count"`
} `json:"result_info"`
}
type WAFRule struct {
ID string `json:"id"`
Description string `json:"description"`
Priority string `json:"priority"`
PackageID string `json:"package_id"`
Group struct {
ID string `json:"id"`
Name string `json:"name"`
} `json:"group"`
Mode string `json:"mode"`
DefaultMode string `json:"default_mode"`
AllowedModes []string `json:"allowed_modes"`
}
type WAFRulesResponse struct {
Result []WAFRule `json:"result"`
Success bool `json:"success"`
ResultInfo struct {
Page uint `json:"page"`
PerPage uint `json:"per_page"`
Count uint `json:"count"`
TotalCount uint `json:"total_count"`
} `json:"result_info"`
}
type PurgeCacheRequest struct {
Everything bool `json:"purge_everything,omitempty"`
Files []string `json:"files,omitempty"`
Tags []string `json:"tags,omitempty"`
}
type PurgeCacheResponse struct {
Success bool `json:"success"`
Errors []string `json:"errors"`
Messages []string `json:"messages"`
}
// IPs contains a list of IPv4 and IPv6 CIDRs
type IPRanges struct {
IPv4CIDRs []string `json:"ipv4_cidrs"`
IPv6CIDRs []string `json:"ipv6_cidrs"`
}
// IPsResponse is the API response containing a list of IPs
type IPsResponse struct {
Success bool `json:"success"`
Errors []string `json:"errors"`
Messages []string `json:"messages"`
Result IPRanges `json:"result"`
}

View File

@ -1,26 +0,0 @@
package cloudflare
// https://api.cloudflare.com/#keyless-ssl-for-a-zone-create-a-keyless-ssl-configuration
// POST /zones/:zone_identifier/keyless_certificates
func (c *API) CreateKeyless() {
}
// https://api.cloudflare.com/#keyless-ssl-for-a-zone-list-keyless-ssls
// GET /zones/:zone_identifier/keyless_certificates
func (c *API) ListKeyless() {
}
// https://api.cloudflare.com/#keyless-ssl-for-a-zone-keyless-ssl-details
// GET /zones/:zone_identifier/keyless_certificates/:identifier
func (c *API) Keyless() {
}
// https://api.cloudflare.com/#keyless-ssl-for-a-zone-update-keyless-configuration
// PATCH /zones/:zone_identifier/keyless_certificates/:identifier
func (c *API) UpdateKeyless() {
}
// https://api.cloudflare.com/#keyless-ssl-for-a-zone-delete-keyless-configuration
// DELETE /zones/:zone_identifier/keyless_certificates/:identifier
func (c *API) DeleteKeyless() {
}

View File

@ -1,37 +0,0 @@
package cloudflare
// Railgun
// https://api.cloudflare.com/#railgun-create-railgun
// POST /railguns
func (c *API) CreateRailgun() {
}
// https://api.cloudflare.com/#railgun-railgun-details
// GET /railguns/:identifier
// https://api.cloudflare.com/#railgun-get-zones-connected-to-a-railgun
// GET /railguns/:identifier/zones
// https://api.cloudflare.com/#railgun-enable-or-disable-a-railgun
// PATCH /railguns/:identifier
// https://api.cloudflare.com/#railgun-delete-railgun
// DELETE /railguns/:identifier
// Zone railgun info
// https://api.cloudflare.com/#railguns-for-a-zone-get-available-railguns
// GET /zones/:zone_identifier/railguns
func (c *API) Railguns() {
}
// https://api.cloudflare.com/#railguns-for-a-zone-get-railgun-details
// GET /zones/:zone_identifier/railguns/:identifier
func (c *API) Railgun() {
}
// https://api.cloudflare.com/#railguns-for-a-zone-connect-or-disconnect-a-railgun
// PATCH /zones/:zone_identifier/railguns/:identifier
func (c *API) ZoneRailgun(connected bool) {
}

View File

@ -1,31 +0,0 @@
package cloudflare
// https://api.cloudflare.com/#custom-ssl-for-a-zone-create-ssl-configuration
// POST /zones/:zone_identifier/custom_certificates
func (c *API) CreateSSL() {
}
// https://api.cloudflare.com/#custom-ssl-for-a-zone-list-ssl-configurations
// GET /zones/:zone_identifier/custom_certificates
func (c *API) ListSSL() {
}
// https://api.cloudflare.com/#custom-ssl-for-a-zone-ssl-configuration-details
// GET /zones/:zone_identifier/custom_certificates/:identifier
func (c *API) SSLDetails() {
}
// https://api.cloudflare.com/#custom-ssl-for-a-zone-update-ssl-configuration
// PATCH /zones/:zone_identifier/custom_certificates/:identifier
func (c *API) UpdateSSL() {
}
// https://api.cloudflare.com/#custom-ssl-for-a-zone-re-prioritize-ssl-certificates
// PUT /zones/:zone_identifier/custom_certificates/prioritize
func (c *API) ReprioSSL() {
}
// https://api.cloudflare.com/#custom-ssl-for-a-zone-delete-an-ssl-certificate
// DELETE /zones/:zone_identifier/custom_certificates/:identifier
func (c *API) DeleteSSL() {
}

View File

@ -1,145 +0,0 @@
package cloudflare
import (
"encoding/json"
"net/url"
"github.com/pkg/errors"
)
/*
Creates a zone on an account.
API reference: https://api.cloudflare.com/#zone-create-a-zone
*/
func (api *API) CreateZone(z Zone) {
// res, err := api.makeRequest("POST", "/zones", z)
}
/*
List zones on an account. Optionally takes a list of zones to filter results.
API reference: https://api.cloudflare.com/#zone-list-zones
*/
func (api *API) ListZones(z ...string) ([]Zone, error) {
v := url.Values{}
var res []byte
var r ZoneResponse
var zones []Zone
var err error
if len(z) > 0 {
for _, zone := range z {
v.Set("name", zone)
res, err = api.makeRequest("GET", "/zones?"+v.Encode(), nil)
if err != nil {
return []Zone{}, errors.Wrap(err, errMakeRequestError)
}
err = json.Unmarshal(res, &r)
if err != nil {
return []Zone{}, errors.Wrap(err, errUnmarshalError)
}
if !r.Success {
// TODO: Provide an actual error message instead of always returning nil
return []Zone{}, err
}
for zi, _ := range r.Result {
zones = append(zones, r.Result[zi])
}
}
} else {
res, err = api.makeRequest("GET", "/zones", nil)
if err != nil {
return []Zone{}, errors.Wrap(err, errMakeRequestError)
}
err = json.Unmarshal(res, &r)
if err != nil {
return []Zone{}, errors.Wrap(err, errUnmarshalError)
}
zones = r.Result
}
return zones, nil
}
/*
Fetches information about a zone.
https://api.cloudflare.com/#zone-zone-details
GET /zones/:id
*/
func (api *API) ZoneDetails(z Zone) {
// XXX: Should we make the user get the zone ID themselves with ListZones, or do the hard work here?
// ListZones gives the same information as this endpoint anyway so perhaps this is of limited use?
// Maybe for users who already know the ID or fetched it in another call.
type result struct {
Response
Result Zone `json:"result"`
}
// If z has an ID then query for that directly, else call ListZones to
// fetch by name.
// var zone Zone
if z.ID != "" {
// res, _ := makeRequest(c, "GET", "/zones/"+z.ID, nil)
// zone = res.Result
} else {
// zones, err := ListZones(c, z.Name)
// if err != nil {
// return
// }
// Only one zone should have been returned
// zone := zones[0]
}
}
// https://api.cloudflare.com/#zone-edit-zone-properties
// PATCH /zones/:id
func EditZone() {
}
// https://api.cloudflare.com/#zone-purge-all-files
// DELETE /zones/:id/purge_cache
func (api *API) PurgeEverything(zoneID string) (PurgeCacheResponse, error) {
uri := "/zones/" + zoneID + "/purge_cache"
res, err := api.makeRequest("DELETE", uri, PurgeCacheRequest{true, nil, nil})
if err != nil {
return PurgeCacheResponse{}, errors.Wrap(err, errMakeRequestError)
}
var r PurgeCacheResponse
err = json.Unmarshal(res, &r)
if err != nil {
return PurgeCacheResponse{}, errors.Wrap(err, errUnmarshalError)
}
return r, nil
}
// https://api.cloudflare.com/#zone-purge-individual-files-by-url-and-cache-tags
// DELETE /zones/:id/purge_cache
func (api *API) PurgeCache(zoneID string, pcr PurgeCacheRequest) (PurgeCacheResponse, error) {
uri := "/zones/" + zoneID + "/purge_cache"
res, err := api.makeRequest("DELETE", uri, pcr)
if err != nil {
return PurgeCacheResponse{}, errors.Wrap(err, errMakeRequestError)
}
var r PurgeCacheResponse
err = json.Unmarshal(res, &r)
if err != nil {
return PurgeCacheResponse{}, errors.Wrap(err, errUnmarshalError)
}
return r, nil
}
// https://api.cloudflare.com/#zone-delete-a-zone
// DELETE /zones/:id
func DeleteZone() {
}
// Zone Plan
// https://api.cloudflare.com/#zone-plan-available-plans
// https://api.cloudflare.com/#zone-plan-plan-details
// Zone Settings
// https://api.cloudflare.com/#zone-settings-for-a-zone-get-all-zone-settings
// e.g.
// https://api.cloudflare.com/#zone-settings-for-a-zone-get-always-online-setting
// https://api.cloudflare.com/#zone-settings-for-a-zone-change-always-online-setting

10
vendor/vendor.json vendored
View File

@ -530,6 +530,12 @@
"path": "github.com/cenkalti/backoff",
"revision": "4dc77674aceaabba2c7e3da25d4c823edfb73f99"
},
{
"checksumSHA1": "JJWLM3YJwgJD4vOLZnOYi1C2k0E=",
"path": "github.com/cloudflare/cloudflare-go",
"revision": "746075f034254832ead032aee02ac072636ff25a",
"revisionTime": "2016-06-01T21:42:51Z"
},
{
"comment": "v2.3.0-alpha.0-652-ge552791",
"path": "github.com/coreos/etcd/client",
@ -989,10 +995,6 @@
"path": "github.com/mitchellh/cli",
"revision": "83f97d41cf100ee5f33944a8815c167d5e4aa272"
},
{
"path": "github.com/mitchellh/cloudflare-go",
"revision": "84c7a0993a06d555dbfddd2b32f5fa9b92fa1dc1"
},
{
"path": "github.com/mitchellh/colorstring",
"revision": "8631ce90f28644f54aeedcb3e389a85174e067d1"