Fix issue with uppercase logrus import (#351)

* chore: use lowercase for logrus repository

* chore: update dependencies using glide
This commit is contained in:
Martin Linkhorst 2017-10-09 17:14:18 +02:00 committed by GitHub
parent 485ede3228
commit 3331a57a18
155 changed files with 3019 additions and 1196 deletions

View File

@ -19,7 +19,7 @@ package controller
import ( import (
"time" "time"
log "github.com/Sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/kubernetes-incubator/external-dns/plan" "github.com/kubernetes-incubator/external-dns/plan"
"github.com/kubernetes-incubator/external-dns/registry" "github.com/kubernetes-incubator/external-dns/registry"

19
glide.lock generated
View File

@ -1,5 +1,5 @@
hash: d1ca92323760e7bdb44d2b80d066dd21bcd49c714faa88372a87a81a9520dffc hash: bd2f3e3117cc6b93553cb182322b717569d29c15d00892b87b04b52084fc3116
updated: 2017-06-16T11:52:01.08864027+02:00 updated: 2017-10-09T14:34:31.295501637+02:00
imports: imports:
- name: bitbucket.org/ww/goautoneg - name: bitbucket.org/ww/goautoneg
version: 75cd24fc2f2c2a2088577d12123ddee5f54e0675 version: 75cd24fc2f2c2a2088577d12123ddee5f54e0675
@ -9,7 +9,7 @@ imports:
- compute/metadata - compute/metadata
- internal - internal
- name: github.com/alecthomas/kingpin - name: github.com/alecthomas/kingpin
version: 7f0871f2e17818990e4eed73f9b5c2f429501228 version: 1087e65c9441605df944fb12c33f0fe7072d18ca
- name: github.com/alecthomas/template - name: github.com/alecthomas/template
version: a0175ee3bccc567396460bf5acd36800cb10c49c version: a0175ee3bccc567396460bf5acd36800cb10c49c
subpackages: subpackages:
@ -17,7 +17,7 @@ imports:
- name: github.com/alecthomas/units - name: github.com/alecthomas/units
version: 2efee857e7cfd4f3d0138cc3cbb1b4966962b93a version: 2efee857e7cfd4f3d0138cc3cbb1b4966962b93a
- name: github.com/aws/aws-sdk-go - name: github.com/aws/aws-sdk-go
version: 3acad2065587626a08fdd692651bf1dd52e79ab4 version: 96358b8282b1a3aa66836d2f2fe66216cc419668
subpackages: subpackages:
- aws - aws
- aws/awserr - aws/awserr
@ -61,7 +61,7 @@ imports:
subpackages: subpackages:
- quantile - quantile
- name: github.com/cloudflare/cloudflare-go - name: github.com/cloudflare/cloudflare-go
version: 9d186a5948cb4bb3d1f3343bc6bcae91e7aa6479 version: 4c6994ac3877fbb627766edadc67f4e816e8c890
- name: github.com/coreos/go-oidc - name: github.com/coreos/go-oidc
version: be73733bb8cc830d0205609b95d125215f8e9c70 version: be73733bb8cc830d0205609b95d125215f8e9c70
subpackages: subpackages:
@ -83,7 +83,7 @@ imports:
- name: github.com/dgrijalva/jwt-go - name: github.com/dgrijalva/jwt-go
version: d2709f9f1f31ebcda9651b03077758c1f3a0018c version: d2709f9f1f31ebcda9651b03077758c1f3a0018c
- name: github.com/digitalocean/godo - name: github.com/digitalocean/godo
version: 4fa9e9d999007b447089056a1c581b5594f0f851 version: 77ea48de76a7b31b234d854f15d003c68bb2fb90
subpackages: subpackages:
- context - context
- name: github.com/docker/distribution - name: github.com/docker/distribution
@ -175,7 +175,7 @@ imports:
version: 8a290539e2e8629dbc4e6bad948158f790ec31f4 version: 8a290539e2e8629dbc4e6bad948158f790ec31f4
- name: github.com/PuerkitoBio/urlesc - name: github.com/PuerkitoBio/urlesc
version: 5bd2802263f21d8788851d5305584c82a5c75d7e version: 5bd2802263f21d8788851d5305584c82a5c75d7e
- name: github.com/Sirupsen/logrus - name: github.com/sirupsen/logrus
version: ba1b36c82c5e05c4f912a88eab0dcd91a171688f version: ba1b36c82c5e05c4f912a88eab0dcd91a171688f
- name: github.com/spf13/pflag - name: github.com/spf13/pflag
version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7 version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7
@ -187,6 +187,7 @@ imports:
- assert - assert
- mock - mock
- require - require
- suite
- name: github.com/tent/http-link-go - name: github.com/tent/http-link-go
version: ac974c61c2f990f4115b119354b5e0b47550e888 version: ac974c61c2f990f4115b119354b5e0b47550e888
- name: github.com/ugorji/go - name: github.com/ugorji/go
@ -254,7 +255,7 @@ imports:
- name: gopkg.in/yaml.v2 - name: gopkg.in/yaml.v2
version: 53feefa2559fb8dfa8d81baad31be332c97d6c77 version: 53feefa2559fb8dfa8d81baad31be332c97d6c77
- name: k8s.io/apimachinery - name: k8s.io/apimachinery
version: 75b8dd260ef0469d96d578705a87cffd0e09dab8 version: 85ace5365f33b16fc735c866a12e3c765b9700f2
subpackages: subpackages:
- pkg/api/errors - pkg/api/errors
- pkg/api/meta - pkg/api/meta
@ -295,7 +296,7 @@ imports:
- pkg/watch - pkg/watch
- third_party/forked/golang/reflect - third_party/forked/golang/reflect
- name: k8s.io/client-go - name: k8s.io/client-go
version: 3627aeb7d4f6ade38f995d2c923e459146493c7e version: 21300e3e11c918b8e6a70fb7293b310683d6c046
subpackages: subpackages:
- discovery - discovery
- discovery/fake - discovery/fake

View File

@ -1,6 +1,6 @@
package: github.com/kubernetes-incubator/external-dns package: github.com/kubernetes-incubator/external-dns
import: import:
- package: github.com/Sirupsen/logrus - package: github.com/sirupsen/logrus
version: ~0.11.5 version: ~0.11.5
- package: github.com/alecthomas/kingpin - package: github.com/alecthomas/kingpin
version: ~2.2.4 version: ~2.2.4

View File

@ -23,8 +23,8 @@ import (
"syscall" "syscall"
"time" "time"
log "github.com/Sirupsen/logrus"
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
log "github.com/sirupsen/logrus"
_ "k8s.io/client-go/plugin/pkg/client/auth" _ "k8s.io/client-go/plugin/pkg/client/auth"

View File

@ -19,8 +19,8 @@ package externaldns
import ( import (
"time" "time"
"github.com/Sirupsen/logrus"
"github.com/alecthomas/kingpin" "github.com/alecthomas/kingpin"
"github.com/sirupsen/logrus"
) )
var ( var (

View File

@ -21,7 +21,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/Sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )

View File

@ -17,8 +17,8 @@ limitations under the License.
package plan package plan
import ( import (
log "github.com/Sirupsen/logrus"
"github.com/kubernetes-incubator/external-dns/endpoint" "github.com/kubernetes-incubator/external-dns/endpoint"
log "github.com/sirupsen/logrus"
) )
// Plan can convert a list of desired and current records to a series of create, // Plan can convert a list of desired and current records to a series of create,

View File

@ -19,8 +19,8 @@ package provider
import ( import (
"strings" "strings"
log "github.com/Sirupsen/logrus"
"github.com/linki/instrumented_http" "github.com/linki/instrumented_http"
log "github.com/sirupsen/logrus"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/aws/session"

View File

@ -21,7 +21,7 @@ import (
"io/ioutil" "io/ioutil"
"strings" "strings"
log "github.com/Sirupsen/logrus" log "github.com/sirupsen/logrus"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"

View File

@ -23,7 +23,7 @@ import (
cloudflare "github.com/cloudflare/cloudflare-go" cloudflare "github.com/cloudflare/cloudflare-go"
log "github.com/Sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/kubernetes-incubator/external-dns/endpoint" "github.com/kubernetes-incubator/external-dns/endpoint"
"github.com/kubernetes-incubator/external-dns/plan" "github.com/kubernetes-incubator/external-dns/plan"

View File

@ -21,7 +21,7 @@ import (
"os" "os"
"strings" "strings"
log "github.com/Sirupsen/logrus" log "github.com/sirupsen/logrus"
"golang.org/x/oauth2" "golang.org/x/oauth2"
"github.com/digitalocean/godo" "github.com/digitalocean/godo"

View File

@ -19,8 +19,8 @@ package provider
import ( import (
"strings" "strings"
log "github.com/Sirupsen/logrus"
"github.com/linki/instrumented_http" "github.com/linki/instrumented_http"
log "github.com/sirupsen/logrus"
dns "google.golang.org/api/dns/v1" dns "google.golang.org/api/dns/v1"

View File

@ -20,7 +20,7 @@ import (
"errors" "errors"
"strings" "strings"
log "github.com/Sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/kubernetes-incubator/external-dns/endpoint" "github.com/kubernetes-incubator/external-dns/endpoint"
"github.com/kubernetes-incubator/external-dns/plan" "github.com/kubernetes-incubator/external-dns/plan"

View File

@ -17,9 +17,9 @@ limitations under the License.
package registry package registry
import ( import (
log "github.com/Sirupsen/logrus"
"github.com/kubernetes-incubator/external-dns/endpoint" "github.com/kubernetes-incubator/external-dns/endpoint"
"github.com/kubernetes-incubator/external-dns/plan" "github.com/kubernetes-incubator/external-dns/plan"
log "github.com/sirupsen/logrus"
) )
// Registry is an interface which should enables ownership concept in external-dns // Registry is an interface which should enables ownership concept in external-dns

View File

@ -17,7 +17,7 @@ limitations under the License.
package source package source
import ( import (
log "github.com/Sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/kubernetes-incubator/external-dns/endpoint" "github.com/kubernetes-incubator/external-dns/endpoint"
) )

View File

@ -22,7 +22,7 @@ import (
"strings" "strings"
"text/template" "text/template"
log "github.com/Sirupsen/logrus" log "github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"

View File

@ -22,7 +22,7 @@ import (
"strings" "strings"
"text/template" "text/template"
log "github.com/Sirupsen/logrus" log "github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"

View File

@ -24,8 +24,8 @@ import (
"sync" "sync"
log "github.com/Sirupsen/logrus"
"github.com/linki/instrumented_http" "github.com/linki/instrumented_http"
log "github.com/sirupsen/logrus"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
) )

View File

@ -581,7 +581,7 @@ Consider the case that you needed to read a local database or a file to
provide suggestions. You can dynamically generate the options provide suggestions. You can dynamically generate the options
``` ```
func listHosts(args []string) []string { func listHosts() []string {
// Provide a dynamic list of hosts from a hosts file or otherwise // Provide a dynamic list of hosts from a hosts file or otherwise
// for bash completion. In this example we simply return static slice. // for bash completion. In this example we simply return static slice.

View File

@ -2,8 +2,8 @@ package kingpin
import ( import (
"io/ioutil" "io/ioutil"
"testing"
"os" "os"
"testing"
"github.com/alecthomas/assert" "github.com/alecthomas/assert"
) )

View File

@ -106,7 +106,7 @@ func main() {
if v.Format != "" { if v.Format != "" {
return v.Format return v.Format
} }
return "fmt.Sprintf(\"%v\", *f)" return "fmt.Sprintf(\"%v\", *f.v)"
}, },
"ValueName": func(v *Value) string { "ValueName": func(v *Value) string {
name := valueName(v) name := valueName(v)

View File

@ -216,11 +216,9 @@ func (p *ParseContext) Next() *Token {
return &Token{p.argi, TokenError, err.Error()} return &Token{p.argi, TokenError, err.Error()}
} }
if len(p.args) == 0 { if len(p.args) == 0 {
p.args = append(p.args, expanded...) p.args = expanded
} else if p.argi >= len(p.args) {
p.args = append(p.args[:p.argi-1], expanded...)
} else { } else {
p.args = append(p.args[:p.argi-1], append(expanded, p.args[p.argi+1:]...)...) p.args = append(expanded, p.args...)
} }
return p.Next() return p.Next()
} }

View File

@ -25,6 +25,86 @@ func TestParserExpandFromFile(t *testing.T) {
assert.Equal(t, "world", *arg1) assert.Equal(t, "world", *arg1)
} }
func TestParserExpandFromFileLeadingArg(t *testing.T) {
f, err := ioutil.TempFile("", "")
assert.NoError(t, err)
defer os.Remove(f.Name())
f.WriteString("hello\nworld\n")
f.Close()
app := New("test", "")
arg0 := app.Arg("arg0", "").String()
arg1 := app.Arg("arg1", "").String()
arg2 := app.Arg("arg2", "").String()
_, err = app.Parse([]string{"prefix", "@" + f.Name()})
assert.NoError(t, err)
assert.Equal(t, "prefix", *arg0)
assert.Equal(t, "hello", *arg1)
assert.Equal(t, "world", *arg2)
}
func TestParserExpandFromFileTrailingArg(t *testing.T) {
f, err := ioutil.TempFile("", "")
assert.NoError(t, err)
defer os.Remove(f.Name())
f.WriteString("hello\nworld\n")
f.Close()
app := New("test", "")
arg0 := app.Arg("arg0", "").String()
arg1 := app.Arg("arg1", "").String()
arg2 := app.Arg("arg2", "").String()
_, err = app.Parse([]string{"@" + f.Name(), "suffix"})
assert.NoError(t, err)
assert.Equal(t, "hello", *arg0)
assert.Equal(t, "world", *arg1)
assert.Equal(t, "suffix", *arg2)
}
func TestParserExpandFromFileMultipleSurroundingArgs(t *testing.T) {
f, err := ioutil.TempFile("", "")
assert.NoError(t, err)
defer os.Remove(f.Name())
f.WriteString("hello\nworld\n")
f.Close()
app := New("test", "")
arg0 := app.Arg("arg0", "").String()
arg1 := app.Arg("arg1", "").String()
arg2 := app.Arg("arg2", "").String()
arg3 := app.Arg("arg3", "").String()
_, err = app.Parse([]string{"prefix", "@" + f.Name(), "suffix"})
assert.NoError(t, err)
assert.Equal(t, "prefix", *arg0)
assert.Equal(t, "hello", *arg1)
assert.Equal(t, "world", *arg2)
assert.Equal(t, "suffix", *arg3)
}
func TestParserExpandFromFileMultipleFlags(t *testing.T) {
f, err := ioutil.TempFile("", "")
assert.NoError(t, err)
defer os.Remove(f.Name())
f.WriteString("--flag1=f1\n--flag2=f2\n")
f.Close()
app := New("test", "")
flag0 := app.Flag("flag0", "").String()
flag1 := app.Flag("flag1", "").String()
flag2 := app.Flag("flag2", "").String()
flag3 := app.Flag("flag3", "").String()
_, err = app.Parse([]string{"--flag0=f0", "@" + f.Name(), "--flag3=f3"})
assert.NoError(t, err)
assert.Equal(t, "f0", *flag0)
assert.Equal(t, "f1", *flag1)
assert.Equal(t, "f2", *flag2)
assert.Equal(t, "f3", *flag3)
}
func TestParseContextPush(t *testing.T) { func TestParseContextPush(t *testing.T) {
app := New("test", "") app := New("test", "")
app.Command("foo", "").Command("bar", "") app.Command("foo", "").Command("bar", "")

View File

@ -28,7 +28,7 @@ func (f *boolValue) Set(s string) error {
func (f *boolValue) Get() interface{} { return (bool)(*f.v) } func (f *boolValue) Get() interface{} { return (bool)(*f.v) }
func (f *boolValue) String() string { return fmt.Sprintf("%v", *f) } func (f *boolValue) String() string { return fmt.Sprintf("%v", *f.v) }
// Bool parses the next command-line value as bool. // Bool parses the next command-line value as bool.
func (p *parserMixin) Bool() (target *bool) { func (p *parserMixin) Bool() (target *bool) {
@ -114,7 +114,7 @@ func (f *uintValue) Set(s string) error {
func (f *uintValue) Get() interface{} { return (uint)(*f.v) } func (f *uintValue) Get() interface{} { return (uint)(*f.v) }
func (f *uintValue) String() string { return fmt.Sprintf("%v", *f) } func (f *uintValue) String() string { return fmt.Sprintf("%v", *f.v) }
// Uint parses the next command-line value as uint. // Uint parses the next command-line value as uint.
func (p *parserMixin) Uint() (target *uint) { func (p *parserMixin) Uint() (target *uint) {
@ -157,7 +157,7 @@ func (f *uint8Value) Set(s string) error {
func (f *uint8Value) Get() interface{} { return (uint8)(*f.v) } func (f *uint8Value) Get() interface{} { return (uint8)(*f.v) }
func (f *uint8Value) String() string { return fmt.Sprintf("%v", *f) } func (f *uint8Value) String() string { return fmt.Sprintf("%v", *f.v) }
// Uint8 parses the next command-line value as uint8. // Uint8 parses the next command-line value as uint8.
func (p *parserMixin) Uint8() (target *uint8) { func (p *parserMixin) Uint8() (target *uint8) {
@ -200,7 +200,7 @@ func (f *uint16Value) Set(s string) error {
func (f *uint16Value) Get() interface{} { return (uint16)(*f.v) } func (f *uint16Value) Get() interface{} { return (uint16)(*f.v) }
func (f *uint16Value) String() string { return fmt.Sprintf("%v", *f) } func (f *uint16Value) String() string { return fmt.Sprintf("%v", *f.v) }
// Uint16 parses the next command-line value as uint16. // Uint16 parses the next command-line value as uint16.
func (p *parserMixin) Uint16() (target *uint16) { func (p *parserMixin) Uint16() (target *uint16) {
@ -243,7 +243,7 @@ func (f *uint32Value) Set(s string) error {
func (f *uint32Value) Get() interface{} { return (uint32)(*f.v) } func (f *uint32Value) Get() interface{} { return (uint32)(*f.v) }
func (f *uint32Value) String() string { return fmt.Sprintf("%v", *f) } func (f *uint32Value) String() string { return fmt.Sprintf("%v", *f.v) }
// Uint32 parses the next command-line value as uint32. // Uint32 parses the next command-line value as uint32.
func (p *parserMixin) Uint32() (target *uint32) { func (p *parserMixin) Uint32() (target *uint32) {
@ -286,7 +286,7 @@ func (f *uint64Value) Set(s string) error {
func (f *uint64Value) Get() interface{} { return (uint64)(*f.v) } func (f *uint64Value) Get() interface{} { return (uint64)(*f.v) }
func (f *uint64Value) String() string { return fmt.Sprintf("%v", *f) } func (f *uint64Value) String() string { return fmt.Sprintf("%v", *f.v) }
// Uint64 parses the next command-line value as uint64. // Uint64 parses the next command-line value as uint64.
func (p *parserMixin) Uint64() (target *uint64) { func (p *parserMixin) Uint64() (target *uint64) {
@ -329,7 +329,7 @@ func (f *intValue) Set(s string) error {
func (f *intValue) Get() interface{} { return (int)(*f.v) } func (f *intValue) Get() interface{} { return (int)(*f.v) }
func (f *intValue) String() string { return fmt.Sprintf("%v", *f) } func (f *intValue) String() string { return fmt.Sprintf("%v", *f.v) }
// Int parses the next command-line value as int. // Int parses the next command-line value as int.
func (p *parserMixin) Int() (target *int) { func (p *parserMixin) Int() (target *int) {
@ -372,7 +372,7 @@ func (f *int8Value) Set(s string) error {
func (f *int8Value) Get() interface{} { return (int8)(*f.v) } func (f *int8Value) Get() interface{} { return (int8)(*f.v) }
func (f *int8Value) String() string { return fmt.Sprintf("%v", *f) } func (f *int8Value) String() string { return fmt.Sprintf("%v", *f.v) }
// Int8 parses the next command-line value as int8. // Int8 parses the next command-line value as int8.
func (p *parserMixin) Int8() (target *int8) { func (p *parserMixin) Int8() (target *int8) {
@ -415,7 +415,7 @@ func (f *int16Value) Set(s string) error {
func (f *int16Value) Get() interface{} { return (int16)(*f.v) } func (f *int16Value) Get() interface{} { return (int16)(*f.v) }
func (f *int16Value) String() string { return fmt.Sprintf("%v", *f) } func (f *int16Value) String() string { return fmt.Sprintf("%v", *f.v) }
// Int16 parses the next command-line value as int16. // Int16 parses the next command-line value as int16.
func (p *parserMixin) Int16() (target *int16) { func (p *parserMixin) Int16() (target *int16) {
@ -458,7 +458,7 @@ func (f *int32Value) Set(s string) error {
func (f *int32Value) Get() interface{} { return (int32)(*f.v) } func (f *int32Value) Get() interface{} { return (int32)(*f.v) }
func (f *int32Value) String() string { return fmt.Sprintf("%v", *f) } func (f *int32Value) String() string { return fmt.Sprintf("%v", *f.v) }
// Int32 parses the next command-line value as int32. // Int32 parses the next command-line value as int32.
func (p *parserMixin) Int32() (target *int32) { func (p *parserMixin) Int32() (target *int32) {
@ -501,7 +501,7 @@ func (f *int64Value) Set(s string) error {
func (f *int64Value) Get() interface{} { return (int64)(*f.v) } func (f *int64Value) Get() interface{} { return (int64)(*f.v) }
func (f *int64Value) String() string { return fmt.Sprintf("%v", *f) } func (f *int64Value) String() string { return fmt.Sprintf("%v", *f.v) }
// Int64 parses the next command-line value as int64. // Int64 parses the next command-line value as int64.
func (p *parserMixin) Int64() (target *int64) { func (p *parserMixin) Int64() (target *int64) {
@ -544,7 +544,7 @@ func (f *float64Value) Set(s string) error {
func (f *float64Value) Get() interface{} { return (float64)(*f.v) } func (f *float64Value) Get() interface{} { return (float64)(*f.v) }
func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) } func (f *float64Value) String() string { return fmt.Sprintf("%v", *f.v) }
// Float64 parses the next command-line value as float64. // Float64 parses the next command-line value as float64.
func (p *parserMixin) Float64() (target *float64) { func (p *parserMixin) Float64() (target *float64) {
@ -587,7 +587,7 @@ func (f *float32Value) Set(s string) error {
func (f *float32Value) Get() interface{} { return (float32)(*f.v) } func (f *float32Value) Get() interface{} { return (float32)(*f.v) }
func (f *float32Value) String() string { return fmt.Sprintf("%v", *f) } func (f *float32Value) String() string { return fmt.Sprintf("%v", *f.v) }
// Float32 parses the next command-line value as float32. // Float32 parses the next command-line value as float32.
func (p *parserMixin) Float32() (target *float32) { func (p *parserMixin) Float32() (target *float32) {
@ -708,7 +708,7 @@ func (f *regexpValue) Set(s string) error {
func (f *regexpValue) Get() interface{} { return (*regexp.Regexp)(*f.v) } func (f *regexpValue) Get() interface{} { return (*regexp.Regexp)(*f.v) }
func (f *regexpValue) String() string { return fmt.Sprintf("%v", *f) } func (f *regexpValue) String() string { return fmt.Sprintf("%v", *f.v) }
// Regexp parses the next command-line value as *regexp.Regexp. // Regexp parses the next command-line value as *regexp.Regexp.
func (p *parserMixin) Regexp() (target **regexp.Regexp) { func (p *parserMixin) Regexp() (target **regexp.Regexp) {
@ -751,7 +751,7 @@ func (f *resolvedIPValue) Set(s string) error {
func (f *resolvedIPValue) Get() interface{} { return (net.IP)(*f.v) } func (f *resolvedIPValue) Get() interface{} { return (net.IP)(*f.v) }
func (f *resolvedIPValue) String() string { return fmt.Sprintf("%v", *f) } func (f *resolvedIPValue) String() string { return fmt.Sprintf("%v", *f.v) }
// Resolve a hostname or IP to an IP. // Resolve a hostname or IP to an IP.
func (p *parserMixin) ResolvedIP() (target *net.IP) { func (p *parserMixin) ResolvedIP() (target *net.IP) {
@ -794,7 +794,7 @@ func (f *hexBytesValue) Set(s string) error {
func (f *hexBytesValue) Get() interface{} { return ([]byte)(*f.v) } func (f *hexBytesValue) Get() interface{} { return ([]byte)(*f.v) }
func (f *hexBytesValue) String() string { return fmt.Sprintf("%v", *f) } func (f *hexBytesValue) String() string { return fmt.Sprintf("%v", *f.v) }
// Bytes as a hex string. // Bytes as a hex string.
func (p *parserMixin) HexBytes() (target *[]byte) { func (p *parserMixin) HexBytes() (target *[]byte) {

View File

@ -1,3 +1,10 @@
Release v1.8.44 (2017-06-16)
===
### Service Client Updates
* `service/xray`: Updates service API, documentation, and paginators
* Add a response time histogram to the services in response of GetServiceGraph API.
Release v1.8.43 (2017-06-15) Release v1.8.43 (2017-06-15)
=== ===

View File

@ -5,4 +5,4 @@ package aws
const SDKName = "aws-sdk-go" const SDKName = "aws-sdk-go"
// SDKVersion is the version of this SDK // SDKVersion is the version of this SDK
const SDKVersion = "1.8.43" const SDKVersion = "1.8.44"

View File

@ -146,14 +146,14 @@
</div> <!-- #pkg-callgraph --> </div> <!-- #pkg-callgraph -->
{{with .Consts}} {{with .Consts}}
<h2 id="pkg-constants">Constants <a class="permalink" href="pkg-constants"></a></h2> <h2 id="pkg-constants">Constants <a class="permalink" href="#pkg-constants"></a></h2>
{{range .}} {{range .}}
<pre>{{node_html $ .Decl true}}</pre> <pre>{{node_html $ .Decl true}}</pre>
{{comment_html .Doc}} {{comment_html .Doc}}
{{end}} {{end}}
{{end}} {{end}}
{{with .Vars}} {{with .Vars}}
<h2 id="pkg-variables">Variables <a class="permalink" href="pkg-variables"></a></h2> <h2 id="pkg-variables">Variables <a class="permalink" href="#pkg-variables"></a></h2>
{{range .}} {{range .}}
<pre>{{node_html $ .Decl true}}</pre> <pre>{{node_html $ .Decl true}}</pre>
{{comment_html .Doc}} {{comment_html .Doc}}
@ -201,7 +201,7 @@
{{range .Methods}} {{range .Methods}}
{{$name_html := html .Name}} {{$name_html := html .Name}}
<h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a> <a class="permalink" href="#{{$tname_html}}"></a></h3> <h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a> <a class="permalink" href="#{{$tname_html}}.{{$name_html}}"></a></h3>
<pre>{{node_html $ .Decl true}}</pre> <pre>{{node_html $ .Decl true}}</pre>
{{comment_html .Doc}} {{comment_html .Doc}}
{{$name := printf "%s_%s" $tname .Name}} {{$name := printf "%s_%s" $tname .Name}}

View File

@ -96,7 +96,7 @@
</div><!-- .expanded --> </div><!-- .expanded -->
</div><!-- #pkg-index --> </div><!-- #pkg-index -->
{{ if $.HasPaginators -}} {{ if $.HasPaginators -}}
<div id="pkg-pagination " class="toggle"> <div id="pkg-pagination " class="toggleVisible">
<div class="collapsed"> <div class="collapsed">
<h2 class="toggleButton" title="Click to show Index section">Paginators ▹</h2> <h2 class="toggleButton" title="Click to show Index section">Paginators ▹</h2>
</div> </div>
@ -114,7 +114,7 @@
</div> </div>
</div> </div>
{{ end -}} {{ end -}}
<div id="pkg-types" class="toggle"> <div id="pkg-types" class="toggleVisible">
<div class="collapsed"> <div class="collapsed">
<h2 class="toggleButton" title="Click to show Index section">Types ▹</h2> <h2 class="toggleButton" title="Click to show Index section">Types ▹</h2>
</div> </div>
@ -130,7 +130,7 @@
{{ range .Methods -}} {{ range .Methods -}}
{{ if is_setter $.PDoc.Name . -}} {{ if is_setter $.PDoc.Name . -}}
{{ $name_html := html .Name -}} {{ $name_html := html .Name -}}
<dd><a href="#{{$tname_html}}.{{$name_html}}">{{name_only_html $ . | sanitize}}</a></dd> <dd><a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
{{ end -}} {{ end -}}
{{ end -}} {{ end -}}
{{ end -}} {{ end -}}
@ -250,9 +250,9 @@
{{ range .Methods -}} {{ range .Methods -}}
{{ $name_html := html .Name -}} {{ $name_html := html .Name -}}
{{ if is_op_deprecated $.PDoc.Name .Name -}} {{ if is_op_deprecated $.PDoc.Name .Name -}}
<h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a><div class="deprecated">Deprecated</div> <a class="permalink" href="#{{$name_html}}"></a></h3> <h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a><div class="deprecated">Deprecated</div> <a class="permalink" href="#{{$tname_html}}.{{$name_html}}"></a></h3>
{{ else }} {{ else }}
<h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a> <a class="permalink" href="#{{$name_html}}"></a></h3> <h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a> <a class="permalink" href="#{{$tname_html}}.{{$name_html}}"></a></h3>
{{ end -}} {{ end -}}
<pre>{{node_html $ .Decl true}}</pre> <pre>{{node_html $ .Decl true}}</pre>
{{comment_html .Doc}} {{comment_html .Doc}}

View File

@ -345,7 +345,8 @@
"EndTime":{"shape":"Timestamp"}, "EndTime":{"shape":"Timestamp"},
"Edges":{"shape":"EdgeList"}, "Edges":{"shape":"EdgeList"},
"SummaryStatistics":{"shape":"ServiceStatistics"}, "SummaryStatistics":{"shape":"ServiceStatistics"},
"DurationHistogram":{"shape":"Histogram"} "DurationHistogram":{"shape":"Histogram"},
"ResponseTimeHistogram":{"shape":"Histogram"}
} }
}, },
"ServiceId":{ "ServiceId":{

View File

@ -5,9 +5,9 @@
"BatchGetTraces": "<p>Retrieves a list of traces specified by ID. Each trace is a collection of segment documents that originates from a single request. Use <code>GetTraceSummaries</code> to get a list of trace IDs.</p>", "BatchGetTraces": "<p>Retrieves a list of traces specified by ID. Each trace is a collection of segment documents that originates from a single request. Use <code>GetTraceSummaries</code> to get a list of trace IDs.</p>",
"GetServiceGraph": "<p>Retrieves a document that describes services that process incoming requests, and downstream services that they call as a result. Root services process incoming requests and make calls to downstream services. Root services are applications that use the AWS X-Ray SDK. Downstream services can be other applications, AWS resources, HTTP web APIs, or SQL databases.</p>", "GetServiceGraph": "<p>Retrieves a document that describes services that process incoming requests, and downstream services that they call as a result. Root services process incoming requests and make calls to downstream services. Root services are applications that use the AWS X-Ray SDK. Downstream services can be other applications, AWS resources, HTTP web APIs, or SQL databases.</p>",
"GetTraceGraph": "<p>Retrieves a service graph for one or more specific trace IDs.</p>", "GetTraceGraph": "<p>Retrieves a service graph for one or more specific trace IDs.</p>",
"GetTraceSummaries": "<p>Retrieves IDs and metadata for traces available for a specified time frame using an optional filter. To get the full traces, pass the trace IDs to <code>BatchGetTraces</code>.</p>", "GetTraceSummaries": "<p>Retrieves IDs and metadata for traces available for a specified time frame using an optional filter. To get the full traces, pass the trace IDs to <code>BatchGetTraces</code>.</p> <p>A filter expression can target traced requests that hit specific service nodes or edges, have errors, or come from a known user. For example, the following filter expression targets traces that pass through <code>api.example.com</code>:</p> <p> <code>service(\"api.example.com\")</code> </p> <p>This filter expression finds traces that have an annotation named <code>account</code> with the value <code>12345</code>:</p> <p> <code>annotation.account = \"12345\"</code> </p> <p>For a full list of indexed fields and keywords that you can use in filter expressions, see <a href=\"http://docs.aws.amazon.com/xray/latest/devguide/xray-console-filters.html\">Using Filter Expressions</a> in the <i>AWS X-Ray Developer Guide</i>.</p>",
"PutTelemetryRecords": "<p>Used by the AWS X-Ray daemon to upload telemetry.</p>", "PutTelemetryRecords": "<p>Used by the AWS X-Ray daemon to upload telemetry.</p>",
"PutTraceSegments": "<p>Uploads segment documents to AWS X-Ray. The X-Ray SDK generates segment documents and sends them to the X-Ray daemon, which uploads them in batches. A segment document can be a completed segment, an in-progress segment, or an array of subsegments.</p>" "PutTraceSegments": "<p>Uploads segment documents to AWS X-Ray. The X-Ray SDK generates segment documents and sends them to the X-Ray daemon, which uploads them in batches. A segment document can be a completed segment, an in-progress segment, or an array of subsegments.</p> <p>Segments must include the following fields. For the full segment document schema, see <a href=\"http://docs.aws.amazon.com/xray/latest/devguide/xray-api-segmentdocuments.html\">AWS X-Ray Segment Documents</a> in the <i>AWS X-Ray Developer Guide</i>.</p> <p class=\"title\"> <b>Required Segment Document Fields</b> </p> <ul> <li> <p> <code>name</code> - The name of the service that handled the request.</p> </li> <li> <p> <code>id</code> - A 64-bit identifier for the segment, unique among segments in the same trace, in 16 hexadecimal digits.</p> </li> <li> <p> <code>trace_id</code> - A unique identifier that connects all segments and subsegments originating from a single client request.</p> </li> <li> <p> <code>start_time</code> - Time the segment or subsegment was created, in floating point seconds in epoch time, accurate to milliseconds. For example, <code>1480615200.010</code> or <code>1.480615200010E9</code>.</p> </li> <li> <p> <code>end_time</code> - Time the segment or subsegment was closed. For example, <code>1480615200.090</code> or <code>1.480615200090E9</code>. Specify either an <code>end_time</code> or <code>in_progress</code>.</p> </li> <li> <p> <code>in_progress</code> - Set to <code>true</code> instead of specifying an <code>end_time</code> to record that a segment has been started, but is not complete. Send an in progress segment when your application receives a request that will take a long time to serve, to trace the fact that the request was received. When the response is sent, send the complete segment to overwrite the in-progress segment.</p> </li> </ul> <p>A <code>trace_id</code> consists of three numbers separated by hyphens. For example, 1-58406520-a006649127e371903a2de979. This includes:</p> <p class=\"title\"> <b>Trace ID Format</b> </p> <ul> <li> <p>The version number, i.e. <code>1</code>.</p> </li> <li> <p>The time of the original request, in Unix epoch time, in 8 hexadecimal digits. For example, 10:00AM December 2nd, 2016 PST in epoch time is <code>1480615200</code> seconds, or <code>58406520</code> in hexadecimal.</p> </li> <li> <p>A 96-bit identifier for the trace, globally unique, in 24 hexadecimal digits.</p> </li> </ul>"
}, },
"shapes": { "shapes": {
"Alias": { "Alias": {
@ -47,9 +47,9 @@
} }
}, },
"BackendConnectionErrors": { "BackendConnectionErrors": {
"base": "<p></p>", "base": "<p/>",
"refs": { "refs": {
"TelemetryRecord$BackendConnectionErrors": "<p></p>" "TelemetryRecord$BackendConnectionErrors": "<p/>"
} }
}, },
"BatchGetTracesRequest": { "BatchGetTracesRequest": {
@ -139,8 +139,9 @@
"Histogram": { "Histogram": {
"base": null, "base": null,
"refs": { "refs": {
"Edge$ResponseTimeHistogram": "<p>Histogram describing the prominence of response times on the edge.</p>", "Edge$ResponseTimeHistogram": "<p>A histogram that maps the spread of client response times on an edge.</p>",
"Service$DurationHistogram": "<p>Histogram mapping the spread of trace durations</p>" "Service$DurationHistogram": "<p>A histogram that maps the spread of service durations.</p>",
"Service$ResponseTimeHistogram": "<p>A histogram that maps the spread of service response times.</p>"
} }
}, },
"HistogramEntry": { "HistogramEntry": {
@ -192,19 +193,19 @@
"NullableInteger": { "NullableInteger": {
"base": null, "base": null,
"refs": { "refs": {
"BackendConnectionErrors$TimeoutCount": "<p></p>", "BackendConnectionErrors$TimeoutCount": "<p/>",
"BackendConnectionErrors$ConnectionRefusedCount": "<p></p>", "BackendConnectionErrors$ConnectionRefusedCount": "<p/>",
"BackendConnectionErrors$HTTPCode4XXCount": "<p></p>", "BackendConnectionErrors$HTTPCode4XXCount": "<p/>",
"BackendConnectionErrors$HTTPCode5XXCount": "<p></p>", "BackendConnectionErrors$HTTPCode5XXCount": "<p/>",
"BackendConnectionErrors$UnknownHostCount": "<p></p>", "BackendConnectionErrors$UnknownHostCount": "<p/>",
"BackendConnectionErrors$OtherCount": "<p></p>", "BackendConnectionErrors$OtherCount": "<p/>",
"Edge$ReferenceId": "<p>Identifier of the edge. Unique within a service map.</p>", "Edge$ReferenceId": "<p>Identifier of the edge. Unique within a service map.</p>",
"Http$HttpStatus": "<p>The response status.</p>", "Http$HttpStatus": "<p>The response status.</p>",
"Service$ReferenceId": "<p>Identifier for the service. Unique within the service map.</p>", "Service$ReferenceId": "<p>Identifier for the service. Unique within the service map.</p>",
"TelemetryRecord$SegmentsReceivedCount": "<p></p>", "TelemetryRecord$SegmentsReceivedCount": "<p/>",
"TelemetryRecord$SegmentsSentCount": "<p></p>", "TelemetryRecord$SegmentsSentCount": "<p/>",
"TelemetryRecord$SegmentsSpilloverCount": "<p></p>", "TelemetryRecord$SegmentsSpilloverCount": "<p/>",
"TelemetryRecord$SegmentsRejectedCount": "<p></p>" "TelemetryRecord$SegmentsRejectedCount": "<p/>"
} }
}, },
"NullableLong": { "NullableLong": {
@ -243,7 +244,7 @@
} }
}, },
"Segment": { "Segment": {
"base": "<p>Information about a segment</p>", "base": "<p>A segment from a trace that has been ingested by the X-Ray service. The segment can be compiled from documents uploaded with <a>PutTraceSegments</a>, or an <code>inferred</code> segment for a downstream service, generated from a subsegment sent by the service that called it.</p>",
"refs": { "refs": {
"SegmentList$member": null "SegmentList$member": null
} }
@ -251,7 +252,7 @@
"SegmentDocument": { "SegmentDocument": {
"base": null, "base": null,
"refs": { "refs": {
"Segment$Document": "<p>The segment document.</p>" "Segment$Document": "<p>The segment document</p>"
} }
}, },
"SegmentId": { "SegmentId": {
@ -273,7 +274,7 @@
} }
}, },
"ServiceId": { "ServiceId": {
"base": "<p></p>", "base": "<p/>",
"refs": { "refs": {
"ServiceIds$member": null "ServiceIds$member": null
} }
@ -297,7 +298,7 @@
"base": null, "base": null,
"refs": { "refs": {
"Service$Names": "<p>A list of names for the service, including the canonical name.</p>", "Service$Names": "<p>A list of names for the service, including the canonical name.</p>",
"ServiceId$Names": "<p></p>" "ServiceId$Names": "<p/>"
} }
}, },
"ServiceStatistics": { "ServiceStatistics": {
@ -325,16 +326,16 @@
"Http$HttpMethod": "<p>The request method.</p>", "Http$HttpMethod": "<p>The request method.</p>",
"Http$UserAgent": "<p>The request's user agent string.</p>", "Http$UserAgent": "<p>The request's user agent string.</p>",
"Http$ClientIp": "<p>The IP address of the requestor.</p>", "Http$ClientIp": "<p>The IP address of the requestor.</p>",
"PutTelemetryRecordsRequest$EC2InstanceId": "<p></p>", "PutTelemetryRecordsRequest$EC2InstanceId": "<p/>",
"PutTelemetryRecordsRequest$Hostname": "<p></p>", "PutTelemetryRecordsRequest$Hostname": "<p/>",
"PutTelemetryRecordsRequest$ResourceARN": "<p></p>", "PutTelemetryRecordsRequest$ResourceARN": "<p/>",
"Service$Name": "<p>The canonical name of the service.</p>", "Service$Name": "<p>The canonical name of the service.</p>",
"Service$AccountId": "<p>Identifier of the AWS account in which the service runs.</p>", "Service$AccountId": "<p>Identifier of the AWS account in which the service runs.</p>",
"Service$Type": "<p>The type of service.</p> <ul> <li> <p>AWS Resource - The type of an AWS resource. For example, <code>AWS::EC2::Instance</code> for a application running on Amazon EC2 or <code>AWS::DynamoDB::Table</code> for an Amazon DynamoDB table that the application used.</p> </li> <li> <p>AWS Service - The type of an AWS service. For example, <code>AWS::DynamoDB</code> for downstream calls to Amazon DynamoDB that didn't target a specific table.</p> </li> <li> <p> <code>client</code> - Represents the clients that sent requests to a root service.</p> </li> <li> <p> <code>remote</code> - A downstream service of indeterminate type.</p> </li> </ul>", "Service$Type": "<p>The type of service.</p> <ul> <li> <p>AWS Resource - The type of an AWS resource. For example, <code>AWS::EC2::Instance</code> for a application running on Amazon EC2 or <code>AWS::DynamoDB::Table</code> for an Amazon DynamoDB table that the application used.</p> </li> <li> <p>AWS Service - The type of an AWS service. For example, <code>AWS::DynamoDB</code> for downstream calls to Amazon DynamoDB that didn't target a specific table.</p> </li> <li> <p> <code>client</code> - Represents the clients that sent requests to a root service.</p> </li> <li> <p> <code>remote</code> - A downstream service of indeterminate type.</p> </li> </ul>",
"Service$State": "<p>The service's state.</p>", "Service$State": "<p>The service's state.</p>",
"ServiceId$Name": "<p></p>", "ServiceId$Name": "<p/>",
"ServiceId$AccountId": "<p></p>", "ServiceId$AccountId": "<p/>",
"ServiceId$Type": "<p></p>", "ServiceId$Type": "<p/>",
"ServiceNames$member": null, "ServiceNames$member": null,
"TraceUser$UserName": "<p>The user's name.</p>", "TraceUser$UserName": "<p>The user's name.</p>",
"UnprocessedTraceSegment$Id": "<p>The segment's ID.</p>", "UnprocessedTraceSegment$Id": "<p>The segment's ID.</p>",
@ -343,7 +344,7 @@
} }
}, },
"TelemetryRecord": { "TelemetryRecord": {
"base": "<p></p>", "base": "<p/>",
"refs": { "refs": {
"TelemetryRecordList$member": null "TelemetryRecordList$member": null
} }
@ -351,7 +352,7 @@
"TelemetryRecordList": { "TelemetryRecordList": {
"base": null, "base": null,
"refs": { "refs": {
"PutTelemetryRecordsRequest$TelemetryRecords": "<p></p>" "PutTelemetryRecordsRequest$TelemetryRecords": "<p/>"
} }
}, },
"ThrottledException": { "ThrottledException": {
@ -373,7 +374,7 @@
"GetTraceSummariesResult$ApproximateTime": "<p>The start time of this page of results.</p>", "GetTraceSummariesResult$ApproximateTime": "<p>The start time of this page of results.</p>",
"Service$StartTime": "<p>The start time of the first segment that the service generated.</p>", "Service$StartTime": "<p>The start time of the first segment that the service generated.</p>",
"Service$EndTime": "<p>The end time of the last segment that the service generated.</p>", "Service$EndTime": "<p>The end time of the last segment that the service generated.</p>",
"TelemetryRecord$Timestamp": "<p></p>" "TelemetryRecord$Timestamp": "<p/>"
} }
}, },
"Trace": { "Trace": {
@ -413,7 +414,7 @@
"TraceSegmentDocumentList": { "TraceSegmentDocumentList": {
"base": null, "base": null,
"refs": { "refs": {
"PutTraceSegmentsRequest$TraceSegmentDocuments": "<p>A JSON document defining one or more segments or subsegments. Segments must include the following fields.</p> <p class=\"title\"> <b>Required Segment Document Fields</b> </p> <ul> <li> <p> <code>name</code> - The name of the service that handled the request.</p> </li> <li> <p> <code>id</code> - A 64-bit identifier for the segment, unique among segments in the same trace, in 16 hexadecimal digits.</p> </li> <li> <p> <code>trace_id</code> - A unique identifier that connects all segments and subsegments originating from a single client request.</p> </li> <li> <p> <code>start_time</code> - Time the segment or subsegment was created, in floating point seconds in epoch time, accurate to milliseconds. For example, <code>1480615200.010</code> or <code>1.480615200010E9</code>.</p> </li> <li> <p> <code>end_time</code> - Time the segment or subsegment was closed. For example, <code>1480615200.090</code> or <code>1.480615200090E9</code>. Specify either an <code>end_time</code> or <code>in_progress</code>.</p> </li> <li> <p> <code>in_progress</code> - Set to <code>true</code> instead of specifying an <code>end_time</code> to record that a segment has been started, but is not complete. Send an in progress segment when your application receives a request that will take a long time to serve, to trace the fact that the request was received. When the response is sent, send the complete segment to overwrite the in-progress segment.</p> </li> </ul> <p>A <code>trace_id</code> consists of three numbers separated by hyphens. For example, 1-58406520-a006649127e371903a2de979. This includes:</p> <p class=\"title\"> <b>Trace ID Format</b> </p> <ul> <li> <p>The version number, i.e. <code>1</code>.</p> </li> <li> <p>The time of the original request, in Unix epoch time, in 8 hexadecimal digits. For example, 10:00AM December 2nd, 2016 PST in epoch time is <code>1480615200</code> seconds, or <code>58406520</code> in hexadecimal.</p> </li> <li> <p>A 96-bit identifier for the trace, globally unique, in 24 hexadecimal digits.</p> </li> </ul>" "PutTraceSegmentsRequest$TraceSegmentDocuments": "<p>A string containing a JSON document defining one or more segments or subsegments.</p>"
} }
}, },
"TraceSummary": { "TraceSummary": {

View File

@ -0,0 +1,4 @@
{
"pagination": {
}
}

View File

@ -313,6 +313,21 @@ func (c *XRay) GetTraceSummariesRequest(input *GetTraceSummariesInput) (req *req
// Retrieves IDs and metadata for traces available for a specified time frame // Retrieves IDs and metadata for traces available for a specified time frame
// using an optional filter. To get the full traces, pass the trace IDs to BatchGetTraces. // using an optional filter. To get the full traces, pass the trace IDs to BatchGetTraces.
// //
// A filter expression can target traced requests that hit specific service
// nodes or edges, have errors, or come from a known user. For example, the
// following filter expression targets traces that pass through api.example.com:
//
// service("api.example.com")
//
// This filter expression finds traces that have an annotation named account
// with the value 12345:
//
// annotation.account = "12345"
//
// For a full list of indexed fields and keywords that you can use in filter
// expressions, see Using Filter Expressions (http://docs.aws.amazon.com/xray/latest/devguide/xray-console-filters.html)
// in the AWS X-Ray Developer Guide.
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions // Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about // with awserr.Error's Code and Message methods to get detailed information about
// the error. // the error.
@ -482,6 +497,48 @@ func (c *XRay) PutTraceSegmentsRequest(input *PutTraceSegmentsInput) (req *reque
// document can be a completed segment, an in-progress segment, or an array // document can be a completed segment, an in-progress segment, or an array
// of subsegments. // of subsegments.
// //
// Segments must include the following fields. For the full segment document
// schema, see AWS X-Ray Segment Documents (http://docs.aws.amazon.com/xray/latest/devguide/xray-api-segmentdocuments.html)
// in the AWS X-Ray Developer Guide.
//
// Required Segment Document Fields
//
// * name - The name of the service that handled the request.
//
// * id - A 64-bit identifier for the segment, unique among segments in the
// same trace, in 16 hexadecimal digits.
//
// * trace_id - A unique identifier that connects all segments and subsegments
// originating from a single client request.
//
// * start_time - Time the segment or subsegment was created, in floating
// point seconds in epoch time, accurate to milliseconds. For example, 1480615200.010
// or 1.480615200010E9.
//
// * end_time - Time the segment or subsegment was closed. For example, 1480615200.090
// or 1.480615200090E9. Specify either an end_time or in_progress.
//
// * in_progress - Set to true instead of specifying an end_time to record
// that a segment has been started, but is not complete. Send an in progress
// segment when your application receives a request that will take a long
// time to serve, to trace the fact that the request was received. When the
// response is sent, send the complete segment to overwrite the in-progress
// segment.
//
// A trace_id consists of three numbers separated by hyphens. For example, 1-58406520-a006649127e371903a2de979.
// This includes:
//
// Trace ID Format
//
// * The version number, i.e. 1.
//
// * The time of the original request, in Unix epoch time, in 8 hexadecimal
// digits. For example, 10:00AM December 2nd, 2016 PST in epoch time is 1480615200
// seconds, or 58406520 in hexadecimal.
//
// * A 96-bit identifier for the trace, globally unique, in 24 hexadecimal
// digits.
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions // Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about // with awserr.Error's Code and Message methods to get detailed information about
// the error. // the error.
@ -772,7 +829,7 @@ type Edge struct {
// Identifier of the edge. Unique within a service map. // Identifier of the edge. Unique within a service map.
ReferenceId *int64 `type:"integer"` ReferenceId *int64 `type:"integer"`
// Histogram describing the prominence of response times on the edge. // A histogram that maps the spread of client response times on an edge.
ResponseTimeHistogram []*HistogramEntry `type:"list"` ResponseTimeHistogram []*HistogramEntry `type:"list"`
// The start time of the first segment on the edge. // The start time of the first segment on the edge.
@ -1474,46 +1531,7 @@ func (s PutTelemetryRecordsOutput) GoString() string {
type PutTraceSegmentsInput struct { type PutTraceSegmentsInput struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
// A JSON document defining one or more segments or subsegments. Segments must // A string containing a JSON document defining one or more segments or subsegments.
// include the following fields.
//
// Required Segment Document Fields
//
// * name - The name of the service that handled the request.
//
// * id - A 64-bit identifier for the segment, unique among segments in the
// same trace, in 16 hexadecimal digits.
//
// * trace_id - A unique identifier that connects all segments and subsegments
// originating from a single client request.
//
// * start_time - Time the segment or subsegment was created, in floating
// point seconds in epoch time, accurate to milliseconds. For example, 1480615200.010
// or 1.480615200010E9.
//
// * end_time - Time the segment or subsegment was closed. For example, 1480615200.090
// or 1.480615200090E9. Specify either an end_time or in_progress.
//
// * in_progress - Set to true instead of specifying an end_time to record
// that a segment has been started, but is not complete. Send an in progress
// segment when your application receives a request that will take a long
// time to serve, to trace the fact that the request was received. When the
// response is sent, send the complete segment to overwrite the in-progress
// segment.
//
// A trace_id consists of three numbers separated by hyphens. For example, 1-58406520-a006649127e371903a2de979.
// This includes:
//
// Trace ID Format
//
// * The version number, i.e. 1.
//
// * The time of the original request, in Unix epoch time, in 8 hexadecimal
// digits. For example, 10:00AM December 2nd, 2016 PST in epoch time is 1480615200
// seconds, or 58406520 in hexadecimal.
//
// * A 96-bit identifier for the trace, globally unique, in 24 hexadecimal
// digits.
// //
// TraceSegmentDocuments is a required field // TraceSegmentDocuments is a required field
TraceSegmentDocuments []*string `type:"list" required:"true"` TraceSegmentDocuments []*string `type:"list" required:"true"`
@ -1572,12 +1590,15 @@ func (s *PutTraceSegmentsOutput) SetUnprocessedTraceSegments(v []*UnprocessedTra
return s return s
} }
// Information about a segment // A segment from a trace that has been ingested by the X-Ray service. The segment
// can be compiled from documents uploaded with PutTraceSegments, or an inferred
// segment for a downstream service, generated from a subsegment sent by the
// service that called it.
// Please also see https://docs.aws.amazon.com/goto/WebAPI/xray-2016-04-12/Segment // Please also see https://docs.aws.amazon.com/goto/WebAPI/xray-2016-04-12/Segment
type Segment struct { type Segment struct {
_ struct{} `type:"structure"` _ struct{} `type:"structure"`
// The segment document. // The segment document
Document *string `min:"1" type:"string"` Document *string `min:"1" type:"string"`
// The segment's ID. // The segment's ID.
@ -1616,7 +1637,7 @@ type Service struct {
// Identifier of the AWS account in which the service runs. // Identifier of the AWS account in which the service runs.
AccountId *string `type:"string"` AccountId *string `type:"string"`
// Histogram mapping the spread of trace durations // A histogram that maps the spread of service durations.
DurationHistogram []*HistogramEntry `type:"list"` DurationHistogram []*HistogramEntry `type:"list"`
// Connections to downstream services. // Connections to downstream services.
@ -1634,6 +1655,9 @@ type Service struct {
// Identifier for the service. Unique within the service map. // Identifier for the service. Unique within the service map.
ReferenceId *int64 `type:"integer"` ReferenceId *int64 `type:"integer"`
// A histogram that maps the spread of service response times.
ResponseTimeHistogram []*HistogramEntry `type:"list"`
// Indicates that the service was the first service to process a request. // Indicates that the service was the first service to process a request.
Root *bool `type:"boolean"` Root *bool `type:"boolean"`
@ -1714,6 +1738,12 @@ func (s *Service) SetReferenceId(v int64) *Service {
return s return s
} }
// SetResponseTimeHistogram sets the ResponseTimeHistogram field's value.
func (s *Service) SetResponseTimeHistogram(v []*HistogramEntry) *Service {
s.ResponseTimeHistogram = v
return s
}
// SetRoot sets the Root field's value. // SetRoot sets the Root field's value.
func (s *Service) SetRoot(v bool) *Service { func (s *Service) SetRoot(v bool) *Service {
s.Root = &v s.Root = &v

View File

@ -26,3 +26,4 @@ notifications:
recipients: recipients:
- jamesog@cloudflare.com - jamesog@cloudflare.com
- msilverlock@cloudflare.com - msilverlock@cloudflare.com
- salvatore@cloudflare.com

View File

@ -28,10 +28,11 @@ The current feature list includes:
- [x] Cloudflare IPs - [x] Cloudflare IPs
- [x] User Administration (partial) - [x] User Administration (partial)
- [x] Virtual DNS Management - [x] Virtual DNS Management
- [x] Custom hostnames
- [ ] Organization Administration - [ ] Organization Administration
- [ ] [Railgun](https://www.cloudflare.com/railgun/) administration - [ ] [Railgun](https://www.cloudflare.com/railgun/) administration
- [ ] [Keyless SSL](https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/) - [ ] [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/) - [x] [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 Pull Requests are welcome, but please open an issue (or comment in an existing issue) to discuss any
non-trivial changes before submitting code. non-trivial changes before submitting code.

View File

@ -12,15 +12,23 @@ import (
) )
const apiURL = "https://api.cloudflare.com/client/v4" const apiURL = "https://api.cloudflare.com/client/v4"
const (
// AuthKeyEmail specifies that we should authenticate with API key and email address
AuthKeyEmail = 1 << iota
// AuthUserService specifies that we should authenticate with a User-Service key
AuthUserService
)
// API holds the configuration for the current API client. A client should not // API holds the configuration for the current API client. A client should not
// be modified concurrently. // be modified concurrently.
type API struct { type API struct {
APIKey string APIKey string
APIEmail string APIEmail string
APIUserServiceKey string
BaseURL string BaseURL string
headers http.Header headers http.Header
httpClient *http.Client httpClient *http.Client
authType int
} }
// New creates a new Cloudflare v4 API client. // New creates a new Cloudflare v4 API client.
@ -34,6 +42,7 @@ func New(key, email string, opts ...Option) (*API, error) {
APIEmail: email, APIEmail: email,
BaseURL: apiURL, BaseURL: apiURL,
headers: make(http.Header), headers: make(http.Header),
authType: AuthKeyEmail,
} }
err := api.parseOptions(opts...) err := api.parseOptions(opts...)
@ -50,6 +59,11 @@ func New(key, email string, opts ...Option) (*API, error) {
return api, nil return api, nil
} }
// SetAuthType sets the authentication method (AuthyKeyEmail or AuthUserService).
func (api *API) SetAuthType(authType int) {
api.authType = authType
}
// ZoneIDByName retrieves a zone's ID from the name. // ZoneIDByName retrieves a zone's ID from the name.
func (api *API) ZoneIDByName(zoneName string) (string, error) { func (api *API) ZoneIDByName(zoneName string) (string, error) {
res, err := api.ListZones(zoneName) res, err := api.ListZones(zoneName)
@ -67,6 +81,10 @@ func (api *API) ZoneIDByName(zoneName string) (string, error) {
// makeRequest makes a HTTP request and returns the body as a byte slice, // makeRequest makes a HTTP request and returns the body as a byte slice,
// closing it before returnng. params will be serialized to JSON. // closing it before returnng. params will be serialized to JSON.
func (api *API) makeRequest(method, uri string, params interface{}) ([]byte, error) { func (api *API) makeRequest(method, uri string, params interface{}) ([]byte, error) {
return api.makeRequestWithAuthType(method, uri, params, api.authType)
}
func (api *API) makeRequestWithAuthType(method, uri string, params interface{}, authType int) ([]byte, error) {
// Replace nil with a JSON object if needed // Replace nil with a JSON object if needed
var reqBody io.Reader var reqBody io.Reader
if params != nil { if params != nil {
@ -79,7 +97,7 @@ func (api *API) makeRequest(method, uri string, params interface{}) ([]byte, err
reqBody = nil reqBody = nil
} }
resp, err := api.request(method, uri, reqBody) resp, err := api.request(method, uri, reqBody, authType)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -114,7 +132,7 @@ func (api *API) makeRequest(method, uri string, params interface{}) ([]byte, err
// request makes a HTTP request to the given API endpoint, returning the raw // 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 // *http.Response, or an error if one occurred. The caller is responsible for
// closing the response body. // closing the response body.
func (api *API) request(method, uri string, reqBody io.Reader) (*http.Response, error) { func (api *API) request(method, uri string, reqBody io.Reader, authType int) (*http.Response, error) {
req, err := http.NewRequest(method, api.BaseURL+uri, reqBody) req, err := http.NewRequest(method, api.BaseURL+uri, reqBody)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "HTTP request creation failed") return nil, errors.Wrap(err, "HTTP request creation failed")
@ -122,8 +140,17 @@ func (api *API) request(method, uri string, reqBody io.Reader) (*http.Response,
// Apply any user-defined headers first. // Apply any user-defined headers first.
req.Header = cloneHeader(api.headers) req.Header = cloneHeader(api.headers)
if authType&AuthKeyEmail != 0 {
req.Header.Set("X-Auth-Key", api.APIKey) req.Header.Set("X-Auth-Key", api.APIKey)
req.Header.Set("X-Auth-Email", api.APIEmail) req.Header.Set("X-Auth-Email", api.APIEmail)
}
if authType&AuthUserService != 0 {
req.Header.Set("X-Auth-User-Service-Key", api.APIUserServiceKey)
}
if req.Header.Get("Content-Type") == "" {
req.Header.Set("Content-Type", "application/json")
}
resp, err := api.httpClient.Do(req) resp, err := api.httpClient.Do(req)
if err != nil { if err != nil {

View File

@ -20,13 +20,13 @@ var (
server *httptest.Server server *httptest.Server
) )
func setup() { func setup(opts ...Option) {
// test server // test server
mux = http.NewServeMux() mux = http.NewServeMux()
server = httptest.NewServer(mux) server = httptest.NewServer(mux)
// Cloudflare client configured to use test server // Cloudflare client configured to use test server
client, _ = New("cloudflare@example.org", "deadbeef") client, _ = New("deadbeef", "cloudflare@example.org", opts...)
client.BaseURL = server.URL client.BaseURL = server.URL
} }
@ -34,6 +34,48 @@ func teardown() {
server.Close() server.Close()
} }
func TestClient_Headers(t *testing.T) {
// it should set default headers
setup()
mux.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %s", r.Method)
assert.Equal(t, "cloudflare@example.org", r.Header.Get("X-Auth-Email"))
assert.Equal(t, "deadbeef", r.Header.Get("X-Auth-Key"))
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
})
client.UserDetails()
teardown()
// it should override appropriate default headers when custom headers given
headers := make(http.Header)
headers.Set("Content-Type", "application/xhtml+xml")
headers.Add("X-Random", "a random header")
setup(Headers(headers))
mux.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %s", r.Method)
assert.Equal(t, "cloudflare@example.org", r.Header.Get("X-Auth-Email"))
assert.Equal(t, "deadbeef", r.Header.Get("X-Auth-Key"))
assert.Equal(t, "application/xhtml+xml", r.Header.Get("Content-Type"))
assert.Equal(t, "a random header", r.Header.Get("X-Random"))
})
client.UserDetails()
teardown()
// it should set X-Auth-User-Service-Key and omit X-Auth-Email and X-Auth-Key when client.authType is AuthUserService
setup()
client.SetAuthType(AuthUserService)
client.APIUserServiceKey = "userservicekey"
mux.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %s", r.Method)
assert.Empty(t, r.Header.Get("X-Auth-Email"))
assert.Empty(t, r.Header.Get("X-Auth-Key"))
assert.Equal(t, "userservicekey", r.Header.Get("X-Auth-User-Service-Key"))
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
})
client.UserDetails()
teardown()
}
func TestClient_Auth(t *testing.T) { func TestClient_Auth(t *testing.T) {
setup() setup()
defer teardown() defer teardown()

View File

@ -0,0 +1,163 @@
package main
import (
"fmt"
"strings"
"github.com/cloudflare/cloudflare-go"
"github.com/codegangsta/cli"
)
func dnsCreate(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
if err := checkFlags(c, "zone", "name", "type", "content"); err != nil {
return
}
zone := c.String("zone")
name := c.String("name")
rtype := c.String("type")
content := c.String("content")
ttl := c.Int("ttl")
proxy := c.Bool("proxy")
zoneID, err := api.ZoneIDByName(zone)
if err != nil {
fmt.Println(err)
return
}
record := cloudflare.DNSRecord{
Name: name,
Type: strings.ToUpper(rtype),
Content: content,
TTL: ttl,
Proxied: proxy,
}
// TODO: Print the result.
_, err = api.CreateDNSRecord(zoneID, record)
if err != nil {
fmt.Println("Error creating DNS record:", err)
}
}
func dnsCreateOrUpdate(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
if err := checkFlags(c, "zone", "name", "type", "content"); err != nil {
return
}
zone := c.String("zone")
name := c.String("name")
rtype := strings.ToUpper(c.String("type"))
content := c.String("content")
ttl := c.Int("ttl")
proxy := c.Bool("proxy")
zoneID, err := api.ZoneIDByName(zone)
if err != nil {
fmt.Println(err)
return
}
// Look for an existing record
rr := cloudflare.DNSRecord{
Name: name + "." + zone,
}
records, err := api.DNSRecords(zoneID, rr)
if err != nil {
fmt.Println(err)
return
}
if len(records) > 0 {
// Record exists - find the ID and update it.
// This is imprecise without knowing the original content; if a label
// has multiple RRs we'll just update the first one.
for _, r := range records {
if r.Type == rtype {
rr.ID = r.ID
rr.Type = r.Type
rr.Content = content
rr.TTL = ttl
rr.Proxied = proxy
err := api.UpdateDNSRecord(zoneID, r.ID, rr)
if err != nil {
fmt.Println("Error updating DNS record:", err)
}
}
}
} else {
// Record doesn't exist - create it
rr.Type = rtype
rr.Content = content
rr.TTL = ttl
rr.Proxied = proxy
// TODO: Print the response.
_, err := api.CreateDNSRecord(zoneID, rr)
if err != nil {
fmt.Println("Error creating DNS record:", err)
}
}
}
func dnsUpdate(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
if err := checkFlags(c, "zone", "id"); err != nil {
return
}
zone := c.String("zone")
recordID := c.String("id")
name := c.String("name")
content := c.String("content")
ttl := c.Int("ttl")
proxy := c.Bool("proxy")
zoneID, err := api.ZoneIDByName(zone)
if err != nil {
fmt.Println(err)
return
}
record := cloudflare.DNSRecord{
ID: recordID,
Name: name,
Content: content,
TTL: ttl,
Proxied: proxy,
}
err = api.UpdateDNSRecord(zoneID, recordID, record)
if err != nil {
fmt.Println("Error updating DNS record:", err)
}
}
func dnsDelete(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
if err := checkFlags(c, "zone", "id"); err != nil {
return
}
zone := c.String("zone")
recordID := c.String("id")
zoneID, err := api.ZoneIDByName(zone)
if err != nil {
fmt.Println(err)
return
}
err = api.DeleteDNSRecord(zoneID, recordID)
if err != nil {
fmt.Println("Error deleting DNS record:", err)
}
}

View File

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"reflect"
"strings" "strings"
"github.com/cloudflare/cloudflare-go" "github.com/cloudflare/cloudflare-go"
@ -82,437 +81,6 @@ func checkFlags(c *cli.Context, flags ...string) error {
return nil return nil
} }
func ips(*cli.Context) {
ips, _ := cloudflare.IPs()
fmt.Println("IPv4 ranges:")
for _, r := range ips.IPv4CIDRs {
fmt.Println(" ", r)
}
fmt.Println()
fmt.Println("IPv6 ranges:")
for _, r := range ips.IPv6CIDRs {
fmt.Println(" ", r)
}
}
func userInfo(*cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
user, err := api.UserDetails()
if err != nil {
fmt.Println(err)
return
}
var output []table
output = append(output, table{
"ID": user.ID,
"Email": user.Email,
"Username": user.Username,
"Name": user.FirstName + " " + user.LastName,
"2FA": fmt.Sprintf("%t", user.TwoFA),
})
makeTable(output, "ID", "Email", "Username", "Name", "2FA")
}
func userUpdate(*cli.Context) {
}
func zoneCreate(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
if err := checkFlags(c, "zone"); err != nil {
return
}
zone := c.String("zone")
jumpstart := c.Bool("jumpstart")
orgID := c.String("org-id")
var org cloudflare.Organization
if orgID != "" {
org.ID = orgID
}
api.CreateZone(zone, jumpstart, org)
}
func zoneCheck(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
if err := checkFlags(c, "zone"); err != nil {
return
}
zone := c.String("zone")
zoneID, err := api.ZoneIDByName(zone)
if err != nil {
fmt.Println(err)
return
}
res, err := api.ZoneActivationCheck(zoneID)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%s\n", res.Messages[0].Message)
}
func zoneList(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
zones, err := api.ListZones()
if err != nil {
fmt.Println(err)
return
}
var output []table
for _, z := range zones {
output = append(output, table{
"ID": z.ID,
"Name": z.Name,
"Plan": z.Plan.LegacyID,
"Status": z.Status,
})
}
makeTable(output, "ID", "Name", "Plan", "Status")
}
func zoneInfo(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
var zone string
if len(c.Args()) > 0 {
zone = c.Args()[0]
} else if c.String("zone") != "" {
zone = c.String("zone")
} else {
cli.ShowSubcommandHelp(c)
return
}
zones, err := api.ListZones(zone)
if err != nil {
fmt.Println(err)
return
}
var output []table
for _, z := range zones {
var nameservers []string
if len(z.VanityNS) > 0 {
nameservers = z.VanityNS
} else {
nameservers = z.NameServers
}
output = append(output, table{
"ID": z.ID,
"Zone": z.Name,
"Plan": z.Plan.LegacyID,
"Status": z.Status,
"Name Servers": strings.Join(nameservers, ", "),
"Paused": fmt.Sprintf("%t", z.Paused),
"Type": z.Type,
})
}
makeTable(output, "ID", "Zone", "Plan", "Status", "Name Servers", "Paused", "Type")
}
func zonePlan(*cli.Context) {
}
func zoneSettings(*cli.Context) {
}
func zoneRecords(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
var zone string
if len(c.Args()) > 0 {
zone = c.Args()[0]
} else if c.String("zone") != "" {
zone = c.String("zone")
} else {
cli.ShowSubcommandHelp(c)
return
}
zoneID, err := api.ZoneIDByName(zone)
if err != nil {
fmt.Println(err)
return
}
// Create a an empty record for searching for records
rr := cloudflare.DNSRecord{}
var records []cloudflare.DNSRecord
if c.String("id") != "" {
rec, err := api.DNSRecord(zoneID, c.String("id"))
if err != nil {
fmt.Println(err)
return
}
records = append(records, rec)
} else {
if c.String("name") != "" {
rr.Name = c.String("name")
}
if c.String("content") != "" {
rr.Name = c.String("content")
}
var err error
records, err = api.DNSRecords(zoneID, rr)
if err != nil {
fmt.Println(err)
return
}
}
var output []table
for _, r := range records {
switch r.Type {
case "MX":
r.Content = fmt.Sprintf("%d %s", r.Priority, r.Content)
case "SRV":
dp := reflect.ValueOf(r.Data).Interface().(map[string]interface{})
r.Content = fmt.Sprintf("%.f %s", dp["priority"], r.Content)
// Cloudflare's API, annoyingly, automatically prepends the weight
// and port into content, separated by tabs.
// XXX: File this as a bug. LOC doesn't do this.
r.Content = strings.Replace(r.Content, "\t", " ", -1)
}
output = append(output, table{
"ID": r.ID,
"Type": r.Type,
"Name": r.Name,
"Content": r.Content,
"Proxied": fmt.Sprintf("%t", r.Proxied),
"TTL": fmt.Sprintf("%d", r.TTL),
})
}
makeTable(output, "ID", "Type", "Name", "Content", "Proxied", "TTL")
}
func dnsCreate(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
if err := checkFlags(c, "zone", "name", "type", "content"); err != nil {
return
}
zone := c.String("zone")
name := c.String("name")
rtype := c.String("type")
content := c.String("content")
ttl := c.Int("ttl")
proxy := c.Bool("proxy")
zoneID, err := api.ZoneIDByName(zone)
if err != nil {
fmt.Println(err)
return
}
record := cloudflare.DNSRecord{
Name: name,
Type: strings.ToUpper(rtype),
Content: content,
TTL: ttl,
Proxied: proxy,
}
// TODO: Print the result.
_, err = api.CreateDNSRecord(zoneID, record)
if err != nil {
fmt.Println("Error creating DNS record:", err)
}
}
func dnsCreateOrUpdate(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
if err := checkFlags(c, "zone", "name", "type", "content"); err != nil {
return
}
zone := c.String("zone")
name := c.String("name")
rtype := strings.ToUpper(c.String("type"))
content := c.String("content")
ttl := c.Int("ttl")
proxy := c.Bool("proxy")
zoneID, err := api.ZoneIDByName(zone)
if err != nil {
fmt.Println(err)
return
}
// Look for an existing record
rr := cloudflare.DNSRecord{
Name: name + "." + zone,
}
records, err := api.DNSRecords(zoneID, rr)
if err != nil {
fmt.Println(err)
return
}
if len(records) > 0 {
// Record exists - find the ID and update it.
// This is imprecise without knowing the original content; if a label
// has multiple RRs we'll just update the first one.
for _, r := range records {
if r.Type == rtype {
rr.ID = r.ID
rr.Type = r.Type
rr.Content = content
rr.TTL = ttl
rr.Proxied = proxy
err := api.UpdateDNSRecord(zoneID, r.ID, rr)
if err != nil {
fmt.Println("Error updating DNS record:", err)
}
}
}
} else {
// Record doesn't exist - create it
rr.Type = rtype
rr.Content = content
rr.TTL = ttl
rr.Proxied = proxy
// TODO: Print the response.
_, err := api.CreateDNSRecord(zoneID, rr)
if err != nil {
fmt.Println("Error creating DNS record:", err)
}
}
}
func dnsUpdate(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
if err := checkFlags(c, "zone", "id"); err != nil {
return
}
zone := c.String("zone")
recordID := c.String("id")
name := c.String("name")
content := c.String("content")
ttl := c.Int("ttl")
proxy := c.Bool("proxy")
zoneID, err := api.ZoneIDByName(zone)
if err != nil {
fmt.Println(err)
return
}
record := cloudflare.DNSRecord{
ID: recordID,
Name: name,
Content: content,
TTL: ttl,
Proxied: proxy,
}
err = api.UpdateDNSRecord(zoneID, recordID, record)
if err != nil {
fmt.Println("Error updating DNS record:", err)
}
}
func dnsDelete(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
if err := checkFlags(c, "zone", "id"); err != nil {
return
}
zone := c.String("zone")
recordID := c.String("id")
zoneID, err := api.ZoneIDByName(zone)
if err != nil {
fmt.Println(err)
return
}
err = api.DeleteDNSRecord(zoneID, recordID)
if err != nil {
fmt.Println("Error deleting DNS record:", err)
}
}
func zoneCerts(*cli.Context) {
}
func zoneKeyless(*cli.Context) {
}
func zoneRailgun(*cli.Context) {
}
func pageRules(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
if err := checkFlags(c, "zone"); err != nil {
return
}
zone := c.String("zone")
zoneID, err := api.ZoneIDByName(zone)
if err != nil {
fmt.Println(err)
return
}
rules, err := api.ListPageRules(zoneID)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%3s %-32s %-8s %s\n", "Pri", "ID", "Status", "URL")
for _, r := range rules {
var settings []string
fmt.Printf("%3d %s %-8s %s\n", r.Priority, r.ID, r.Status, r.Targets[0].Constraint.Value)
for _, a := range r.Actions {
v := reflect.ValueOf(a.Value)
var s string
switch a.Value.(type) {
case int:
s = fmt.Sprintf("%s: %d", cloudflare.PageRuleActions[a.ID], v.Int())
case float64:
s = fmt.Sprintf("%s: %.f", cloudflare.PageRuleActions[a.ID], v.Float())
case map[string]interface{}:
vmap := a.Value.(map[string]interface{})
s = fmt.Sprintf("%s: %.f - %s", cloudflare.PageRuleActions[a.ID], vmap["status_code"], vmap["url"])
case nil:
s = fmt.Sprintf("%s", cloudflare.PageRuleActions[a.ID])
default:
s = fmt.Sprintf("%s: %s", cloudflare.PageRuleActions[a.ID], strings.Title(strings.Replace(v.String(), "_", " ", -1)))
}
settings = append(settings, s)
}
fmt.Println(" ", strings.Join(settings, ", "))
}
}
func railgun(*cli.Context) {
}
func main() { func main() {
app := cli.NewApp() app := cli.NewApp()
app.Name = "flarectl" app.Name = "flarectl"

View File

@ -0,0 +1,96 @@
package main
import (
"fmt"
"strings"
"github.com/cloudflare/cloudflare-go"
"github.com/codegangsta/cli"
)
func ips(*cli.Context) {
ips, _ := cloudflare.IPs()
fmt.Println("IPv4 ranges:")
for _, r := range ips.IPv4CIDRs {
fmt.Println(" ", r)
}
fmt.Println()
fmt.Println("IPv6 ranges:")
for _, r := range ips.IPv6CIDRs {
fmt.Println(" ", r)
}
}
func userInfo(*cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
user, err := api.UserDetails()
if err != nil {
fmt.Println(err)
return
}
var output []table
output = append(output, table{
"ID": user.ID,
"Email": user.Email,
"Username": user.Username,
"Name": user.FirstName + " " + user.LastName,
"2FA": fmt.Sprintf("%t", user.TwoFA),
})
makeTable(output, "ID", "Email", "Username", "Name", "2FA")
}
func userUpdate(*cli.Context) {
}
func pageRules(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
if err := checkFlags(c, "zone"); err != nil {
return
}
zone := c.String("zone")
zoneID, err := api.ZoneIDByName(zone)
if err != nil {
fmt.Println(err)
return
}
rules, err := api.ListPageRules(zoneID)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%3s %-32s %-8s %s\n", "Pri", "ID", "Status", "URL")
for _, r := range rules {
var settings []string
fmt.Printf("%3d %s %-8s %s\n", r.Priority, r.ID, r.Status, r.Targets[0].Constraint.Value)
for _, a := range r.Actions {
var s string
switch v := a.Value.(type) {
case int:
s = fmt.Sprintf("%s: %d", cloudflare.PageRuleActions[a.ID], v)
case float64:
s = fmt.Sprintf("%s: %.f", cloudflare.PageRuleActions[a.ID], v)
case map[string]interface{}:
s = fmt.Sprintf("%s: %.f - %s", cloudflare.PageRuleActions[a.ID], v["status_code"], v["url"])
case nil:
s = fmt.Sprintf("%s", cloudflare.PageRuleActions[a.ID])
default:
vs := fmt.Sprintf("%s", v)
s = fmt.Sprintf("%s: %s", cloudflare.PageRuleActions[a.ID], strings.Title(strings.Replace(vs, "_", " ", -1)))
}
settings = append(settings, s)
}
fmt.Println(" ", strings.Join(settings, ", "))
}
}
func railgun(*cli.Context) {
}

View File

@ -0,0 +1,198 @@
package main
import (
"fmt"
"strings"
"github.com/cloudflare/cloudflare-go"
"github.com/codegangsta/cli"
)
func zoneCerts(*cli.Context) {
}
func zoneKeyless(*cli.Context) {
}
func zoneRailgun(*cli.Context) {
}
func zoneCreate(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
if err := checkFlags(c, "zone"); err != nil {
return
}
zone := c.String("zone")
jumpstart := c.Bool("jumpstart")
orgID := c.String("org-id")
var org cloudflare.Organization
if orgID != "" {
org.ID = orgID
}
api.CreateZone(zone, jumpstart, org)
}
func zoneCheck(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
if err := checkFlags(c, "zone"); err != nil {
return
}
zone := c.String("zone")
zoneID, err := api.ZoneIDByName(zone)
if err != nil {
fmt.Println(err)
return
}
res, err := api.ZoneActivationCheck(zoneID)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%s\n", res.Messages[0].Message)
}
func zoneList(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
zones, err := api.ListZones()
if err != nil {
fmt.Println(err)
return
}
var output []table
for _, z := range zones {
output = append(output, table{
"ID": z.ID,
"Name": z.Name,
"Plan": z.Plan.Name,
"Status": z.Status,
})
}
makeTable(output, "ID", "Name", "Plan", "Status")
}
func zoneInfo(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
var zone string
if len(c.Args()) > 0 {
zone = c.Args()[0]
} else if c.String("zone") != "" {
zone = c.String("zone")
} else {
cli.ShowSubcommandHelp(c)
return
}
zones, err := api.ListZones(zone)
if err != nil {
fmt.Println(err)
return
}
var output []table
for _, z := range zones {
var nameservers []string
if len(z.VanityNS) > 0 {
nameservers = z.VanityNS
} else {
nameservers = z.NameServers
}
output = append(output, table{
"ID": z.ID,
"Zone": z.Name,
"Plan": z.Plan.Name,
"Status": z.Status,
"Name Servers": strings.Join(nameservers, ", "),
"Paused": fmt.Sprintf("%t", z.Paused),
"Type": z.Type,
})
}
makeTable(output, "ID", "Zone", "Plan", "Status", "Name Servers", "Paused", "Type")
}
func zonePlan(*cli.Context) {
}
func zoneSettings(*cli.Context) {
}
func zoneRecords(c *cli.Context) {
if err := checkEnv(); err != nil {
fmt.Println(err)
return
}
var zone string
if len(c.Args()) > 0 {
zone = c.Args()[0]
} else if c.String("zone") != "" {
zone = c.String("zone")
} else {
cli.ShowSubcommandHelp(c)
return
}
zoneID, err := api.ZoneIDByName(zone)
if err != nil {
fmt.Println(err)
return
}
// Create a an empty record for searching for records
rr := cloudflare.DNSRecord{}
var records []cloudflare.DNSRecord
if c.String("id") != "" {
rec, err := api.DNSRecord(zoneID, c.String("id"))
if err != nil {
fmt.Println(err)
return
}
records = append(records, rec)
} else {
if c.String("name") != "" {
rr.Name = c.String("name")
}
if c.String("content") != "" {
rr.Name = c.String("content")
}
var err error
records, err = api.DNSRecords(zoneID, rr)
if err != nil {
fmt.Println(err)
return
}
}
var output []table
for _, r := range records {
switch r.Type {
case "MX":
r.Content = fmt.Sprintf("%d %s", r.Priority, r.Content)
case "SRV":
dp := r.Data.(map[string]interface{})
r.Content = fmt.Sprintf("%.f %s", dp["priority"], r.Content)
// Cloudflare's API, annoyingly, automatically prepends the weight
// and port into content, separated by tabs.
// XXX: File this as a bug. LOC doesn't do this.
r.Content = strings.Replace(r.Content, "\t", " ", -1)
}
output = append(output, table{
"ID": r.ID,
"Type": r.Type,
"Name": r.Name,
"Content": r.Content,
"Proxied": fmt.Sprintf("%t", r.Proxied),
"TTL": fmt.Sprintf("%d", r.TTL),
})
}
makeTable(output, "ID", "Type", "Name", "Content", "Proxied", "TTL")
}

View File

@ -0,0 +1,149 @@
package cloudflare
import (
"encoding/json"
"net/url"
"strconv"
"github.com/pkg/errors"
)
// CustomHostnameSSL represents the SSL section in a given custom hostname.
type CustomHostnameSSL struct {
Status string `json:"status,omitempty"`
Method string `json:"method,omitempty"`
Type string `json:"type,omitempty"`
CnameTarget string `json:"cname_target,omitempty"`
CnameName string `json:"cname_name,omitempty"`
}
// CustomMetadata defines custom metadata for the hostname. This requires logic to be implemented by Cloudflare to act on the data provided.
type CustomMetadata map[string]interface{}
// CustomHostname represents a custom hostname in a zone.
type CustomHostname struct {
ID string `json:"id,omitempty"`
Hostname string `json:"hostname,omitempty"`
SSL CustomHostnameSSL `json:"ssl,omitempty"`
CustomMetadata CustomMetadata `json:"custom_metadata,omitempty"`
}
// CustomHostNameResponse represents a response from the Custom Hostnames endpoints.
type CustomHostnameResponse struct {
Result CustomHostname `json:"result"`
Response
}
// CustomHostnameListResponse represents a response from the Custom Hostnames endpoints.
type CustomHostnameListResponse struct {
Result []CustomHostname `json:"result"`
Response
ResultInfo `json:"result_info"`
}
// Modify SSL configuration for the given custom hostname in the given zone.
//
// API reference: https://api.cloudflare.com/#custom-hostname-for-a-zone-update-custom-hostname-configuration
func (api *API) UpdateCustomHostnameSSL(zoneID string, customHostnameID string, ssl CustomHostnameSSL) (CustomHostname, error) {
return CustomHostname{}, errors.New("Not implemented")
}
// Delete a custom hostname (and any issued SSL certificates)
//
// API reference: https://api.cloudflare.com/#custom-hostname-for-a-zone-delete-a-custom-hostname-and-any-issued-ssl-certificates-
func (api *API) DeleteCustomHostname(zoneID string, customHostnameID string) error {
uri := "/zones/" + zoneID + "/custom_hostnames/" + customHostnameID
res, err := api.makeRequest("DELETE", uri, nil)
if err != nil {
return errors.Wrap(err, errMakeRequestError)
}
var response *CustomHostnameResponse
err = json.Unmarshal(res, &response)
if err != nil {
return errors.Wrap(err, errUnmarshalError)
}
return nil
}
// CreateCustomHostname creates a new custom hostname and requests that an SSL certificate be issued for it.
//
// API reference: https://api.cloudflare.com/#custom-hostname-for-a-zone-create-custom-hostname
func (api *API) CreateCustomHostname(zoneID string, ch CustomHostname) (*CustomHostnameResponse, error) {
uri := "/zones/" + zoneID + "/custom_hostnames"
res, err := api.makeRequest("POST", uri, ch)
if err != nil {
return nil, errors.Wrap(err, errMakeRequestError)
}
var response *CustomHostnameResponse
err = json.Unmarshal(res, &response)
if err != nil {
return nil, errors.Wrap(err, errUnmarshalError)
}
return response, nil
}
// CustomHostnames fetches custom hostnames for the given zone,
// by applying filter.Hostname if not empty and scoping the result to page'th 50 items.
//
// The returned ResultInfo can be used to implement pagination.
//
// API reference: https://api.cloudflare.com/#custom-hostname-for-a-zone-list-custom-hostnames
func (api *API) CustomHostnames(zoneID string, page int, filter CustomHostname) ([]CustomHostname, ResultInfo, error) {
v := url.Values{}
v.Set("per_page", "50")
v.Set("page", strconv.Itoa(page))
if filter.Hostname != "" {
v.Set("hostname", filter.Hostname)
}
query := "?" + v.Encode()
uri := "/zones/" + zoneID + "/custom_hostnames" + query
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return []CustomHostname{}, ResultInfo{}, errors.Wrap(err, errMakeRequestError)
}
var customHostnameListResponse CustomHostnameListResponse
err = json.Unmarshal(res, &customHostnameListResponse)
if err != nil {
return []CustomHostname{}, ResultInfo{}, errors.Wrap(err, errMakeRequestError)
}
return customHostnameListResponse.Result, customHostnameListResponse.ResultInfo, nil
}
// CustomHostname inspects the given custom hostname in the given zone.
//
// API reference: https://api.cloudflare.com/#custom-hostname-for-a-zone-custom-hostname-configuration-details
func (api *API) CustomHostname(zoneID string, customHostnameID string) (CustomHostname, error) {
uri := "/zones/" + zoneID + "/custom_hostnames/" + customHostnameID
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return CustomHostname{}, errors.Wrap(err, errMakeRequestError)
}
var response CustomHostnameResponse
err = json.Unmarshal(res, &response)
if err != nil {
return CustomHostname{}, errors.Wrap(err, errUnmarshalError)
}
return response.Result, nil
}
// CustomHostnameIDByName retrieves the ID for the given hostname in the given zone.
func (api *API) CustomHostnameIDByName(zoneID string, hostname string) (string, error) {
customHostnames, _, err := api.CustomHostnames(zoneID, 1, CustomHostname{Hostname: hostname})
if err != nil {
return "", errors.Wrap(err, "CustomHostnames command failed")
}
for _, ch := range customHostnames {
if ch.Hostname == hostname {
return ch.ID, nil
}
}
return "", errors.New("CustomHostname could not be found")
}

View File

@ -0,0 +1,177 @@
package cloudflare
import (
"fmt"
"net/http"
"testing"
"github.com/stretchr/testify/assert"
)
func TestCustomHostname_DeleteCustomHostname(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/zones/foo/custom_hostnames/bar", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "DELETE", r.Method, "Expected method 'DELETE', got %s", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `
{
"id": "bar"
}`)
})
err := client.DeleteCustomHostname("foo", "bar")
assert.NoError(t, err)
}
func TestCustomHostname_CreateCustomHostname(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/zones/foo/custom_hostnames", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "POST", r.Method, "Expected method 'POST', got %s", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `
{
"success": true,
"errors": [],
"messages": [],
"result": {
"id": "0d89c70d-ad9f-4843-b99f-6cc0252067e9",
"hostname": "app.example.com",
"ssl": {
"status": "pending_validation",
"method": "cname",
"type": "dv",
"cname_target": "dcv.digicert.com",
"cname_name": "810b7d5f01154524b961ba0cd578acc2.app.example.com"
}
}
}`)
})
response, err := client.CreateCustomHostname("foo", CustomHostname{Hostname: "app.example.com", SSL: CustomHostnameSSL{Method: "cname", Type: "dv"}})
want := &CustomHostnameResponse{
Result: CustomHostname{
ID: "0d89c70d-ad9f-4843-b99f-6cc0252067e9",
Hostname: "app.example.com",
SSL: CustomHostnameSSL{
Type: "dv",
Method: "cname",
Status: "pending_validation",
CnameTarget: "dcv.digicert.com",
CnameName: "810b7d5f01154524b961ba0cd578acc2.app.example.com",
},
},
Response: Response{Success: true, Errors: []ResponseInfo{}, Messages: []ResponseInfo{}},
}
if assert.NoError(t, err) {
assert.Equal(t, want, response)
}
}
func TestCustomHostname_CustomHostnames(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/zones/foo/custom_hostnames", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %s", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
"result": [
{
"id": "custom_host_1",
"hostname": "custom.host.one",
"ssl": {
"type": "dv",
"method": "cname",
"status": "pending_validation",
"cname_target": "dcv.digicert.com",
"cname_name": "810b7d5f01154524b961ba0cd578acc2.app.example.com"
},
"custom_metadata": {
"a_random_field": "random field value"
}
}
],
"result_info": {
"page": 1,
"per_page": 20,
"count": 5,
"total_count": 5
}
}`)
})
customHostnames, _, err := client.CustomHostnames("foo", 1, CustomHostname{})
want := []CustomHostname{
{
ID: "custom_host_1",
Hostname: "custom.host.one",
SSL: CustomHostnameSSL{
Type: "dv",
Method: "cname",
Status: "pending_validation",
CnameTarget: "dcv.digicert.com",
CnameName: "810b7d5f01154524b961ba0cd578acc2.app.example.com",
},
CustomMetadata: CustomMetadata{"a_random_field": "random field value"},
},
}
if assert.NoError(t, err) {
assert.Equal(t, want, customHostnames)
}
}
func TestCustomHostname_CustomHostname(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/zones/foo/custom_hostnames/bar", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %s", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
"result": {
"id": "bar",
"hostname": "foo.bar.com",
"ssl": {
"type": "dv",
"method": "http",
"status": "active"
},
"custom_metadata": {
"origin": "a.custom.origin"
}
}
}`)
})
customHostname, err := client.CustomHostname("foo", "bar")
want := CustomHostname{
ID: "bar",
Hostname: "foo.bar.com",
SSL: CustomHostnameSSL{
Status: "active",
Method: "http",
Type: "dv",
},
CustomMetadata: CustomMetadata{"origin": "a.custom.origin"},
}
if assert.NoError(t, err) {
assert.Equal(t, want, customHostname)
}
}

View File

@ -43,9 +43,8 @@ type DNSListResponse struct {
} }
// CreateDNSRecord creates a DNS record for the zone identifier. // CreateDNSRecord creates a DNS record for the zone identifier.
// API reference: //
// https://api.cloudflare.com/#dns-records-for-a-zone-create-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) (*DNSRecordResponse, error) { func (api *API) CreateDNSRecord(zoneID string, rr DNSRecord) (*DNSRecordResponse, error) {
uri := "/zones/" + zoneID + "/dns_records" uri := "/zones/" + zoneID + "/dns_records"
res, err := api.makeRequest("POST", uri, rr) res, err := api.makeRequest("POST", uri, rr)
@ -63,9 +62,10 @@ func (api *API) CreateDNSRecord(zoneID string, rr DNSRecord) (*DNSRecordResponse
} }
// DNSRecords returns a slice of DNS records for the given zone identifier. // 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 // This takes a DNSRecord to allow filtering of the results returned.
// GET /zones/:zone_identifier/dns_records //
// API reference: https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records
func (api *API) DNSRecords(zoneID string, rr DNSRecord) ([]DNSRecord, error) { func (api *API) DNSRecords(zoneID string, rr DNSRecord) ([]DNSRecord, error) {
// Construct a query string // Construct a query string
v := url.Values{} v := url.Values{}
@ -111,9 +111,8 @@ func (api *API) DNSRecords(zoneID string, rr DNSRecord) ([]DNSRecord, error) {
// DNSRecord returns a single DNS record for the given zone & record // DNSRecord returns a single DNS record for the given zone & record
// identifiers. // identifiers.
// API reference: //
// https://api.cloudflare.com/#dns-records-for-a-zone-dns-record-details // 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) { func (api *API) DNSRecord(zoneID, recordID string) (DNSRecord, error) {
uri := "/zones/" + zoneID + "/dns_records/" + recordID uri := "/zones/" + zoneID + "/dns_records/" + recordID
res, err := api.makeRequest("GET", uri, nil) res, err := api.makeRequest("GET", uri, nil)
@ -130,9 +129,8 @@ func (api *API) DNSRecord(zoneID, recordID string) (DNSRecord, error) {
// UpdateDNSRecord updates a single DNS record for the given zone & record // UpdateDNSRecord updates a single DNS record for the given zone & record
// identifiers. // identifiers.
// API reference: //
// https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record // 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 { func (api *API) UpdateDNSRecord(zoneID, recordID string, rr DNSRecord) error {
rec, err := api.DNSRecord(zoneID, recordID) rec, err := api.DNSRecord(zoneID, recordID)
if err != nil { if err != nil {
@ -159,9 +157,8 @@ func (api *API) UpdateDNSRecord(zoneID, recordID string, rr DNSRecord) error {
// DeleteDNSRecord deletes a single DNS record for the given zone & record // DeleteDNSRecord deletes a single DNS record for the given zone & record
// identifiers. // identifiers.
// API reference: //
// https://api.cloudflare.com/#dns-records-for-a-zone-delete-dns-record // 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 { func (api *API) DeleteDNSRecord(zoneID, recordID string) error {
uri := "/zones/" + zoneID + "/dns_records/" + recordID uri := "/zones/" + zoneID + "/dns_records/" + recordID
res, err := api.makeRequest("DELETE", uri, nil) res, err := api.makeRequest("DELETE", uri, nil)

View File

@ -0,0 +1,100 @@
package cloudflare_test
import (
"fmt"
"log"
cloudflare "github.com/cloudflare/cloudflare-go"
)
func ExampleAPI_DNSRecords_all() {
api, err := cloudflare.New("deadbeef", "test@example.org")
if err != nil {
log.Fatal(err)
}
zoneID, err := api.ZoneIDByName("example.com")
if err != nil {
log.Fatal(err)
}
// Fetch all records for a zone
recs, err := api.DNSRecords(zoneID, cloudflare.DNSRecord{})
if err != nil {
log.Fatal(err)
}
for _, r := range recs {
fmt.Printf("%s: %s\n", r.Name, r.Content)
}
}
func ExampleAPI_DNSRecords_filterByContent() {
api, err := cloudflare.New("deadbeef", "test@example.org")
if err != nil {
log.Fatal(err)
}
zoneID, err := api.ZoneIDByName("example.com")
if err != nil {
log.Fatal(err)
}
// Fetch only records whose content is 127.0.0.1
localhost := cloudflare.DNSRecord{Content: "127.0.0.1"}
recs, err := api.DNSRecords(zoneID, localhost)
if err != nil {
log.Fatal(err)
}
for _, r := range recs {
fmt.Printf("%s: %s\n", r.Name, r.Content)
}
}
func ExampleAPI_DNSRecords_filterByName() {
api, err := cloudflare.New("deadbeef", "test@example.org")
if err != nil {
log.Fatal(err)
}
zoneID, err := api.ZoneIDByName("example.com")
if err != nil {
log.Fatal(err)
}
// Fetch records of any type with name "foo.example.com"
// The name must be fully-qualified
foo := cloudflare.DNSRecord{Name: "foo.example.com"}
recs, err := api.DNSRecords(zoneID, foo)
if err != nil {
log.Fatal(err)
}
for _, r := range recs {
fmt.Printf("%s: %s\n", r.Name, r.Content)
}
}
func ExampleAPI_DNSRecords_filterByType() {
api, err := cloudflare.New("deadbeef", "test@example.org")
if err != nil {
log.Fatal(err)
}
zoneID, err := api.ZoneIDByName("example.com")
if err != nil {
log.Fatal(err)
}
// Fetch only AAAA type records
aaaa := cloudflare.DNSRecord{Type: "AAAA"}
recs, err := api.DNSRecords(zoneID, aaaa)
if err != nil {
log.Fatal(err)
}
for _, r := range recs {
fmt.Printf("%s: %s\n", r.Name, r.Content)
}
}

View File

@ -5,6 +5,7 @@ const (
errEmptyCredentials = "invalid credentials: key & email must not be empty" errEmptyCredentials = "invalid credentials: key & email must not be empty"
errMakeRequestError = "error from makeRequest" errMakeRequestError = "error from makeRequest"
errUnmarshalError = "error unmarshalling the JSON response" errUnmarshalError = "error unmarshalling the JSON response"
errRequestNotSuccessful = "error reported by API"
) )
var _ Error = &UserError{} var _ Error = &UserError{}

View File

@ -0,0 +1,33 @@
package cloudflare_test
import (
"fmt"
cloudflare "github.com/cloudflare/cloudflare-go"
)
func Example() {
api, err := cloudflare.New("deadbeef", "cloudflare@example.org")
if err != nil {
fmt.Println(err)
return
}
// Fetch the zone ID for zone example.org
zoneID, err := api.ZoneIDByName("example.org")
if err != nil {
fmt.Println(err)
return
}
// Fetch all DNS records for example.org
records, err := api.DNSRecords(zoneID, cloudflare.DNSRecord{})
if err != nil {
fmt.Println(err)
return
}
for _, r := range records {
fmt.Printf("%s: %s\n", r.Name, r.Content)
}
}

View File

@ -8,27 +8,23 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// IPRanges contains lists of IPv4 and IPv6 CIDRs // IPRanges contains lists of IPv4 and IPv6 CIDRs.
type IPRanges struct { type IPRanges struct {
IPv4CIDRs []string `json:"ipv4_cidrs"` IPv4CIDRs []string `json:"ipv4_cidrs"`
IPv6CIDRs []string `json:"ipv6_cidrs"` IPv6CIDRs []string `json:"ipv6_cidrs"`
} }
// IPsResponse is the API response containing a list of IPs // IPsResponse is the API response containing a list of IPs.
type IPsResponse struct { type IPsResponse struct {
Response Response
Result IPRanges `json:"result"` Result IPRanges `json:"result"`
} }
/* // IPs gets a list of Cloudflare's IP ranges.
IPs gets a list of Cloudflare's IP ranges //
// This does not require logging in to the API.
This does not require logging in to the API. //
// API reference: https://api.cloudflare.com/#cloudflare-ips
API reference:
https://api.cloudflare.com/#cloudflare-ips
GET /client/v4/ips
*/
func IPs() (IPRanges, error) { func IPs() (IPRanges, error) {
resp, err := http.Get(apiURL + "/ips") resp, err := http.Get(apiURL + "/ips")
if err != nil { if err != nil {

View File

@ -22,36 +22,31 @@ type KeylessSSLResponse struct {
} }
// CreateKeyless creates a new Keyless SSL configuration for the zone. // 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 // 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() { func (api *API) CreateKeyless() {
} }
// ListKeyless lists Keyless SSL configurations for a zone. // ListKeyless lists Keyless SSL configurations for a zone.
// API reference: //
// https://api.cloudflare.com/#keyless-ssl-for-a-zone-list-keyless-ssls // API reference: https://api.cloudflare.com/#keyless-ssl-for-a-zone-list-keyless-ssls
// GET /zones/:zone_identifier/keyless_certificates
func (api *API) ListKeyless() { func (api *API) ListKeyless() {
} }
// Keyless provides the configuration for a given Keyless SSL identifier. // Keyless provides the configuration for a given Keyless SSL identifier.
// API reference: //
// https://api.cloudflare.com/#keyless-ssl-for-a-zone-keyless-ssl-details // 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() { func (api *API) Keyless() {
} }
// UpdateKeyless updates an existing Keyless SSL configuration. // UpdateKeyless updates an existing Keyless SSL configuration.
// API reference: //
// https://api.cloudflare.com/#keyless-ssl-for-a-zone-update-keyless-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() { func (api *API) UpdateKeyless() {
} }
// DeleteKeyless deletes an existing Keyless SSL configuration. // DeleteKeyless deletes an existing Keyless SSL configuration.
// API reference: //
// https://api.cloudflare.com/#keyless-ssl-for-a-zone-delete-keyless-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() { func (api *API) DeleteKeyless() {
} }

View File

@ -2,6 +2,7 @@ package cloudflare
import ( import (
"encoding/json" "encoding/json"
"time"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -22,10 +23,55 @@ type organizationResponse struct {
ResultInfo `json:"result_info"` ResultInfo `json:"result_info"`
} }
// OrganizationMember has details on a member.
type OrganizationMember struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
Status string `json:"status,omitempty"`
Roles []OrganizationRole `json:"roles,omitempty"`
}
// OrganizationInvite has details on an invite.
type OrganizationInvite struct {
ID string `json:"id,omitempty"`
InvitedMemberID string `json:"invited_member_id,omitempty"`
InvitedMemberEmail string `json:"invited_member_email,omitempty"`
OrganizationID string `json:"organization_id,omitempty"`
OrganizationName string `json:"organization_name,omitempty"`
Roles []OrganizationRole `json:"roles,omitempty"`
InvitedBy string `json:"invited_by,omitempty"`
InvitedOn *time.Time `json:"invited_on,omitempty"`
ExpiresOn *time.Time `json:"expires_on,omitempty"`
Status string `json:"status,omitempty"`
}
// OrganizationRole has details on a role.
type OrganizationRole struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Permissions []string `json:"permissions,omitempty"`
}
// OrganizationDetails represents details of an organization.
type OrganizationDetails struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Members []OrganizationMember `json:"members"`
Invites []OrganizationInvite `json:"invites"`
Roles []OrganizationRole `json:"roles,omitempty"`
}
// organizationDetailsResponse represents the response from the OrganizationDetails endpoint.
type organizationDetailsResponse struct {
Response
Result OrganizationDetails `json:"result"`
}
// ListOrganizations lists organizations of the logged-in user. // ListOrganizations lists organizations of the logged-in user.
// API reference: //
// https://api.cloudflare.com/#user-s-organizations-list-organizations // API reference: https://api.cloudflare.com/#user-s-organizations-list-organizations
// GET /user/organizations
func (api *API) ListOrganizations() ([]Organization, ResultInfo, error) { func (api *API) ListOrganizations() ([]Organization, ResultInfo, error) {
var r organizationResponse var r organizationResponse
res, err := api.makeRequest("GET", "/user/organizations", nil) res, err := api.makeRequest("GET", "/user/organizations", nil)
@ -40,3 +86,100 @@ func (api *API) ListOrganizations() ([]Organization, ResultInfo, error) {
return r.Result, r.ResultInfo, nil return r.Result, r.ResultInfo, nil
} }
// OrganizationDetails returns details for the specified organization of the logged-in user.
//
// API reference: https://api.cloudflare.com/#organizations-organization-details
func (api *API) OrganizationDetails(organizationID string) (OrganizationDetails, error) {
var r organizationDetailsResponse
uri := "/organizations/" + organizationID
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return OrganizationDetails{}, errors.Wrap(err, errMakeRequestError)
}
err = json.Unmarshal(res, &r)
if err != nil {
return OrganizationDetails{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}
// organizationMembersResponse represents the response from the Organization members endpoint.
type organizationMembersResponse struct {
Response
Result []OrganizationMember `json:"result"`
ResultInfo `json:"result_info"`
}
// OrganizationMembers returns list of members for specified organization of the logged-in user.
//
// API reference: https://api.cloudflare.com/#organization-members-list-members
func (api *API) OrganizationMembers(organizationID string) ([]OrganizationMember, ResultInfo, error) {
var r organizationMembersResponse
uri := "/organizations/" + organizationID + "/members"
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return []OrganizationMember{}, ResultInfo{}, errors.Wrap(err, errMakeRequestError)
}
err = json.Unmarshal(res, &r)
if err != nil {
return []OrganizationMember{}, ResultInfo{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, r.ResultInfo, nil
}
// organizationInvitesResponse represents the response from the Organization invites endpoint.
type organizationInvitesResponse struct {
Response
Result []OrganizationInvite `json:"result"`
ResultInfo `json:"result_info"`
}
// OrganizationMembers returns list of invites for specified organization of the logged-in user.
//
// API reference: https://api.cloudflare.com/#organization-invites
func (api *API) OrganizationInvites(organizationID string) ([]OrganizationInvite, ResultInfo, error) {
var r organizationInvitesResponse
uri := "/organizations/" + organizationID + "/invites"
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return []OrganizationInvite{}, ResultInfo{}, errors.Wrap(err, errMakeRequestError)
}
err = json.Unmarshal(res, &r)
if err != nil {
return []OrganizationInvite{}, ResultInfo{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, r.ResultInfo, nil
}
// organizationRolesResponse represents the response from the Organization roles endpoint.
type organizationRolesResponse struct {
Response
Result []OrganizationRole `json:"result"`
ResultInfo `json:"result_info"`
}
// OrganizationRoles returns list of roles for specified organization of the logged-in user.
//
// API reference: https://api.cloudflare.com/#organization-roles-list-roles
func (api *API) OrganizationRoles(organizationID string) ([]OrganizationRole, ResultInfo, error) {
var r organizationRolesResponse
uri := "/organizations/" + organizationID + "/roles"
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return []OrganizationRole{}, ResultInfo{}, errors.Wrap(err, errMakeRequestError)
}
err = json.Unmarshal(res, &r)
if err != nil {
return []OrganizationRole{}, ResultInfo{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, r.ResultInfo, nil
}

View File

@ -2,10 +2,10 @@ package cloudflare
import ( import (
"fmt" "fmt"
"github.com/stretchr/testify/assert"
"net/http" "net/http"
"testing" "testing"
"time"
"github.com/stretchr/testify/assert"
) )
func TestOrganizations_ListOrganizations(t *testing.T) { func TestOrganizations_ListOrganizations(t *testing.T) {
@ -56,11 +56,340 @@ func TestOrganizations_ListOrganizations(t *testing.T) {
assert.Equal(t, user, want) assert.Equal(t, user, want)
} }
want_pagination := ResultInfo{ wantPagination := ResultInfo{
Page: 1, Page: 1,
PerPage: 20, PerPage: 20,
Count: 1, Count: 1,
Total: 2000, Total: 2000,
} }
assert.Equal(t, paginator, want_pagination) assert.Equal(t, paginator, wantPagination)
}
func TestOrganizations_OrganizationDetails(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/organizations/01a7362d577a6c3019a474fd6f485823", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %s", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
"errors": [],
"messages": [],
"result": {
"id": "01a7362d577a6c3019a474fd6f485823",
"name": "Cloudflare, Inc.",
"members": [
{
"id": "7c5dae5552338874e5053f2534d2767a",
"name": "John Smith",
"email": "user@example.com",
"status": "accepted",
"roles": [
{
"id": "3536bcfad5faccb999b47003c79917fb",
"name": "Organization Admin",
"description": "Administrative access to the entire Organization",
"permissions": [
"#zones:read"
]
}
]
}
],
"invites": [
{
"id": "4f5f0c14a2a41d5063dd301b2f829f04",
"invited_member_id": "5a7805061c76ada191ed06f989cc3dac",
"invited_member_email": "user@example.com",
"organization_id": "5a7805061c76ada191ed06f989cc3dac",
"organization_name": "Cloudflare, Inc.",
"roles": [
{
"id": "3536bcfad5faccb999b47003c79917fb",
"name": "Organization Admin",
"description": "Administrative access to the entire Organization",
"permissions": [
"#zones:read"
]
}
],
"invited_by": "user@example.com",
"invited_on": "2014-01-01T05:20:00Z",
"expires_on": "2014-01-01T05:20:00Z",
"status": "accepted"
}
],
"roles": [
{
"id": "3536bcfad5faccb999b47003c79917fb",
"name": "Organization Admin",
"description": "Administrative access to the entire Organization",
"permissions": [
"#zones:read"
]
}
]
}
}`)
})
organizationDetails, err := client.OrganizationDetails("01a7362d577a6c3019a474fd6f485823")
invitedOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z")
expiresOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z")
want := OrganizationDetails{
ID: "01a7362d577a6c3019a474fd6f485823",
Name: "Cloudflare, Inc.",
Members: []OrganizationMember{{
ID: "7c5dae5552338874e5053f2534d2767a",
Name: "John Smith",
Email: "user@example.com",
Status: "accepted",
Roles: []OrganizationRole{{
ID: "3536bcfad5faccb999b47003c79917fb",
Name: "Organization Admin",
Description: "Administrative access to the entire Organization",
Permissions: []string{
"#zones:read",
},
}},
}},
Invites: []OrganizationInvite{{
ID: "4f5f0c14a2a41d5063dd301b2f829f04",
InvitedMemberID: "5a7805061c76ada191ed06f989cc3dac",
InvitedMemberEmail: "user@example.com",
OrganizationID: "5a7805061c76ada191ed06f989cc3dac",
OrganizationName: "Cloudflare, Inc.",
Roles: []OrganizationRole{{
ID: "3536bcfad5faccb999b47003c79917fb",
Name: "Organization Admin",
Description: "Administrative access to the entire Organization",
Permissions: []string{
"#zones:read",
}}},
InvitedBy: "user@example.com",
InvitedOn: &invitedOn,
ExpiresOn: &expiresOn,
Status: "accepted",
}},
Roles: []OrganizationRole{{
ID: "3536bcfad5faccb999b47003c79917fb",
Name: "Organization Admin",
Description: "Administrative access to the entire Organization",
Permissions: []string{"#zones:read"},
}},
}
if assert.NoError(t, err) {
assert.Equal(t, organizationDetails, want)
}
}
func TestOrganizations_OrganizationMembers(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/organizations/01a7362d577a6c3019a474fd6f485823/members", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %s", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
"errors": [],
"messages": [],
"result": [
{
"id": "7c5dae5552338874e5053f2534d2767a",
"name": "John Smith",
"email": "user@example.com",
"status": "accepted",
"roles": [
{
"id": "3536bcfad5faccb999b47003c79917fb",
"name": "Organization Admin",
"description": "Administrative access to the entire Organization",
"permissions": [
"#zones:read"
]
}
]
}
],
"result_info": {
"page": 1,
"per_page": 20,
"count": 1,
"total_count": 2000
}
}`)
})
members, paginator, err := client.OrganizationMembers("01a7362d577a6c3019a474fd6f485823")
want := []OrganizationMember{{
ID: "7c5dae5552338874e5053f2534d2767a",
Name: "John Smith",
Email: "user@example.com",
Status: "accepted",
Roles: []OrganizationRole{{
ID: "3536bcfad5faccb999b47003c79917fb",
Name: "Organization Admin",
Description: "Administrative access to the entire Organization",
Permissions: []string{
"#zones:read",
},
}},
}}
if assert.NoError(t, err) {
assert.Equal(t, members, want)
}
wantPagination := ResultInfo{
Page: 1,
PerPage: 20,
Count: 1,
Total: 2000,
}
assert.Equal(t, paginator, wantPagination)
}
func TestOrganizations_OrganizationInvites(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/organizations/01a7362d577a6c3019a474fd6f485823/invites", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %s", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
"errors": [],
"messages": [],
"result": [
{
"id": "4f5f0c14a2a41d5063dd301b2f829f04",
"invited_member_id": "5a7805061c76ada191ed06f989cc3dac",
"invited_member_email": "user@example.com",
"organization_id": "5a7805061c76ada191ed06f989cc3dac",
"organization_name": "Cloudflare, Inc.",
"roles": [
{
"id": "3536bcfad5faccb999b47003c79917fb",
"name": "Organization Admin",
"description": "Administrative access to the entire Organization",
"permissions": [
"#zones:read"
]
}
],
"invited_by": "user@example.com",
"invited_on": "2014-01-01T05:20:00Z",
"expires_on": "2014-01-01T05:20:00Z",
"status": "accepted"
}
],
"result_info": {
"page": 1,
"per_page": 20,
"count": 1,
"total_count": 2000
}
}`)
})
members, paginator, err := client.OrganizationInvites("01a7362d577a6c3019a474fd6f485823")
invitedOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z")
expiresOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z")
want := []OrganizationInvite{{
ID: "4f5f0c14a2a41d5063dd301b2f829f04",
InvitedMemberID: "5a7805061c76ada191ed06f989cc3dac",
InvitedMemberEmail: "user@example.com",
OrganizationID: "5a7805061c76ada191ed06f989cc3dac",
OrganizationName: "Cloudflare, Inc.",
Roles: []OrganizationRole{{
ID: "3536bcfad5faccb999b47003c79917fb",
Name: "Organization Admin",
Description: "Administrative access to the entire Organization",
Permissions: []string{
"#zones:read",
}}},
InvitedBy: "user@example.com",
InvitedOn: &invitedOn,
ExpiresOn: &expiresOn,
Status: "accepted",
}}
if assert.NoError(t, err) {
assert.Equal(t, members, want)
}
wantPagination := ResultInfo{
Page: 1,
PerPage: 20,
Count: 1,
Total: 2000,
}
assert.Equal(t, paginator, wantPagination)
}
func TestOrganizations_OrganizationRoles(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/organizations/01a7362d577a6c3019a474fd6f485823/roles", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %s", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
"errors": [],
"messages": [],
"result": [
{
"id": "3536bcfad5faccb999b47003c79917fb",
"name": "Organization Admin",
"description": "Administrative access to the entire Organization",
"permissions": [
"#zones:read"
]
}
],
"result_info": {
"page": 1,
"per_page": 20,
"count": 1,
"total_count": 2000
}
}`)
})
members, paginator, err := client.OrganizationRoles("01a7362d577a6c3019a474fd6f485823")
want := []OrganizationRole{{
ID: "3536bcfad5faccb999b47003c79917fb",
Name: "Organization Admin",
Description: "Administrative access to the entire Organization",
Permissions: []string{
"#zones:read",
}}}
if assert.NoError(t, err) {
assert.Equal(t, members, want)
}
wantPagination := ResultInfo{
Page: 1,
PerPage: 20,
Count: 1,
Total: 2000,
}
assert.Equal(t, paginator, wantPagination)
} }

168
vendor/github.com/cloudflare/cloudflare-go/origin_ca.go generated vendored Normal file
View File

@ -0,0 +1,168 @@
package cloudflare
import (
"encoding/json"
"net/url"
"time"
"github.com/pkg/errors"
)
// OriginCACertificate represents a Cloudflare-issued certificate.
//
// API reference: https://api.cloudflare.com/#cloudflare-ca
type OriginCACertificate struct {
ID string `json:"id"`
Certificate string `json:"certificate"`
Hostnames []string `json:"hostnames"`
ExpiresOn time.Time `json:"expires_on"`
RequestType string `json:"request_type"`
RequestValidity int `json:"requested_validity"`
CSR string `json:"csr"`
}
// OriginCACertificateListOptions represents the parameters used to list Cloudflare-issued certificates.
type OriginCACertificateListOptions struct {
ZoneID string
}
// OriginCACertificateID represents the ID of the revoked certificate from the Revoke Certificate endpoint.
type OriginCACertificateID struct {
ID string `json:"id"`
}
// originCACertificateResponse represents the response from the Create Certificate and the Certificate Details endpoints.
type originCACertificateResponse struct {
Response
Result OriginCACertificate `json:"result"`
}
// originCACertificateResponseList represents the response from the List Certificates endpoint.
type originCACertificateResponseList struct {
Response
Result []OriginCACertificate `json:"result"`
ResultInfo ResultInfo `json:"result_info"`
}
// originCACertificateResponseRevoke represents the response from the Revoke Certificate endpoint.
type originCACertificateResponseRevoke struct {
Response
Result OriginCACertificateID `json:"result"`
}
// CreateOriginCertificate creates a Cloudflare-signed certificate.
//
// This function requires api.APIUserServiceKey be set to your Certificates API key.
//
// API reference: https://api.cloudflare.com/#cloudflare-ca-create-certificate
func (api *API) CreateOriginCertificate(certificate OriginCACertificate) (*OriginCACertificate, error) {
uri := "/certificates"
res, err := api.makeRequestWithAuthType("POST", uri, certificate, AuthUserService)
if err != nil {
return nil, errors.Wrap(err, errMakeRequestError)
}
var originResponse *originCACertificateResponse
err = json.Unmarshal(res, &originResponse)
if err != nil {
return nil, errors.Wrap(err, errUnmarshalError)
}
if !originResponse.Success {
return nil, errors.New(errRequestNotSuccessful)
}
return &originResponse.Result, nil
}
// OriginCertificates lists all Cloudflare-issued certificates.
//
// This function requires api.APIUserServiceKey be set to your Certificates API key.
//
// API reference: https://api.cloudflare.com/#cloudflare-ca-list-certificates
func (api *API) OriginCertificates(options OriginCACertificateListOptions) ([]OriginCACertificate, error) {
v := url.Values{}
if options.ZoneID != "" {
v.Set("zone_id", options.ZoneID)
}
uri := "/certificates" + "?" + v.Encode()
res, err := api.makeRequestWithAuthType("GET", uri, nil, AuthUserService)
if err != nil {
return nil, errors.Wrap(err, errMakeRequestError)
}
var originResponse *originCACertificateResponseList
err = json.Unmarshal(res, &originResponse)
if err != nil {
return nil, errors.Wrap(err, errUnmarshalError)
}
if !originResponse.Success {
return nil, errors.New(errRequestNotSuccessful)
}
return originResponse.Result, nil
}
// OriginCertificate returns the details for a Cloudflare-issued certificate.
//
// This function requires api.APIUserServiceKey be set to your Certificates API key.
//
// API reference: https://api.cloudflare.com/#cloudflare-ca-certificate-details
func (api *API) OriginCertificate(certificateID string) (*OriginCACertificate, error) {
uri := "/certificates/" + certificateID
res, err := api.makeRequestWithAuthType("GET", uri, nil, AuthUserService)
if err != nil {
return nil, errors.Wrap(err, errMakeRequestError)
}
var originResponse *originCACertificateResponse
err = json.Unmarshal(res, &originResponse)
if err != nil {
return nil, errors.Wrap(err, errUnmarshalError)
}
if !originResponse.Success {
return nil, errors.New(errRequestNotSuccessful)
}
return &originResponse.Result, nil
}
// RevokeOriginCertificate revokes a created certificate for a zone.
//
// This function requires api.APIUserServiceKey be set to your Certificates API key.
//
// API reference: https://api.cloudflare.com/#cloudflare-ca-revoke-certificate
func (api *API) RevokeOriginCertificate(certificateID string) (*OriginCACertificateID, error) {
uri := "/certificates/" + certificateID
res, err := api.makeRequestWithAuthType("DELETE", uri, nil, AuthUserService)
if err != nil {
return nil, errors.Wrap(err, errMakeRequestError)
}
var originResponse *originCACertificateResponseRevoke
err = json.Unmarshal(res, &originResponse)
if err != nil {
return nil, errors.Wrap(err, errUnmarshalError)
}
if !originResponse.Success {
return nil, errors.New(errRequestNotSuccessful)
}
return &originResponse.Result, nil
}

View File

@ -0,0 +1,187 @@
package cloudflare
import (
"fmt"
"net/http"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestOriginCA_CreateOriginCertificate(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/certificates", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "POST", r.Method, "Expected method 'POST', got %ss", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
"errors": [],
"messages": [],
"result": {
"id": "0x47530d8f561faa08",
"certificate": "-----BEGIN CERTIFICATE-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE-----",
"hostnames": [
"example.com",
"*.another.com"
],
"expires_on": "2014-01-01T05:20:00.12345Z",
"request_type": "origin-rsa",
"requested_validity": 5475,
"csr": "-----BEGIN CERTIFICATE REQUEST-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE REQUEST-----"
}
}`)
})
expiresOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
testCertificate := OriginCACertificate{
ID: "0x47530d8f561faa08",
Certificate: "-----BEGIN CERTIFICATE-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE-----",
Hostnames: []string{"example.com", "*.another.com"},
ExpiresOn: expiresOn,
RequestType: "origin-rsa",
RequestValidity: 5475,
CSR: "-----BEGIN CERTIFICATE REQUEST-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE REQUEST-----",
}
createdCertificate, err := client.CreateOriginCertificate(testCertificate)
if assert.NoError(t, err) {
assert.Equal(t, createdCertificate, &testCertificate)
}
}
func TestOriginCA_OriginCertificates(t *testing.T) {
setup()
defer teardown()
testZoneID := "023e105f4ecef8ad9ca31a8372d0c353"
mux.HandleFunc("/certificates", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %ss", r.Method)
assert.Equal(t, testZoneID, r.URL.Query().Get("zone_id"), "Expected zone_id '', got %%s", testZoneID)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
"errors": [],
"messages": [],
"result": [
{
"id": "0x47530d8f561faa08",
"certificate": "-----BEGIN CERTIFICATE-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE-----",
"hostnames": [
"example.com",
"*.another.com"
],
"expires_on": "2014-01-01T05:20:00.12345Z",
"request_type": "origin-rsa",
"requested_validity": 5475,
"csr": "-----BEGIN CERTIFICATE REQUEST-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE REQUEST-----"
}
],
"result_info": {
"page": 1,
"per_page": 20,
"count": 1,
"total_count": 2000
}
}`)
})
expiresOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
testCertificate := OriginCACertificate{
ID: "0x47530d8f561faa08",
Certificate: "-----BEGIN CERTIFICATE-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE-----",
Hostnames: []string{"example.com", "*.another.com"},
ExpiresOn: expiresOn,
RequestType: "origin-rsa",
RequestValidity: 5475,
CSR: "-----BEGIN CERTIFICATE REQUEST-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE REQUEST-----",
}
certs, err := client.OriginCertificates(OriginCACertificateListOptions{ZoneID: testZoneID})
if assert.NoError(t, err) {
assert.IsType(t, []OriginCACertificate{}, certs, "Expected type []OriginCACertificate and got %v", certs)
assert.Equal(t, certs[0], testCertificate)
}
}
func TestOriginCA_OriginCertificate(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/certificates/0x47530d8f561faa08", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %ss", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
"errors": [],
"messages": [],
"result": {
"id": "0x47530d8f561faa08",
"certificate": "-----BEGIN CERTIFICATE-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE-----",
"hostnames": [
"example.com",
"*.another.com"
],
"expires_on": "2014-01-01T05:20:00.12345Z",
"request_type": "origin-rsa",
"requested_validity": 5475,
"csr": "-----BEGIN CERTIFICATE REQUEST-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE REQUEST-----"
}
}`)
})
expiresOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z")
testCertificate := OriginCACertificate{
ID: "0x47530d8f561faa08",
Certificate: "-----BEGIN CERTIFICATE-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE-----",
Hostnames: []string{"example.com", "*.another.com"},
ExpiresOn: expiresOn,
RequestType: "origin-rsa",
RequestValidity: 5475,
CSR: "-----BEGIN CERTIFICATE REQUEST-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE REQUEST-----",
}
cert, err := client.OriginCertificate(testCertificate.ID)
if assert.NoError(t, err) {
assert.IsType(t, &OriginCACertificate{}, cert, "Expected type &OriginCACertificate and got %v", cert)
assert.Equal(t, cert, &testCertificate)
}
}
func TestOriginCA_RevokeCertificate(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/certificates/0x47530d8f561faa08", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "DELETE", r.Method, "Expected method 'DELETE', got %ss", r.Method)
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
"errors": [],
"messages": [],
"result": {
"id": "0x47530d8f561faa08"
}
}`)
})
testCertificate := OriginCACertificateID{
ID: "0x47530d8f561faa08",
}
cert, err := client.RevokeOriginCertificate(testCertificate.ID)
if assert.NoError(t, err) {
assert.IsType(t, &OriginCACertificateID{}, cert, "Expected type &OriginCACertificateID and got %v", cert)
assert.Equal(t, cert, &testCertificate)
}
}

View File

@ -7,12 +7,10 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
/* // PageRuleTarget is the target to evaluate on a request.
PageRuleTarget is the target to evaluate on a request. //
// Currently Target must always be "url" and Operator must be "matches". Value
Currently Target must always be "url" and Operator must be "matches". Value // is the URL pattern to match against.
is the URL pattern to match against.
*/
type PageRuleTarget struct { type PageRuleTarget struct {
Target string `json:"target"` Target string `json:"target"`
Constraint struct { Constraint struct {
@ -52,7 +50,7 @@ type PageRuleAction struct {
Value interface{} `json:"value"` Value interface{} `json:"value"`
} }
// PageRuleActions maps API action IDs to human-readable strings // PageRuleActions maps API action IDs to human-readable strings.
var PageRuleActions = map[string]string{ var PageRuleActions = map[string]string{
"always_online": "Always Online", // Value of type string "always_online": "Always Online", // Value of type string
"always_use_https": "Always Use HTTPS", // Value of type interface{} "always_use_https": "Always Use HTTPS", // Value of type interface{}
@ -103,13 +101,9 @@ type PageRulesResponse struct {
Result []PageRule `json:"result"` Result []PageRule `json:"result"`
} }
/* // CreatePageRule creates a new Page Rule for a zone.
CreatePageRule creates a new Page Rule for a zone. //
// API reference: https://api.cloudflare.com/#page-rules-for-a-zone-create-a-page-rule
API reference:
https://api.cloudflare.com/#page-rules-for-a-zone-create-a-page-rule
POST /zones/:zone_identifier/pagerules
*/
func (api *API) CreatePageRule(zoneID string, rule PageRule) error { func (api *API) CreatePageRule(zoneID string, rule PageRule) error {
uri := "/zones/" + zoneID + "/pagerules" uri := "/zones/" + zoneID + "/pagerules"
res, err := api.makeRequest("POST", uri, rule) res, err := api.makeRequest("POST", uri, rule)
@ -124,13 +118,9 @@ func (api *API) CreatePageRule(zoneID string, rule PageRule) error {
return nil return nil
} }
/* // ListPageRules returns all Page Rules for a zone.
ListPageRules returns all Page Rules for a zone. //
// API reference: https://api.cloudflare.com/#page-rules-for-a-zone-list-page-rules
API reference:
https://api.cloudflare.com/#page-rules-for-a-zone-list-page-rules
GET /zones/:zone_identifier/pagerules
*/
func (api *API) ListPageRules(zoneID string) ([]PageRule, error) { func (api *API) ListPageRules(zoneID string) ([]PageRule, error) {
uri := "/zones/" + zoneID + "/pagerules" uri := "/zones/" + zoneID + "/pagerules"
res, err := api.makeRequest("GET", uri, nil) res, err := api.makeRequest("GET", uri, nil)
@ -145,13 +135,9 @@ func (api *API) ListPageRules(zoneID string) ([]PageRule, error) {
return r.Result, nil return r.Result, nil
} }
/* // PageRule fetches detail about one Page Rule for a zone.
PageRule fetches detail about one Page Rule for a zone. //
// API reference: https://api.cloudflare.com/#page-rules-for-a-zone-page-rule-details
API reference:
https://api.cloudflare.com/#page-rules-for-a-zone-page-rule-details
GET /zones/:zone_identifier/pagerules/:identifier
*/
func (api *API) PageRule(zoneID, ruleID string) (PageRule, error) { func (api *API) PageRule(zoneID, ruleID string) (PageRule, error) {
uri := "/zones/" + zoneID + "/pagerules/" + ruleID uri := "/zones/" + zoneID + "/pagerules/" + ruleID
res, err := api.makeRequest("GET", uri, nil) res, err := api.makeRequest("GET", uri, nil)
@ -166,14 +152,10 @@ func (api *API) PageRule(zoneID, ruleID string) (PageRule, error) {
return r.Result, nil return r.Result, nil
} }
/* // ChangePageRule lets you change individual settings for a Page Rule. This is
ChangePageRule lets change individual settings for a Page Rule. This is in // in contrast to UpdatePageRule which replaces the entire Page Rule.
contrast to UpdatePageRule which replaces the entire Page Rule. //
// API reference: https://api.cloudflare.com/#page-rules-for-a-zone-change-a-page-rule
API reference:
https://api.cloudflare.com/#page-rules-for-a-zone-change-a-page-rule
PATCH /zones/:zone_identifier/pagerules/:identifier
*/
func (api *API) ChangePageRule(zoneID, ruleID string, rule PageRule) error { func (api *API) ChangePageRule(zoneID, ruleID string, rule PageRule) error {
uri := "/zones/" + zoneID + "/pagerules/" + ruleID uri := "/zones/" + zoneID + "/pagerules/" + ruleID
res, err := api.makeRequest("PATCH", uri, rule) res, err := api.makeRequest("PATCH", uri, rule)
@ -188,14 +170,10 @@ func (api *API) ChangePageRule(zoneID, ruleID string, rule PageRule) error {
return nil return nil
} }
/* // UpdatePageRule lets you replace a Page Rule. This is in contrast to
UpdatePageRule lets you replace a Page Rule. This is in contrast to // ChangePageRule which lets you change individual settings.
ChangePageRule which lets you change individual settings. //
// API reference: https://api.cloudflare.com/#page-rules-for-a-zone-update-a-page-rule
API reference:
https://api.cloudflare.com/#page-rules-for-a-zone-update-a-page-rule
PUT /zones/:zone_identifier/pagerules/:identifier
*/
func (api *API) UpdatePageRule(zoneID, ruleID string, rule PageRule) error { func (api *API) UpdatePageRule(zoneID, ruleID string, rule PageRule) error {
uri := "/zones/" + zoneID + "/pagerules/" + ruleID uri := "/zones/" + zoneID + "/pagerules/" + ruleID
res, err := api.makeRequest("PUT", uri, nil) res, err := api.makeRequest("PUT", uri, nil)
@ -210,13 +188,9 @@ func (api *API) UpdatePageRule(zoneID, ruleID string, rule PageRule) error {
return nil return nil
} }
/* // DeletePageRule deletes a Page Rule for a zone.
DeletePageRule deletes a Page Rule for a zone. //
// API reference: https://api.cloudflare.com/#page-rules-for-a-zone-delete-a-page-rule
API reference:
https://api.cloudflare.com/#page-rules-for-a-zone-delete-a-page-rule
DELETE /zones/:zone_identifier/pagerules/:identifier
*/
func (api *API) DeletePageRule(zoneID, ruleID string) error { func (api *API) DeletePageRule(zoneID, ruleID string) error {
uri := "/zones/" + zoneID + "/pagerules/" + ruleID uri := "/zones/" + zoneID + "/pagerules/" + ruleID
res, err := api.makeRequest("DELETE", uri, nil) res, err := api.makeRequest("DELETE", uri, nil)

View File

@ -46,9 +46,8 @@ type railgunsResponse struct {
} }
// CreateRailgun creates a new Railgun. // CreateRailgun creates a new Railgun.
// API reference: //
// https://api.cloudflare.com/#railgun-create-railgun // API reference: https://api.cloudflare.com/#railgun-create-railgun
// POST /railguns
func (api *API) CreateRailgun(name string) (Railgun, error) { func (api *API) CreateRailgun(name string) (Railgun, error) {
uri := "/railguns" uri := "/railguns"
params := struct { params := struct {
@ -68,9 +67,8 @@ func (api *API) CreateRailgun(name string) (Railgun, error) {
} }
// ListRailguns lists Railguns connected to an account. // ListRailguns lists Railguns connected to an account.
// API reference: //
// https://api.cloudflare.com/#railgun-list-railguns // API reference: https://api.cloudflare.com/#railgun-list-railguns
// GET /railguns
func (api *API) ListRailguns(options RailgunListOptions) ([]Railgun, error) { func (api *API) ListRailguns(options RailgunListOptions) ([]Railgun, error) {
v := url.Values{} v := url.Values{}
if options.Direction != "" { if options.Direction != "" {
@ -89,9 +87,8 @@ func (api *API) ListRailguns(options RailgunListOptions) ([]Railgun, error) {
} }
// RailgunDetails returns the details for a Railgun. // RailgunDetails returns the details for a Railgun.
// API reference: //
// https://api.cloudflare.com/#railgun-railgun-details // API reference: https://api.cloudflare.com/#railgun-railgun-details
// GET /railguns/:identifier
func (api *API) RailgunDetails(railgunID string) (Railgun, error) { func (api *API) RailgunDetails(railgunID string) (Railgun, error) {
uri := "/railguns/" + railgunID uri := "/railguns/" + railgunID
res, err := api.makeRequest("GET", uri, nil) res, err := api.makeRequest("GET", uri, nil)
@ -106,9 +103,8 @@ func (api *API) RailgunDetails(railgunID string) (Railgun, error) {
} }
// RailgunZones returns the zones that are currently using a Railgun. // RailgunZones returns the zones that are currently using a Railgun.
// API reference: //
// https://api.cloudflare.com/#railgun-get-zones-connected-to-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) { func (api *API) RailgunZones(railgunID string) ([]Zone, error) {
uri := "/railguns/" + railgunID + "/zones" uri := "/railguns/" + railgunID + "/zones"
res, err := api.makeRequest("GET", uri, nil) res, err := api.makeRequest("GET", uri, nil)
@ -123,9 +119,8 @@ func (api *API) RailgunZones(railgunID string) ([]Zone, error) {
} }
// enableRailgun enables (true) or disables (false) a Railgun for all zones connected to it. // 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 // 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) { func (api *API) enableRailgun(railgunID string, enable bool) (Railgun, error) {
uri := "/railguns/" + railgunID uri := "/railguns/" + railgunID
params := struct { params := struct {
@ -145,25 +140,22 @@ func (api *API) enableRailgun(railgunID string, enable bool) (Railgun, error) {
} }
// EnableRailgun enables a Railgun for all zones connected to it. // EnableRailgun enables a Railgun for all zones connected to it.
// API reference: //
// https://api.cloudflare.com/#railgun-enable-or-disable-a-railgun // API reference: https://api.cloudflare.com/#railgun-enable-or-disable-a-railgun
// PATCH /railguns/:identifier
func (api *API) EnableRailgun(railgunID string) (Railgun, error) { func (api *API) EnableRailgun(railgunID string) (Railgun, error) {
return api.enableRailgun(railgunID, true) return api.enableRailgun(railgunID, true)
} }
// DisableRailgun enables a Railgun for all zones connected to it. // DisableRailgun enables a Railgun for all zones connected to it.
// API reference: //
// https://api.cloudflare.com/#railgun-enable-or-disable-a-railgun // API reference: https://api.cloudflare.com/#railgun-enable-or-disable-a-railgun
// PATCH /railguns/:identifier
func (api *API) DisableRailgun(railgunID string) (Railgun, error) { func (api *API) DisableRailgun(railgunID string) (Railgun, error) {
return api.enableRailgun(railgunID, false) return api.enableRailgun(railgunID, false)
} }
// DeleteRailgun disables and deletes a Railgun. // DeleteRailgun disables and deletes a Railgun.
// API reference: //
// https://api.cloudflare.com/#railgun-delete-railgun // API reference: https://api.cloudflare.com/#railgun-delete-railgun
// DELETE /railguns/:identifier
func (api *API) DeleteRailgun(railgunID string) error { func (api *API) DeleteRailgun(railgunID string) error {
uri := "/railguns/" + railgunID uri := "/railguns/" + railgunID
if _, err := api.makeRequest("DELETE", uri, nil); err != nil { if _, err := api.makeRequest("DELETE", uri, nil); err != nil {
@ -222,9 +214,8 @@ type railgunDiagnosisResponse struct {
} }
// ZoneRailguns returns the available Railguns for a zone. // ZoneRailguns returns the available Railguns for a zone.
// API reference: //
// https://api.cloudflare.com/#railguns-for-a-zone-get-available-railguns // 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) { func (api *API) ZoneRailguns(zoneID string) ([]ZoneRailgun, error) {
uri := "/zones/" + zoneID + "/railguns" uri := "/zones/" + zoneID + "/railguns"
res, err := api.makeRequest("GET", uri, nil) res, err := api.makeRequest("GET", uri, nil)
@ -239,9 +230,8 @@ func (api *API) ZoneRailguns(zoneID string) ([]ZoneRailgun, error) {
} }
// ZoneRailgunDetails returns the configuration for a given Railgun. // ZoneRailgunDetails returns the configuration for a given Railgun.
// API reference: //
// https://api.cloudflare.com/#railguns-for-a-zone-get-railgun-details // 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) { func (api *API) ZoneRailgunDetails(zoneID, railgunID string) (ZoneRailgun, error) {
uri := "/zones/" + zoneID + "/railguns/" + railgunID uri := "/zones/" + zoneID + "/railguns/" + railgunID
res, err := api.makeRequest("GET", uri, nil) res, err := api.makeRequest("GET", uri, nil)
@ -256,9 +246,8 @@ func (api *API) ZoneRailgunDetails(zoneID, railgunID string) (ZoneRailgun, error
} }
// TestRailgunConnection tests a Railgun connection for a given zone. // TestRailgunConnection tests a Railgun connection for a given zone.
// API reference: //
// https://api.cloudflare.com/#railgun-connections-for-a-zone-test-railgun-connection // 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) { func (api *API) TestRailgunConnection(zoneID, railgunID string) (RailgunDiagnosis, error) {
uri := "/zones/" + zoneID + "/railguns/" + railgunID + "/diagnose" uri := "/zones/" + zoneID + "/railguns/" + railgunID + "/diagnose"
res, err := api.makeRequest("GET", uri, nil) res, err := api.makeRequest("GET", uri, nil)
@ -273,9 +262,8 @@ func (api *API) TestRailgunConnection(zoneID, railgunID string) (RailgunDiagnosi
} }
// connectZoneRailgun connects (true) or disconnects (false) a Railgun for a given zone. // 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 // 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) { func (api *API) connectZoneRailgun(zoneID, railgunID string, connect bool) (ZoneRailgun, error) {
uri := "/zones/" + zoneID + "/railguns/" + railgunID uri := "/zones/" + zoneID + "/railguns/" + railgunID
params := struct { params := struct {
@ -295,17 +283,15 @@ func (api *API) connectZoneRailgun(zoneID, railgunID string, connect bool) (Zone
} }
// ConnectZoneRailgun connects a Railgun for a given zone. // ConnectZoneRailgun connects a Railgun for a given zone.
// API reference: //
// https://api.cloudflare.com/#railguns-for-a-zone-connect-or-disconnect-a-railgun // 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) { func (api *API) ConnectZoneRailgun(zoneID, railgunID string) (ZoneRailgun, error) {
return api.connectZoneRailgun(zoneID, railgunID, true) return api.connectZoneRailgun(zoneID, railgunID, true)
} }
// DisconnectZoneRailgun disconnects a Railgun for a given zone. // DisconnectZoneRailgun disconnects a Railgun for a given zone.
// API reference: //
// https://api.cloudflare.com/#railguns-for-a-zone-connect-or-disconnect-a-railgun // 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) { func (api *API) DisconnectZoneRailgun(zoneID, railgunID string) (ZoneRailgun, error) {
return api.connectZoneRailgun(zoneID, railgunID, false) return api.connectZoneRailgun(zoneID, railgunID, false)
} }

View File

@ -51,9 +51,8 @@ type ZoneCustomSSLPriority struct {
} }
// CreateSSL allows you to add a custom SSL certificate to the given zone. // 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 // 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) { func (api *API) CreateSSL(zoneID string, options ZoneCustomSSLOptions) (ZoneCustomSSL, error) {
uri := "/zones/" + zoneID + "/custom_certificates" uri := "/zones/" + zoneID + "/custom_certificates"
res, err := api.makeRequest("POST", uri, options) res, err := api.makeRequest("POST", uri, options)
@ -68,9 +67,8 @@ func (api *API) CreateSSL(zoneID string, options ZoneCustomSSLOptions) (ZoneCust
} }
// ListSSL lists the custom certificates for the given zone. // ListSSL lists the custom certificates for the given zone.
// API reference: //
// https://api.cloudflare.com/#custom-ssl-for-a-zone-list-ssl-configurations // 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) { func (api *API) ListSSL(zoneID string) ([]ZoneCustomSSL, error) {
uri := "/zones/" + zoneID + "/custom_certificates" uri := "/zones/" + zoneID + "/custom_certificates"
res, err := api.makeRequest("GET", uri, nil) res, err := api.makeRequest("GET", uri, nil)
@ -85,9 +83,8 @@ func (api *API) ListSSL(zoneID string) ([]ZoneCustomSSL, error) {
} }
// SSLDetails returns the configuration details for a custom SSL certificate. // SSLDetails returns the configuration details for a custom SSL certificate.
// API reference: //
// https://api.cloudflare.com/#custom-ssl-for-a-zone-ssl-configuration-details // 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) { func (api *API) SSLDetails(zoneID, certificateID string) (ZoneCustomSSL, error) {
uri := "/zones/" + zoneID + "/custom_certificates/" + certificateID uri := "/zones/" + zoneID + "/custom_certificates/" + certificateID
res, err := api.makeRequest("GET", uri, nil) res, err := api.makeRequest("GET", uri, nil)
@ -102,9 +99,8 @@ func (api *API) SSLDetails(zoneID, certificateID string) (ZoneCustomSSL, error)
} }
// UpdateSSL updates (replaces) a custom SSL certificate. // UpdateSSL updates (replaces) a custom SSL certificate.
// API reference: //
// https://api.cloudflare.com/#custom-ssl-for-a-zone-update-ssl-configuration // 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) { func (api *API) UpdateSSL(zoneID, certificateID string, options ZoneCustomSSLOptions) (ZoneCustomSSL, error) {
uri := "/zones/" + zoneID + "/custom_certificates/" + certificateID uri := "/zones/" + zoneID + "/custom_certificates/" + certificateID
res, err := api.makeRequest("PATCH", uri, options) res, err := api.makeRequest("PATCH", uri, options)
@ -120,9 +116,8 @@ func (api *API) UpdateSSL(zoneID, certificateID string, options ZoneCustomSSLOpt
// ReprioritizeSSL allows you to change the priority (which is served for a given // ReprioritizeSSL allows you to change the priority (which is served for a given
// request) of custom SSL certificates associated with the given zone. // 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 // 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) { func (api *API) ReprioritizeSSL(zoneID string, p []ZoneCustomSSLPriority) ([]ZoneCustomSSL, error) {
uri := "/zones/" + zoneID + "/custom_certificates/prioritize" uri := "/zones/" + zoneID + "/custom_certificates/prioritize"
params := struct { params := struct {
@ -142,9 +137,8 @@ func (api *API) ReprioritizeSSL(zoneID string, p []ZoneCustomSSLPriority) ([]Zon
} }
// DeleteSSL deletes a custom SSL certificate from the given zone. // 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 // 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 { func (api *API) DeleteSSL(zoneID, certificateID string) error {
uri := "/zones/" + zoneID + "/custom_certificates/" + certificateID uri := "/zones/" + zoneID + "/custom_certificates/" + certificateID
if _, err := api.makeRequest("DELETE", uri, nil); err != nil { if _, err := api.makeRequest("DELETE", uri, nil); err != nil {

View File

@ -59,9 +59,8 @@ type UserBillingProfile struct {
} }
// UserDetails provides information about the logged-in user. // UserDetails provides information about the logged-in user.
// API reference: //
// https://api.cloudflare.com/#user-user-details // API reference: https://api.cloudflare.com/#user-user-details
// GET /user
func (api *API) UserDetails() (User, error) { func (api *API) UserDetails() (User, error) {
var r UserResponse var r UserResponse
res, err := api.makeRequest("GET", "/user", nil) res, err := api.makeRequest("GET", "/user", nil)
@ -78,9 +77,8 @@ func (api *API) UserDetails() (User, error) {
} }
// UpdateUser updates the properties of the given user. // UpdateUser updates the properties of the given user.
// API reference: //
// https://api.cloudflare.com/#user-update-user // API reference: https://api.cloudflare.com/#user-update-user
// PATCH /user
func (api *API) UpdateUser(user *User) (User, error) { func (api *API) UpdateUser(user *User) (User, error) {
var r UserResponse var r UserResponse
res, err := api.makeRequest("PATCH", "/user", user) res, err := api.makeRequest("PATCH", "/user", user)
@ -97,9 +95,8 @@ func (api *API) UpdateUser(user *User) (User, error) {
} }
// UserBillingProfile returns the billing profile of the user. // UserBillingProfile returns the billing profile of the user.
// API reference: //
// https://api.cloudflare.com/#user-billing-profile // API reference: https://api.cloudflare.com/#user-billing-profile
// GET /user/billing/profile
func (api *API) UserBillingProfile() (UserBillingProfile, error) { func (api *API) UserBillingProfile() (UserBillingProfile, error) {
var r userBillingProfileResponse var r userBillingProfileResponse
res, err := api.makeRequest("GET", "/user/billing/profile", nil) res, err := api.makeRequest("GET", "/user/billing/profile", nil)

View File

@ -31,9 +31,8 @@ type VirtualDNSListResponse struct {
} }
// CreateVirtualDNS creates a new Virtual DNS cluster. // CreateVirtualDNS creates a new Virtual DNS cluster.
// API reference: //
// https://api.cloudflare.com/#virtual-dns-users--create-a-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) { func (api *API) CreateVirtualDNS(v *VirtualDNS) (*VirtualDNS, error) {
res, err := api.makeRequest("POST", "/user/virtual_dns", v) res, err := api.makeRequest("POST", "/user/virtual_dns", v)
if err != nil { if err != nil {
@ -50,9 +49,8 @@ func (api *API) CreateVirtualDNS(v *VirtualDNS) (*VirtualDNS, error) {
} }
// VirtualDNS fetches a single virtual DNS cluster. // VirtualDNS fetches a single virtual DNS cluster.
// API reference: //
// https://api.cloudflare.com/#virtual-dns-users--get-a-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) { func (api *API) VirtualDNS(virtualDNSID string) (*VirtualDNS, error) {
uri := "/user/virtual_dns/" + virtualDNSID uri := "/user/virtual_dns/" + virtualDNSID
res, err := api.makeRequest("GET", uri, nil) res, err := api.makeRequest("GET", uri, nil)
@ -70,9 +68,8 @@ func (api *API) VirtualDNS(virtualDNSID string) (*VirtualDNS, error) {
} }
// ListVirtualDNS lists the virtual DNS clusters associated with an account. // ListVirtualDNS lists the virtual DNS clusters associated with an account.
// API reference: //
// https://api.cloudflare.com/#virtual-dns-users--get-virtual-dns-clusters // API reference: https://api.cloudflare.com/#virtual-dns-users--get-virtual-dns-clusters
// GET /user/virtual_dns
func (api *API) ListVirtualDNS() ([]*VirtualDNS, error) { func (api *API) ListVirtualDNS() ([]*VirtualDNS, error) {
res, err := api.makeRequest("GET", "/user/virtual_dns", nil) res, err := api.makeRequest("GET", "/user/virtual_dns", nil)
if err != nil { if err != nil {
@ -89,9 +86,8 @@ func (api *API) ListVirtualDNS() ([]*VirtualDNS, error) {
} }
// UpdateVirtualDNS updates a Virtual DNS cluster. // UpdateVirtualDNS updates a Virtual DNS cluster.
// API reference: //
// https://api.cloudflare.com/#virtual-dns-users--modify-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 { func (api *API) UpdateVirtualDNS(virtualDNSID string, vv VirtualDNS) error {
uri := "/user/virtual_dns/" + virtualDNSID uri := "/user/virtual_dns/" + virtualDNSID
res, err := api.makeRequest("PUT", uri, vv) res, err := api.makeRequest("PUT", uri, vv)
@ -110,9 +106,8 @@ func (api *API) UpdateVirtualDNS(virtualDNSID string, vv VirtualDNS) error {
// DeleteVirtualDNS deletes a Virtual DNS cluster. Note that this cannot be // DeleteVirtualDNS deletes a Virtual DNS cluster. Note that this cannot be
// undone, and will stop all traffic to that cluster. // undone, and will stop all traffic to that cluster.
// API reference: //
// https://api.cloudflare.com/#virtual-dns-users--delete-a-virtual-dns-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 { func (api *API) DeleteVirtualDNS(virtualDNSID string) error {
uri := "/user/virtual_dns/" + virtualDNSID uri := "/user/virtual_dns/" + virtualDNSID
res, err := api.makeRequest("DELETE", uri, nil) res, err := api.makeRequest("DELETE", uri, nil)

View File

@ -20,6 +20,8 @@ type Owner struct {
type Zone struct { type Zone struct {
ID string `json:"id"` ID string `json:"id"`
Name string `json:"name"` Name string `json:"name"`
// DevMode contains the time in seconds until development expires (if
// positive) or since it expired (if negative). It will be 0 if never used.
DevMode int `json:"development_mode"` DevMode int `json:"development_mode"`
OriginalNS []string `json:"original_name_servers"` OriginalNS []string `json:"original_name_servers"`
OriginalRegistrar string `json:"original_registrar"` OriginalRegistrar string `json:"original_registrar"`
@ -29,8 +31,8 @@ type Zone struct {
NameServers []string `json:"name_servers"` NameServers []string `json:"name_servers"`
Owner Owner `json:"owner"` Owner Owner `json:"owner"`
Permissions []string `json:"permissions"` Permissions []string `json:"permissions"`
Plan ZonePlan `json:"plan"` Plan ZoneRatePlan `json:"plan"`
PlanPending ZonePlan `json:"plan_pending,omitempty"` PlanPending ZoneRatePlan `json:"plan_pending,omitempty"`
Status string `json:"status"` Status string `json:"status"`
Paused bool `json:"paused"` Paused bool `json:"paused"`
Type string `json:"type"` Type string `json:"type"`
@ -44,7 +46,7 @@ type Zone struct {
Meta ZoneMeta `json:"meta"` Meta ZoneMeta `json:"meta"`
} }
// ZoneMeta metadata about a zone. // ZoneMeta describes metadata about a zone.
type ZoneMeta struct { type ZoneMeta struct {
// custom_certificate_quota is broken - sometimes it's a string, sometimes a number! // custom_certificate_quota is broken - sometimes it's a string, sometimes a number!
// CustCertQuota int `json:"custom_certificate_quota"` // CustCertQuota int `json:"custom_certificate_quota"`
@ -53,16 +55,21 @@ type ZoneMeta struct {
PhishingDetected bool `json:"phishing_detected"` PhishingDetected bool `json:"phishing_detected"`
} }
// ZonePlan contains the plan information for a zone. // ZoneRatePlan contains the plan information for a zone.
type ZonePlan struct { type ZoneRatePlan struct {
ID string `json:"id"` ID string `json:"id"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Price int `json:"price,omitempty"` Price int `json:"price,omitempty"`
Currency string `json:"currency,omitempty"` Currency string `json:"currency,omitempty"`
Duration int `json:"duration,omitempty"`
Frequency string `json:"frequency,omitempty"` Frequency string `json:"frequency,omitempty"`
LegacyID string `json:"legacy_id,omitempty"` Components []zoneRatePlanComponents `json:"components,omitempty"`
IsSubscribed bool `json:"is_subscribed,omitempty"` }
CanSubscribe bool `json:"can_subscribe,omitempty"`
type zoneRatePlanComponents struct {
Name string `json:"name"`
Default int `json:"Default"`
UnitPrice int `json:"unit_price"`
} }
// ZoneID contains only the zone ID. // ZoneID contains only the zone ID.
@ -88,17 +95,17 @@ type ZoneIDResponse struct {
Result ZoneID `json:"result"` Result ZoneID `json:"result"`
} }
// AvailableZonePlansResponse represents the response from the Available Plans endpoint. // AvailableZoneRatePlansResponse represents the response from the Available Rate Plans endpoint.
type AvailableZonePlansResponse struct { type AvailableZoneRatePlansResponse struct {
Response Response
Result []ZonePlan `json:"result"` Result []ZoneRatePlan `json:"result"`
ResultInfo ResultInfo
} }
// ZonePlanResponse represents the response from the Plan Details endpoint. // ZoneRatePlanResponse represents the response from the Plan Details endpoint.
type ZonePlanResponse struct { type ZoneRatePlanResponse struct {
Response Response
Result ZonePlan `json:"result"` Result ZoneRatePlan `json:"result"`
} }
// ZoneSetting contains settings for a zone. // ZoneSetting contains settings for a zone.
@ -116,6 +123,21 @@ type ZoneSettingResponse struct {
Result []ZoneSetting `json:"result"` Result []ZoneSetting `json:"result"`
} }
// ZoneSSLSetting contains ssl setting for a zone.
type ZoneSSLSetting struct {
ID string `json:"id"`
Editable bool `json:"editable"`
ModifiedOn string `json:"modified_on"`
Value string `json:"value"`
CertificateStatus string `json:"certificate_status"`
}
// ZoneSettingResponse represents the response from the Zone SSL Setting endpoint.
type ZoneSSLSettingResponse struct {
Response
Result ZoneSSLSetting `json:"result"`
}
// ZoneAnalyticsData contains totals and timeseries analytics data for a zone. // ZoneAnalyticsData contains totals and timeseries analytics data for a zone.
type ZoneAnalyticsData struct { type ZoneAnalyticsData struct {
Totals ZoneAnalytics `json:"totals"` Totals ZoneAnalytics `json:"totals"`
@ -212,6 +234,12 @@ type newZone struct {
// CreateZone creates a zone on an account. // CreateZone creates a zone on an account.
// //
// Setting jumpstart to true will attempt to automatically scan for existing
// DNS records. Setting this to false will create the zone with no DNS records.
//
// If Organization is non-empty, it must have at least the ID field populated.
// This will add the new zone to the specified multi-user organization.
//
// API reference: https://api.cloudflare.com/#zone-create-a-zone // API reference: https://api.cloudflare.com/#zone-create-a-zone
func (api *API) CreateZone(name string, jumpstart bool, org Organization) (Zone, error) { func (api *API) CreateZone(name string, jumpstart bool, org Organization) (Zone, error) {
var newzone newZone var newzone newZone
@ -315,17 +343,15 @@ func (api *API) ZoneDetails(zoneID string) (Zone, error) {
// ZoneOptions is a subset of Zone, for editable options. // ZoneOptions is a subset of Zone, for editable options.
type ZoneOptions struct { type ZoneOptions struct {
// FIXME(jamesog): Using omitempty here means we can't disable Paused. Paused *bool `json:"paused,omitempty"`
// Currently unsure how to work around this.
Paused bool `json:"paused,omitempty"`
VanityNS []string `json:"vanity_name_servers,omitempty"` VanityNS []string `json:"vanity_name_servers,omitempty"`
Plan *ZonePlan `json:"plan,omitempty"` Plan *ZoneRatePlan `json:"plan,omitempty"`
} }
// ZoneSetPaused pauses Cloudflare service for the entire zone, sending all // ZoneSetPaused pauses Cloudflare service for the entire zone, sending all
// traffic direct to the origin. // traffic direct to the origin.
func (api *API) ZoneSetPaused(zoneID string, paused bool) (Zone, error) { func (api *API) ZoneSetPaused(zoneID string, paused bool) (Zone, error) {
zoneopts := ZoneOptions{Paused: paused} zoneopts := ZoneOptions{Paused: &paused}
zone, err := api.EditZone(zoneID, zoneopts) zone, err := api.EditZone(zoneID, zoneopts)
if err != nil { if err != nil {
return Zone{}, err return Zone{}, err
@ -346,8 +372,8 @@ func (api *API) ZoneSetVanityNS(zoneID string, ns []string) (Zone, error) {
return zone, nil return zone, nil
} }
// ZoneSetPlan changes the zone plan. // ZoneSetRatePlan changes the zone plan.
func (api *API) ZoneSetPlan(zoneID string, plan ZonePlan) (Zone, error) { func (api *API) ZoneSetRatePlan(zoneID string, plan ZoneRatePlan) (Zone, error) {
zoneopts := ZoneOptions{Plan: &plan} zoneopts := ZoneOptions{Plan: &plan}
zone, err := api.EditZone(zoneID, zoneopts) zone, err := api.EditZone(zoneID, zoneopts)
if err != nil { if err != nil {
@ -358,6 +384,7 @@ func (api *API) ZoneSetPlan(zoneID string, plan ZonePlan) (Zone, error) {
} }
// EditZone edits the given zone. // EditZone edits the given zone.
//
// This is usually called by ZoneSetPaused, ZoneSetVanityNS or ZoneSetPlan. // This is usually called by ZoneSetPaused, ZoneSetVanityNS or ZoneSetPlan.
// //
// API reference: https://api.cloudflare.com/#zone-edit-zone-properties // API reference: https://api.cloudflare.com/#zone-edit-zone-properties
@ -376,6 +403,7 @@ func (api *API) EditZone(zoneID string, zoneOpts ZoneOptions) (Zone, error) {
} }
// PurgeEverything purges the cache for the given zone. // PurgeEverything purges the cache for the given zone.
//
// Note: this will substantially increase load on the origin server for that // Note: this will substantially increase load on the origin server for that
// zone if there is a high cached vs. uncached request ratio. // zone if there is a high cached vs. uncached request ratio.
// //
@ -427,36 +455,19 @@ func (api *API) DeleteZone(zoneID string) (ZoneID, error) {
return r.Result, nil return r.Result, nil
} }
// AvailableZonePlans returns information about all plans available to the specified zone. // AvailableZoneRatePlans returns information about all plans available to the specified zone.
// //
// API reference: https://api.cloudflare.com/#zone-plan-available-plans // API reference: https://api.cloudflare.com/#zone-plan-available-plans
func (api *API) AvailableZonePlans(zoneID string) ([]ZonePlan, error) { func (api *API) AvailableZoneRatePlans(zoneID string) ([]ZoneRatePlan, error) {
uri := "/zones/" + zoneID + "/available_plans" uri := "/zones/" + zoneID + "/available_rate_plans"
res, err := api.makeRequest("GET", uri, nil) res, err := api.makeRequest("GET", uri, nil)
if err != nil { if err != nil {
return []ZonePlan{}, errors.Wrap(err, errMakeRequestError) return []ZoneRatePlan{}, errors.Wrap(err, errMakeRequestError)
} }
var r AvailableZonePlansResponse var r AvailableZoneRatePlansResponse
err = json.Unmarshal(res, &r) err = json.Unmarshal(res, &r)
if err != nil { if err != nil {
return []ZonePlan{}, errors.Wrap(err, errUnmarshalError) return []ZoneRatePlan{}, 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 return r.Result, nil
} }
@ -478,9 +489,7 @@ func (o ZoneAnalyticsOptions) encode() string {
// ZoneAnalyticsDashboard returns zone analytics information. // ZoneAnalyticsDashboard returns zone analytics information.
// //
// API reference: // API reference: https://api.cloudflare.com/#zone-analytics-dashboard
// https://api.cloudflare.com/#zone-analytics-dashboard
// GET /zones/:zone_identifier/analytics/dashboard
func (api *API) ZoneAnalyticsDashboard(zoneID string, options ZoneAnalyticsOptions) (ZoneAnalyticsData, error) { func (api *API) ZoneAnalyticsDashboard(zoneID string, options ZoneAnalyticsOptions) (ZoneAnalyticsData, error) {
uri := "/zones/" + zoneID + "/analytics/dashboard" + "?" + options.encode() uri := "/zones/" + zoneID + "/analytics/dashboard" + "?" + options.encode()
res, err := api.makeRequest("GET", uri, nil) res, err := api.makeRequest("GET", uri, nil)
@ -497,9 +506,7 @@ func (api *API) ZoneAnalyticsDashboard(zoneID string, options ZoneAnalyticsOptio
// ZoneAnalyticsByColocation returns zone analytics information by datacenter. // ZoneAnalyticsByColocation returns zone analytics information by datacenter.
// //
// API reference: // API reference: https://api.cloudflare.com/#zone-analytics-analytics-by-co-locations
// 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) { func (api *API) ZoneAnalyticsByColocation(zoneID string, options ZoneAnalyticsOptions) ([]ZoneAnalyticsColocation, error) {
uri := "/zones/" + zoneID + "/analytics/colos" + "?" + options.encode() uri := "/zones/" + zoneID + "/analytics/colos" + "?" + options.encode()
res, err := api.makeRequest("GET", uri, nil) res, err := api.makeRequest("GET", uri, nil)
@ -514,8 +521,19 @@ func (api *API) ZoneAnalyticsByColocation(zoneID string, options ZoneAnalyticsOp
return r.Result, nil return r.Result, nil
} }
// Zone Settings // ZoneSSLSetting returns information about ssl setting to the specified zone.
// https://api.cloudflare.com/#zone-settings-for-a-zone-get-all-zone-settings //
// e.g. // API reference: https://api.cloudflare.com/#zone-settings-get-ssl-setting
// https://api.cloudflare.com/#zone-settings-for-a-zone-get-always-online-setting func (api *API) ZoneSSLSettings(zoneID string) (ZoneSSLSetting, error) {
// https://api.cloudflare.com/#zone-settings-for-a-zone-change-always-online-setting uri := "/zones/" + zoneID + "/settings/ssl"
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return ZoneSSLSetting{}, errors.Wrap(err, errMakeRequestError)
}
var r ZoneSSLSettingResponse
err = json.Unmarshal(res, &r)
if err != nil {
return ZoneSSLSetting{}, errors.Wrap(err, errUnmarshalError)
}
return r.Result, nil
}

View File

@ -0,0 +1,42 @@
package cloudflare_test
import (
"fmt"
"log"
cloudflare "github.com/cloudflare/cloudflare-go"
)
func ExampleAPI_ListZones_all() {
api, err := cloudflare.New("deadbeef", "test@example.org")
if err != nil {
log.Fatal(err)
}
// Fetch a slice of all zones available to this account.
zones, err := api.ListZones()
if err != nil {
log.Fatal(err)
}
for _, z := range zones {
fmt.Println(z.Name)
}
}
func ExampleAPI_ListZones_filter() {
api, err := cloudflare.New("deadbeef", "test@example.org")
if err != nil {
log.Fatal(err)
}
// Fetch a slice of zones example.org and example.net.
zones, err := api.ListZones("example.org", "example.net")
if err != nil {
log.Fatal(err)
}
for _, z := range zones {
fmt.Println(z.Name)
}
}

View File

@ -1,5 +1,10 @@
# Change Log # Change Log
## [v1.1.1] - 2017-09-29
- #151 Following user agent field recommendations - @joonas
- #148 AsRequest method to create load balancers requests - @lukegb
## [v1.1.0] - 2017-06-06 ## [v1.1.0] - 2017-06-06
### Added ### Added

View File

@ -1,6 +1,10 @@
package godo package godo
import "github.com/digitalocean/godo/context" import (
"net/http"
"github.com/digitalocean/godo/context"
)
// AccountService is an interface for interfacing with the Account // AccountService is an interface for interfacing with the Account
// endpoints of the DigitalOcean API // endpoints of the DigitalOcean API
@ -41,7 +45,7 @@ func (s *AccountServiceOp) Get(ctx context.Context) (*Account, *Response, error)
path := "v2/account" path := "v2/account"
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -12,7 +12,7 @@ func TestAccountGet(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/account", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/account", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
response := ` response := `
{ "account": { { "account": {

View File

@ -2,6 +2,7 @@ package godo
import ( import (
"fmt" "fmt"
"net/http"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
) )
@ -61,7 +62,7 @@ func (s *ActionsServiceOp) List(ctx context.Context, opt *ListOptions) ([]Action
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -85,7 +86,7 @@ func (s *ActionsServiceOp) Get(ctx context.Context, id int) (*Action, *Response,
} }
path := fmt.Sprintf("%s/%d", actionsBasePath, id) path := fmt.Sprintf("%s/%d", actionsBasePath, id)
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -14,7 +14,7 @@ func TestAction_List(t *testing.T) {
mux.HandleFunc("/v2/actions", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/actions", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `{"actions": [{"id":1},{"id":2}]}`) fmt.Fprint(w, `{"actions": [{"id":1},{"id":2}]}`)
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
}) })
actions, _, err := client.Actions.List(ctx, nil) actions, _, err := client.Actions.List(ctx, nil)
@ -34,7 +34,7 @@ func TestAction_ListActionMultiplePages(t *testing.T) {
mux.HandleFunc("/v2/actions", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/actions", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `{"actions": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/droplets/?page=2"}}}`) fmt.Fprint(w, `{"actions": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/droplets/?page=2"}}}`)
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
}) })
_, resp, err := client.Actions.List(ctx, nil) _, resp, err := client.Actions.List(ctx, nil)
@ -63,7 +63,7 @@ func TestAction_RetrievePageByNumber(t *testing.T) {
}` }`
mux.HandleFunc("/v2/actions", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/actions", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })
@ -82,7 +82,7 @@ func TestAction_Get(t *testing.T) {
mux.HandleFunc("/v2/actions/12345", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/actions/12345", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `{"action": {"id":12345,"region":{"name":"name","slug":"slug","available":true,"sizes":["512mb"],"features":["virtio"]},"region_slug":"slug"}}`) fmt.Fprint(w, `{"action": {"id":12345,"region":{"name":"name","slug":"slug","available":true,"sizes":["512mb"],"features":["virtio"]},"region_slug":"slug"}}`)
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
}) })
action, _, err := client.Actions.Get(ctx, 12345) action, _, err := client.Actions.Get(ctx, 12345)

View File

@ -1,6 +1,7 @@
package godo package godo
import ( import (
"net/http"
"path" "path"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
@ -54,7 +55,7 @@ var _ CertificatesService = &CertificatesServiceOp{}
func (c *CertificatesServiceOp) Get(ctx context.Context, cID string) (*Certificate, *Response, error) { func (c *CertificatesServiceOp) Get(ctx context.Context, cID string) (*Certificate, *Response, error) {
urlStr := path.Join(certificatesBasePath, cID) urlStr := path.Join(certificatesBasePath, cID)
req, err := c.client.NewRequest(ctx, "GET", urlStr, nil) req, err := c.client.NewRequest(ctx, http.MethodGet, urlStr, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -75,7 +76,7 @@ func (c *CertificatesServiceOp) List(ctx context.Context, opt *ListOptions) ([]C
return nil, nil, err return nil, nil, err
} }
req, err := c.client.NewRequest(ctx, "GET", urlStr, nil) req, err := c.client.NewRequest(ctx, http.MethodGet, urlStr, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -94,7 +95,7 @@ func (c *CertificatesServiceOp) List(ctx context.Context, opt *ListOptions) ([]C
// Create a new certificate with provided configuration. // Create a new certificate with provided configuration.
func (c *CertificatesServiceOp) Create(ctx context.Context, cr *CertificateRequest) (*Certificate, *Response, error) { func (c *CertificatesServiceOp) Create(ctx context.Context, cr *CertificateRequest) (*Certificate, *Response, error) {
req, err := c.client.NewRequest(ctx, "POST", certificatesBasePath, cr) req, err := c.client.NewRequest(ctx, http.MethodPost, certificatesBasePath, cr)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -112,7 +113,7 @@ func (c *CertificatesServiceOp) Create(ctx context.Context, cr *CertificateReque
func (c *CertificatesServiceOp) Delete(ctx context.Context, cID string) (*Response, error) { func (c *CertificatesServiceOp) Delete(ctx context.Context, cID string) (*Response, error) {
urlStr := path.Join(certificatesBasePath, cID) urlStr := path.Join(certificatesBasePath, cID)
req, err := c.client.NewRequest(ctx, "DELETE", urlStr, nil) req, err := c.client.NewRequest(ctx, http.MethodDelete, urlStr, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -55,7 +55,7 @@ func TestCertificates_Get(t *testing.T) {
cID := "892071a0-bb95-49bc-8021-3afd67a210bf" cID := "892071a0-bb95-49bc-8021-3afd67a210bf"
urlStr = path.Join(urlStr, cID) urlStr = path.Join(urlStr, cID)
mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, certJSONResponse) fmt.Fprint(w, certJSONResponse)
}) })
@ -81,7 +81,7 @@ func TestCertificates_List(t *testing.T) {
urlStr := "/v2/certificates" urlStr := "/v2/certificates"
mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, certsJSONResponse) fmt.Fprint(w, certsJSONResponse)
}) })
@ -130,7 +130,7 @@ func TestCertificates_Create(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
assert.Equal(t, createRequest, v) assert.Equal(t, createRequest, v)
fmt.Fprint(w, certJSONResponse) fmt.Fprint(w, certJSONResponse)
@ -160,7 +160,7 @@ func TestCertificates_Delete(t *testing.T) {
urlStr := "/v2/certificates" urlStr := "/v2/certificates"
urlStr = path.Join(urlStr, cID) urlStr = path.Join(urlStr, cID)
mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
_, err := client.Certificates.Delete(ctx, cID) _, err := client.Certificates.Delete(ctx, cID)

View File

@ -2,6 +2,7 @@ package godo
import ( import (
"fmt" "fmt"
"net/http"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
) )
@ -101,7 +102,7 @@ func (s DomainsServiceOp) List(ctx context.Context, opt *ListOptions) ([]Domain,
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -126,7 +127,7 @@ func (s *DomainsServiceOp) Get(ctx context.Context, name string) (*Domain, *Resp
path := fmt.Sprintf("%s/%s", domainsBasePath, name) path := fmt.Sprintf("%s/%s", domainsBasePath, name)
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -148,7 +149,7 @@ func (s *DomainsServiceOp) Create(ctx context.Context, createRequest *DomainCrea
path := domainsBasePath path := domainsBasePath
req, err := s.client.NewRequest(ctx, "POST", path, createRequest) req, err := s.client.NewRequest(ctx, http.MethodPost, path, createRequest)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -169,7 +170,7 @@ func (s *DomainsServiceOp) Delete(ctx context.Context, name string) (*Response,
path := fmt.Sprintf("%s/%s", domainsBasePath, name) path := fmt.Sprintf("%s/%s", domainsBasePath, name)
req, err := s.client.NewRequest(ctx, "DELETE", path, nil) req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -201,7 +202,7 @@ func (s *DomainsServiceOp) Records(ctx context.Context, domain string, opt *List
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -230,7 +231,7 @@ func (s *DomainsServiceOp) Record(ctx context.Context, domain string, id int) (*
path := fmt.Sprintf("%s/%s/records/%d", domainsBasePath, domain, id) path := fmt.Sprintf("%s/%s/records/%d", domainsBasePath, domain, id)
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -256,7 +257,7 @@ func (s *DomainsServiceOp) DeleteRecord(ctx context.Context, domain string, id i
path := fmt.Sprintf("%s/%s/records/%d", domainsBasePath, domain, id) path := fmt.Sprintf("%s/%s/records/%d", domainsBasePath, domain, id)
req, err := s.client.NewRequest(ctx, "DELETE", path, nil) req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -313,7 +314,7 @@ func (s *DomainsServiceOp) CreateRecord(ctx context.Context,
} }
path := fmt.Sprintf("%s/%s/records", domainsBasePath, domain) path := fmt.Sprintf("%s/%s/records", domainsBasePath, domain)
req, err := s.client.NewRequest(ctx, "POST", path, createRequest) req, err := s.client.NewRequest(ctx, http.MethodPost, path, createRequest)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err

View File

@ -13,7 +13,7 @@ func TestDomains_ListDomains(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/domains", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/domains", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"domains": [{"name":"foo.com"},{"name":"bar.com"}]}`) fmt.Fprint(w, `{"domains": [{"name":"foo.com"},{"name":"bar.com"}]}`)
}) })
@ -33,7 +33,7 @@ func TestDomains_ListDomainsMultiplePages(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/domains", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/domains", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"domains": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/domains/?page=2"}}}`) fmt.Fprint(w, `{"domains": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/domains/?page=2"}}}`)
}) })
@ -63,7 +63,7 @@ func TestDomains_RetrievePageByNumber(t *testing.T) {
}` }`
mux.HandleFunc("/v2/domains", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/domains", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })
@ -81,7 +81,7 @@ func TestDomains_GetDomain(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/domains/example.com", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/domains/example.com", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"domain":{"name":"example.com"}}`) fmt.Fprint(w, `{"domain":{"name":"example.com"}}`)
}) })
@ -112,7 +112,7 @@ func TestDomains_Create(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, createRequest) { if !reflect.DeepEqual(v, createRequest) {
t.Errorf("Request body = %+v, expected %+v", v, createRequest) t.Errorf("Request body = %+v, expected %+v", v, createRequest)
} }
@ -136,7 +136,7 @@ func TestDomains_Destroy(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/domains/example.com", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/domains/example.com", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
_, err := client.Domains.Delete(ctx, "example.com") _, err := client.Domains.Delete(ctx, "example.com")
@ -150,7 +150,7 @@ func TestDomains_AllRecordsForDomainName(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/domains/example.com/records", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/domains/example.com/records", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"domain_records":[{"id":1},{"id":2}]}`) fmt.Fprint(w, `{"domain_records":[{"id":1},{"id":2}]}`)
}) })
@ -195,7 +195,7 @@ func TestDomains_GetRecordforDomainName(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/domains/example.com/records/1", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/domains/example.com/records/1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"domain_record":{"id":1}}`) fmt.Fprint(w, `{"domain_record":{"id":1}}`)
}) })
@ -215,7 +215,7 @@ func TestDomains_DeleteRecordForDomainName(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/domains/example.com/records/1", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/domains/example.com/records/1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
_, err := client.Domains.DeleteRecord(ctx, "example.com", 1) _, err := client.Domains.DeleteRecord(ctx, "example.com", 1)
@ -247,7 +247,7 @@ func TestDomains_CreateRecordForDomainName(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, createRequest) { if !reflect.DeepEqual(v, createRequest) {
t.Errorf("Request body = %+v, expected %+v", v, createRequest) t.Errorf("Request body = %+v, expected %+v", v, createRequest)
} }

View File

@ -2,6 +2,7 @@ package godo
import ( import (
"fmt" "fmt"
"net/http"
"net/url" "net/url"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
@ -247,7 +248,7 @@ func (s *DropletActionsServiceOp) doAction(ctx context.Context, id int, request
path := dropletActionPath(id) path := dropletActionPath(id)
req, err := s.client.NewRequest(ctx, "POST", path, request) req, err := s.client.NewRequest(ctx, http.MethodPost, path, request)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -272,7 +273,7 @@ func (s *DropletActionsServiceOp) doActionByTag(ctx context.Context, tag string,
path := dropletActionPathByTag(tag) path := dropletActionPathByTag(tag)
req, err := s.client.NewRequest(ctx, "POST", path, request) req, err := s.client.NewRequest(ctx, http.MethodPost, path, request)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -312,7 +313,7 @@ func (s *DropletActionsServiceOp) GetByURI(ctx context.Context, rawurl string) (
} }
func (s *DropletActionsServiceOp) get(ctx context.Context, path string) (*Action, *Response, error) { func (s *DropletActionsServiceOp) get(ctx context.Context, path string) (*Action, *Response, error) {
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -23,7 +23,7 @@ func TestDropletActions_Shutdown(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
} }
@ -61,7 +61,7 @@ func TestDropletActions_ShutdownByTag(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
} }
@ -95,7 +95,7 @@ func TestDropletAction_PowerOff(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
} }
@ -133,7 +133,7 @@ func TestDropletAction_PowerOffByTag(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
} }
@ -167,7 +167,7 @@ func TestDropletAction_PowerOn(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
} }
@ -205,7 +205,7 @@ func TestDropletAction_PowerOnByTag(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
} }
@ -238,7 +238,7 @@ func TestDropletAction_Reboot(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
} }
@ -274,7 +274,7 @@ func TestDropletAction_Restore(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -312,7 +312,7 @@ func TestDropletAction_Resize(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -349,7 +349,7 @@ func TestDropletAction_Rename(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -384,7 +384,7 @@ func TestDropletAction_PowerCycle(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
} }
@ -423,7 +423,7 @@ func TestDropletAction_PowerCycleByTag(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
} }
@ -458,7 +458,7 @@ func TestDropletAction_Snapshot(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -498,7 +498,7 @@ func TestDropletAction_SnapshotByTag(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -533,7 +533,7 @@ func TestDropletAction_EnableBackups(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -572,7 +572,7 @@ func TestDropletAction_EnableBackupsByTag(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -607,7 +607,7 @@ func TestDropletAction_DisableBackups(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -646,7 +646,7 @@ func TestDropletAction_DisableBackupsByTag(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -681,7 +681,7 @@ func TestDropletAction_PasswordReset(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -717,7 +717,7 @@ func TestDropletAction_RebuildByImageID(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = \n%#v, expected \n%#v", v, request) t.Errorf("Request body = \n%#v, expected \n%#v", v, request)
@ -753,7 +753,7 @@ func TestDropletAction_RebuildByImageSlug(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -789,7 +789,7 @@ func TestDropletAction_ChangeKernel(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -824,7 +824,7 @@ func TestDropletAction_EnableIPv6(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -863,7 +863,7 @@ func TestDropletAction_EnableIPv6ByTag(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -898,7 +898,7 @@ func TestDropletAction_EnablePrivateNetworking(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -937,7 +937,7 @@ func TestDropletAction_EnablePrivateNetworkingByTag(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -972,7 +972,7 @@ func TestDropletAction_Upgrade(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, request) { if !reflect.DeepEqual(v, request) {
t.Errorf("Request body = %+v, expected %+v", v, request) t.Errorf("Request body = %+v, expected %+v", v, request)
@ -997,7 +997,7 @@ func TestDropletActions_Get(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/droplets/123/actions/456", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/droplets/123/actions/456", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`) fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
}) })

View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"net/http"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
) )
@ -275,7 +276,7 @@ func (n NetworkV6) String() string {
// Performs a list request given a path. // Performs a list request given a path.
func (s *DropletsServiceOp) list(ctx context.Context, path string) ([]Droplet, *Response, error) { func (s *DropletsServiceOp) list(ctx context.Context, path string) ([]Droplet, *Response, error) {
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -322,7 +323,7 @@ func (s *DropletsServiceOp) Get(ctx context.Context, dropletID int) (*Droplet, *
path := fmt.Sprintf("%s/%d", dropletBasePath, dropletID) path := fmt.Sprintf("%s/%d", dropletBasePath, dropletID)
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -344,7 +345,7 @@ func (s *DropletsServiceOp) Create(ctx context.Context, createRequest *DropletCr
path := dropletBasePath path := dropletBasePath
req, err := s.client.NewRequest(ctx, "POST", path, createRequest) req, err := s.client.NewRequest(ctx, http.MethodPost, path, createRequest)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -369,7 +370,7 @@ func (s *DropletsServiceOp) CreateMultiple(ctx context.Context, createRequest *D
path := dropletBasePath path := dropletBasePath
req, err := s.client.NewRequest(ctx, "POST", path, createRequest) req, err := s.client.NewRequest(ctx, http.MethodPost, path, createRequest)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -388,7 +389,7 @@ func (s *DropletsServiceOp) CreateMultiple(ctx context.Context, createRequest *D
// Performs a delete request given a path // Performs a delete request given a path
func (s *DropletsServiceOp) delete(ctx context.Context, path string) (*Response, error) { func (s *DropletsServiceOp) delete(ctx context.Context, path string) (*Response, error) {
req, err := s.client.NewRequest(ctx, "DELETE", path, nil) req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -432,7 +433,7 @@ func (s *DropletsServiceOp) Kernels(ctx context.Context, dropletID int, opt *Lis
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -458,7 +459,7 @@ func (s *DropletsServiceOp) Actions(ctx context.Context, dropletID int, opt *Lis
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -487,7 +488,7 @@ func (s *DropletsServiceOp) Backups(ctx context.Context, dropletID int, opt *Lis
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -516,7 +517,7 @@ func (s *DropletsServiceOp) Snapshots(ctx context.Context, dropletID int, opt *L
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -541,7 +542,7 @@ func (s *DropletsServiceOp) Neighbors(ctx context.Context, dropletID int) ([]Dro
path := fmt.Sprintf("%s/%d/neighbors", dropletBasePath, dropletID) path := fmt.Sprintf("%s/%d/neighbors", dropletBasePath, dropletID)
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -13,7 +13,7 @@ func TestDroplets_ListDroplets(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"droplets": [{"id":1},{"id":2}]}`) fmt.Fprint(w, `{"droplets": [{"id":1},{"id":2}]}`)
}) })
@ -37,7 +37,7 @@ func TestDroplets_ListDropletsByTag(t *testing.T) {
t.Errorf("Droplets.ListByTag did not request with a tag parameter") t.Errorf("Droplets.ListByTag did not request with a tag parameter")
} }
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"droplets": [{"id":1},{"id":2}]}`) fmt.Fprint(w, `{"droplets": [{"id":1},{"id":2}]}`)
}) })
@ -57,7 +57,7 @@ func TestDroplets_ListDropletsMultiplePages(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
dr := dropletsRoot{ dr := dropletsRoot{
Droplets: []Droplet{ Droplets: []Droplet{
@ -103,7 +103,7 @@ func TestDroplets_RetrievePageByNumber(t *testing.T) {
}` }`
mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })
@ -121,7 +121,7 @@ func TestDroplets_GetDroplet(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/droplets/12345", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/droplets/12345", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"droplet":{"id":12345}}`) fmt.Fprint(w, `{"droplet":{"id":12345}}`)
}) })
@ -265,7 +265,7 @@ func TestDroplets_Destroy(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/droplets/12345", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/droplets/12345", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
_, err := client.Droplets.Delete(ctx, 12345) _, err := client.Droplets.Delete(ctx, 12345)
@ -283,7 +283,7 @@ func TestDroplets_DestroyByTag(t *testing.T) {
t.Errorf("Droplets.DeleteByTag did not request with a tag parameter") t.Errorf("Droplets.DeleteByTag did not request with a tag parameter")
} }
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
_, err := client.Droplets.DeleteByTag(ctx, "testing-1") _, err := client.Droplets.DeleteByTag(ctx, "testing-1")
@ -297,7 +297,7 @@ func TestDroplets_Kernels(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/droplets/12345/kernels", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/droplets/12345/kernels", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"kernels": [{"id":1},{"id":2}]}`) fmt.Fprint(w, `{"kernels": [{"id":1},{"id":2}]}`)
}) })
@ -318,7 +318,7 @@ func TestDroplets_Snapshots(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/droplets/12345/snapshots", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/droplets/12345/snapshots", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"snapshots": [{"id":1},{"id":2}]}`) fmt.Fprint(w, `{"snapshots": [{"id":1},{"id":2}]}`)
}) })
@ -339,7 +339,7 @@ func TestDroplets_Backups(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/droplets/12345/backups", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/droplets/12345/backups", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"backups": [{"id":1},{"id":2}]}`) fmt.Fprint(w, `{"backups": [{"id":1},{"id":2}]}`)
}) })
@ -360,7 +360,7 @@ func TestDroplets_Actions(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/droplets/12345/actions", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/droplets/12345/actions", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"actions": [{"id":1},{"id":2}]}`) fmt.Fprint(w, `{"actions": [{"id":1},{"id":2}]}`)
}) })
@ -381,7 +381,7 @@ func TestDroplets_Neighbors(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/droplets/12345/neighbors", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/droplets/12345/neighbors", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"droplets": [{"id":1},{"id":2}]}`) fmt.Fprint(w, `{"droplets": [{"id":1},{"id":2}]}`)
}) })

View File

@ -1,6 +1,7 @@
package godo package godo
import ( import (
"net/http"
"path" "path"
"strconv" "strconv"
@ -107,7 +108,7 @@ var _ FirewallsService = &FirewallsServiceOp{}
func (fw *FirewallsServiceOp) Get(ctx context.Context, fID string) (*Firewall, *Response, error) { func (fw *FirewallsServiceOp) Get(ctx context.Context, fID string) (*Firewall, *Response, error) {
path := path.Join(firewallsBasePath, fID) path := path.Join(firewallsBasePath, fID)
req, err := fw.client.NewRequest(ctx, "GET", path, nil) req, err := fw.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -123,7 +124,7 @@ func (fw *FirewallsServiceOp) Get(ctx context.Context, fID string) (*Firewall, *
// Create a new Firewall with a given configuration. // Create a new Firewall with a given configuration.
func (fw *FirewallsServiceOp) Create(ctx context.Context, fr *FirewallRequest) (*Firewall, *Response, error) { func (fw *FirewallsServiceOp) Create(ctx context.Context, fr *FirewallRequest) (*Firewall, *Response, error) {
req, err := fw.client.NewRequest(ctx, "POST", firewallsBasePath, fr) req, err := fw.client.NewRequest(ctx, http.MethodPost, firewallsBasePath, fr)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -158,7 +159,7 @@ func (fw *FirewallsServiceOp) Update(ctx context.Context, fID string, fr *Firewa
// Delete a Firewall by its identifier. // Delete a Firewall by its identifier.
func (fw *FirewallsServiceOp) Delete(ctx context.Context, fID string) (*Response, error) { func (fw *FirewallsServiceOp) Delete(ctx context.Context, fID string) (*Response, error) {
path := path.Join(firewallsBasePath, fID) path := path.Join(firewallsBasePath, fID)
return fw.createAndDoReq(ctx, "DELETE", path, nil) return fw.createAndDoReq(ctx, http.MethodDelete, path, nil)
} }
// List Firewalls. // List Firewalls.
@ -185,37 +186,37 @@ func (fw *FirewallsServiceOp) ListByDroplet(ctx context.Context, dID int, opt *L
// AddDroplets to a Firewall. // AddDroplets to a Firewall.
func (fw *FirewallsServiceOp) AddDroplets(ctx context.Context, fID string, dropletIDs ...int) (*Response, error) { func (fw *FirewallsServiceOp) AddDroplets(ctx context.Context, fID string, dropletIDs ...int) (*Response, error) {
path := path.Join(firewallsBasePath, fID, "droplets") path := path.Join(firewallsBasePath, fID, "droplets")
return fw.createAndDoReq(ctx, "POST", path, &dropletsRequest{IDs: dropletIDs}) return fw.createAndDoReq(ctx, http.MethodPost, path, &dropletsRequest{IDs: dropletIDs})
} }
// RemoveDroplets from a Firewall. // RemoveDroplets from a Firewall.
func (fw *FirewallsServiceOp) RemoveDroplets(ctx context.Context, fID string, dropletIDs ...int) (*Response, error) { func (fw *FirewallsServiceOp) RemoveDroplets(ctx context.Context, fID string, dropletIDs ...int) (*Response, error) {
path := path.Join(firewallsBasePath, fID, "droplets") path := path.Join(firewallsBasePath, fID, "droplets")
return fw.createAndDoReq(ctx, "DELETE", path, &dropletsRequest{IDs: dropletIDs}) return fw.createAndDoReq(ctx, http.MethodDelete, path, &dropletsRequest{IDs: dropletIDs})
} }
// AddTags to a Firewall. // AddTags to a Firewall.
func (fw *FirewallsServiceOp) AddTags(ctx context.Context, fID string, tags ...string) (*Response, error) { func (fw *FirewallsServiceOp) AddTags(ctx context.Context, fID string, tags ...string) (*Response, error) {
path := path.Join(firewallsBasePath, fID, "tags") path := path.Join(firewallsBasePath, fID, "tags")
return fw.createAndDoReq(ctx, "POST", path, &tagsRequest{Tags: tags}) return fw.createAndDoReq(ctx, http.MethodPost, path, &tagsRequest{Tags: tags})
} }
// RemoveTags from a Firewall. // RemoveTags from a Firewall.
func (fw *FirewallsServiceOp) RemoveTags(ctx context.Context, fID string, tags ...string) (*Response, error) { func (fw *FirewallsServiceOp) RemoveTags(ctx context.Context, fID string, tags ...string) (*Response, error) {
path := path.Join(firewallsBasePath, fID, "tags") path := path.Join(firewallsBasePath, fID, "tags")
return fw.createAndDoReq(ctx, "DELETE", path, &tagsRequest{Tags: tags}) return fw.createAndDoReq(ctx, http.MethodDelete, path, &tagsRequest{Tags: tags})
} }
// AddRules to a Firewall. // AddRules to a Firewall.
func (fw *FirewallsServiceOp) AddRules(ctx context.Context, fID string, rr *FirewallRulesRequest) (*Response, error) { func (fw *FirewallsServiceOp) AddRules(ctx context.Context, fID string, rr *FirewallRulesRequest) (*Response, error) {
path := path.Join(firewallsBasePath, fID, "rules") path := path.Join(firewallsBasePath, fID, "rules")
return fw.createAndDoReq(ctx, "POST", path, rr) return fw.createAndDoReq(ctx, http.MethodPost, path, rr)
} }
// RemoveRules from a Firewall. // RemoveRules from a Firewall.
func (fw *FirewallsServiceOp) RemoveRules(ctx context.Context, fID string, rr *FirewallRulesRequest) (*Response, error) { func (fw *FirewallsServiceOp) RemoveRules(ctx context.Context, fID string, rr *FirewallRulesRequest) (*Response, error) {
path := path.Join(firewallsBasePath, fID, "rules") path := path.Join(firewallsBasePath, fID, "rules")
return fw.createAndDoReq(ctx, "DELETE", path, rr) return fw.createAndDoReq(ctx, http.MethodDelete, path, rr)
} }
type dropletsRequest struct { type dropletsRequest struct {
@ -245,7 +246,7 @@ func (fw *FirewallsServiceOp) createAndDoReq(ctx context.Context, method, path s
} }
func (fw *FirewallsServiceOp) listHelper(ctx context.Context, path string) ([]Firewall, *Response, error) { func (fw *FirewallsServiceOp) listHelper(ctx context.Context, path string) ([]Firewall, *Response, error) {
req, err := fw.client.NewRequest(ctx, "GET", path, nil) req, err := fw.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -224,7 +224,7 @@ func TestFirewalls_Get(t *testing.T) {
urlStr = path.Join(urlStr, fID) urlStr = path.Join(urlStr, fID)
mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, firewallJSONResponse) fmt.Fprint(w, firewallJSONResponse)
}) })
@ -333,7 +333,7 @@ func TestFirewalls_Create(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, expectedFirewallRequest) { if !reflect.DeepEqual(v, expectedFirewallRequest) {
t.Errorf("Request body = %+v, expected %+v", v, expectedFirewallRequest) t.Errorf("Request body = %+v, expected %+v", v, expectedFirewallRequest)
} }
@ -481,7 +481,7 @@ func TestFirewalls_Delete(t *testing.T) {
fID := "fe6b88f2-b42b-4bf7-bbd3-5ae20208f0b0" fID := "fe6b88f2-b42b-4bf7-bbd3-5ae20208f0b0"
urlStr = path.Join(urlStr, fID) urlStr = path.Join(urlStr, fID)
mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
_, err := client.Firewalls.Delete(ctx, fID) _, err := client.Firewalls.Delete(ctx, fID)
@ -496,7 +496,7 @@ func TestFirewalls_List(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/firewalls", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/firewalls", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, firewallListJSONResponse) fmt.Fprint(w, firewallListJSONResponse)
}) })
@ -517,7 +517,7 @@ func TestFirewalls_ListByDroplet(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/droplets/123/firewalls", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/droplets/123/firewalls", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, firewallListJSONResponse) fmt.Fprint(w, firewallListJSONResponse)
}) })
@ -550,7 +550,7 @@ func TestFirewalls_AddDroplets(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, dRequest) { if !reflect.DeepEqual(v, dRequest) {
t.Errorf("Request body = %+v, expected %+v", v, dRequest) t.Errorf("Request body = %+v, expected %+v", v, dRequest)
} }
@ -589,7 +589,7 @@ func TestFirewalls_RemoveDroplets(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
if !reflect.DeepEqual(v, dRequest) { if !reflect.DeepEqual(v, dRequest) {
t.Errorf("Request body = %+v, expected %+v", v, dRequest) t.Errorf("Request body = %+v, expected %+v", v, dRequest)
} }
@ -628,7 +628,7 @@ func TestFirewalls_AddTags(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, tRequest) { if !reflect.DeepEqual(v, tRequest) {
t.Errorf("Request body = %+v, expected %+v", v, tRequest) t.Errorf("Request body = %+v, expected %+v", v, tRequest)
} }
@ -666,7 +666,7 @@ func TestFirewalls_RemoveTags(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
if !reflect.DeepEqual(v, tRequest) { if !reflect.DeepEqual(v, tRequest) {
t.Errorf("Request body = %+v, expected %+v", v, tRequest) t.Errorf("Request body = %+v, expected %+v", v, tRequest)
} }
@ -721,7 +721,7 @@ func TestFirewalls_AddRules(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, rr) { if !reflect.DeepEqual(v, rr) {
t.Errorf("Request body = %+v, expected %+v", v, rr) t.Errorf("Request body = %+v, expected %+v", v, rr)
} }
@ -776,7 +776,7 @@ func TestFirewalls_RemoveRules(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
if !reflect.DeepEqual(v, rr) { if !reflect.DeepEqual(v, rr) {
t.Errorf("Request body = %+v, expected %+v", v, rr) t.Errorf("Request body = %+v, expected %+v", v, rr)
} }

View File

@ -2,6 +2,7 @@ package godo
import ( import (
"fmt" "fmt"
"net/http"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
) )
@ -63,7 +64,7 @@ func (f *FloatingIPsServiceOp) List(ctx context.Context, opt *ListOptions) ([]Fl
return nil, nil, err return nil, nil, err
} }
req, err := f.client.NewRequest(ctx, "GET", path, nil) req, err := f.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -84,7 +85,7 @@ func (f *FloatingIPsServiceOp) List(ctx context.Context, opt *ListOptions) ([]Fl
func (f *FloatingIPsServiceOp) Get(ctx context.Context, ip string) (*FloatingIP, *Response, error) { func (f *FloatingIPsServiceOp) Get(ctx context.Context, ip string) (*FloatingIP, *Response, error) {
path := fmt.Sprintf("%s/%s", floatingBasePath, ip) path := fmt.Sprintf("%s/%s", floatingBasePath, ip)
req, err := f.client.NewRequest(ctx, "GET", path, nil) req, err := f.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -103,7 +104,7 @@ func (f *FloatingIPsServiceOp) Get(ctx context.Context, ip string) (*FloatingIP,
func (f *FloatingIPsServiceOp) Create(ctx context.Context, createRequest *FloatingIPCreateRequest) (*FloatingIP, *Response, error) { func (f *FloatingIPsServiceOp) Create(ctx context.Context, createRequest *FloatingIPCreateRequest) (*FloatingIP, *Response, error) {
path := floatingBasePath path := floatingBasePath
req, err := f.client.NewRequest(ctx, "POST", path, createRequest) req, err := f.client.NewRequest(ctx, http.MethodPost, path, createRequest)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -124,7 +125,7 @@ func (f *FloatingIPsServiceOp) Create(ctx context.Context, createRequest *Floati
func (f *FloatingIPsServiceOp) Delete(ctx context.Context, ip string) (*Response, error) { func (f *FloatingIPsServiceOp) Delete(ctx context.Context, ip string) (*Response, error) {
path := fmt.Sprintf("%s/%s", floatingBasePath, ip) path := fmt.Sprintf("%s/%s", floatingBasePath, ip)
req, err := f.client.NewRequest(ctx, "DELETE", path, nil) req, err := f.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -2,6 +2,7 @@ package godo
import ( import (
"fmt" "fmt"
"net/http"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
) )
@ -57,7 +58,7 @@ func (s *FloatingIPActionsServiceOp) List(ctx context.Context, ip string, opt *L
func (s *FloatingIPActionsServiceOp) doAction(ctx context.Context, ip string, request *ActionRequest) (*Action, *Response, error) { func (s *FloatingIPActionsServiceOp) doAction(ctx context.Context, ip string, request *ActionRequest) (*Action, *Response, error) {
path := floatingIPActionPath(ip) path := floatingIPActionPath(ip)
req, err := s.client.NewRequest(ctx, "POST", path, request) req, err := s.client.NewRequest(ctx, http.MethodPost, path, request)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -72,7 +73,7 @@ func (s *FloatingIPActionsServiceOp) doAction(ctx context.Context, ip string, re
} }
func (s *FloatingIPActionsServiceOp) get(ctx context.Context, path string) (*Action, *Response, error) { func (s *FloatingIPActionsServiceOp) get(ctx context.Context, path string) (*Action, *Response, error) {
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -87,7 +88,7 @@ func (s *FloatingIPActionsServiceOp) get(ctx context.Context, path string) (*Act
} }
func (s *FloatingIPActionsServiceOp) list(ctx context.Context, path string) ([]Action, *Response, error) { func (s *FloatingIPActionsServiceOp) list(ctx context.Context, path string) ([]Action, *Response, error) {
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -24,7 +24,7 @@ func TestFloatingIPsActions_Assign(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, assignRequest) { if !reflect.DeepEqual(v, assignRequest) {
t.Errorf("Request body = %#v, expected %#v", v, assignRequest) t.Errorf("Request body = %#v, expected %#v", v, assignRequest)
} }
@ -59,7 +59,7 @@ func TestFloatingIPsActions_Unassign(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, unassignRequest) { if !reflect.DeepEqual(v, unassignRequest) {
t.Errorf("Request body = %+v, expected %+v", v, unassignRequest) t.Errorf("Request body = %+v, expected %+v", v, unassignRequest)
} }
@ -83,7 +83,7 @@ func TestFloatingIPsActions_Get(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/floating_ips/192.168.0.1/actions/456", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/floating_ips/192.168.0.1/actions/456", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`) fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
}) })
@ -103,7 +103,7 @@ func TestFloatingIPsActions_List(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/floating_ips/192.168.0.1/actions", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/floating_ips/192.168.0.1/actions", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprintf(w, `{"actions":[{"status":"in-progress"}]}`) fmt.Fprintf(w, `{"actions":[{"status":"in-progress"}]}`)
}) })
@ -123,7 +123,7 @@ func TestFloatingIPsActions_ListMultiplePages(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/floating_ips/192.168.0.1/actions", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/floating_ips/192.168.0.1/actions", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"actions":[{"status":"in-progress"}], "links":{"pages":{"next":"http://example.com/v2/floating_ips/192.168.0.1/actions?page=2"}}}`) fmt.Fprint(w, `{"actions":[{"status":"in-progress"}], "links":{"pages":{"next":"http://example.com/v2/floating_ips/192.168.0.1/actions?page=2"}}}`)
}) })
@ -153,7 +153,7 @@ func TestFloatingIPsActions_ListPageByNumber(t *testing.T) {
}` }`
mux.HandleFunc("/v2/floating_ips/192.168.0.1/actions", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/floating_ips/192.168.0.1/actions", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })

View File

@ -13,7 +13,7 @@ func TestFloatingIPs_ListFloatingIPs(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/floating_ips", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/floating_ips", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"floating_ips": [{"region":{"slug":"nyc3"},"droplet":{"id":1},"ip":"192.168.0.1"},{"region":{"slug":"nyc3"},"droplet":{"id":2},"ip":"192.168.0.2"}]}`) fmt.Fprint(w, `{"floating_ips": [{"region":{"slug":"nyc3"},"droplet":{"id":1},"ip":"192.168.0.1"},{"region":{"slug":"nyc3"},"droplet":{"id":2},"ip":"192.168.0.2"}]}`)
}) })
@ -36,7 +36,7 @@ func TestFloatingIPs_ListFloatingIPsMultiplePages(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/floating_ips", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/floating_ips", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"floating_ips": [{"region":{"slug":"nyc3"},"droplet":{"id":1},"ip":"192.168.0.1"},{"region":{"slug":"nyc3"},"droplet":{"id":2},"ip":"192.168.0.2"}], "links":{"pages":{"next":"http://example.com/v2/floating_ips/?page=2"}}}`) fmt.Fprint(w, `{"floating_ips": [{"region":{"slug":"nyc3"},"droplet":{"id":1},"ip":"192.168.0.1"},{"region":{"slug":"nyc3"},"droplet":{"id":2},"ip":"192.168.0.2"}], "links":{"pages":{"next":"http://example.com/v2/floating_ips/?page=2"}}}`)
}) })
@ -66,7 +66,7 @@ func TestFloatingIPs_RetrievePageByNumber(t *testing.T) {
}` }`
mux.HandleFunc("/v2/floating_ips", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/floating_ips", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })
@ -84,7 +84,7 @@ func TestFloatingIPs_Get(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/floating_ips/192.168.0.1", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/floating_ips/192.168.0.1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"floating_ip":{"region":{"slug":"nyc3"},"droplet":{"id":1},"ip":"192.168.0.1"}}`) fmt.Fprint(w, `{"floating_ip":{"region":{"slug":"nyc3"},"droplet":{"id":1},"ip":"192.168.0.1"}}`)
}) })
@ -115,7 +115,7 @@ func TestFloatingIPs_Create(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, createRequest) { if !reflect.DeepEqual(v, createRequest) {
t.Errorf("Request body = %+v, expected %+v", v, createRequest) t.Errorf("Request body = %+v, expected %+v", v, createRequest)
} }
@ -139,7 +139,7 @@ func TestFloatingIPs_Destroy(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/floating_ips/192.168.0.1", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/floating_ips/192.168.0.1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
_, err := client.FloatingIPs.Delete(ctx, "192.168.0.1") _, err := client.FloatingIPs.Delete(ctx, "192.168.0.1")

View File

@ -210,7 +210,7 @@ func SetBaseURL(bu string) ClientOpt {
// SetUserAgent is a client option for setting the user agent. // SetUserAgent is a client option for setting the user agent.
func SetUserAgent(ua string) ClientOpt { func SetUserAgent(ua string) ClientOpt {
return func(c *Client) error { return func(c *Client) error {
c.UserAgent = fmt.Sprintf("%s+%s", ua, c.UserAgent) c.UserAgent = fmt.Sprintf("%s %s", ua, c.UserAgent)
return nil return nil
} }
} }

View File

@ -106,7 +106,7 @@ func testClientDefaultBaseURL(t *testing.T, c *Client) {
func testClientDefaultUserAgent(t *testing.T, c *Client) { func testClientDefaultUserAgent(t *testing.T, c *Client) {
if c.UserAgent != userAgent { if c.UserAgent != userAgent {
t.Errorf("NewClick UserAgent = %v, expected %v", c.UserAgent, userAgent) t.Errorf("NewClient UserAgent = %v, expected %v", c.UserAgent, userAgent)
} }
} }
@ -138,7 +138,7 @@ func TestNewRequest(t *testing.T) {
`{"name":"l","region":"","size":"","image":0,`+ `{"name":"l","region":"","size":"","image":0,`+
`"ssh_keys":null,"backups":false,"ipv6":false,`+ `"ssh_keys":null,"backups":false,"ipv6":false,`+
`"private_networking":false,"monitoring":false,"tags":null}`+"\n" `"private_networking":false,"monitoring":false,"tags":null}`+"\n"
req, _ := c.NewRequest(ctx, "GET", inURL, inBody) req, _ := c.NewRequest(ctx, http.MethodGet, inURL, inBody)
// test relative URL was expanded // test relative URL was expanded
if req.URL.String() != outURL { if req.URL.String() != outURL {
@ -166,7 +166,7 @@ func TestNewRequest_withUserData(t *testing.T) {
`{"name":"l","region":"","size":"","image":0,`+ `{"name":"l","region":"","size":"","image":0,`+
`"ssh_keys":null,"backups":false,"ipv6":false,`+ `"ssh_keys":null,"backups":false,"ipv6":false,`+
`"private_networking":false,"monitoring":false,"user_data":"u","tags":null}`+"\n" `"private_networking":false,"monitoring":false,"user_data":"u","tags":null}`+"\n"
req, _ := c.NewRequest(ctx, "GET", inURL, inBody) req, _ := c.NewRequest(ctx, http.MethodGet, inURL, inBody)
// test relative URL was expanded // test relative URL was expanded
if req.URL.String() != outURL { if req.URL.String() != outURL {
@ -188,21 +188,21 @@ func TestNewRequest_withUserData(t *testing.T) {
func TestNewRequest_badURL(t *testing.T) { func TestNewRequest_badURL(t *testing.T) {
c := NewClient(nil) c := NewClient(nil)
_, err := c.NewRequest(ctx, "GET", ":", nil) _, err := c.NewRequest(ctx, http.MethodGet, ":", nil)
testURLParseError(t, err) testURLParseError(t, err)
} }
func TestNewRequest_withCustomUserAgent(t *testing.T) { func TestNewRequest_withCustomUserAgent(t *testing.T) {
ua := "testing" ua := "testing/0.0.1"
c, err := New(nil, SetUserAgent(ua)) c, err := New(nil, SetUserAgent(ua))
if err != nil { if err != nil {
t.Fatalf("New() unexpected error: %v", err) t.Fatalf("New() unexpected error: %v", err)
} }
req, _ := c.NewRequest(ctx, "GET", "/foo", nil) req, _ := c.NewRequest(ctx, http.MethodGet, "/foo", nil)
expected := fmt.Sprintf("%s+%s", ua, userAgent) expected := fmt.Sprintf("%s %s", ua, userAgent)
if got := req.Header.Get("User-Agent"); got != expected { if got := req.Header.Get("User-Agent"); got != expected {
t.Errorf("New() UserAgent = %s; expected %s", got, expected) t.Errorf("New() UserAgent = %s; expected %s", got, expected)
} }
@ -217,13 +217,13 @@ func TestDo(t *testing.T) {
} }
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if m := "GET"; m != r.Method { if m := http.MethodGet; m != r.Method {
t.Errorf("Request method = %v, expected %v", r.Method, m) t.Errorf("Request method = %v, expected %v", r.Method, m)
} }
fmt.Fprint(w, `{"A":"a"}`) fmt.Fprint(w, `{"A":"a"}`)
}) })
req, _ := client.NewRequest(ctx, "GET", "/", nil) req, _ := client.NewRequest(ctx, http.MethodGet, "/", nil)
body := new(foo) body := new(foo)
_, err := client.Do(context.Background(), req, body) _, err := client.Do(context.Background(), req, body)
if err != nil { if err != nil {
@ -244,7 +244,7 @@ func TestDo_httpError(t *testing.T) {
http.Error(w, "Bad Request", 400) http.Error(w, "Bad Request", 400)
}) })
req, _ := client.NewRequest(ctx, "GET", "/", nil) req, _ := client.NewRequest(ctx, http.MethodGet, "/", nil)
_, err := client.Do(context.Background(), req, nil) _, err := client.Do(context.Background(), req, nil)
if err == nil { if err == nil {
@ -262,7 +262,7 @@ func TestDo_redirectLoop(t *testing.T) {
http.Redirect(w, r, "/", http.StatusFound) http.Redirect(w, r, "/", http.StatusFound)
}) })
req, _ := client.NewRequest(ctx, "GET", "/", nil) req, _ := client.NewRequest(ctx, http.MethodGet, "/", nil)
_, err := client.Do(context.Background(), req, nil) _, err := client.Do(context.Background(), req, nil)
if err == nil { if err == nil {
@ -347,7 +347,7 @@ func TestDo_rateLimit(t *testing.T) {
t.Errorf("Client rate reset not initialized to zero value") t.Errorf("Client rate reset not initialized to zero value")
} }
req, _ := client.NewRequest(ctx, "GET", "/", nil) req, _ := client.NewRequest(ctx, http.MethodGet, "/", nil)
_, err := client.Do(context.Background(), req, nil) _, err := client.Do(context.Background(), req, nil)
if err != nil { if err != nil {
t.Fatalf("Do(): %v", err) t.Fatalf("Do(): %v", err)
@ -378,7 +378,7 @@ func TestDo_rateLimit_errorResponse(t *testing.T) {
var expected int var expected int
req, _ := client.NewRequest(ctx, "GET", "/", nil) req, _ := client.NewRequest(ctx, http.MethodGet, "/", nil)
_, _ = client.Do(context.Background(), req, nil) _, _ = client.Do(context.Background(), req, nil)
if expected = 60; client.Rate.Limit != expected { if expected = 60; client.Rate.Limit != expected {
@ -414,13 +414,13 @@ func TestDo_completion_callback(t *testing.T) {
} }
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if m := "GET"; m != r.Method { if m := http.MethodGet; m != r.Method {
t.Errorf("Request method = %v, expected %v", r.Method, m) t.Errorf("Request method = %v, expected %v", r.Method, m)
} }
fmt.Fprint(w, `{"A":"a"}`) fmt.Fprint(w, `{"A":"a"}`)
}) })
req, _ := client.NewRequest(ctx, "GET", "/", nil) req, _ := client.NewRequest(ctx, http.MethodGet, "/", nil)
body := new(foo) body := new(foo)
var completedReq *http.Request var completedReq *http.Request
var completedResp string var completedResp string
@ -506,13 +506,14 @@ func TestAddOptions(t *testing.T) {
} }
func TestCustomUserAgent(t *testing.T) { func TestCustomUserAgent(t *testing.T) {
c, err := New(nil, SetUserAgent("testing")) ua := "testing/0.0.1"
c, err := New(nil, SetUserAgent(ua))
if err != nil { if err != nil {
t.Fatalf("New() unexpected error: %v", err) t.Fatalf("New() unexpected error: %v", err)
} }
expected := fmt.Sprintf("%s+%s", "testing", userAgent) expected := fmt.Sprintf("%s %s", ua, userAgent)
if got := c.UserAgent; got != expected { if got := c.UserAgent; got != expected {
t.Errorf("New() UserAgent = %s; expected %s", got, expected) t.Errorf("New() UserAgent = %s; expected %s", got, expected)
} }

View File

@ -2,6 +2,7 @@ package godo
import ( import (
"fmt" "fmt"
"net/http"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
) )
@ -35,7 +36,7 @@ func (i *ImageActionsServiceOp) Transfer(ctx context.Context, imageID int, trans
path := fmt.Sprintf("v2/images/%d/actions", imageID) path := fmt.Sprintf("v2/images/%d/actions", imageID)
req, err := i.client.NewRequest(ctx, "POST", path, transferRequest) req, err := i.client.NewRequest(ctx, http.MethodPost, path, transferRequest)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -61,7 +62,7 @@ func (i *ImageActionsServiceOp) Convert(ctx context.Context, imageID int) (*Acti
"type": "convert", "type": "convert",
} }
req, err := i.client.NewRequest(ctx, "POST", path, convertRequest) req, err := i.client.NewRequest(ctx, http.MethodPost, path, convertRequest)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -87,7 +88,7 @@ func (i *ImageActionsServiceOp) Get(ctx context.Context, imageID, actionID int)
path := fmt.Sprintf("v2/images/%d/actions/%d", imageID, actionID) path := fmt.Sprintf("v2/images/%d/actions/%d", imageID, actionID)
req, err := i.client.NewRequest(ctx, "GET", path, nil) req, err := i.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -21,7 +21,7 @@ func TestImageActions_Transfer(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, transferRequest) { if !reflect.DeepEqual(v, transferRequest) {
t.Errorf("Request body = %+v, expected %+v", v, transferRequest) t.Errorf("Request body = %+v, expected %+v", v, transferRequest)
} }
@ -56,7 +56,7 @@ func TestImageActions_Convert(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, convertRequest) { if !reflect.DeepEqual(v, convertRequest) {
t.Errorf("Request body = %+v, expected %+v", v, convertRequest) t.Errorf("Request body = %+v, expected %+v", v, convertRequest)
} }
@ -81,7 +81,7 @@ func TestImageActions_Get(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/images/123/actions/456", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/images/123/actions/456", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`) fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
}) })

View File

@ -2,6 +2,7 @@ package godo
import ( import (
"fmt" "fmt"
"net/http"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
) )
@ -140,7 +141,7 @@ func (s *ImagesServiceOp) Delete(ctx context.Context, imageID int) (*Response, e
path := fmt.Sprintf("%s/%d", imageBasePath, imageID) path := fmt.Sprintf("%s/%d", imageBasePath, imageID)
req, err := s.client.NewRequest(ctx, "DELETE", path, nil) req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -154,7 +155,7 @@ func (s *ImagesServiceOp) Delete(ctx context.Context, imageID int) (*Response, e
func (s *ImagesServiceOp) get(ctx context.Context, ID interface{}) (*Image, *Response, error) { func (s *ImagesServiceOp) get(ctx context.Context, ID interface{}) (*Image, *Response, error) {
path := fmt.Sprintf("%s/%v", imageBasePath, ID) path := fmt.Sprintf("%s/%v", imageBasePath, ID)
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -180,7 +181,7 @@ func (s *ImagesServiceOp) list(ctx context.Context, opt *ListOptions, listOpt *l
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -13,7 +13,7 @@ func TestImages_List(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"images":[{"id":1},{"id":2}]}`) fmt.Fprint(w, `{"images":[{"id":1},{"id":2}]}`)
}) })
@ -33,7 +33,7 @@ func TestImages_ListDistribution(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
expected := "distribution" expected := "distribution"
actual := r.URL.Query().Get("type") actual := r.URL.Query().Get("type")
if actual != expected { if actual != expected {
@ -58,7 +58,7 @@ func TestImages_ListApplication(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
expected := "application" expected := "application"
actual := r.URL.Query().Get("type") actual := r.URL.Query().Get("type")
if actual != expected { if actual != expected {
@ -83,7 +83,7 @@ func TestImages_ListUser(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
expected := "true" expected := "true"
actual := r.URL.Query().Get("private") actual := r.URL.Query().Get("private")
if actual != expected { if actual != expected {
@ -109,7 +109,7 @@ func TestImages_ListImagesMultiplePages(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"images": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/images/?page=2"}}}`) fmt.Fprint(w, `{"images": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/images/?page=2"}}}`)
}) })
@ -138,7 +138,7 @@ func TestImages_RetrievePageByNumber(t *testing.T) {
}` }`
mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })
@ -156,7 +156,7 @@ func TestImages_GetImageByID(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/images/12345", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/images/12345", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"image":{"id":12345}}`) fmt.Fprint(w, `{"image":{"id":12345}}`)
}) })
@ -176,7 +176,7 @@ func TestImages_GetImageBySlug(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/images/ubuntu", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/images/ubuntu", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"image":{"id":12345}}`) fmt.Fprint(w, `{"image":{"id":12345}}`)
}) })
@ -232,7 +232,7 @@ func TestImages_Destroy(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/images/12345", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/images/12345", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
_, err := client.Images.Delete(ctx, 12345) _, err := client.Images.Delete(ctx, 12345)

View File

@ -2,6 +2,7 @@ package godo
import ( import (
"fmt" "fmt"
"net/http"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
) )
@ -70,7 +71,7 @@ func (s *KeysServiceOp) List(ctx context.Context, opt *ListOptions) ([]Key, *Res
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -89,7 +90,7 @@ func (s *KeysServiceOp) List(ctx context.Context, opt *ListOptions) ([]Key, *Res
// Performs a get given a path // Performs a get given a path
func (s *KeysServiceOp) get(ctx context.Context, path string) (*Key, *Response, error) { func (s *KeysServiceOp) get(ctx context.Context, path string) (*Key, *Response, error) {
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -129,7 +130,7 @@ func (s *KeysServiceOp) Create(ctx context.Context, createRequest *KeyCreateRequ
return nil, nil, NewArgError("createRequest", "cannot be nil") return nil, nil, NewArgError("createRequest", "cannot be nil")
} }
req, err := s.client.NewRequest(ctx, "POST", keysBasePath, createRequest) req, err := s.client.NewRequest(ctx, http.MethodPost, keysBasePath, createRequest)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -195,7 +196,7 @@ func (s *KeysServiceOp) UpdateByFingerprint(ctx context.Context, fingerprint str
// Delete key using a path // Delete key using a path
func (s *KeysServiceOp) delete(ctx context.Context, path string) (*Response, error) { func (s *KeysServiceOp) delete(ctx context.Context, path string) (*Response, error) {
req, err := s.client.NewRequest(ctx, "DELETE", path, nil) req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -13,7 +13,7 @@ func TestKeys_List(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"ssh_keys":[{"id":1},{"id":2}]}`) fmt.Fprint(w, `{"ssh_keys":[{"id":1},{"id":2}]}`)
}) })
@ -33,7 +33,7 @@ func TestKeys_ListKeysMultiplePages(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"droplets": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/account/keys/?page=2"}}}`) fmt.Fprint(w, `{"droplets": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/account/keys/?page=2"}}}`)
}) })
@ -62,7 +62,7 @@ func TestKeys_RetrievePageByNumber(t *testing.T) {
}` }`
mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })
@ -79,7 +79,7 @@ func TestKeys_GetByID(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/account/keys/12345", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/account/keys/12345", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"ssh_key": {"id":12345}}`) fmt.Fprint(w, `{"ssh_key": {"id":12345}}`)
}) })
@ -99,7 +99,7 @@ func TestKeys_GetByFingerprint(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/account/keys/aa:bb:cc", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/account/keys/aa:bb:cc", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"ssh_key": {"fingerprint":"aa:bb:cc"}}`) fmt.Fprint(w, `{"ssh_key": {"fingerprint":"aa:bb:cc"}}`)
}) })
@ -130,7 +130,7 @@ func TestKeys_Create(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, createRequest) { if !reflect.DeepEqual(v, createRequest) {
t.Errorf("Request body = %+v, expected %+v", v, createRequest) t.Errorf("Request body = %+v, expected %+v", v, createRequest)
} }
@ -226,7 +226,7 @@ func TestKeys_DestroyByID(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/account/keys/12345", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/account/keys/12345", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
_, err := client.Keys.DeleteByID(ctx, 12345) _, err := client.Keys.DeleteByID(ctx, 12345)
@ -240,7 +240,7 @@ func TestKeys_DestroyByFingerprint(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/account/keys/aa:bb:cc", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/account/keys/aa:bb:cc", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
_, err := client.Keys.DeleteByFingerprint(ctx, "aa:bb:cc") _, err := client.Keys.DeleteByFingerprint(ctx, "aa:bb:cc")

View File

@ -2,12 +2,14 @@ package godo
import ( import (
"fmt" "fmt"
"net/http"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
) )
const loadBalancersBasePath = "/v2/load_balancers" const loadBalancersBasePath = "/v2/load_balancers"
const forwardingRulesPath = "forwarding_rules" const forwardingRulesPath = "forwarding_rules"
const dropletsPath = "droplets" const dropletsPath = "droplets"
// LoadBalancersService is an interface for managing load balancers with the DigitalOcean API. // LoadBalancersService is an interface for managing load balancers with the DigitalOcean API.
@ -46,6 +48,32 @@ func (l LoadBalancer) String() string {
return Stringify(l) return Stringify(l)
} }
// AsRequest creates a LoadBalancerRequest that can be submitted to Update with the current values of the LoadBalancer.
// Modifying the returned LoadBalancerRequest will not modify the original LoadBalancer.
func (l LoadBalancer) AsRequest() *LoadBalancerRequest {
r := LoadBalancerRequest{
Name: l.Name,
Algorithm: l.Algorithm,
ForwardingRules: append([]ForwardingRule(nil), l.ForwardingRules...),
DropletIDs: append([]int(nil), l.DropletIDs...),
Tag: l.Tag,
RedirectHttpToHttps: l.RedirectHttpToHttps,
HealthCheck: l.HealthCheck,
}
if l.HealthCheck != nil {
r.HealthCheck = &HealthCheck{}
*r.HealthCheck = *l.HealthCheck
}
if l.StickySessions != nil {
r.StickySessions = &StickySessions{}
*r.StickySessions = *l.StickySessions
}
if l.Region != nil {
r.Region = l.Region.Slug
}
return &r
}
// ForwardingRule represents load balancer forwarding rules. // ForwardingRule represents load balancer forwarding rules.
type ForwardingRule struct { type ForwardingRule struct {
EntryProtocol string `json:"entry_protocol,omitempty"` EntryProtocol string `json:"entry_protocol,omitempty"`
@ -143,7 +171,7 @@ var _ LoadBalancersService = &LoadBalancersServiceOp{}
func (l *LoadBalancersServiceOp) Get(ctx context.Context, lbID string) (*LoadBalancer, *Response, error) { func (l *LoadBalancersServiceOp) Get(ctx context.Context, lbID string) (*LoadBalancer, *Response, error) {
path := fmt.Sprintf("%s/%s", loadBalancersBasePath, lbID) path := fmt.Sprintf("%s/%s", loadBalancersBasePath, lbID)
req, err := l.client.NewRequest(ctx, "GET", path, nil) req, err := l.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -164,7 +192,7 @@ func (l *LoadBalancersServiceOp) List(ctx context.Context, opt *ListOptions) ([]
return nil, nil, err return nil, nil, err
} }
req, err := l.client.NewRequest(ctx, "GET", path, nil) req, err := l.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -183,7 +211,7 @@ func (l *LoadBalancersServiceOp) List(ctx context.Context, opt *ListOptions) ([]
// Create a new load balancer with a given configuration. // Create a new load balancer with a given configuration.
func (l *LoadBalancersServiceOp) Create(ctx context.Context, lbr *LoadBalancerRequest) (*LoadBalancer, *Response, error) { func (l *LoadBalancersServiceOp) Create(ctx context.Context, lbr *LoadBalancerRequest) (*LoadBalancer, *Response, error) {
req, err := l.client.NewRequest(ctx, "POST", loadBalancersBasePath, lbr) req, err := l.client.NewRequest(ctx, http.MethodPost, loadBalancersBasePath, lbr)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -219,7 +247,7 @@ func (l *LoadBalancersServiceOp) Update(ctx context.Context, lbID string, lbr *L
func (l *LoadBalancersServiceOp) Delete(ctx context.Context, ldID string) (*Response, error) { func (l *LoadBalancersServiceOp) Delete(ctx context.Context, ldID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", loadBalancersBasePath, ldID) path := fmt.Sprintf("%s/%s", loadBalancersBasePath, ldID)
req, err := l.client.NewRequest(ctx, "DELETE", path, nil) req, err := l.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -231,7 +259,7 @@ func (l *LoadBalancersServiceOp) Delete(ctx context.Context, ldID string) (*Resp
func (l *LoadBalancersServiceOp) AddDroplets(ctx context.Context, lbID string, dropletIDs ...int) (*Response, error) { func (l *LoadBalancersServiceOp) AddDroplets(ctx context.Context, lbID string, dropletIDs ...int) (*Response, error) {
path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, dropletsPath) path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, dropletsPath)
req, err := l.client.NewRequest(ctx, "POST", path, &dropletIDsRequest{IDs: dropletIDs}) req, err := l.client.NewRequest(ctx, http.MethodPost, path, &dropletIDsRequest{IDs: dropletIDs})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -243,7 +271,7 @@ func (l *LoadBalancersServiceOp) AddDroplets(ctx context.Context, lbID string, d
func (l *LoadBalancersServiceOp) RemoveDroplets(ctx context.Context, lbID string, dropletIDs ...int) (*Response, error) { func (l *LoadBalancersServiceOp) RemoveDroplets(ctx context.Context, lbID string, dropletIDs ...int) (*Response, error) {
path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, dropletsPath) path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, dropletsPath)
req, err := l.client.NewRequest(ctx, "DELETE", path, &dropletIDsRequest{IDs: dropletIDs}) req, err := l.client.NewRequest(ctx, http.MethodDelete, path, &dropletIDsRequest{IDs: dropletIDs})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -255,7 +283,7 @@ func (l *LoadBalancersServiceOp) RemoveDroplets(ctx context.Context, lbID string
func (l *LoadBalancersServiceOp) AddForwardingRules(ctx context.Context, lbID string, rules ...ForwardingRule) (*Response, error) { func (l *LoadBalancersServiceOp) AddForwardingRules(ctx context.Context, lbID string, rules ...ForwardingRule) (*Response, error) {
path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, forwardingRulesPath) path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, forwardingRulesPath)
req, err := l.client.NewRequest(ctx, "POST", path, &forwardingRulesRequest{Rules: rules}) req, err := l.client.NewRequest(ctx, http.MethodPost, path, &forwardingRulesRequest{Rules: rules})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -267,7 +295,7 @@ func (l *LoadBalancersServiceOp) AddForwardingRules(ctx context.Context, lbID st
func (l *LoadBalancersServiceOp) RemoveForwardingRules(ctx context.Context, lbID string, rules ...ForwardingRule) (*Response, error) { func (l *LoadBalancersServiceOp) RemoveForwardingRules(ctx context.Context, lbID string, rules ...ForwardingRule) (*Response, error) {
path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, forwardingRulesPath) path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, forwardingRulesPath)
req, err := l.client.NewRequest(ctx, "DELETE", path, &forwardingRulesRequest{Rules: rules}) req, err := l.client.NewRequest(ctx, http.MethodDelete, path, &forwardingRulesRequest{Rules: rules})
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -272,7 +272,7 @@ var lbUpdateJSONResponse = `
} }
` `
func TestLoadBlanacers_Get(t *testing.T) { func TestLoadBalancers_Get(t *testing.T) {
setup() setup()
defer teardown() defer teardown()
@ -280,7 +280,7 @@ func TestLoadBlanacers_Get(t *testing.T) {
loadBalancerId := "37e6be88-01ec-4ec7-9bc6-a514d4719057" loadBalancerId := "37e6be88-01ec-4ec7-9bc6-a514d4719057"
path = fmt.Sprintf("%s/%s", path, loadBalancerId) path = fmt.Sprintf("%s/%s", path, loadBalancerId)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, lbGetJSONResponse) fmt.Fprint(w, lbGetJSONResponse)
}) })
@ -333,7 +333,7 @@ func TestLoadBlanacers_Get(t *testing.T) {
assert.Equal(t, expected, loadBalancer) assert.Equal(t, expected, loadBalancer)
} }
func TestLoadBlanacers_Create(t *testing.T) { func TestLoadBalancers_Create(t *testing.T) {
setup() setup()
defer teardown() defer teardown()
@ -377,7 +377,7 @@ func TestLoadBlanacers_Create(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
assert.Equal(t, createRequest, v) assert.Equal(t, createRequest, v)
fmt.Fprint(w, lbCreateJSONResponse) fmt.Fprint(w, lbCreateJSONResponse)
@ -440,7 +440,7 @@ func TestLoadBlanacers_Create(t *testing.T) {
assert.Equal(t, expected, loadBalancer) assert.Equal(t, expected, loadBalancer)
} }
func TestLoadBlanacers_Update(t *testing.T) { func TestLoadBalancers_Update(t *testing.T) {
setup() setup()
defer teardown() defer teardown()
@ -547,13 +547,13 @@ func TestLoadBlanacers_Update(t *testing.T) {
assert.Equal(t, expected, loadBalancer) assert.Equal(t, expected, loadBalancer)
} }
func TestLoadBlanacers_List(t *testing.T) { func TestLoadBalancers_List(t *testing.T) {
setup() setup()
defer teardown() defer teardown()
path := "/v2/load_balancers" path := "/v2/load_balancers"
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, lbListJSONResponse) fmt.Fprint(w, lbListJSONResponse)
}) })
@ -608,13 +608,13 @@ func TestLoadBlanacers_List(t *testing.T) {
assert.Equal(t, expected, loadBalancers) assert.Equal(t, expected, loadBalancers)
} }
func TestLoadBlanacers_List_Pagination(t *testing.T) { func TestLoadBalancers_List_Pagination(t *testing.T) {
setup() setup()
defer teardown() defer teardown()
path := "/v2/load_balancers" path := "/v2/load_balancers"
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
testFormValues(t, r, map[string]string{"page": "2"}) testFormValues(t, r, map[string]string{"page": "2"})
fmt.Fprint(w, lbListJSONResponse) fmt.Fprint(w, lbListJSONResponse)
}) })
@ -630,7 +630,7 @@ func TestLoadBlanacers_List_Pagination(t *testing.T) {
assert.Equal(t, "http://localhost:3001/v2/load_balancers?page=3&per_page=1", resp.Links.Pages.Last) assert.Equal(t, "http://localhost:3001/v2/load_balancers?page=3&per_page=1", resp.Links.Pages.Last)
} }
func TestLoadBlanacers_Delete(t *testing.T) { func TestLoadBalancers_Delete(t *testing.T) {
setup() setup()
defer teardown() defer teardown()
@ -638,7 +638,7 @@ func TestLoadBlanacers_Delete(t *testing.T) {
path := "/v2/load_balancers" path := "/v2/load_balancers"
path = fmt.Sprintf("%s/%s", path, lbID) path = fmt.Sprintf("%s/%s", path, lbID)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
_, err := client.LoadBalancers.Delete(ctx, lbID) _, err := client.LoadBalancers.Delete(ctx, lbID)
@ -648,7 +648,7 @@ func TestLoadBlanacers_Delete(t *testing.T) {
} }
} }
func TestLoadBlanacers_AddDroplets(t *testing.T) { func TestLoadBalancers_AddDroplets(t *testing.T) {
setup() setup()
defer teardown() defer teardown()
@ -665,7 +665,7 @@ func TestLoadBlanacers_AddDroplets(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
assert.Equal(t, dropletIdsRequest, v) assert.Equal(t, dropletIdsRequest, v)
fmt.Fprint(w, nil) fmt.Fprint(w, nil)
@ -678,7 +678,7 @@ func TestLoadBlanacers_AddDroplets(t *testing.T) {
} }
} }
func TestLoadBlanacers_RemoveDroplets(t *testing.T) { func TestLoadBalancers_RemoveDroplets(t *testing.T) {
setup() setup()
defer teardown() defer teardown()
@ -695,7 +695,7 @@ func TestLoadBlanacers_RemoveDroplets(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
assert.Equal(t, dropletIdsRequest, v) assert.Equal(t, dropletIdsRequest, v)
fmt.Fprint(w, nil) fmt.Fprint(w, nil)
@ -708,7 +708,7 @@ func TestLoadBlanacers_RemoveDroplets(t *testing.T) {
} }
} }
func TestLoadBlanacers_AddForwardingRules(t *testing.T) { func TestLoadBalancers_AddForwardingRules(t *testing.T) {
setup() setup()
defer teardown() defer teardown()
@ -739,7 +739,7 @@ func TestLoadBlanacers_AddForwardingRules(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
assert.Equal(t, frr, v) assert.Equal(t, frr, v)
fmt.Fprint(w, nil) fmt.Fprint(w, nil)
@ -752,7 +752,7 @@ func TestLoadBlanacers_AddForwardingRules(t *testing.T) {
} }
} }
func TestLoadBlanacers_RemoveForwardingRules(t *testing.T) { func TestLoadBalancers_RemoveForwardingRules(t *testing.T) {
setup() setup()
defer teardown() defer teardown()
@ -782,7 +782,7 @@ func TestLoadBlanacers_RemoveForwardingRules(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
assert.Equal(t, frr, v) assert.Equal(t, frr, v)
fmt.Fprint(w, nil) fmt.Fprint(w, nil)
@ -794,3 +794,108 @@ func TestLoadBlanacers_RemoveForwardingRules(t *testing.T) {
t.Errorf("LoadBalancers.RemoveForwardingRules returned error: %v", err) t.Errorf("LoadBalancers.RemoveForwardingRules returned error: %v", err)
} }
} }
func TestLoadBalancers_AsRequest(t *testing.T) {
lb := &LoadBalancer{
ID: "37e6be88-01ec-4ec7-9bc6-a514d4719057",
Name: "test-loadbalancer",
IP: "10.0.0.1",
Algorithm: "least_connections",
Status: "active",
Created: "2011-06-24T12:00:00Z",
HealthCheck: &HealthCheck{
Protocol: "http",
Port: 80,
Path: "/ping",
CheckIntervalSeconds: 30,
ResponseTimeoutSeconds: 10,
HealthyThreshold: 3,
UnhealthyThreshold: 3,
},
StickySessions: &StickySessions{
Type: "cookies",
CookieName: "nomnom",
CookieTtlSeconds: 32,
},
Region: &Region{
Slug: "lon1",
},
RedirectHttpToHttps: true,
}
lb.DropletIDs = make([]int, 1, 2)
lb.DropletIDs[0] = 12345
lb.ForwardingRules = make([]ForwardingRule, 1, 2)
lb.ForwardingRules[0] = ForwardingRule{
EntryProtocol: "http",
EntryPort: 80,
TargetProtocol: "http",
TargetPort: 80,
}
want := &LoadBalancerRequest{
Name: "test-loadbalancer",
Algorithm: "least_connections",
Region: "lon1",
ForwardingRules: []ForwardingRule{ForwardingRule{
EntryProtocol: "http",
EntryPort: 80,
TargetProtocol: "http",
TargetPort: 80,
}},
HealthCheck: &HealthCheck{
Protocol: "http",
Port: 80,
Path: "/ping",
CheckIntervalSeconds: 30,
ResponseTimeoutSeconds: 10,
HealthyThreshold: 3,
UnhealthyThreshold: 3,
},
StickySessions: &StickySessions{
Type: "cookies",
CookieName: "nomnom",
CookieTtlSeconds: 32,
},
DropletIDs: []int{12345},
RedirectHttpToHttps: true,
}
r := lb.AsRequest()
assert.Equal(t, want, r)
assert.False(t, r.HealthCheck == lb.HealthCheck, "HealthCheck points to same struct")
assert.False(t, r.StickySessions == lb.StickySessions, "StickySessions points to same struct")
r.DropletIDs = append(r.DropletIDs, 54321)
r.ForwardingRules = append(r.ForwardingRules, ForwardingRule{
EntryProtocol: "https",
EntryPort: 443,
TargetProtocol: "https",
TargetPort: 443,
TlsPassthrough: true,
})
// Check that original LoadBalancer hasn't changed
lb.DropletIDs = append(lb.DropletIDs, 13579)
lb.ForwardingRules = append(lb.ForwardingRules, ForwardingRule{
EntryProtocol: "tcp",
EntryPort: 587,
TargetProtocol: "tcp",
TargetPort: 587,
})
assert.Equal(t, []int{12345, 54321}, r.DropletIDs)
assert.Equal(t, []ForwardingRule{
ForwardingRule{
EntryProtocol: "http",
EntryPort: 80,
TargetProtocol: "http",
TargetPort: 80,
},
ForwardingRule{
EntryProtocol: "https",
EntryPort: 443,
TargetProtocol: "https",
TargetPort: 443,
TlsPassthrough: true,
},
}, r.ForwardingRules)
}

View File

@ -1,6 +1,10 @@
package godo package godo
import "github.com/digitalocean/godo/context" import (
"net/http"
"github.com/digitalocean/godo/context"
)
// RegionsService is an interface for interfacing with the regions // RegionsService is an interface for interfacing with the regions
// endpoints of the DigitalOcean API // endpoints of the DigitalOcean API
@ -43,7 +47,7 @@ func (s *RegionsServiceOp) List(ctx context.Context, opt *ListOptions) ([]Region
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -12,7 +12,7 @@ func TestRegions_List(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/regions", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/regions", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"regions":[{"slug":"1"},{"slug":"2"}]}`) fmt.Fprint(w, `{"regions":[{"slug":"1"},{"slug":"2"}]}`)
}) })
@ -32,7 +32,7 @@ func TestRegions_ListRegionsMultiplePages(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/regions", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/regions", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"regions": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/regions/?page=2"}}}`) fmt.Fprint(w, `{"regions": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/regions/?page=2"}}}`)
}) })
@ -62,7 +62,7 @@ func TestRegions_RetrievePageByNumber(t *testing.T) {
}` }`
mux.HandleFunc("/v2/regions", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/regions", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })

View File

@ -1,6 +1,10 @@
package godo package godo
import "github.com/digitalocean/godo/context" import (
"net/http"
"github.com/digitalocean/godo/context"
)
// SizesService is an interface for interfacing with the size // SizesService is an interface for interfacing with the size
// endpoints of the DigitalOcean API // endpoints of the DigitalOcean API
@ -47,7 +51,7 @@ func (s *SizesServiceOp) List(ctx context.Context, opt *ListOptions) ([]Size, *R
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -12,7 +12,7 @@ func TestSizes_List(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/sizes", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/sizes", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"sizes":[{"slug":"1"},{"slug":"2"}]}`) fmt.Fprint(w, `{"sizes":[{"slug":"1"},{"slug":"2"}]}`)
}) })
@ -32,7 +32,7 @@ func TestSizes_ListSizesMultiplePages(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/sizes", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/sizes", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"sizes": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/sizes/?page=2"}}}`) fmt.Fprint(w, `{"sizes": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/sizes/?page=2"}}}`)
}) })
@ -62,7 +62,7 @@ func TestSizes_RetrievePageByNumber(t *testing.T) {
}` }`
mux.HandleFunc("/v2/sizes", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/sizes", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })

View File

@ -2,6 +2,7 @@ package godo
import ( import (
"fmt" "fmt"
"net/http"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
) )
@ -82,7 +83,7 @@ func (s *SnapshotsServiceOp) Get(ctx context.Context, snapshotID string) (*Snaps
func (s *SnapshotsServiceOp) Delete(ctx context.Context, snapshotID string) (*Response, error) { func (s *SnapshotsServiceOp) Delete(ctx context.Context, snapshotID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", snapshotBasePath, snapshotID) path := fmt.Sprintf("%s/%s", snapshotBasePath, snapshotID)
req, err := s.client.NewRequest(ctx, "DELETE", path, nil) req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -96,7 +97,7 @@ func (s *SnapshotsServiceOp) Delete(ctx context.Context, snapshotID string) (*Re
func (s *SnapshotsServiceOp) get(ctx context.Context, ID string) (*Snapshot, *Response, error) { func (s *SnapshotsServiceOp) get(ctx context.Context, ID string) (*Snapshot, *Response, error) {
path := fmt.Sprintf("%s/%s", snapshotBasePath, ID) path := fmt.Sprintf("%s/%s", snapshotBasePath, ID)
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -122,7 +123,7 @@ func (s *SnapshotsServiceOp) list(ctx context.Context, opt *ListOptions, listOpt
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -14,7 +14,7 @@ func TestSnapshots_List(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"snapshots":[{"id":"1"},{"id":"2", "size_gigabytes": 4.84}]}`) fmt.Fprint(w, `{"snapshots":[{"id":"1"},{"id":"2", "size_gigabytes": 4.84}]}`)
}) })
ctx := context.Background() ctx := context.Background()
@ -34,7 +34,7 @@ func TestSnapshots_ListVolume(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
expected := "volume" expected := "volume"
actual := r.URL.Query().Get("resource_type") actual := r.URL.Query().Get("resource_type")
if actual != expected { if actual != expected {
@ -60,7 +60,7 @@ func TestSnapshots_ListDroplet(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
expected := "droplet" expected := "droplet"
actual := r.URL.Query().Get("resource_type") actual := r.URL.Query().Get("resource_type")
if actual != expected { if actual != expected {
@ -87,7 +87,7 @@ func TestSnapshots_ListSnapshotsMultiplePages(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"snapshots": [{"id":"1"},{"id":"2"}], "links":{"pages":{"next":"http://example.com/v2/snapshots/?page=2"}}}`) fmt.Fprint(w, `{"snapshots": [{"id":"1"},{"id":"2"}], "links":{"pages":{"next":"http://example.com/v2/snapshots/?page=2"}}}`)
}) })
@ -117,7 +117,7 @@ func TestSnapshots_RetrievePageByNumber(t *testing.T) {
}` }`
mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })
@ -136,7 +136,7 @@ func TestSnapshots_GetSnapshotByID(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/snapshots/12345", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/snapshots/12345", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"snapshot":{"id":"12345"}}`) fmt.Fprint(w, `{"snapshot":{"id":"12345"}}`)
}) })
@ -157,7 +157,7 @@ func TestSnapshots_Destroy(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/snapshots/12345", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/snapshots/12345", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
ctx := context.Background() ctx := context.Background()

View File

@ -4,6 +4,8 @@ import (
"fmt" "fmt"
"time" "time"
"net/http"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
) )
@ -94,7 +96,7 @@ func (svc *StorageServiceOp) ListVolumes(ctx context.Context, params *ListVolume
} }
} }
req, err := svc.client.NewRequest(ctx, "GET", path, nil) req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -116,7 +118,7 @@ func (svc *StorageServiceOp) ListVolumes(ctx context.Context, params *ListVolume
func (svc *StorageServiceOp) CreateVolume(ctx context.Context, createRequest *VolumeCreateRequest) (*Volume, *Response, error) { func (svc *StorageServiceOp) CreateVolume(ctx context.Context, createRequest *VolumeCreateRequest) (*Volume, *Response, error) {
path := storageAllocPath path := storageAllocPath
req, err := svc.client.NewRequest(ctx, "POST", path, createRequest) req, err := svc.client.NewRequest(ctx, http.MethodPost, path, createRequest)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -133,7 +135,7 @@ func (svc *StorageServiceOp) CreateVolume(ctx context.Context, createRequest *Vo
func (svc *StorageServiceOp) GetVolume(ctx context.Context, id string) (*Volume, *Response, error) { func (svc *StorageServiceOp) GetVolume(ctx context.Context, id string) (*Volume, *Response, error) {
path := fmt.Sprintf("%s/%s", storageAllocPath, id) path := fmt.Sprintf("%s/%s", storageAllocPath, id)
req, err := svc.client.NewRequest(ctx, "GET", path, nil) req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -151,7 +153,7 @@ func (svc *StorageServiceOp) GetVolume(ctx context.Context, id string) (*Volume,
func (svc *StorageServiceOp) DeleteVolume(ctx context.Context, id string) (*Response, error) { func (svc *StorageServiceOp) DeleteVolume(ctx context.Context, id string) (*Response, error) {
path := fmt.Sprintf("%s/%s", storageAllocPath, id) path := fmt.Sprintf("%s/%s", storageAllocPath, id)
req, err := svc.client.NewRequest(ctx, "DELETE", path, nil) req, err := svc.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -174,7 +176,7 @@ func (svc *StorageServiceOp) ListSnapshots(ctx context.Context, volumeID string,
return nil, nil, err return nil, nil, err
} }
req, err := svc.client.NewRequest(ctx, "GET", path, nil) req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -196,7 +198,7 @@ func (svc *StorageServiceOp) ListSnapshots(ctx context.Context, volumeID string,
func (svc *StorageServiceOp) CreateSnapshot(ctx context.Context, createRequest *SnapshotCreateRequest) (*Snapshot, *Response, error) { func (svc *StorageServiceOp) CreateSnapshot(ctx context.Context, createRequest *SnapshotCreateRequest) (*Snapshot, *Response, error) {
path := fmt.Sprintf("%s/%s/snapshots", storageAllocPath, createRequest.VolumeID) path := fmt.Sprintf("%s/%s/snapshots", storageAllocPath, createRequest.VolumeID)
req, err := svc.client.NewRequest(ctx, "POST", path, createRequest) req, err := svc.client.NewRequest(ctx, http.MethodPost, path, createRequest)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -213,7 +215,7 @@ func (svc *StorageServiceOp) CreateSnapshot(ctx context.Context, createRequest *
func (svc *StorageServiceOp) GetSnapshot(ctx context.Context, id string) (*Snapshot, *Response, error) { func (svc *StorageServiceOp) GetSnapshot(ctx context.Context, id string) (*Snapshot, *Response, error) {
path := fmt.Sprintf("%s/%s", storageSnapPath, id) path := fmt.Sprintf("%s/%s", storageSnapPath, id)
req, err := svc.client.NewRequest(ctx, "GET", path, nil) req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -231,7 +233,7 @@ func (svc *StorageServiceOp) GetSnapshot(ctx context.Context, id string) (*Snaps
func (svc *StorageServiceOp) DeleteSnapshot(ctx context.Context, id string) (*Response, error) { func (svc *StorageServiceOp) DeleteSnapshot(ctx context.Context, id string) (*Response, error) {
path := fmt.Sprintf("%s/%s", storageSnapPath, id) path := fmt.Sprintf("%s/%s", storageSnapPath, id)
req, err := svc.client.NewRequest(ctx, "DELETE", path, nil) req, err := svc.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -2,6 +2,7 @@ package godo
import ( import (
"fmt" "fmt"
"net/http"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
) )
@ -77,7 +78,7 @@ func (s *StorageActionsServiceOp) Resize(ctx context.Context, volumeID string, s
func (s *StorageActionsServiceOp) doAction(ctx context.Context, volumeID string, request *ActionRequest) (*Action, *Response, error) { func (s *StorageActionsServiceOp) doAction(ctx context.Context, volumeID string, request *ActionRequest) (*Action, *Response, error) {
path := storageAllocationActionPath(volumeID) path := storageAllocationActionPath(volumeID)
req, err := s.client.NewRequest(ctx, "POST", path, request) req, err := s.client.NewRequest(ctx, http.MethodPost, path, request)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -92,7 +93,7 @@ func (s *StorageActionsServiceOp) doAction(ctx context.Context, volumeID string,
} }
func (s *StorageActionsServiceOp) get(ctx context.Context, path string) (*Action, *Response, error) { func (s *StorageActionsServiceOp) get(ctx context.Context, path string) (*Action, *Response, error) {
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -107,7 +108,7 @@ func (s *StorageActionsServiceOp) get(ctx context.Context, path string) (*Action
} }
func (s *StorageActionsServiceOp) list(ctx context.Context, path string) ([]Action, *Response, error) { func (s *StorageActionsServiceOp) list(ctx context.Context, path string) ([]Action, *Response, error) {
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -28,7 +28,7 @@ func TestStoragesActions_Attach(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, attachRequest) { if !reflect.DeepEqual(v, attachRequest) {
t.Errorf("want=%#v", attachRequest) t.Errorf("want=%#v", attachRequest)
t.Errorf("got=%#v", v) t.Errorf("got=%#v", v)
@ -60,7 +60,7 @@ func TestStoragesActions_DetachByDropletID(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, detachByDropletIDRequest) { if !reflect.DeepEqual(v, detachByDropletIDRequest) {
t.Errorf("want=%#v", detachByDropletIDRequest) t.Errorf("want=%#v", detachByDropletIDRequest)
t.Errorf("got=%#v", v) t.Errorf("got=%#v", v)
@ -80,7 +80,7 @@ func TestStorageActions_Get(t *testing.T) {
volumeID := "98d414c6-295e-4e3a-ac58-eb9456c1e1d1" volumeID := "98d414c6-295e-4e3a-ac58-eb9456c1e1d1"
mux.HandleFunc("/v2/volumes/"+volumeID+"/actions/456", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/volumes/"+volumeID+"/actions/456", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`) fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
}) })
@ -101,7 +101,7 @@ func TestStorageActions_List(t *testing.T) {
volumeID := "98d414c6-295e-4e3a-ac58-eb9456c1e1d1" volumeID := "98d414c6-295e-4e3a-ac58-eb9456c1e1d1"
mux.HandleFunc("/v2/volumes/"+volumeID+"/actions", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/volumes/"+volumeID+"/actions", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprintf(w, `{"actions":[{"status":"in-progress"}]}`) fmt.Fprintf(w, `{"actions":[{"status":"in-progress"}]}`)
}) })
@ -134,7 +134,7 @@ func TestStoragesActions_Resize(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, resizeRequest) { if !reflect.DeepEqual(v, resizeRequest) {
t.Errorf("want=%#v", resizeRequest) t.Errorf("want=%#v", resizeRequest)
t.Errorf("got=%#v", v) t.Errorf("got=%#v", v)

View File

@ -48,7 +48,7 @@ func TestStorageVolumes_ListStorageVolumes(t *testing.T) {
}` }`
mux.HandleFunc("/v2/volumes/", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/volumes/", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })
@ -114,7 +114,7 @@ func TestStorageVolumes_Get(t *testing.T) {
}` }`
mux.HandleFunc("/v2/volumes/80d414c6-295e-4e3a-ac58-eb9456c1e1d1", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/volumes/80d414c6-295e-4e3a-ac58-eb9456c1e1d1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })
@ -166,7 +166,7 @@ func TestStorageVolumes_ListVolumesByName(t *testing.T) {
if r.URL.Query().Get("name") != "myvolume" || r.URL.Query().Get("region") != "nyc3" { if r.URL.Query().Get("name") != "myvolume" || r.URL.Query().Get("region") != "nyc3" {
t.Errorf("Storage.GetVolumeByName did not request the correct name or region") t.Errorf("Storage.GetVolumeByName did not request the correct name or region")
} }
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })
@ -222,7 +222,7 @@ func TestStorageVolumes_Create(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, createRequest) { if !reflect.DeepEqual(v, createRequest) {
t.Errorf("Request body = %+v, expected %+v", v, createRequest) t.Errorf("Request body = %+v, expected %+v", v, createRequest)
} }
@ -277,7 +277,7 @@ func TestStorageVolumes_CreateFromSnapshot(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, createRequest) { if !reflect.DeepEqual(v, createRequest) {
t.Errorf("Request body = %+v, expected %+v", v, createRequest) t.Errorf("Request body = %+v, expected %+v", v, createRequest)
} }
@ -299,7 +299,7 @@ func TestStorageVolumes_Destroy(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/volumes/80d414c6-295e-4e3a-ac58-eb9456c1e1d1", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/volumes/80d414c6-295e-4e3a-ac58-eb9456c1e1d1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
_, err := client.Storage.DeleteVolume(ctx, "80d414c6-295e-4e3a-ac58-eb9456c1e1d1") _, err := client.Storage.DeleteVolume(ctx, "80d414c6-295e-4e3a-ac58-eb9456c1e1d1")
@ -342,7 +342,7 @@ func TestStorageSnapshots_ListStorageSnapshots(t *testing.T) {
}` }`
mux.HandleFunc("/v2/volumes/98d414c6-295e-4e3a-ac58-eb9456c1e1d1/snapshots", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/volumes/98d414c6-295e-4e3a-ac58-eb9456c1e1d1/snapshots", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })
@ -402,7 +402,7 @@ func TestStorageSnapshots_Get(t *testing.T) {
}` }`
mux.HandleFunc("/v2/snapshots/80d414c6-295e-4e3a-ac58-eb9456c1e1d1", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/snapshots/80d414c6-295e-4e3a-ac58-eb9456c1e1d1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, jBlob) fmt.Fprint(w, jBlob)
}) })
@ -459,7 +459,7 @@ func TestStorageSnapshots_Create(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, createRequest) { if !reflect.DeepEqual(v, createRequest) {
t.Errorf("Request body = %+v, expected %+v", v, createRequest) t.Errorf("Request body = %+v, expected %+v", v, createRequest)
} }
@ -481,7 +481,7 @@ func TestStorageSnapshots_Destroy(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/snapshots/80d414c6-295e-4e3a-ac58-eb9456c1e1d1", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/snapshots/80d414c6-295e-4e3a-ac58-eb9456c1e1d1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
_, err := client.Storage.DeleteSnapshot(ctx, "80d414c6-295e-4e3a-ac58-eb9456c1e1d1") _, err := client.Storage.DeleteSnapshot(ctx, "80d414c6-295e-4e3a-ac58-eb9456c1e1d1")

View File

@ -2,6 +2,7 @@ package godo
import ( import (
"fmt" "fmt"
"net/http"
"github.com/digitalocean/godo/context" "github.com/digitalocean/godo/context"
) )
@ -93,7 +94,7 @@ func (s *TagsServiceOp) List(ctx context.Context, opt *ListOptions) ([]Tag, *Res
return nil, nil, err return nil, nil, err
} }
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -114,7 +115,7 @@ func (s *TagsServiceOp) List(ctx context.Context, opt *ListOptions) ([]Tag, *Res
func (s *TagsServiceOp) Get(ctx context.Context, name string) (*Tag, *Response, error) { func (s *TagsServiceOp) Get(ctx context.Context, name string) (*Tag, *Response, error) {
path := fmt.Sprintf("%s/%s", tagsBasePath, name) path := fmt.Sprintf("%s/%s", tagsBasePath, name)
req, err := s.client.NewRequest(ctx, "GET", path, nil) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -134,7 +135,7 @@ func (s *TagsServiceOp) Create(ctx context.Context, createRequest *TagCreateRequ
return nil, nil, NewArgError("createRequest", "cannot be nil") return nil, nil, NewArgError("createRequest", "cannot be nil")
} }
req, err := s.client.NewRequest(ctx, "POST", tagsBasePath, createRequest) req, err := s.client.NewRequest(ctx, http.MethodPost, tagsBasePath, createRequest)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -155,7 +156,7 @@ func (s *TagsServiceOp) Delete(ctx context.Context, name string) (*Response, err
} }
path := fmt.Sprintf("%s/%s", tagsBasePath, name) path := fmt.Sprintf("%s/%s", tagsBasePath, name)
req, err := s.client.NewRequest(ctx, "DELETE", path, nil) req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -176,7 +177,7 @@ func (s *TagsServiceOp) TagResources(ctx context.Context, name string, tagReques
} }
path := fmt.Sprintf("%s/%s/resources", tagsBasePath, name) path := fmt.Sprintf("%s/%s/resources", tagsBasePath, name)
req, err := s.client.NewRequest(ctx, "POST", path, tagRequest) req, err := s.client.NewRequest(ctx, http.MethodPost, path, tagRequest)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -197,7 +198,7 @@ func (s *TagsServiceOp) UntagResources(ctx context.Context, name string, untagRe
} }
path := fmt.Sprintf("%s/%s/resources", tagsBasePath, name) path := fmt.Sprintf("%s/%s/resources", tagsBasePath, name)
req, err := s.client.NewRequest(ctx, "DELETE", path, untagRequest) req, err := s.client.NewRequest(ctx, http.MethodDelete, path, untagRequest)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -169,7 +169,7 @@ func TestTags_List(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/tags", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/tags", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, listJSON) fmt.Fprint(w, listJSON)
}) })
@ -190,7 +190,7 @@ func TestTags_ListEmpty(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/tags", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/tags", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, listEmptyJSON) fmt.Fprint(w, listEmptyJSON)
}) })
@ -210,7 +210,7 @@ func TestTags_ListPaging(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/tags", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/tags", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, listJSON) fmt.Fprint(w, listJSON)
}) })
@ -226,7 +226,7 @@ func TestTags_Get(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/tags/testing-1", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/tags/testing-1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET") testMethod(t, r, http.MethodGet)
fmt.Fprint(w, getJSON) fmt.Fprint(w, getJSON)
}) })
@ -263,7 +263,7 @@ func TestTags_Create(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, createRequest) { if !reflect.DeepEqual(v, createRequest) {
t.Errorf("Request body = %+v, expected %+v", v, createRequest) t.Errorf("Request body = %+v, expected %+v", v, createRequest)
} }
@ -287,7 +287,7 @@ func TestTags_Delete(t *testing.T) {
defer teardown() defer teardown()
mux.HandleFunc("/v2/tags/testing-1", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/v2/tags/testing-1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
}) })
_, err := client.Tags.Delete(ctx, "testing-1") _, err := client.Tags.Delete(ctx, "testing-1")
@ -312,7 +312,7 @@ func TestTags_TagResource(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "POST") testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, tagResourcesRequest) { if !reflect.DeepEqual(v, tagResourcesRequest) {
t.Errorf("Request body = %+v, expected %+v", v, tagResourcesRequest) t.Errorf("Request body = %+v, expected %+v", v, tagResourcesRequest)
} }
@ -341,7 +341,7 @@ func TestTags_UntagResource(t *testing.T) {
t.Fatalf("decode json: %v", err) t.Fatalf("decode json: %v", err)
} }
testMethod(t, r, "DELETE") testMethod(t, r, http.MethodDelete)
if !reflect.DeepEqual(v, untagResourcesRequest) { if !reflect.DeepEqual(v, untagResourcesRequest) {
t.Errorf("Request body = %+v, expected %+v", v, untagResourcesRequest) t.Errorf("Request body = %+v, expected %+v", v, untagResourcesRequest)
} }

Some files were not shown because too many files have changed in this diff Show More